1. Todos los Pares de Rutas más Cortas
(All-Pairs Shortest Paths)
DR. JESÚS A. GONZÁLEZ BERNAL
CIENCIAS COMPUTACIONALES
INAOE
2. Problema de Encontrar todos los Pares de Rutas más
Cortas
2
Encontrar las rutas más cortas entre todos los pares de vértices
de un grafo
Es el problema para hacer una tabla de distancias entre todos los
pares de ciudades en un Atlas de carreteras
Partimos de un grafo pesado y dirigido G = (V, E) con una
función de pesos w : E R que mapea arcos a pesos con valores
reales
Encontrar para cada par de vértices u, v ∈ V
Una ruta más corta (con menor peso) de u a v
Donde el peso de la ruta es la suma de los pesos de sus arcos
Salida en forma tabular
Entrada en renglón u y columna v es el peso de la ruta más corta entre
uyv
3. Problema de Encontrar todos los Pares de Rutas más
Cortas
3
Podemos resolver el problema ejecutando el algoritmo de
rutas más cortas con una sola fuente |V| veces, una para cada
vértice como la fuente
Si todos los pesos son no-negativos, podemos utilizar el
algoritmo de Dijkstra
Con un arreglo lineal implementando una priority-queue
podemos tener un tiempo de O(V3 +VE) = O(V3)
Con min-heap binario para priority-queue, O(VElgV)
Mejora para grafos poco densos
Con Fibonacci-heap para priority-queue O(V2lgV+VE)
4. Problema de Encontrar todos los Pares de Rutas más
Cortas
4
Si hay pesos negativos ya no podemos utilizar Dijkstra
Entonces utilizaríamos Bellman-Ford (aunque más lento), una
vez para cada vértice
O(V2E), que para un grafo denso se convierte en O(V4)
Estos tiempos se pueden mejorar con otros algoritmos
Algunos algoritmos utilizan representación de matriz
de adyacencia y no la de lista de adyacencia como en
los algoritmos de una sola fuente
5. Modelado del Problema
5
Grafo dirigido y pesado, G = (V, E)
Representación de matriz de adyacencia
Pesos: W =(wij)
⎧0 si i = j,
⎪
wij = ⎨ el peso del arco dirigido (i, j) si i ≠ j y (i, j) ∈ E,
⎪∞ si i ≠ j y (i, j) ∉ E
⎩
Se permiten arcos con peso negativo
El grafo de entrada no contiene ciclos con peso
negativo
6. Modelado del Problema
6
Salida tabular de todos los pares de rutas más
cortas
Matriz de n x n, D = (dij)
dij contiene el peso de una ruta más corta del vértice i al j
δ(i,j) denota el peso de la ruta más corta del vértice i al j
En la terminación del algoritmo dij = δ(i,j)
También calculamos una matriz de predecesores
Π = (πij), con valor NIL si i = j o si no hay ruta de i a j y en
otro caso πij es el predecesor de j para alguna ruta más
corta desde i
7. Modelado del Problema
7
Subgrafo predecesor
El subgrafo inducido por el i-ésimo renglón de la matriz
Π debe ser un árbol de rutas más cortas con raíz en i
El subgrafo predecesor de G para i se define como
Gπ,i = (Vπ,i, Eπ,i), donde
Vπ,i = {j ∈ V : πij ≠ NIL} ∪ {i}, y
Eπ,i = {(πij, j) : j ∈ Vπ,i – {i}}.
8. Imprimir Ruta más Corta de i a j
8
Dada la matriz de predecesores Π podemos imprimir la
ruta más corta de i a j
9. Rutas más Cortas y Multiplicación de Matrices
9
Solución con programación dinámica para el problema
de todos los pares de rutas más cortas con un grafo
dirigido G = (V, E)
Invoca operación parecida a multiplicación de matrices
Primer algoritmo Θ(V4)
Mejora en Θ(V3lgV)
10. Recordando Programación Dinámica
10
4 pasos
Caracterizar la estructura de la solución óptima
Definir recursivamente el valor de una solución óptima
Calcular el valor de la solución óptima de manera bottom-
up
Construir la solución óptima con la información calculada
11. Estructura de la Ruta más Corta, con Lema 24.1
11
Prueba al lema 24.1
Descomponemos la ruta p en: v1 ⎯⎯→ vi ⎯pij v j ⎯⎯→ vk
p1i
⎯→ pjk
Tenemos entonces que: w( p ) = w( p1i ) + w( pij ) + w( p jk )
Asumimos que hay una ruta
p’ij de vi a vj con peso: w( p 'ij ) < w( pij )
Entonces la ruta de v1 a vk que
pasa por p’ij: v1 ⎯⎯→ vi ⎯⎯→ v j ⎯⎯→ vk
p1i p 'ij pjk
Con peso: w( p1i ) + w( p 'ij ) + w( p jk )
Tiene un peso menor a w(p)
Contradice lo que asumimos,
que p es una ruta más corta de
v1 a vk.
12. Solución Recursiva para Todos los Pares de Rutas más Cortas
12
Sea lij(m) el mínimo peso de una ruta del vértice i al j que tiene al menos m arcos
Cuando m = 0, hay una ruta más corta de i a j sin arcos sí y solo si i = j,
entonces ⎧ 0 si i = j,
lij = ⎨
( 0)
⎩∞ si i ≠ j.
Para m ≥ 1, calculamos lij(m) como el mínimo de lij(m-1) y el mínimo peso de la
ruta de i a j con a lo más m arcos
Con todos los posibles predecesores k de j
lijm ) = min(lijm −1) , min{likm −1) + wkj })
( ( (
1≤ k ≤ n
lijm ) = min (likm −1) + wkj )
( (
1≤ k ≤ n
Los pesos de la ruta más corta están dados por
δ(i,j) =lij(n-1) = lij(n) = lij(n+1) = ….
Hay a lo más n-1 arcos en la ruta más corta de i a j asumiendo que no
hay ciclos con peso negativo
13. Calculando los Pesos de la Ruta más Corta Bottom-UP
13
Tomamos como entrada la matriz W = (wij)
Calculamos las matrices
L(1), L(2), …, L(n-1), donde para m = 1, 2, …, n-1 tenemos que L(m)
= (lij(m))
La matriz final tiene los pesos de las rutas más cortas
lij(1) = wij para todos los vértices i, j ∈ V, entonces L(1) = W
14. Algoritmo
14
Dadas las matrices L(m-1) y W regresa L(m)
Extiende las rutas más cortas obtenidas hasta ahora con
un arco
15. Algoritmo
15
El algoritmo se basa en la ecuación recursiva
Tiempo de ejecución Θ(n3) por los ciclos anidados
Parecido a multiplicación de matrices
16. Algoritmo
16
Algoritmo para encontrar todos los pares de rutas más
cortas
Basado en Extend-Shortest-Paths
Este algoritmo se ejecuta en un tiempo de Θ(n4)
18. Algoritmo más Rápido
18
No queremos calcular L(m) porque el resultado lo tenemos
desde L(n-1) asumiendo que no hay ciclos con peso negativo,
L(m) = L(n-1) para todos los enteros m ≥ n-1
Podemos calcular L(n-1) en ceiling(lg(n-1)) con la secuencia:
L(1) = W
L(2) = W2 = W ⋅ W
L(4) = W4 = W2 ⋅ W2
L(8) = W8 = W4 ⋅ W4
L(2 ⎡ lg(n-1)⎤ ) = W2 ⎡ lg(n-1)⎤ = W2 ⎡ lg(n-1)⎤ -1 ⋅ W2 ⎡ lg(n-1)⎤ -1
Continuamos hasta L(2 ⎡ lg(n-1)⎤ )
Proceso conocido como técnica de “repeating squaring”
Requiere solo ⎡lg(n-1)⎤ productos de matrices, llamadas a Extend
20. Algoritmo Floyd-Warshall
20
Utiliza un enfoque diferente de programación
dinámica
Tiempo de ejecución de Θ(V3)
Puede haber vértices con peso negativo pero no ciclos
con peso negativo
Seguimos el proceso de programación dinámica para
desarrollar el algoritmo
21. Algoritmo Floyd-Warshall
21
Considera los vértices intermedios de una ruta más corta
Si p = <v1, v2, …, vl>
v2 … vl-1 son los vértices intermedios
El algoritmo Floyd-Warshall trabaja reduciendo
sucesivamente el número de vértices intermedios que pueden
ocurrir en una ruta más corta y sus subrutas
Sea el grafo G = (V, E) con vértices V numerados de 1...n, V =
{1, 2, …, n}, y considerando un subconjunto {1, 2, …, k} para
algún k
Sea p el mínimo peso de ruta desde el vértice i al vértice j para
el que los vértices intermedios son tomados de {1, 2, …, k},
puede ocurrir una de dos situaciones:
22. Algoritmo Floyd-Warshall
22
1) k no es un vértice intermedio de p
i ↝p j
Contiene los vértices de {1, 2, …, k-1}
2) k es un vértice intermedio de p
i ↝p1 k ↝p2 j
Contiene los vértices de {1, 2, …, k-1}
p1 es la ruta más corta desde 1 a k
p2 es la ruta más corta desde k a j
Esto por el lema 24.1
23. Solución Recursiva
23
Sea dij(k) el peso de la ruta más corta desde i a j con
todos los vértices intermedios en {1, 2, …, k}
Como para cada ruta, los vértices intermedios están
en el conjunto {1, 2, …, n}, la matriz D(n) = (dij(n))
contendrá la solución final δ(i,j) para cada i, j ∈ V.
Recurrencia:
⎧wij si k = 0
d =⎨
(k )
( k −1) ( k −1) ( k −1)
⎩ min(d ij , d ik + d kj ) si k ≥ 1
ij
D = [d ij ] = [δ (i, j )], n =| V |
(n) (n)
24. Algoritmo
24
Calcula valores dij(k) en orden creciente de los valores de k
Entrada, matriz nxn W
Regresa D(n) con los pesos de las rutas más cortas
Tiempo de ejecución es Θ(n3), mejor que los anteriores con
O(n3lgn) y O(n4)
29. Construcción de la Ruta más Corta
29
Hay varios métodos de construir las rutas con el algoritmo
Floyd-Warshall
Construir la matriz D de pesos de rutas más cortas y luego la matriz
de predecesores Π a partir de D
Construir la matriz de predecesores en línea, conforme el algoritmo
Floyd-Warshall construye las matrices D(k)
⎧ NIL si i = j ó w ij = ∞,
π (0)
=⎨
ij
⎩i si i ≠ j y w ij ≤ ∞.
⎧π ijk −1)
⎪
(
si d ijk −1) ≤ d ikk −1) + d kjk −1)
( ( (
π ijk )
(
= ⎨ ( k −1)
⎪π kj si d ijk −1) > d ikk −1) + d kjk −1)
( ( (
⎩