stringtranslate.com

Algoritmo de Hopcroft-Karp

En informática , el algoritmo Hopcroft–Karp (a veces llamado con más 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 ningún par de bordes comparta un punto final. Se ejecuta en el tiempo en el peor de los casos , donde es el conjunto de bordes en el gráfico, es el conjunto de vértices del gráfico y se supone que . En el caso de gráficos densos , el límite de tiempo se convierte en , 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] Al igual que en métodos anteriores para emparejamiento como el algoritmo húngaro y el trabajo de Edmonds (1965), el algoritmo Hopcroft-Karp aumenta repetidamente el tamaño de un emparejamiento parcial al encontrar caminos de aumento . Estos caminos son secuencias de aristas del grafo, que alternan entre aristas en el emparejamiento y aristas fuera del emparejamiento parcial, y donde la arista inicial y final no están en el emparejamiento parcial. Encontrar un camino de aumento nos permite incrementar el tamaño del emparejamiento parcial, simplemente alternando las aristas del camino de aumento (poniendo en el emparejamiento parcial aquellas que no lo estaban, y viceversa). Los algoritmos más simples para el emparejamiento bipartito, como el algoritmo Ford-Fulkerson , encuentran un camino de aumento por iteración; el algoritmo Hopcroft-Karp, en cambio, encuentra un conjunto máximo de caminos de aumento más cortos, de modo de garantizar que solo se necesiten iteraciones en lugar de iteraciones. Se puede lograr el mismo rendimiento para encontrar emparejamientos de máxima cardinalidad en grafos arbitrarios, con el algoritmo más complicado de Micali y Vazirani. [4]

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

Ampliando caminos

Un vértice que no es el punto final de una arista en alguna coincidencia parcial se denomina vértice libre . El concepto básico en el que se basa el algoritmo es el de una ruta de aumento , una ruta que comienza en un vértice libre, termina en un vértice libre y alterna entre aristas no coincidentes y coincidentes dentro de la ruta. De esta definición se deduce que, a excepción de los puntos finales, todos los demás vértices (si los hay) en la ruta de aumento deben ser vértices no libres. Una ruta de aumento podría constar de solo dos vértices (ambos libres) y una única arista no coincidente 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 tamaño . Por lo tanto, al encontrar rutas 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 es una coincidencia óptima. Como y son ambas coincidencias, cada vértice tiene grado como máximo 2 en . Por lo que debe formar una colección de ciclos disjuntos, de caminos con un número igual de aristas coincidentes y no coincidentes en , de caminos de aumento para , y de caminos de aumento para ; pero esto último es imposible porque es óptimo. Ahora, los ciclos y los caminos con un número igual 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 de aumento para en . Por lo tanto, siempre que exista una coincidencia mayor que la coincidencia actual , también debe existir un camino de aumento. Si no se puede encontrar un camino de aumento, un algoritmo puede terminar de manera segura, ya que en este caso debe ser óptimo.

Un camino de aumento en un problema de emparejamiento 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 los terminales del flujo. Es posible transformar el problema de emparejamiento bipartito en una instancia de flujo máximo, de modo que los caminos alternativos del problema de emparejamiento se conviertan en caminos de aumento 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 en hasta el sumidero; y dejar que las aristas de a tengan capacidad unitaria. [6] Una generalización de la técnica utilizada en el algoritmo de 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 disjuntos entre vértices
hasta

En más detalle, sean y los dos conjuntos en la bipartición de , y sea la correspondencia de a en cualquier momento representada como el conjunto . El algoritmo se ejecuta en fases. Cada fase consta de los siguientes pasos.

El algoritmo finaliza cuando no se encuentran más rutas de aumento en la 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. Por lo tanto, se puede implementar una única fase en el tiempo. Por lo tanto, las primeras fases, en un grafo con vértices y aristas, toman tiempo .

Cada fase incrementa 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 final y del emparejamiento parcial M encontrado por las fases iniciales forma una colección de caminos de aumento disjuntos en vértices y ciclos alternos. Si cada uno de los caminos en esta colección tiene una longitud de al menos , puede haber como máximo caminos en la colección, y el tamaño del emparejamiento óptimo puede diferir del tamaño de en como máximo aristas. Dado que cada fase del algoritmo incrementa el tamaño del emparejamiento en al menos uno, puede haber como máximo fases adicionales antes de que el algoritmo termine.

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

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

Comparación con otros algoritmos de emparejamiento bipartito

Para gráficos dispersos , el algoritmo Hopcroft–Karp sigue teniendo el mejor rendimiento conocido en el peor de los casos, pero para gráficos densos ( ) un algoritmo más reciente de Alt et al. (1991) logra un límite de tiempo ligeramente mejor, . Su algoritmo se basa en el uso de un algoritmo de flujo máximo push-relabel 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 tanto por estrategias más simples de búsqueda de rutas ampliadas en amplitud y profundidad, como por técnicas de reetiquetado por inserción. [7]

Grafos no bipartitos

La misma idea de encontrar un conjunto máximo de caminos de aumento más cortos funciona también para encontrar emparejamientos de cardinalidad máxima en grafos no bipartitos, y por las mismas razones los algoritmos basados ​​en esta idea toman fases. Sin embargo, para grafos no bipartitos, la tarea de encontrar los caminos de aumento 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 resultó en un algoritmo de emparejamiento no bipartito con el mismo límite de tiempo que el algoritmo Hopcroft-Karp para grafos bipartitos. La técnica de Micali-Vazirani es compleja, y sus autores no proporcionaron 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 Micali-Vazirani. [9]

Pseudocódigo

/* G = U ∪ V ∪ {NUL} 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 Vacío(Q) = falso hacer u := Quitar de cola(Q) si Dist[u] < Dist[NIL] entonces  para cada v en Aj[u] haz  si Dist[Pair_V[v]] = ∞ entonces Dist[Par_V[v]] := Dist[u] + 1 Poner en cola (Q, Par_V[v]) devuelve Dist[NIL] ≠ ∞La función DFS(u) es  si u ≠ NIL entonces  para cada v en Adj[u] hacer  si Dist[Pair_V[v]] = Dist[u] + 1 entonces  si DFS(Pair_V[v]) = verdadero entonces Par_V[v] := u Par_U[u] := v devuelve verdadero Dist[u] := ∞ devuelve falso devuelve verdaderoLa función Hopcroft  Karp es  para cada u en U. Par_U[u] := NIL para cada v en V hacer Par_V[v] := NIL Coincidencia := 0 mientras BFS() = verdadero hacer  para cada u en U hacer  si Pair_U[u] = NIL entonces  si DFS(u) = verdadero entonces coincidencia := coincidencia + 1 devolver coincidencia
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 grafo se particionen en U y V, y consideremos una coincidencia parcial, como lo indican las tablas Pair_U y Pair_V que contienen el vértice con el que se coincide cada vértice de U y de V, o NIL para los vértices no coincidentes. La idea clave es agregar dos vértices ficticios en cada lado del grafo: 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) de uDummy a vDummy, entonces podemos obtener las rutas 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 grafo es bipartito, estas rutas siempre alternan entre vértices en U y vértices en V, y requerimos en nuestra BFS que cuando vayamos de V a U, siempre seleccionemos una arista coincidente. Si llegamos a un vértice no coincidente de V, entonces terminamos en vDummy y la búsqueda de caminos en el BFS termina. Para resumir, el BFS comienza en vértices no coincidentes en U, va a todos sus vecinos en V, si todos coinciden entonces vuelve a los vértices en U con los que coinciden todos estos vértices (y que no fueron visitados antes), luego va a todos los vecinos de estos vértices, etc., hasta que uno de los vértices alcanzados en V no coincide.

Observe en particular que BFS marca los nodos no coincidentes de U con una distancia 0, luego incrementa la distancia cada vez que regresa a U. Esto garantiza que las rutas consideradas en BFS tengan una longitud mínima para conectar vértices no coincidentes de U con vértices no coincidentes de V mientras siempre regresan de V a U en los bordes que actualmente son parte de la coincidencia. En particular, al vértice especial NIL, que corresponde a vDummy, se le asigna una distancia finita, por lo que la función BFS devuelve verdadero solo 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 usando una búsqueda en profundidad (DFS). Tenga en cuenta que cada vértice en V en dicha ruta, excepto el último, está actualmente emparejado. Por lo tanto, podemos explorar con la DFS, asegurándonos de que las rutas que seguimos corresponden a las distancias calculadas en la BFS. Actualizamos a lo largo de cada una de esas rutas 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: como se trata de una ruta de aumento (los primeros y últimos bordes de la ruta no eran parte de la coincidencia, y la ruta alternaba entre bordes coincidentes y no coincidentes), entonces 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.

Nótese que el código garantiza que todas las rutas de aumento que consideramos sean disjuntas en sus vértices. De hecho, después de hacer la diferencia simétrica para una ruta, ninguno de sus vértices podría considerarse nuevamente en el DFS, simplemente porque 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 se debe a las siguientes líneas:

Dist[u] = ∞devuelve falso

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 visiten nuevamente.

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 denota como NIL en el pseudocódigo anterior.

Véase 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 correspondencia de cardinalidad bipartita, págs. 469-470.
  7. ^ Chang y McCormick (1990); Darby-Dowman (1980); Setúbal (1993); Setúbal (1996).
  8. ^ Gabow y Tarjan (1991).
  9. ^ Vazirani (2012)

Referencias