CI2613: Algoritmos y Estructuras III Caminos de costo mı́nimo en grafos Blai Bonet Universidad Simón Bolı́var, Caracas, Venezuela Enero-Marzo 2015 c 2014 Blai Bonet Caminos entre todos los pares de vértices Caminos entre todos los pares de vértices Estamos interesados en calcular distancias y caminos más cortos entre todos los pares de vértices La salida de un algoritmo para calcular las distancias y caminos más cortos entre todos los pares de vértices es: – una matriz D de distancias donde la entrada dij es δ(i, j) Podemos ejecutar Bellman-Ford desde cada vértice s en un tiempo O(V 2 E), ya que Bellman-Ford requiere O(V E) unidades de tiempo – una matrix Π de predecesores tal que el grafo Gi = (Vi , Ei ) con Vi = {j : πij 6= null} ∪ {i} y Ei = {(πij , j) : j ∈ Vi \ {i}} es un árbol de caminos más cortos relativo al vértice i Con pesos no-negativos, se utiliza Dijkstra en lugar de Bellman-Ford. El tiempo dependerá de la implementación de la cola de prioridad: – Heap de Fibonacci: O(V E + V 2 log V ) unidades de tiempo Los algoritmos asumen un grafo dado por una matriz W de pesos: wij es el peso de la arista (i, j) (con wjj = 0 y wij = ∞ si no existe la arista) El heap de Fibonacci hace diferencia cuando O(V 2 log V ) es “menor” a O(V E log V ); i.e. cuando |V | = o(E) Esto no causa problema ya que el algoritmo debe invertir tiempo Ω(V 2 ) para generar la salida – Heap binario: O(V E log V ) unidades de tiempo c 2014 Blai Bonet CI2613 CI2613 c 2014 Blai Bonet CI2613 Primer algoritmo: Programación dinámica Primer algoritmo: Programación dinámica (m) Sea `ij el costo del mejor camino del vértice i al vértice j que tiene a lo sumo m aristas (0) `ij = Observe: (m) `ij 0 si i = j ∞ si i 6= j = min (m−1) `ij , = El mejor camino con a lo sumo m aristas es: el mejor camino con a lo sumo m − 1 aristas ó un camino con m aristas (m) `ij = min (m−1) `ij , (m−1) min `ik 1≤k≤n (n−1) + wkj (m) CI2613 = min 1≤k≤n (m−1) `ik 3 4 5 6 7 8 9 CI2613 El algoritmo computa las matrices L(1) , L(2) , L(3) , . . . , L(n−1) + wkj 2 2 + wkj Primer algoritmo: Pseudocódigo 1 1 c 2014 Blai Bonet Primer algoritmo: Subrutina central El algoritmo computa matrices L(1) , L(2) , L(3) , . . . , L(n−1) tal que (m) L(m) = (`ij ) Por definición, δ(i, j) = `ij = `ij , para m > n − 1, ya que el mejor camino tiene ≤ n − 1 aristas (si no hay ciclos de costo negativo) (m) `ij (m−1) `ik + wkj ya que wjj = 0 por definición c 2014 Blai Bonet min 1≤k≤n (m−1) min ` 1≤k≤n ik 3 Matriz Extender-Caminos(L, W): n = nrows(L) L’ = new Matriz(n,n) for i = 1 to n for j = 1 to n L’[i,j] = ∞ for k = 1 to n L’[i,j] = min { L’[i,j], L[i,k] + W[k,j] } return L’ 4 5 6 void Calcular-Distancias(W): n = nrows(W) L(1) = W for m = 2 to n - 1 L(m) = Extender-Caminos(L(m-1), W) return L(n-1) Calcular-Distancias toma tiempo Θ(n4 ) Θ(n4 ) iguala el tiempo Θ(V 2 E) para n corridas de Bellman-Ford en grafos densos (i.e. |E| = Θ(V 2 )) Extender-Caminos c 2014 Blai Bonet toma tiempo Θ(n3 ) CI2613 c 2014 Blai Bonet CI2613 Primer algoritmo: Ejemplo Relación con multiplicación de matrices hola 2 3 4 1 L(1) 8 2 3 −5 −4 7 1 (2) 5 L(4) 0 3 = 7 2 8 6 1 0 4 −1 5 L 4 −3 −4 0 −5 1 2 1 5 0 6 −4 −1 3 −2 0 0 ∞ = ∞ 2 ∞ 3 0 4 ∞ ∞ 3 0 4 −1 ∞ 0 3 = ∞ 2 8 L(3) 0 3 = 7 2 8 3 0 4 −1 5 8 ∞ 0 −5 ∞ 8 −4 0 −5 1 −3 −4 0 −5 1 ∞ 1 ∞ 0 6 −4 7 ∞ ∞ 0 2 1 5 0 6 −4 7 11 −2 0 2 1 5 0 6 La operación implementada por Extender-Caminos(A, relacionada con la multiplación de matrices Defina A ⊗ B = Extender-Caminos(A, matrices A, B de dimensión n × n B) B) está para cualquier par de Lema Para cualquier i, j ≥ 0, L(i) ⊗ L(j) = L(i+j) Prueba: por inducción en j (para cualquier i fijo) Base j = 0: L(i) ⊗ L(0) = L(i) (ejercicio) −4 −1 3 −2 0 Caso j > 0: L(i) ⊗ L(j) = L(i) ⊗ (L(j−1) ⊗ W ) = (L(i) ⊗ L(j−1) ) ⊗ W = L(i+j−1) ⊗ W = L(i+j) c 2014 Blai Bonet CI2613 c 2014 Blai Bonet Relación con multiplicación de matrices Segundo algoritmo: Pseudocódigo El algoritmo computa las matrices L(1) , L(2) , L(4) , . . . , L(2m) con 2m > n − 1 Corolario Para cualquier m ≥ 0, L(2m) = L(m) ⊗ L(m) 1 2 Por ejemplo, 3 4 (2) L (1) =L ⊗L (1) CI2613 =W ⊗W 5 6 L(4) = L(2) ⊗ L(2) = W ⊗ W ⊗ W ⊗ W 7 8 bool Calcular-Distancias-II(W): n = nrows(W) L(1) = W m = 1 while m < n - 1 L(2m) = Extender-Caminos(L(m), L(m)) m = 2m return L(m/2) L(8) = L(4) ⊗ L(4) = W ⊗ W ⊗ W ⊗ W ⊗ W ⊗ W ⊗ W ⊗ W L(16) = L(8) ⊗ L(8) = W ⊗ · · · ⊗ W c 2014 Blai Bonet Calcular-Distancias-II mejor a Θ(n4 ) CI2613 c 2014 Blai Bonet toma tiempo Θ(n3 log n) que es mucho CI2613 Computar caminos más cortos 1 2 3 4 5 6 7 8 9 Algoritmo de Floyd-Warshall Hemos visto como computar la matriz D = L(n−1) de distancias en un grafo con n vertices También basado en programación dinámica pero con una formulación diferente Caminos más cortos entre todos los pares de vértices se pueden calcular en tiempo Θ(n3 ) a partir de D de la siguiente forma: Floyd-Warshall toma tiempo Θ(n3 ) que es una mejora sobre Θ(n3 log n) En lugar de considerar caminos de i a j con a lo sumo k aristas, F-W considera caminos de i a j que pasan sólo sobre {1, 2, . . . , k} bool Calcular-Caminos(D, W): n = nrows(W) Π = new Matriz(n,n) for i = 1 to n for j = 1 to n for k = 1 to n if D[i,j] == D[i,k] + W[k,j] Π[i,j] = k return Π Defina: (k) dij = costo mejor camino de i a j que pasa sólo sobre {1, . . . , k} (n) (0) Por definición, dij = δ(i, j) y dij = wij c 2014 Blai Bonet CI2613 c 2014 Blai Bonet Programación dinámica de Floyd-Warshall CI2613 Floyd-Warshall: Pseudocódigo (m) Se computan las matrices D(m) = (dij ) para m = 1, 2, . . . , n Consider un mejor camino de i a j que pasa sobre {1, 2, . . . , k}. Existen dos posibilidades: ( (k) dij – el camino no visita el vértice k (i.e. pasa sobre {1, 2, . . . , k − 1}), ó = wij si k = 0 (k−1) (k−1) (k−1) min dij , dik + dkj si k > 0 – el camino visita el vértice k 1 Como todo camino óptimo no tiene ciclos, en el segundo caso se visita k una sóla vez 2 3 4 5 (k) dij = w ij 7 8 min 6 si k = 0 (k−1) dij , (k−1) dik + (k−1) dkj 9 si k > 0 Matriz Floyd-Warshall(W): n = nrows(L) D(0) = W for k = 1 to n D(k) = new Matriz(n,n) for i = 1 to n for j = 1 to n D(k) = min { D(k-1)[i,j], D(k-1)[i,k] + D(k-1)[k,j] } return D(n) Floyd-Warshall c 2014 Blai Bonet CI2613 c 2014 Blai Bonet toma tiempo Θ(n3 ) CI2613 Floyd-Warshall: Ejemplo Floyd-Warshall: Ejemplo hola hola 2 3 1 8 2 3 0 4 ∞ ∞ 8 ∞ 0 −5 ∞ ∞ 1 ∞ 0 6 −4 7 ∞ ∞ 0 3 D(0) 0 ∞ = ∞ 2 ∞ 3 0 4 5 ∞ 8 ∞ 0 −5 ∞ ∞ 1 ∞ 0 6 −4 7 ∞ −2 0 3 0 4 5 ∞ 8 ∞ 0 −5 ∞ 4 1 5 0 6 2 3 7 5 6 4 8 2 D(1) D(2) 0 ∞ = ∞ 2 ∞ 7 5 −4 7 11 −2 0 3 D(3) 1 6 4 D(4) D(5) CI2613 c 2014 Blai Bonet 0 ∞ = ∞ 2 ∞ 3 0 4 −1 ∞ 8 ∞ 0 −5 ∞ 4 1 5 0 6 −4 7 11 −2 0 −5 −4 1 4 1 −5 −4 c 2014 Blai Bonet 0 ∞ = ∞ 2 ∞ 4 3 0 4 −1 5 −1 −4 0 −5 1 4 1 5 0 6 −4 −1 3 −2 0 1 0 4 −1 5 −3 −4 0 −5 1 2 1 5 0 6 −4 −1 3 −2 0 0 3 = 7 2 8 0 3 = 7 2 8 CI2613