Algoritmos de Caminho Mínimo em Grafos CC/EC/Mestrado Teoria dos Grafos CC/EC/PPGI/UFES CAMINHOS MAIS CURTOS CC/EC/PPGI/UFES Caminhos mais Curtos • Dados: grafo G=(V,A) orientado e distância cij associada ao arco (i,j) A. Problema: Obter o caminho mais curto entre dois nós s e t. O comprimento de um caminho é igual à soma dos comprimentos (distâncias) dos arcos que formam o caminho. A “distância” ou “comprimento” de um arco pode ter diversas interpretações dependendo da aplicação: custos, distâncias, consumo de combustível, etc. Exemplo 1: Dado um mapa rodoviário, determinar a rota mais curta de uma cidade a outra. (rota mais rápida, rota com menor consumo de combustível, ...) CC/EC/PPGI/UFES Caminhos mais Curtos Exemplo 2: Construção de uma estrada entre duas cidades A e K. O grafo abaixo representa os diversos trechos possíveis e o custo de construção de cada um. Determinar o trajeto ótimo cujo custo de construção seja mínimo (corresponde a achar o caminho mais curto de A a K em relação a estes custos). B 2 8 5 C D Solução: 4 4 F I 2 4 4 7 H 4 4 5 A E 6 5 K 2 4 2 G 4 J A–D–G–I–K custo = 7 + 2 + 2 + 5 = 16 CC/EC/PPGI/UFES Caminhos mais Curtos • Condição de existência: Caminho de i a j contendo um ciclo w: k j i w Comprimento do caminho = comprimento (i k) + comprimento (w) + comprimento (k j) Qual é o comprimento do caminho mais curto de i a j se o comprimento do ciclo w é negativo? CC/EC/PPGI/UFES Caminhos mais Curtos Condição de existência: não há ciclos de comprimento negativo. A solução ótima (caminho mais curto) sempre será um caminho elementar (sem ciclos). CC/EC/PPGI/UFES Caminhos mais Curtos Caminho mais curto: - De um nó a outro - De um nó a todos os demais - Entre todos os pares de nós de um grafo CC/EC/PPGI/UFES Caminhos mais Curtos Caminho mais curto do nó 1 a cada nó do grafo G=(V,A) Hipótese: todas as distâncias cij são positivas: cij ≥ 0, (i,j) A Algoritmo de Moore-Dijkstra (1957-1959) *(i) = comprimento do caminho mais curto do nó 1 ao nó i Em especial, *(1)=0 (distâncias positivas). Algoritmo com n-1 iterações No início de cada iteração, o conjunto V de nós está particionado em dois subconjuntos S e S, com o nó 1 em S. CC/EC/PPGI/UFES Algoritmo de Dijkstra • Resolve o problema com um vértice-fonte em grafos cujas arestas tenham peso maior ou igual a zero. Este algoritmo é capaz de determinar o caminho mínimo, a partir de um vértice inicial v, para todos os outros vértices do grafo. CC/EC/Mestrado Teoria dos Grafos CC/EC/PPGI/UFES Algoritmo de Dijkstra vINI = vértice inicial d(vINI, vINI) = 0 d(vINI, i) = INFINITO, i, i V – {vINI} fechado = aberto = V anterior(i) = 0, i, i V enquanto(aberto ≠ ) { k = vértice pertencente a aberto, mais próximo do vértice inicial fechado = fechado k; aberto = aberto – k; para cada vizinho i de k que está em aberto faça{ custo = min{d(vINI, i), d(vINI,k) + c(k,i)} se (custo < d(vINI, i)) então d(vINI, i) = custo; anterior(i) = k } } CC/EC/Mestrado Teoria dos Grafos CC/EC/PPGI/UFES Execução 7. 2 é o vértice 13. de menor 6 é o custo; vértice de menor custo; fechado = fechado+{6} fechado = fechado+{2} 2. inicializando os custos 8. examinando os vértices vizinhos ao 14. fim alcançado 2 3. atualizando o conjunto fechado 9. 4 é o vértice de menor custo; 4. examinando os vértices ao fechado vizinhos = fechado+{4} 1 que estão em aberto 10. examinando os vértices vizinhos 5. 3 é o vértice de custo; ao menor 4 fechado = fechado+{3} 11. 5 é o vértice de menor custo; 6. examinando os fechado vértices= vizinhos ao fechado+{5} 3 12. examinando os vértices vizinhos ao 5 1. o grafo inicial fim do algoritmo CC/EC/Mestrado Teoria dos Grafos CC/EC/PPGI/UFES Outros algoritmos de caminho mínimo • Algoritmo de Bellmann-Ford • Algoritmo de Floyd CC/EC/Mestrado Teoria dos Grafos CC/EC/PPGI/UFES Algoritmo de Bellmann-Ford Entrada: matriz de pesos das arestas c(i, j) de G = (V,E) 1. v_inicial ← vértice inicial; 2. d(v_inicial, v_inicial)←0; 3. d(v_inicial, i)←INFINITO,para todo i de V – v_inicial 4. anterior(i)←0, para todo i de V 5. enquanto (j, i) de E tal que d(v_inicial, i) > d(v_inicial, j) + c(j, i) faça 6. d(v_inicial, i) ← d(v_inicial, j) + c(j, i) 7. anterior(i) ← j 1. o grafo inicial 8. fim-enquanto CC/EC/Mestrado CC/EC/PPGI/UFES Ciclos negativos.... {j,i} 1 3 2 10 1 d(1, i) 0 anterior(i) 0 2 3 0 0 -13 3 3 2 -29 10 -5 -21 10 1 2 111 2 Teoria dos Grafos -8 3 (1,2) {1,2} {1,3} (2,1) {2,3} (1,3) (3,1) (2,3) (3,2) CC/EC/PPGI/UFES Caminhos mais Curtos Caminho mais curto entre todos os pares de nós de um grafo • Dados: Grafo G=(V, A), |V | = n. Não há circuitos negativos. c = {cij}, j = 1,...,n, i = 1,...,n cij ≥ 0 cii = 0 cij = +, (i, j ) A Ak(i, j ) = valor do caminho mais curto de i a j podendo usar apenas nós numerados de 1 a k como nós intermediários. CC/EC/PPGI/UFES Caminhos mais Curtos A0(i, j ) = cij : caminho mais curto de i a j usando no máximo o nó “0” (que não existe) como nó intermediário (caminho mais curto de i a j sem nós intermediários) Ak(i, j ) : pode usar o nó k ou não. Ak+1(i, j ) : pode usar o nó k+1 ou não. A0 A1 A1 A2 ... An-1 An An(i, j ) = valor do caminho mais curto de i a j podendo usar qualquer nó de 1 a n como nó intermediário. CC/EC/PPGI/UFES Caminhos mais Curtos • Se Ak+1(i, j ) não usa o nó k+1 como intermediário, então: Ak+1(i, j ) = Ak(i, j ) Se Ak+1(i, j ) usa o nó k+1 como intermediário, então: Ak+1(i, j ) = Ak(i, k+1) + Ak(k+1, j ) Ak+1(i, j ) = min { Ak(i, j ), Ak(i, k+1) + Ak(k+1, j ) } CC/EC/PPGI/UFES Caminhos mais Curtos • Se Ak+1(i, j ) não usa o nó k+1 como intermediário, então: Ak+1(i, j ) = Ak(i, j ) Se Ak+1(i, j ) usa o nó k+1 como intermediário, então: Ak+1(i, j ) = Ak(i, k+1) + Ak(k+1, j ) Ak+1(i, j ) = min { Ak(i, j ), Ak(i, k+1) + Ak(k+1, j ) } CC/EC/PPGI/UFES Caminhos mais Curtos Algoritmo de Floyd: Para i = 1,...,n faça Para j = 1,...,n faça A0(i,j) cij fim-para fim-para Para k = 1,...,n faça Para i = 1,...,n faça Para j = 1,...,n faça Ak(i,j) min{Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j)} fim-para fim-para fim-para CC/EC/PPGI/UFES Caminhos mais Curtos Algoritmo de Floyd: Para i = 1,...,n faça Para j = 1,...,n faça A0(i,j) cij fim-para fim-para Para k = 1,...,n faça Para i = 1,...,n faça Para j = 1,...,n faça Ak(i,j) min{Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j)} fim-para fim-para fim-para CC/EC/PPGI/UFES Caminhos mais Curtos Exemplo: 6 1 2 4 3 C= 11 2 0 4 11 6 0 2 3 +∞ 0 A0 = 0 4 11 6 0 2 3 +∞ 0 0 4 6 5 0 2 3 7 0 3 A1 = 0 4 11 6 0 2 3 7 0 A2 = 0 4 6 6 0 2 3 7 0 A3 = CC/EC/PPGI/UFES Caminhos mais Curtos Algoritmo de Dijkstra: número de operações (tempo) ~ n2 n-1 iterações, cada iteração busca o mínimo em uma lista com até n-1 elementos Algoritmo de Floyd: número de operações (tempo) ~ n3 Três comandos for de 1 até n um dentro do outro Ou seja, o problema de calcular os caminhos mais curtos entre todos os pares de nós pode ser resolvido com a mesma eficiência aplicando-se n vezes o algoritmo de Dijkstra, uma vez a partir de cada nó inicial. CC/EC/PPGI/UFES Floyd em grafos não direcionados? Como aplicar o algoritmo de Floyd no grafo abaixo? 1 3 2 10 -8 3 CC/EC/PPGI/UFES