En informática , el algoritmo de Floyd-Warshall (también conocido como algoritmo de Floyd , algoritmo de Roy-Warshall , algoritmo de Roy-Floyd o algoritmo WFI ) es un algoritmo para encontrar caminos más cortos en un grafo dirigido ponderado con pesos de aristas positivos o negativos (pero sin ciclos negativos). [ 1 ] [ 2 ] Una sola ejecución del algoritmo encontrará las longitudes (pesos sumados) de los caminos más cortos entre todos los pares de vértices. Aunque no devuelve detalles de los caminos en sí, es posible reconstruirlos con simples modificaciones al algoritmo. También se pueden usar versiones del algoritmo para encontrar el cierre transitivo de una relación o (en conexión con el sistema de votación de Schulze ) los caminos más amplios entre todos los pares de vértices en un grafo ponderado.
Historia y denominación
El algoritmo de Floyd-Warshall es un ejemplo de programación dinámica y fue publicado en su forma actualmente reconocida por Robert Floyd en 1962. [ 3 ] Sin embargo, es esencialmente el mismo que los algoritmos publicados previamente por Bernard Roy en 1959 [ 4 ] y también por Stephen Warshall en 1962 [ 5 ] para encontrar el cierre transitivo de un grafo, [ 6 ] y está estrechamente relacionado con el algoritmo de Kleene (publicado en 1956) para convertir un autómata finito determinista en una expresión regular , con la diferencia de que utiliza un semianillo min-plus . [ 7 ] La formulación moderna del algoritmo como tres bucles for anidados fue descrita por primera vez por Peter Ingerman, también en 1962. [ 8 ]
Algoritmo
El algoritmo de Floyd-Warshall compara muchos caminos posibles a través del grafo entre cada par de vértices. Está garantizado que encontrará todos los caminos más cortos y es capaz de hacerlo concomparaciones en un gráfico, [ 1 ] [ 9 ] aunque puede haberaristas en el grafo. Lo hace mejorando incrementalmente una estimación del camino más corto entre dos vértices, hasta que la estimación sea óptima.
Consideremos un gráficocon vérticesnumerados del 1 al Consideremos además una funciónque devuelve la longitud del camino más corto posible (si existe) desdeautilizando vértices únicamente del conjuntocomo puntos intermedios en el camino. Ahora, dada esta función, nuestro objetivo es encontrar la longitud del camino más corto desde cada uno.a cadausando cualquier vértice enPor definición, este es el valor, que encontraremos recursivamente .
Observa quedebe ser menor o igual que: tenemos más flexibilidad si se nos permite usar el vértice. Sies de hecho menos que, entonces debe haber un camino desdeautilizando los vérticesque sea más corto que cualquier ruta de este tipo que no utilice el vérticeDado que no existen ciclos negativos, este camino se puede descomponer de la siguiente manera:
- (1) un camino desdeaque utiliza los vértices, seguido de
- (2) un camino desdeaque utiliza los vértices.
Y, por supuesto, debe existir un camino más corto (o varios de ellos), de lo contrario podríamos reducir aún más la longitud. En otras palabras, hemos llegado a la fórmula recursiva:
- .
El caso base viene dado por
dóndedenota el peso del borde deasi existe uno e ∞ (infinito) en caso contrario.
Estas fórmulas son la base del algoritmo de Floyd-Warshall. El algoritmo funciona calculando primeroa pesar depares para, entonces, entoncesy así sucesivamente. Este proceso continúa hastay hemos encontrado el camino más corto para todosempareja utilizando cualquier vértice intermedio. A continuación se muestra el pseudocódigo para esta versión básica.
Pseudocódigo
sea dist un arreglo |V| × |V| de distancias mínimas inicializado a ∞ (infinito) para cada arista ( u , v ) hacer dist[ u ][ v ] = w( u , v ) // El peso de la arista ( u , v ) para cada vértice v hacer dist[ v ][ v ] = 0 para k desde 1 hasta |V| para i desde 1 hasta |V| para j desde 1 hasta |V| si dist[ i ][ j ] > dist[ i ][ k ] + dist[ k ][ j ] dist[ i ][ j ] = dist[ i ][ k ] + dist[ k ][ j ] fin si
Nota: Un error común al implementar el algoritmo de Floyd-Warshall es ordenar incorrectamente los bucles triplemente anidados (el orden correcto es KIJ). Los algoritmos incorrectos IJKno IKJproporcionan soluciones correctas para algunas instancias. Sin embargo, podemos demostrar que si se repiten tres veces, obtenemos las soluciones correctas. [ 10 ]
Ejemplo
El algoritmo anterior se ejecuta en el gráfico de la izquierda que aparece a continuación:
![]()
Antes de la primera recursión del bucle externo, etiquetado como k = 0 arriba, los únicos caminos conocidos corresponden a las aristas individuales en el grafo. En k = 1 , se encuentran caminos que pasan por el vértice 1: en particular, se encuentra el camino [2,1,3], reemplazando el camino [2,3] que tiene menos aristas pero es más largo (en términos de peso). En k = 2 , se encuentran caminos que pasan por los vértices {1,2}. Los recuadros rojo y azul muestran cómo el camino [4,2,1,3] se construye a partir de los dos caminos conocidos [4,2] y [2,1,3] encontrados en iteraciones anteriores, con 2 en la intersección. El camino [4,2,3] no se considera, porque [2,1,3] es el camino más corto encontrado hasta ahora de 2 a 3. En k = 3 , se encuentran caminos que pasan por los vértices {1,2,3}. Finalmente, en k = 4 , se encuentran todos los caminos más cortos.
La matriz de distancias en cada iteración de k , con las distancias actualizadas en negrita , será:
Comportamiento con ciclos negativos
Un ciclo negativo es un ciclo cuyas aristas suman un valor negativo. No existe un camino más corto entre ningún par de vértices.,que forman parte de un ciclo negativo, porque las longitudes de los caminos desdeapuede ser arbitrariamente pequeño (negativo). Para obtener resultados numéricamente significativos, el algoritmo de Floyd-Warshall asume que no existen ciclos negativos. Sin embargo, si existen ciclos negativos, el algoritmo de Floyd-Warshall puede utilizarse para detectarlos. La idea es la siguiente:
- El algoritmo de Floyd-Warshall revisa iterativamente las longitudes de los caminos entre todos los pares de vértices., incluyendo dónde;
- Inicialmente, la longitud del caminoes cero;
- Un caminoSolo se puede mejorar esto si tiene una longitud menor que cero, es decir, denota un ciclo negativo;
- Por lo tanto, después del algoritmo,será negativo si existe un camino de longitud negativa desdevolver a.
Por lo tanto, para detectar ciclos negativos utilizando el algoritmo de Floyd-Warshall, se puede inspeccionar la diagonal de la matriz de ruta, y la presencia de un número negativo indica que el grafo contiene al menos un ciclo negativo. [ 9 ] Sin embargo, cuando hay un ciclo negativo presente, durante la ejecución del algoritmo se generan números exponencialmente grandes del orden depuede aparecer, dondees el mayor valor absoluto del peso de la arista en el grafo. Para evitar problemas de subdesbordamiento de enteros, se debe comprobar si hay un ciclo negativo dentro del bucle for más interno del algoritmo. [ 11 ]
Reconstrucción de trayectoria
El algoritmo de Floyd-Warshall normalmente solo proporciona las longitudes de los caminos entre todos los pares de vértices. Con modificaciones sencillas, es posible crear un método para reconstruir el camino real entre cualquier par de vértices extremos. Si bien uno podría inclinarse a almacenar el camino real de cada vértice a cada otro vértice, esto no es necesario y, de hecho, es muy costoso en términos de memoria. En su lugar, podemos usar el árbol de caminos más cortos , que se puede calcular para cada nodo entiempo usandomemoria, y nos permite reconstruir de manera eficiente un camino dirigido entre dos vértices conectados cualesquiera.
Pseudocódigo
El arreglo prev[u][v]contiene el penúltimo vértice en el camino de ua v(excepto en el caso de prev[v][v], donde siempre contiene vincluso si no hay un bucle en v): [ 12 ]
que esto sea unmatriz de distancias mínimas inicializadas a(infinito) sea prev unmatriz de índices de vértices inicializada a nuloEl procedimiento FloydWarshallWithPathReconstruction () es para cada arista (u, v) hacer dist[u][v] = w(u, v) // El peso de la arista (u, v) prev[u][v] = u para cada vértice v hacer dist[v][v] = 0 prev[v][v] = v para k desde 1 hasta |V| hacer // implementación estándar de Floyd-Warshall para i desde 1 hasta |V| para j desde 1 hasta |V| si dist[i][j] > dist[i][k] + dist[k][j] entonces dist[i][j] = dist[i][k] + dist[k][j] prev[i][j] = prev[k][j]
El procedimiento Path (u, v) es si prev[u][v] = null entonces devuelve [] ruta = [v] mientras u ≠ v hacer v = prev[u][v] ruta.anteponer(v) ruta de retorno
complejidad temporal
Dejarser, el número de vértices. Para encontrar todosde (a pesar dey) de aquellos de requiereoperaciones. Dado que comenzamos con y calcular la secuencia dematrices,,,, cada uno con un costo de, la complejidad temporal total del algoritmo es. [ 9 ] [ 13 ]
Aplicaciones y generalizaciones
El algoritmo de Floyd-Warshall se puede utilizar para resolver los siguientes problemas:
- Cierre transitivo de grafos dirigidos (algoritmo de Warshall). En la formulación original del algoritmo de Warshall, el grafo no tiene ponderación y se representa mediante una matriz de adyacencia booleana . La operación de suma se reemplaza por la conjunción lógica (AND) y la operación de mínimo por la disyunción lógica (OR).
- Encontrar una expresión regular que denote el lenguaje regular aceptado por un autómata finito ( algoritmo de Kleene , una generalización estrechamente relacionada del algoritmo de Floyd-Warshall) [ 14 ]
- Inversión de matrices reales ( algoritmo de Gauss-Jordan ) [ 15 ]
- Enrutamiento óptimo. En esta aplicación, el objetivo es encontrar la ruta con el máximo flujo entre dos vértices. Esto significa que, en lugar de tomar mínimos como en el pseudocódigo anterior, se toman máximos. Los pesos de las aristas representan restricciones fijas al flujo. Los pesos de las rutas representan cuellos de botella; por lo tanto, la operación de suma anterior se reemplaza por la operación de mínimo.
- Cálculo rápido de redes Pathfinder .
- Rutas más anchas/Rutas de máximo ancho de banda
- Cálculo de la forma canónica de las matrices de límites de diferencias (DBM)
- Calcular la similitud entre grafos
- Cierre transitivo en grafos AND/OR/umbral. [ 16 ]
Implementaciones
Existen implementaciones disponibles para muchos lenguajes de programación .
- Para C++ , en la biblioteca boost::graph
- Para C# , en QuikGraph
- Para C# , en QuickGraphPCL (una bifurcación de QuickGraph con mejor compatibilidad con proyectos que utilizan bibliotecas de clases portátiles).
- Para Java , en la biblioteca Apache Commons Graph
- Para JavaScript , en la biblioteca Cytoscape
- Para Julia , en el paquete Graphs.jl
- Para MATLAB , en el paquete Matlab_bgl archivado el 17 de agosto de 2013 en Wayback Machine
- Para Perl , en el módulo Graph
- Para Python , en la biblioteca SciPy (módulo scipy.sparse.csgraph ) o en la biblioteca NetworkX.
- Para R , en los paquetes e1071 y Rfast
- Para C , una implementación paralela con pthreads que incluye una interfaz SQLite para los datos en floydWarshall.h
Comparación con otros algoritmos de ruta más corta
Para grafos con pesos de aristas no negativos, el algoritmo de Dijkstra se puede utilizar para encontrar todos los caminos más cortos desde un único vértice con un tiempo de ejecuciónPor lo tanto, ejecutar Dijkstra comenzando en cada vértice lleva tiempo.. Desde, esto produce un tiempo de ejecución en el peor de los casos de Dijkstra repetido de. Si bien esto coincide con el tiempo de ejecución asintótico en el peor de los casos del algoritmo de Floyd-Warshall, las constantes involucradas importan bastante. Cuando un grafo es denso (es decir,), el algoritmo de Floyd-Warshall tiende a funcionar mejor en la práctica. Cuando el grafo es disperso (es decir,es significativamente más pequeño que), Dijkstra tiende a dominar.
Para grafos dispersos con aristas negativas pero sin ciclos negativos, se puede utilizar el algoritmo de Johnson , con el mismo tiempo de ejecución asintótico que el método de Dijkstra repetido.
También se conocen algoritmos que utilizan la multiplicación rápida de matrices para acelerar el cálculo de la ruta más corta entre todos los pares de nodos en grafos densos, pero estos suelen hacer suposiciones adicionales sobre los pesos de las aristas (como requerir que sean enteros pequeños). [ 17 ] [ 18 ] Además, debido a los altos factores constantes en su tiempo de ejecución, solo proporcionarían una mejora de velocidad con respecto al algoritmo de Floyd-Warshall para grafos muy grandes.
Referencias
- ^ Cormen , Thomas H .; Leiserson, Charles E .; Rivest, Ronald L. (1990). Introducción a los algoritmos (1ª ed.). MIT Press y McGraw-Hill. ISBN 0-262-03141-8.Véase en particular la Sección 26.2, "El algoritmo de Floyd-Warshall", págs. 558-565 y la Sección 26.4, "Un marco general para resolver problemas de caminos en grafos dirigidos", págs. 570-576.
- ↑ Kenneth H. Rosen (2003). Matemáticas discretas y sus aplicaciones, 5.ª edición . Addison Wesley. ISBN 978-0-07-119881-3.
- ↑ Floyd, Robert W. (junio de 1962). "Algoritmo 97: Camino más corto" . Communications of the ACM . 5 (6): 345. doi : 10.1145/367766.368168 . S2CID 2003382 .
- ^ Roy, Bernard (1959). "Transitivité et connexité" . CR Acad. Ciencia. París (en francés). 249 : 216-218 .
- ↑ Warshall, Stephen (enero de 1962). "Un teorema sobre matrices booleanas" . Journal of the ACM . 9 (1): 11– 12. doi : 10.1145/321105.321107 . S2CID 33763989 .
- ↑ Weisstein, Eric W. "Algoritmo de Floyd-Warshall" . MathWorld .
- ↑ Kleene, SC (1956). "Representación de eventos en redes nerviosas y autómatas finitos". En CE Shannon y J. McCarthy (eds.). Estudios de autómatas . Princeton University Press. págs. 3–42 .
- ↑ Ingerman, Peter Z. (noviembre de 1962). "Algoritmo 141: Matriz de ruta" . Communications of the ACM . 5 (11): 556. doi : 10.1145/368996.369016 . S2CID 29010500 .
- 1 2 3 Hochbaum, Dorit (2014). "Sección 8.9: Algoritmo de Floyd-Warshall para todos los pares de caminos más cortos" (PDF) . Apuntes de clase para IEOR 266: Algoritmos de grafos y flujos de red . Departamento de Ingeniería Industrial e Investigación Operativa, Universidad de California, Berkeley . págs. 41–42 .
- ↑ Hide, Ikumi (2019). "Las implementaciones incorrectas del algoritmo de Floyd-Warshall dan soluciones correctas después de tres repeticiones". arXiv : 1904.01210 [ cs.DS ].
- ↑ Stefan Hougardy (abril de 2010). "El algoritmo de Floyd-Warshall en grafos con ciclos negativos". Information Processing Letters . 110 ( 8–9 ): 279–281 . doi : 10.1016/j.ipl.2010.02.001 .
- ↑ "Libro gratuito de algoritmos" .
- ↑ Baras, John; Theodorakopoulos, George (2022). Problemas de caminos en redes . Springer International Publishing. ISBN 9783031799839.
- ↑ Gross, Jonathan L.; Yellen, Jay (2003). Manual de teoría de grafos . Matemáticas discretas y sus aplicaciones. CRC Press. pág. 65. ISBN 9780203490204..
- ↑ Peñaloza, Rafael. «Estructuras algebraicas para el cierre transitivo» . Seminario «Algoritmos de grafos» . Universidad Tecnológica de Dresde, Departamento de Informática, Instituto de Informática Teórica. Archivado del original el 22 de octubre de 2009.
- ↑ Gillies, Donald (1993). Programación de tareas con restricciones de precedencia AND/OR (Tesis doctoral, Apéndice B) (PDF) (Informe).
- ↑ Zwick, Uri (mayo de 2002). "Todos los caminos más cortos entre pares usando conjuntos puente y multiplicación de matrices rectangulares". Journal of the ACM . 49 (3): 289– 317. arXiv : cs/0008011 . doi : 10.1145/567112.567114 . S2CID 1065901 . .
- ↑ Chan, Timothy M. (enero de 2010). "Más algoritmos para encontrar los caminos más cortos entre todos los pares de nodos en grafos ponderados". SIAM Journal on Computing . 39 (5): 2075– 2089. CiteSeerX 10.1.1.153.6864 . doi : 10.1137/08071990x . .
Enlaces externos
- Animación interactiva del algoritmo de Floyd-Warshall.
- Animación interactiva del algoritmo de Floyd-Warshall (Universidad Técnica de Múnich)
- Algoritmos de grafos
- Algoritmos de enrutamiento
- Problemas de tiempo polinomial
- Programación dinámica
- Distancia del gráfico