08.07.2008 Kürzeste Wege - Überblick Kap. 6.6: Kürzeste Wege • Single-source-shortest-path (SSSP) - Algorithmus von Dijkstra Professor Dr. Petra Mutzel Lehrstuhl für Algorithm Engineering, LS11 Fakultät für Informatik, TU Dortmund • All-pair-shortest-paths - Algorithmus von Floyd-Warshall 23./24. VO DAP2 SS 2008 3./8. Juli 2008 Petra Mutzel DAP2 SS08 1 DAP2 SS08 2 Kürzeste Wege Motivation Achtung: in diesem Abschnitt gerichtete gewichtete Graphen! „Was gibt es heute Besonderes?“ Dijkstra oder Wie funktioniert mein Navi? Kürzeste Wege Problem Gegeben: gerichteter Graph G=(V,A) Gewichtsfunktion w : A→R hier: w≥0 Keine Mehrfachkanten Gesucht: Der bzgl. Gewicht w kürzeste Weg von Startknoten zu Zielknoten. „Und wenn mir das zu schwer ist?“ Einfacher Algorithmus für APSP Petra Mutzel Petra Mutzel DAP2 SS08 3 Petra Mutzel DAP2 SS08 4 Anwendungen Direkte und indirekte (Teilproblem) Anwendungen: • Routenplaner (Streckenlänge) • Auskunftssysteme für Bus und Bahn (Zeit) • Berechnung minimaler Flüsse in Netzwerken • DNA Sequenz Analyse • … Petra Mutzel DAP2 SS08 5 Petra Mutzel DAP2 SS08 6 1 08.07.2008 Kürzeste Wege Probleme • • • • 6.1 Single Source Shortest Path (SSSP) Single Source Shortest Path (SSSP) Single Destination Shortest Path Single Pair Shortest Path All Pairs Shortest Path (APSP) Petra Mutzel DAP2 SS08 • Bekannt: BFS für ungewichtete kürzeste Wege (USSSP) • Jetzt: Kürzeste Wege mit Kantengewichten: – Gerichteter Graph G = (V, A) – Kantengewichte w(e) ∈ R (Strecke, Fahrtzeit) – Startknoten s – Weglänge w(p) := für p=v0,e1,…ek,vk 7 Optimale Substruktur Petra Mutzel Keine negativen Kreise!! ? -k vh vj Petra Mutzel -∞ ⇒Kürzeste Wege von Knoten s bilden immer einen Baum vk Spezialfall: w(e) ≥ 0 (Strecke, Fahrtzeit) DAP2 SS08 9 Algorithmus von Dijkstra Petra Mutzel DAP2 SS08 10 Algorithmus von Dijkstra Analogien mit BFS und Prim: S := {s} • BFS/Prim läßt einzelnen Baum wachsen: Neue Kante verbindet Baum mit Rest d[s] := 0; π[s] := nil // s Wurzel while A(S) ≠ ø do // erreichbare Knoten • Dijkstra bildet Kürzeste-Wege Baum (SPT) ausgehend von Wurzel s, aber andere Auswahl // S Knoten im SPT // Optimale Substruktur Sei e = (u, v) ∈ A(S) mit d[u] + w(e) minimal • Greedy, Priority Queue S := S ⋃ {v} Bezeichnungen • Vorgänger von Knoten v im SPT: π[v] • Kanten, die Knotenmenge S verlassen: A(S) • Min. Abstand vom Startknoten zu Knoten v: d[v] Petra Mutzel 8 Single Source Shortest Path Pfad über v0=s, v1, …, vk kürzester Weg von s nach vk ⇒ Teilweg vh → vj kürzester Weg von vh nach vj v0 DAP2 SS08 DAP2 SS08 d[v] := d[u] + w(e) π[v] := u end while 11 Petra Mutzel DAP2 SS08 12 2 08.07.2008 Korrektheit Korrektheit Induktion über die Kanten e1,…,en, die der Algorithmus für v wählt, ei = (ui,vi), v0:= s. Zeige: v0,…,vi ist kürzester Weg von v0 nach vi i=0: Keine Kante, korrekt 1≤i≤n: Annahme v0,…,vj kürzester Weg für j<i. Dijkstra wählt Weg mit Kosten d[ui]+w(ei). Jeder andere Weg v0vi beginnt mit Knoten aus Vi := {v0,…,vi-1} gefolgt von Kante (x, y) ∈ A(Vi-1) und hat deshalb Kosten mind. d[ui]+w(ei), da ei als Minimum gewählt wurde. • Alle erreichbaren Knoten werden auch erreicht • Knoten ausserhalb von S sind nur über Knoten bzw. Pfade in S erreichbar • Dijkstra wählt Minimum der Weglänge aus S hinaus und erweitert S • w nicht-negativ: Spätere Weglängen können nur größer sein als Minimum! • Optimale Substruktur: Kürzester Weg besteht aus kürzestem Weg plus Kante Petra Mutzel DAP2 SS08 13 Petra Mutzel Realisierung von Dijkstra 22 ∞ • Knotenmenge V \ S: Speichere vorläufige Werte für den Abstand zu s (obere Schranke δ(v) ≥ d[v]) in Priority Queue, und aktualisiere Priorität, falls günstigerer Weg gefunden wird, δ(s) = 0 ∞ 10 4 15 2 12 ∞ 12 ∞ 5 7 4 1 5 ∞ 7 8 DAP2 SS08 2 12 ∞ ∞ 12 ∞ 5 ∞ 16 7 4 11 9 s 0 2 ∞ 26 10 4 ∞ DAP2 SS08 ∞ 1 22 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Petra Mutzel ∞ Algorithmus von Dijkstra 5 ∞ 8 Petra Mutzel ∞ 4 ∞ 4 11 9 s 0 2 ∞ 7 4 5 7 Priority Queue PQ: Knoten, Priorität Weglänge Kandidatenmenge K in PQ: Weg von s gefunden Abgeschlossene Knoten: Minimum aus PQ Algorithmus von Dijkstra 22 ∞ 12 2. Aktualisiere für ausgehende Kanten (u, v) Abstandswerte der Endknoten („Relaxieren“) mit DECREASEPRIORITY und Vorgänger π[v] DAP2 SS08 2 ∞ 4 11 9 s ∞ 0 2 ∞ 10 4 1. Wähle mit EXTRACTMIN Knoten u mit minimalem Abstandswert. Start: δ(s) = d[s] = 0 ∞ 4 14 Algorithmus von Dijkstra • Knotenmenge S: Kürzester Weg mit Länge d[v] bereits ermittelt Petra Mutzel DAP2 SS08 7 4 8 ∞ 5 ∞ 1 ∞ Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π 18 Petra Mutzel DAP2 SS08 19 3 08.07.2008 Algorithmus von Dijkstra Algorithmus von Dijkstra 22 4 ∞ 2 12 12 ∞ 7 4 ∞ 8 12 ∞ 1 Petra Mutzel DAP2 SS08 ∞ 4 4 2 12 12 14 7 4 17 5 ∞ 4 ∞ 7 10 2 12 12 14 7 4 5 17 7 4 17 5 ∞ 7 8 ∞ 5 ∞ 1 Petra Mutzel DAP2 SS08 22 8 2 12 ∞ 12 14 7 4 5 ∞ 23 7 4 11 9 s 0 ∞ 2 25 10 4 7 DAP2 SS08 21 Algorithmus von Dijkstra 17 1 8 18 ∞ 5 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Petra Mutzel 2 4 14 22 5 1 12 ∞ 4 ∞ 4 11 9 s 0 2 DAP2 SS08 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Algorithmus von Dijkstra 4 2 12 DAP2 SS08 25 1 11 9 s 0 ∞ 5 22 5 25 10 4 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π ∞ 4 5 ∞ ∞ Petra Mutzel ∞ Petra Mutzel 17 8 Algorithmus von Dijkstra 8 1 7 4 22 4 11 9 s 0 26 10 14 20 Algorithmus von Dijkstra 2 12 7 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π 22 2 ∞ 4 11 9 s 0 ∞ 2 26 10 4 7 5 ∞ 5 22 4 ∞ 4 11 9 s 0 26 10 4 2 24 Petra Mutzel DAP2 SS08 25 4 08.07.2008 Algorithmus von Dijkstra 22 ∞ 4 2 12 12 14 7 4 17 5 22 ∞ 4 26 7 4 11 9 s 0 22 10 4 2 Algorithmus von Dijkstra 1 5 12 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Petra Mutzel DAP2 SS08 ∞ 4 4 26 2 12 12 14 7 4 5 17 1 23 8 5 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Petra Mutzel DAP2 SS08 28 Pseudo-Code 5 17 1 23 8 18 5 Petra Mutzel DAP2 SS08 27 Petra Mutzel DAP2 SS08 29 Analyse (8) while not Q.ISEMPTY() do { (9) (du, u ) := Q.EXTRACTMIN(); // du Abstand s zu u (10) pos[u] := nil // Minimum entfernt (11) for all e = (u,v) ∈ A-(u) do { // Erreichbare Knoten (12) if du+w(e) < Q.PRIORITY(pos[v]) then { (13) Q.DECREASEPRIORITY(pos[v], du + w(e)) (14) π[v] := u (15) } (16) } (17) } Petra Mutzel 7 4 G=(V, A), w: A→R0+ (1) var π[V], PriorityQueue Q, pos[V] (2) for each u ∈ V \ {s} do { (3) pos[u] := Q.INSERT(∞, u) (4) π[u] := nil (5) } (6) pos[s] := Q.INSERT(0, s) (7) π[s] := nil 7 18 14 Pseudo-Code: Initialisierung 26 4 11 9 s 0 2 22 10 12 7 Ausgehende Kanten des gewählten Knoten Erreichte Kandidaten Vorgänger-Kanten: π Algorithmus von Dijkstra 22 2 26 4 11 9 s 0 23 8 18 4 2 22 10 DAP2 SS08 Laufzeit abhängig von Datenstruktur: • Kosten der ExtractMin und vor allem der DecreasePriority Operationen • Wir betrachten Binary Heaps Spezielle PQ mit amortisiert konstanter DecreasePriority Zeit: Fibonacci-Heaps 30 Petra Mutzel DAP2 SS08 31 5 08.07.2008 Analyse 6.6.2 All Pairs Shortest Paths • Aufbau des Heaps in O(|V|) All-Pairs Shortest Paths (APSP) • |V| Durchläufe der while-Schleife mit EXTRACTMIN ⇒ O(|V| log |V|) Gegeben: gerichteter Graph G = (V,A) Gewichtsfunktion w : A!R0+ Gesucht: ein kürzester Weg von u nach v für jedes Paar u, v ∈ V • |A| Aufrufe von DECREASEPRIORITY max. ⇒ O(|A| log |V|) if dwhile Q.P RIORITY not<Q.I SE MPTY()(pos[v]) do u + w(e) Gesamtlaufzeit O((|V|+|A|)log|V|) Petra Mutzel DAP2 SS08 32 Algorithmen für APSP • Sei Vk:={v1,…,vk} die Menge der ersten k Knoten • Finde kürzeste Wege, die nur Knoten aus Vk als Zwischenknoten benutzen dürfen – für dünne Graphen: O( log |V|) – für dichte Graphen: O( |V|3 log |V|) • Zwischenknoten sind alle Knoten eines Weges außer die beiden Endknoten • Sei dij(k) die Länge eines kürzesten Weges von vi nach vj, der nur Knoten aus Vk als Zwischenknoten benutzt jetzt: schnellerer Algorithmus für dichte Graphen Berechnung von dij(k) Berechnung von dij(k): • dij(0) = w(vi,vj} • Bereits berechnet: dij(k-1) für alle 1≤i,j≤n Für einen kürzesten Weg von vi nach vj gibt es zwei Möglichkeiten: vk 33 Idee: Löse eingeschränkte Teilprobleme: |V|2 DAP2 SS08 DAP2 SS08 Algorithmus von Floyd-Warshall Idee: • Aufruf von Dijkstra für alle Knoten v∈V • Laufzeit: O( |V| (|V|+|E|) log |V|) Petra Mutzel Petra Mutzel 34 Petra Mutzel DAP2 SS08 35 Berechnung von dij(k) Zwei Möglichkeiten für kürzesten Weg von vi nach vj: – Der Weg p benutzt vk nicht als Zwischenknoten: dann ist dij(k) = dij(k-1) – Der Weg p benutzt vk als Zwischenknoten: dann setzt sich p aus einem kürzesten Weg von vi nach vk und einem von vk nach vj zusammen, die jeweils nur Zwischenknoten aus Vk-1 benutzen: dij(k) = dik(k-1) + dkj(k-1) vk vi Vk-1 vj dij(k) (dij(k-1) dik(k-1) + dkj(k-1) ) • := min , vi vj • Für k=n: optimale Wege gefunden V k-1 6 08.07.2008 Beispiel 4 v1 v2 3 v4 6 2 5 7 1 Beispiel 4 v5 v1 v2 D(0 ) = v3 v4 v5 0 4 ∞ ∞ ∞ ∞ 1 0 ∞ 5 0 2 ∞ ∞ ∞ 5 ∞ ∞ 7 0 6 7 ∞ 3 2 ∞ 0 D(0)= 0 4 ∞ ∞ ∞ ∞ 1 0 ∞ 5 0 2 ∞ ∞ ∞ ∞ ∞ 7 0 6 4 v1 5 v4 6 7 1 D(1)= 0 4 ∞ ∞ ∞ ∞ 1 0 5 5 0 2 ∞ ∞ ∞ 4 v5 v1 ∞ ∞ 7 0 6 ∞ 3 2 ∞ 0 v2 D(2)= 0 4 9 6 ∞ ∞ 0 5 2 ∞ 1 ∞ ∞ 5 ∞ 3 0 7 2 7 0 5 ∞ 6 0 DAP2 SS08 D(2)= 0 4 9 6 ∞ ∞ 0 5 2 ∞ 1 ∞ ∞ 5 ∞ 3 0 7 2 7 0 5 ∞ 6 0 40 v1 5 v4 6 7 1 D(3)= 0 4 9 6 ∞ 6 0 5 2 ∞ 1 5 0 7 ∞ 8 12 7 0 6 3 3 2 5 0 4 v5 v1 v2 5 v5 D(3)= v4 6 7 0 4 9 6 ∞ 6 0 5 2 ∞ 1 5 0 7 ∞ 8 12 7 0 6 3 3 2 5 0 DAP2 SS08 41 0 4 9 6 12 6 1 0 5 5 0 2 7 8 13 8 12 7 0 6 DAP2 SS08 3 3 2 5 0 D(4)= 42 0 4 9 6 12 6 1 0 5 5 0 2 7 8 13 8 12 7 0 6 v5 2 v3 Petra Mutzel 39 3 2 1 D(4)= ∞ 3 2 ∞ 0 Beispiel 2 v3 ∞ ∞ 7 0 6 DAP2 SS08 Petra Mutzel 3 2 ∞ 1 0 5 5 0 2 ∞ ∞ ∞ 2 v3 Beispiel 4 v4 6 7 1 Petra Mutzel v2 0 4 ∞ ∞ ∞ 3 2 5 2 v3 D(1)= Beispiel 3 2 ∞ 3 2 ∞ 0 Petra Mutzel Beispiel v2 v5 2 v3 v1 v2 v3 v4 v5 v1 3 v4 6 2 1 2 v3 v2 3 3 2 5 0 D(5)= Petra Mutzel 0 4 9 6 12 6 1 0 5 5 0 2 7 8 13 8 3 9 3 7 2 0 5 6 0 DAP2 SS08 43 7 08.07.2008 Algorithmus von Floyd-Warshall Diskussion • Ist man auch an den Wegen selbst interessiert, dann: Vorgängermatrix: πij(k) für jedes 0≤k≤n • Initialisierung: – Falls i=j oder w(vi,vj)=∞, dann: πij(0) := nil – Sonst: πij(0) := i • Aktualisierung: – Falls dij(k) < dik(k-1)+ dkj(k-1) – dann: πij(k) := πij(k-1) – sonst: πij(k) := πkj(k-1) (1) for i:=1 to n do (2) for j:=1 to n do (3) dij(0):= w(vi,vj} (4) } } (5) for k:=1 to n do (6) for i:=1 to n do (7) for j:=1 to n do (8) dij(k) := min (dij(k-1) , dik(k-1) + dkj(k-1) ) (9) } } } Petra Mutzel DAP2 SS08 44 Analyse Petra Mutzel DAP2 SS08 45 Algorithmus von Floyd-Warshall • Speicherplatzverbrauch für d-Matrizen: Θ(|V|3) • Man benötigt zur Berechnung von dij(k) nur die Werte von dij(k-1) → Θ(|V|2) Speicherplatz, • Der Algorithmus von Floyd-Warshall berechnet das APSP-Problem in einer Laufzeit von Θ(|V|3) mit einem Speicherverbrauch von Θ(|V|2) . • genauso für die π-Matrizen • Laufzeit: Θ(|V|3) Petra Mutzel DAP2 SS08 46 Petra Mutzel DAP2 SS08 47 Diskussion • • • • Dijkstra-Algorithmus kann durch eine andere Implementierung der Priority-Queue in Laufzeit O(|V|2+|E|) realisiert werden Dann: APSP für dichte Graphen: O(|V|3) Dijkstra-Algorithmus kann durch eine andere Implementierung der Priority-Queue (FibonacciHeaps) in Laufzeit O(|E|+|V| log |V|) realisiert werden (aber eher theoretisch) Dann: APSP für dichte Graphen: O(|V|3) Aber: Floyd-Warshall konzeptionell einfacher! Petra Mutzel DAP2 EndeSS08 Graphen 48 8