stringtranslate.com

Algoritmo de Hopcroft-Karp

En informática , el algoritmo Hopcroft-Karp (a veces llamado con mayor precisión algoritmo Hopcroft-Karp-Karzanov ) [1] es un algoritmo que toma un gráfico bipartito como entrada y produce una coincidencia de cardinalidad máxima como salida: un conjunto de tantos bordes como sea posible con la propiedad de que no hay dos bordes que compartan un punto final. Se ejecuta en el tiempo en el peor de los casos , donde es un conjunto de aristas en el gráfico, es un conjunto de vértices del gráfico, y se supone que . En el caso de gráficos densos, el límite de tiempo se vuelve , y para gráficos aleatorios dispersos , se ejecuta en el tiempo con alta probabilidad. [2]

El algoritmo fue descubierto por John Hopcroft y Richard Karp  (1973) e independientemente por Alexander Karzanov  (1973). [3] Como en métodos anteriores de coincidencia, como el algoritmo húngaro y el trabajo de Edmonds (1965), el algoritmo Hopcroft-Karp aumenta repetidamente el tamaño de una coincidencia parcial al encontrar caminos de aumento . Estas rutas son secuencias de aristas del gráfico, que alternan entre aristas en la coincidencia y aristas fuera de la coincidencia parcial, y donde las aristas inicial y final no están en la coincidencia parcial. Encontrar una ruta de aumento nos permite incrementar el tamaño de la coincidencia parcial, simplemente alternando los bordes de la ruta de aumento (poniendo en la coincidencia parcial aquellos que no lo eran, y viceversa). Los algoritmos más simples para el emparejamiento bipartito, como el algoritmo Ford-Fulkerson , encuentran una ruta de aumento por iteración: el algoritmo Hopcroft-Karp, en cambio, encuentra un conjunto máximo de rutas de aumento más cortas, para garantizar que solo se necesiten iteraciones en lugar de iteraciones. Se puede lograr el mismo rendimiento para encontrar coincidencias de cardinalidad máxima en gráficos arbitrarios, con el algoritmo más complicado de Micali y Vazirani. [4]

El algoritmo Hopcroft-Karp puede verse como un caso especial del algoritmo de Dinic para el problema de flujo máximo . [5]

Caminos de aumento

Un vértice que no es el punto final de una arista en alguna coincidencia parcial se llama vértice libre . El concepto básico en el que se basa el algoritmo es el de una ruta aumentada , una ruta que comienza en un vértice libre, termina en un vértice libre y alterna entre aristas coincidentes y no coincidentes dentro de la ruta. De esta definición se deduce que, excepto los puntos finales, todos los demás vértices (si los hay) en la ruta aumentada deben ser vértices no libres. Un camino aumentado podría consistir en sólo dos vértices (ambos libres) y un único borde inigualable entre ellos.

Si es una coincidencia y es una ruta de aumento relativa a , entonces la diferencia simétrica de los dos conjuntos de aristas, formaría una coincidencia con el tamaño . Por lo tanto, al encontrar caminos de aumento, un algoritmo puede aumentar el tamaño de la coincidencia.

Por el contrario, supongamos que una coincidencia no es óptima y sea la diferencia simétrica donde hay una coincidencia óptima. Debido a que y son ambos coincidentes, cada vértice tiene un grado como máximo de 2 pulg . Por lo tanto, debe formar una colección de ciclos disjuntos, de caminos con un número igual de aristas coincidentes y no coincidentes en , de caminos aumentados para y de caminos aumentados para ; pero esto último es imposible porque es óptimo. Ahora, los ciclos y los caminos con igual número de vértices coincidentes y no coincidentes no contribuyen a la diferencia de tamaño entre y , por lo que esta diferencia es igual al número de caminos aumentados para in . Por lo tanto, siempre que exista una coincidencia mayor que la coincidencia actual , también debe existir una ruta de aumento. Si no se puede encontrar una ruta de aumento, un algoritmo puede terminar de forma segura, ya que en este caso debe ser óptimo.

Un camino de aumento en un problema de coincidencia está estrechamente relacionado con los caminos de aumento que surgen en los problemas de flujo máximo , caminos a lo largo de los cuales se puede aumentar la cantidad de flujo entre las terminales del flujo. Es posible transformar el problema de coincidencia bipartito en una instancia de flujo máximo, de modo que los caminos alternos del problema de coincidencia se conviertan en caminos crecientes del problema de flujo. Basta con insertar dos vértices, fuente y sumidero, e insertar aristas de capacidad unitaria desde la fuente hasta cada vértice en , y desde cada vértice hasta el sumidero; y deje que los bordes tengan capacidad unitaria. [6] Una generalización de la técnica utilizada en el algoritmo Hopcroft-Karp para encontrar el flujo máximo en una red arbitraria se conoce como algoritmo de Dinic .

Algoritmo

El algoritmo puede expresarse en el siguiente pseudocódigo .

Entrada : gráfico bipartito
Salida : Coincidencia
repetir
conjunto máximo de caminos de aumento más cortos separados por vértices
hasta

Con más detalle, sean y los dos conjuntos en la bipartición de y deje que la coincidencia de a en cualquier momento se represente como el conjunto . El algoritmo se ejecuta en fases. Cada fase consta de los siguientes pasos.

El algoritmo termina cuando no se encuentran más rutas de aumento en la primera parte de búsqueda en amplitud de una de las fases.

Análisis

Cada fase consta de una única búsqueda en amplitud y una única búsqueda en profundidad. De este modo, se podrá implementar una sola fase a tiempo. Por tanto, las primeras fases, en un gráfico con vértices y aristas, toman tiempo .

Cada fase aumenta la longitud del camino de aumento más corto en al menos uno: la fase encuentra un conjunto máximo de caminos de aumento de la longitud dada, por lo que cualquier camino de aumento restante debe ser más largo. Por lo tanto, una vez que se completan las fases iniciales del algoritmo, el camino de aumento restante más corto tiene al menos aristas. Sin embargo, la diferencia simétrica del emparejamiento óptimo eventual y del emparejamiento parcial M encontrado por las fases iniciales forma una colección de caminos de aumento disjuntos de vértices y ciclos alternos. Si cada una de las rutas de esta colección tiene una longitud de al menos , puede haber como máximo rutas en la colección y el tamaño de la coincidencia óptima puede diferir del tamaño de como máximo los bordes. Dado que cada fase del algoritmo aumenta el tamaño de la coincidencia en al menos uno, puede haber como máximo fases adicionales antes de que finalice el algoritmo.

Dado que el algoritmo realiza un total de como máximo fases, en el peor de los casos tarda un tiempo total .

Sin embargo, en muchos casos, el tiempo que tarda el algoritmo puede ser incluso más rápido de lo que indica el análisis del peor de los casos. Por ejemplo, en el caso promedio de gráficos aleatorios bipartitos dispersos , Bast et al. (2006) (mejorando un resultado anterior de Motwani 1994) mostraron que con alta probabilidad todos los emparejamientos no óptimos tienen caminos crecientes de longitud logarítmica . Como consecuencia, para estos gráficos, el algoritmo Hopcroft-Karp toma fases y tiempo total.

Comparación con otros algoritmos de coincidencia bipartita

Para gráficos dispersos , el algoritmo Hopcroft-Karp sigue teniendo el peor rendimiento mejor conocido, pero para gráficos densos ( ) un algoritmo más reciente de Alt et al. (1991) logra un límite temporal ligeramente mejor . Su algoritmo se basa en el uso de un algoritmo de flujo máximo de reetiquetación push y luego, cuando la coincidencia creada por este algoritmo se acerca al óptimo, cambia al método Hopcroft-Karp.

Varios autores han realizado comparaciones experimentales de algoritmos de emparejamiento bipartito. Sus resultados en general tienden a mostrar que el método Hopcroft-Karp no es tan bueno en la práctica como lo es en teoría: es superado por estrategias más simples de primero en amplitud y primero en profundidad para encontrar caminos de aumento, y por técnicas de reetiquetado por empuje. . [7]

Gráficos no bipartitos

La misma idea de encontrar un conjunto máximo de caminos de aumento más cortos funciona también para encontrar coincidencias de cardinalidad máxima en gráficos no bipartitos y, por las mismas razones, los algoritmos basados ​​en esta idea toman fases. Sin embargo, para gráficos no bipartitos, la tarea de encontrar los caminos crecientes dentro de cada fase es más difícil. Basándose en el trabajo de varios predecesores más lentos, Micali y Vazirani (1980) mostraron cómo implementar una fase en tiempo lineal, lo que dio como resultado un algoritmo de coincidencia no bipartito con el mismo límite de tiempo que el algoritmo Hopcroft-Karp para gráficos bipartitos. La técnica de Micali-Vazirani es compleja y sus autores no aportaron pruebas completas de sus resultados; Posteriormente, Peterson y Loui (1988) publicaron una "exposición clara" y otros autores describieron métodos alternativos. [8] En 2012, Vazirani ofreció una nueva prueba simplificada del algoritmo de Micali-Vazirani. [9]

Pseudocódigo

/* GRAMO = U ∪ V ∪ {NIL} donde U y V son los lados izquierdo y derecho del gráfico bipartito y NIL es un vértice nulo especial*/ la función BFS() es  para cada u en U si Pair_U[u] = NIL entonces Dist[u] := 0 Poner en cola(Q,u) demás Dist[u] := ∞ Dist[NIL] := ∞ mientras que Vacío (Q) = falso u := Sacar de la cola(Q) si Dist[u] < Dist[NIL] entonces  para cada v en Adj[u] haga  si Dist[Pair_V[v]] = ∞ entonces Dist[Par_V[v]] := Dist[u] + 1 Poner en cola(Q, Pair_V[v]) devolver Dist[NIL] ≠ ∞la función DFS(u) es  si u ≠ NIL entonces  para cada v en Adj[u] haga  si Dist[Pair_V[v]] = Dist[u] + 1 entonces  si DFS(Pair_V[v]) = verdadero entonces Par_V[v] := u Par_U[u] := v devolver verdadero Dist[u] := ∞ devolver falso devolver verdaderola función Hopcroft-Karp es  para cada u en U do Par_U[u] := NULO para cada v en V hacer Par_V[v] := NULO coincidencia := 0 mientras que BFS() = verdadero hazlo  para cada u en U hazlo  si Pair_U[u] = NIL entonces  si DFS(u) = verdadero entonces coincidencia := coincidencia + 1 coincidencia de retorno
Ejecución en un gráfico de ejemplo que muestra el gráfico de entrada y la coincidencia después de la iteración intermedia 1 y la iteración final 2.

Explicación

Dejemos que los vértices de nuestro gráfico estén divididos en U y V, y considere una coincidencia parcial, como lo indican las tablas Pair_U y Pair_V que contienen el único vértice con el que coincide cada vértice de U y V, o NIL para vértices no coincidentes. La idea clave es agregar dos vértices ficticios a cada lado del gráfico: uDummy conectado a todos los vértices no coincidentes en U y vDummy conectado a todos los vértices no coincidentes en V. Ahora, si ejecutamos una búsqueda en amplitud (BFS) desde uDummy hasta vDummy entonces podemos obtener los caminos de longitud mínima que conectan los vértices actualmente no coincidentes en U con los vértices actualmente no coincidentes en V. Tenga en cuenta que, como el gráfico es bipartito, estos caminos siempre alternan entre vértices en U y vértices en V, y requerimos en nuestro BFS que al pasar de V a U, siempre seleccionamos un borde coincidente. Si alcanzamos un vértice de V no coincidente, terminamos en vDummy y termina la búsqueda de rutas en el BFS. Para resumir, el BFS comienza en vértices no coincidentes en U, va a todos sus vecinos en V, si todos coinciden entonces regresa a los vértices en U con los que coinciden todos estos vértices (y que no fueron visitados antes), entonces va a todos los vecinos de estos vértices, etc., hasta que uno de los vértices alcanzados en V no coincida.

Observe en particular que BFS marca los nodos no coincidentes de U con distancia 0, luego incrementa la distancia cada vez que regresa a U. Esto garantiza que los caminos considerados en el BFS sean de longitud mínima para conectar vértices no coincidentes de U con vértices no coincidentes de V mientras siempre retrocede de V a U en los bordes que actualmente forman parte de la coincidencia. En particular, al vértice NIL especial, que corresponde a vDummy, se le asigna una distancia finita, por lo que la función BFS devuelve verdadero si se ha encontrado alguna ruta. Si no se ha encontrado ninguna ruta, entonces no quedan rutas de aumento y la coincidencia es máxima.

Si BFS devuelve verdadero, entonces podemos continuar y actualizar el emparejamiento de los vértices en las rutas de longitud mínima encontradas de U a V: lo hacemos utilizando una búsqueda en profundidad (DFS). Tenga en cuenta que cada vértice en V en dicha ruta, excepto el último, coincide actualmente. Entonces podemos explorar con el DFS, asegurándonos de que los caminos que seguimos corresponden a las distancias calculadas en el BFS. Actualizamos a lo largo de cada ruta eliminando de la coincidencia todos los bordes de la ruta que están actualmente en la coincidencia y agregando a la coincidencia todos los bordes de la ruta que actualmente no están en la coincidencia: ya que esta es una ruta de aumento (la primera y los últimos bordes del camino no eran parte de la coincidencia, y el camino alternaba entre bordes coincidentes y no coincidentes), esto aumenta el número de bordes en la coincidencia. Esto es lo mismo que reemplazar la coincidencia actual por la diferencia simétrica entre la coincidencia actual y la ruta completa.

Tenga en cuenta que el código garantiza que todas las rutas de aumento que consideramos sean vértices disjuntos. De hecho, después de hacer la diferencia simétrica para un camino, ninguno de sus vértices podría ser considerado nuevamente en el DFS, simplemente porque el Dist[Pair_V[v]] no será igual a Dist[u] + 1 (sería exactamente Dist [u]).

Observe también que el DFS no visita el mismo vértice varias veces. Esto es gracias a las siguientes líneas:

Dist[u] = ∞falso retorno

Cuando no pudimos encontrar ninguna ruta de aumento más corta desde un vértice u, entonces el DFS marca el vértice u estableciendo Dist[u] en infinito, de modo que estos vértices no se vuelvan a visitar.

Una última observación es que en realidad no necesitamos uDummy: su función es simplemente poner todos los vértices no coincidentes de U en la cola cuando iniciamos el BFS. En cuanto a vDummy, se indica como NIL en el pseudocódigo anterior.

Ver también

Notas

  1. ^ Gabow (2017); Annamalai (2018)
  2. ^ Bast y otros. (2006).
  3. ^ Dinitz (2006).
  4. ^ Peterson y Loui (1988).
  5. ^ Tarjan (1983), pág. 102.
  6. ^ Ahuja, Magnanti y Orlin (1993), sección 12.3, problema de coincidencia de cardinalidad bipartita, págs.
  7. ^ Chang y McCormick (1990); Darby-Dowman (1980); Setúbal (1993); Setúbal (1996).
  8. ^ Gabow y Tarjan (1991).
  9. ^ Vazirani (2012)

Referencias