El método Ford-Fulkerson o algoritmo Ford-Fulkerson ( FFA ) es un algoritmo codicioso que calcula el flujo máximo en una red de flujo . A veces se le llama "método" en lugar de "algoritmo", ya que el enfoque para encontrar rutas de aumento en un gráfico residual no está completamente especificado [1] o se especifica en varias implementaciones con diferentes tiempos de ejecución. [2] Fue publicado en 1956 por LR Ford Jr. y DR Fulkerson . [3] El nombre "Ford-Fulkerson" también se utiliza a menudo para el algoritmo de Edmonds-Karp , que es una implementación completamente definida del método Ford-Fulkerson.
La idea detrás del algoritmo es la siguiente: siempre que haya una ruta desde la fuente (nodo inicial) hasta el sumidero (nodo final), con capacidad disponible en todos los bordes de la ruta, enviamos flujo a lo largo de una de las rutas. Luego encontramos otro camino, y así sucesivamente. Un camino con capacidad disponible se llama camino aumentante .
Sea una gráfica, y para cada arista de u a v , sea la capacidad y sea el flujo. Queremos encontrar el flujo máximo desde la fuente s hasta el sumidero t . Después de cada paso del algoritmo se mantiene lo siguiente:
Esto significa que el flujo a través de la red es un flujo legal después de cada ronda del algoritmo. Definimos la red residual como la red con capacidad y sin flujo. Tenga en cuenta que puede suceder que se permita un flujo de v a u en la red residual, aunque no esté permitido en la red original: if y then .
Algoritmo Ford-Fulkerson
La ruta en el paso 2 se puede encontrar, por ejemplo, con la búsqueda en amplitud (BFS) o la búsqueda en profundidad en . El primero se conoce como algoritmo de Edmonds-Karp .
Cuando no se puedan encontrar más rutas en el paso 2, s no podrá alcanzar t en la red residual. Si S es el conjunto de nodos alcanzables por s en la red residual, entonces la capacidad total en la red original de bordes desde S hasta el resto de V es, por un lado, igual al flujo total que encontramos de s a t , y por otro lado, sirve como límite superior para todos esos flujos. Esto prueba que el flujo que encontramos es máximo. Véase también Teorema de flujo máximo y corte mínimo .
Si el gráfico tiene múltiples fuentes y sumideros, actuamos de la siguiente manera: Supongamos que y . Agregue una nueva fuente con una ventaja desde cada nodo , con capacidad . Y añadir un nuevo fregadero con un borde desde cada nodo hasta , con capacidad . Luego aplique el algoritmo de Ford-Fulkerson.
Además, si un nodo u tiene restricción de capacidad , reemplazamos este nodo con dos nodos y un borde con capacidad . Luego aplique el algoritmo de Ford-Fulkerson.
Al agregar la ruta de aumento de flujo al flujo ya establecido en el gráfico, se alcanzará el flujo máximo cuando no se puedan encontrar más rutas de aumento de flujo en el gráfico. Sin embargo, no hay certeza de que alguna vez se llegue a esta situación, por lo que lo mejor que se puede garantizar es que la respuesta será correcta si el algoritmo termina. En el caso de que el algoritmo se ejecute indefinidamente, es posible que el flujo ni siquiera converja hacia el flujo máximo. Sin embargo, esta situación sólo ocurre con valores de flujo irracionales. [4] Cuando las capacidades son números enteros, el tiempo de ejecución de Ford-Fulkerson está limitado por (ver notación O grande ), donde es el número de aristas en el gráfico y es el flujo máximo en el gráfico. Esto se debe a que cada camino de aumento se puede encontrar en el tiempo y aumenta el flujo en una cantidad entera de al menos , con el límite superior .
Una variación del algoritmo Ford-Fulkerson con terminación garantizada y un tiempo de ejecución independiente del valor de flujo máximo es el algoritmo Edmonds-Karp , que se ejecuta en el tiempo.
El siguiente ejemplo muestra los primeros pasos de Ford-Fulkerson en una red de flujo con 4 nodos, fuente y sumidero . Este ejemplo muestra el peor comportamiento del algoritmo. En cada paso, solo se envía un flujo a través de la red. Si en su lugar se utilizara la búsqueda en amplitud, sólo se necesitarían dos pasos.
Observe cómo el flujo "retrocede" desde hacia cuando se encuentra el camino .
Considere la red de flujo que se muestra a la derecha, con fuente , sumidero , capacidades de los bordes y respectivamente , y la capacidad de todos los demás bordes es un número entero . La constante fue elegida de modo que . Usamos rutas aumentadas de acuerdo con la siguiente tabla, donde y .
Tenga en cuenta que después del paso 1 y después del paso 5, las capacidades residuales de los bordes y están en la forma y , respectivamente, para algunos . Esto significa que podemos usar caminos aumentados , e infinitas veces y las capacidades residuales de estos bordes siempre estarán en la misma forma . El flujo total en la red después del paso 5 es . Si continuamos usando caminos aumentantes como se indicó anteriormente, el flujo total converge a . Sin embargo, tenga en cuenta que hay un flujo de valor , al enviar unidades de flujo a lo largo , 1 unidad de flujo a lo largo y unidades de flujo a lo largo . Por lo tanto, el algoritmo nunca termina y el flujo ni siquiera converge al flujo máximo. [5]
Backman y Huynh (2018) dan otro ejemplo no terminante basado en el algoritmo euclidiano , donde también muestran que el peor tiempo de ejecución del algoritmo Ford-Fulkerson en una red en números ordinales es .
importar colecciones gráfico de clase : """ Esta clase representa un gráfico dirigido usando representación de matriz de adyacencia. """ def __init__ ( auto , gráfico ): ser . gráfico = gráfico # gráfico residual ser . fila = len ( gráfico ) def bfs ( yo , s , t , padre ): """ Devuelve verdadero si hay una ruta desde fuente 's' para hundir 't' en el gráfico residual. También llena parent[] para almacenar la ruta. """ # Marcar todos los vértices como no visitados visitado = [ Falso ] * yo . fila # Crea una cola para BFS cola = colecciones . deque () # Marcar el nodo de origen como visitado y ponerlo en cola cola . agregar ( s ) visitado [ s ] = Verdadero # Bucle BFS estándar mientras cola : u = cola . popizquierda () # Obtener todos los vértices adyacentes del vértice u retirado de la cola # Si un adyacente no ha sido visitado, márquelo # visitado y puesto en cola para ind , val en enumerar ( self . graph [ u ]): si ( visitado [ ind ] == False ) y ( val > 0 ): cola . añadir ( ind ) visitado [ ind ] = Verdadero padre [ ind ] = u # Si alcanzamos el sumidero en BFS comenzando desde la fuente, entonces regresamos # verdadero, de lo contrario falso volver visitado [ t ] # Devuelve el flujo máximo de s a t en el gráfico dado def edmonds_karp ( auto , fuente , sumidero ): # Esta matriz se llena con BFS y para almacenar la ruta padre = [ -1 ] * yo . fila max_flow = 0 # No hay flujo inicialmente # Aumentar el flujo mientras haya un camino desde la fuente hasta el sumidero. mientras que uno mismo . bfs ( fuente , receptor , padre ): # Encuentre la capacidad residual mínima de los bordes a lo largo del # ruta llena por BFS. O podemos decir encontrar el flujo máximo. # por el camino encontrado. ruta_flujo = flotante ( "Inf" ) s = fregadero mientras s ! = fuente : path_flow = min ( path_flow , self . gráfico [ padre [ s ]][ s ]) s = padre [ s ] # Agregar flujo de ruta al flujo general flujo_max += flujo_ruta # actualizar capacidades residuales de los bordes y bordes inversos # a lo largo del camino v = hundirse mientras v ! = fuente : u = padre [ v ] ser . gráfico [ u ][ v ] -= flujo_ruta ser . gráfico [ v ][ u ] += flujo_ruta v = padre [ v ] devolver flujo_max
{{cite book}}
: CS1 maint: multiple names: authors list (link)Medios relacionados con el algoritmo de Ford-Fulkerson en Wikimedia Commons