Grundlegende Algorithmen Kapitel 4: Kürzeste Wege Christian Scheideler WS 2009 08.02.2010 Kapitel 4 1 Kürzeste Wege Zentrale Frage: Wie komme ich am schnellsten von A nach B? B A 08.02.2010 Kapitel 4 2 Kürzeste Wege Zentrale Frage: Wie komme ich am schnellsten von A nach B? Fälle: • Kantenkosten 1 • DAG, beliebige Kantenkosten • Beliebiger Graph, positive Kantenkosten • Beliebiger Graph, beliebige Kosten 08.02.2010 Kapitel 4 3 Einführung Kürzeste-Wege-Problem: • gerichteter Graph G=(V,E) • Kantenkosten c:E→ℝ • SSSP (single source shortest path): Kürzeste Wege von einer Quelle zu allen anderen Knoten • APSP (all pairs shortest path): Kürzeste Wege zwischen allen Paaren 08.02.2010 Kapitel 4 4 Einführung 42 0 -∞ 5 -∞ -1 0 +∞ -∞ -∞ 2 2 0 s 0 -2 -3 -1 -2 -1 -2 -3 µ(s,v): Distanz zwischen s und v ∞ µ(s,v) = -∞ kein Weg von s nach v Weg bel. kleiner Kosten von s nach v min{ c(p) | p ist Weg von s nach v} 08.02.2010 Kapitel 4 5 Einführung 42 5 0 -∞ -∞ -1 0 +∞ -∞ 0 -2 -3 2 0 s -∞ 2 -1 -2 -1 -2 -3 Wann sind die Kosten -∞? Wenn es einen negativen Kreis gibt: s 08.02.2010 C v Kapitel 4 c(C)<0 6 Einführung Negativer Kreis hinreichend und notwendig für Wegekosten -∞. Negativer Kreis hinreichend: s Weg p Weg q C v c(C)<0 Kosten für i-fachen Durchlauf von C: c(p) + i⋅c(C) + c(q) Für i→∞ geht Ausdruck gegen -∞. 08.02.2010 Kapitel 4 7 Einführung Negativer Kreis hinreichend und notwendig für Wegekosten -∞. Negativer Kreis notwendig: • l: minimale Kosten eines einfachen Weges von s nach v • es gibt nichteinfachen Weg r von s nach v mit Kosten c(r)<l • r nicht einfach: Zerlegung in pCq, wobei C ein Kreis ist und pq ein einfacher Pfad • da c(r) < l≤c(pq) ist, gilt c(C)<0 08.02.2010 Kapitel 4 8 Kürzeste Wege Graph mit Kantenkosten 1: Führe Breitensuche durch. 3 2 4 1 3 3 1 4 s 2 2 08.02.2010 Kapitel 4 9 Kürzeste Wege in DAGs Reine Breitensuche funktioniert nicht. 2 1 4 2 1 1 3 2 s 2 8 7 2 1 2 4 6 08.02.2010 1 1 3 1 2 9 5 1 Kapitel 4 10 Kürzeste Wege in DAGs Korrekte Distanzen: 2 1 4 2 1 1 3 2 s 2 5 4 2 1 2 4 4 08.02.2010 1 1 3 1 2 6 5 1 Kapitel 4 11 Kürzeste Wege in DAGs Strategie: nutze aus, dass Knoten in DAGs topologisch sortiert werden können (alle b erfüllen a<b) Kanten a 4 2 2 1 3 s 08.02.2010 6 1 1 2 10 2 3 1 5 9 1 1 2 1 11 2 4 7 1 4 Kapitel 8 12 Kürzeste Wege in DAGs Strategie: betrachte dann Knoten in der Reihenfolge ihrer topologischen Sortierung und aktualisiere Distanzen zu s 4 1 2 1 s 08.02.2010 4 6 1 3 3 2 2 5 2 3 1 1 2 10 2 9 1 2 2 7 46 5 1 4 Kapitel 5 46 1 4 1 11 6 8 13 Kürzeste Wege in DAGs Strategie: 1. Topologische Sortierung der Knoten 2. Aktualisierung der Distanzen gemäß der topologischen Sortierung Warum funktioniert das?? 08.02.2010 Kapitel 4 14 Kürzeste Wege in DAGs Betrachte kürzesten Weg von s nach v. Dieser hat topologische Sortierung (ti)i mit ti<ti+1 for alle i. t1 s 0 t2 c1 d1 c2 t3 t4 t5 d2 d3 d4 c3 c4 v Besuch in topologischer Reihenfolge führt zu richtigen Distanzen (di = ∑j≤i ci). 08.02.2010 Kapitel 4 15 Kürzeste Wege in DAGs Betrachte kürzesten Weg von s nach v. Dieser hat topologische Sortierung (ti)i mit ti<ti+1 für alle i. t1 s 0 t2 c1 d1 c2 t3 t4 t5 d2 d3 d4 c3 c4 v Bemerkung: kein Knoten auf dem Weg zu v kann Distanz < di zu s haben, da sonst kürzerer Weg zu v möglich wäre. 08.02.2010 Kapitel 4 16 Kürzeste Wege in Graphen Allgemeine Strategie: • Am Anfang, setze d(s):=0 und d(v):=∞ für alle Knoten • besuche Knoten in einer Reihenfolge, die sicherstellt, dass mindestens ein kürzester Weg von s zu jedem v in der Reihenfolge seiner Knoten besucht wird • für jeden besuchten Knoten v, aktualisiere die Distanzen der Knoten w mit (v,w)∈E, d.h. setze d(w) := min{d(w), d(v)+c(v,w)} 08.02.2010 Kapitel 4 17 Kürzeste Wege in DAGs Zurück zur Strategie: 1. Topologische Sortierung der Knoten 2. Aktualisierung der Distanzen gemäß der topologischen Sortierung Wie führe ich eine topologische Sortierung durch? 08.02.2010 Kapitel 4 18 Kürzeste Wege in DAGs Topologische Sortierung: • Verwende eine FIFO Queue q • Anfangs enthält q alle Knoten, die keine eingehende Kante haben (Quellen). • Entnehme v aus q und markiere alle (v,w)∈E. Falls alle Kanten nach w markiert sind und w noch nicht in q war, füge w in q ein. Wiederhole das, bis q leer ist. 08.02.2010 Kapitel 4 19 Kürzeste Wege in DAGs Beispiel: • : Knoten momentan in Queue q • Nummerierung nach Einfügereihenfolge 2 1 6 4 2 1 5 1 3 3 1 08.02.2010 2 2 1 1 10 9 2 1 2 4 7 11 8 1 4 Kapitel 20 Kürzeste Wege in DAGs Korrektheit der topologischen Nummerierung: Knoten wird erst dann nummeriert, wenn alle Vorgänger nummeriert sind. 2 1 6 4 2 1 5 1 3 3 1 08.02.2010 2 2 1 1 10 9 2 1 2 4 7 11 8 1 4 Kapitel 21 Kürzeste Wege in DAGs Laufzeit: Zur Bestimmung aller Knoten ohne eingehende Kante muss Graph einmal durchlaufen werden. Danach wird jeder Knoten und jede Kante genau einmal betrachtet, also Zeit O(n+m). 2 1 6 4 2 1 5 1 3 3 1 08.02.2010 2 2 1 1 10 9 2 1 2 4 7 11 8 1 4 Kapitel 22 Kürzeste Wege in DAGs Bemerkung: topologische Sortierung kann nicht alle Knoten nummerieren genau dann, wenn Graph gerichteten Kreis enthält (kein DAG ist) Test auf DAG-Eigenschaft 2 1 6 4 2 1 5 1 3 3 1 08.02.2010 2 2 1 1 10 9 2 1 2 4 7 11 8 1 4 Kapitel 23 Kürzeste Wege in DAGs DAG-Strategie: 1. Topologische Sortierung der Knoten Laufzeit O(n+m) 2. Aktualisierung der Distanzen gemäß der topologischen Sortierung Laufzeit O(n+m) Insgesamt Laufzeit O(n+m). 08.02.2010 Kapitel 4 24 Dijkstras Algorithmus Nächster Schritt: Kürzeste Wege für beliebige Graphen mit positiven Kanten. Problem: besuche Knoten eines kürzesten Weges in richtiger Reihenfolge s w 0 d1 d2 d3 d4 v Lösung: besuche Knoten in der Reihenfolge der kürzesten Distanz zur Quelle s 08.02.2010 Kapitel 4 25 Dijkstras Algorithmus • Am Anfang, setze d(s):=0 und d(v):=∞ für alle Knoten. Füge s in Priority Queue q ein, wobei die Prioritäten in q gemäß der aktuellen Distanzen d(v) definiert sind. • Wiederhole, bis q leer ist: Entferne aus q (deleteMin) den Knoten v mit niedrigstem d(v). Für alle (v,w)∈E, setze d(w) := min{d(w), d(v)+c(v,w)}. Falls w noch nicht in q war, füge w in q ein. 08.02.2010 Kapitel 4 26 Dijkstras Algorithmus Beispiel: ( : aktuell, : fertig) 1 1 ∞ 3 ∞ 2 1 2 ∞ 1 4 2 5 4 ∞ 1 s 08.02.2010 2 2 ∞ 2 ∞ 4 3 3 5 ∞ Kapitel 4 1 5∞ 2 27 Dijkstras Algorithmus Procedure Dijkstra(s: NodeId) d=<∞,…, ∞>: NodeArray of ℝ∪{-∞,∞} parent=<⊥,…,⊥>: ⊥ ⊥ NodeArray of NodeId d[s]:=0; parent[s]:=s q=<s>: NodePQ while q =<> do u:=q.deleteMin() // u: min. Distanz zu s in q foreach e=(u,v)∈E do if d[v] > d[u]+c(e) then // aktualisiere d[v] if d[v]=∞ then q.insert(v) // v schon in q? parent[v]:=u // d[v] wird auf d[u]+c(e) gesetzt q.decreaseKey(v, d[v]-(d[u]+c(e))) 08.02.2010 Kapitel 4 28 Dijkstras Algorithmus Korrektheit: • Angenommen, Algo sei inkorrekt. • Sei v der Knoten mit kleinstem µ(s,v), der aus q entfernt wird mit d[v]>µ(s,v). • Sei p=(s=v1,v2,…,vk=v) ein kürzester Weg von s nach v. • Weil alle c(e)>0 sind, steigt minimales d[w] in q monoton an. Da d[vk-1]<d[vk], muss vk-1 vor vk aus q entfernt worden sein, und wegen der Annahme galt d[vk-1]=µ(s,vk-1) • Bei Entfernung von vk-1 hat Algo überprüft, ob d[vk-1] + c(vk-1,vk)<d[vk]. Das muss bei Annahme oben der Fall gewesen sein, aber dann hätte Algo d[v] auf d[vk-1] + c(vk-1,v)=µ(s,v) gesetzt, ein Widerspruch. 08.02.2010 Kapitel 4 29 Dijkstras Algorithmus • TOp(n): Laufzeit von Operation Op auf Datenstruktur mit n Elementen Laufzeit: TDijkstra = O(n(TDeleteMin(n)+TInsert(n)) + m⋅TdecreaseKey(n)) Binärer Heap: alle Operationen O(log n), also TDijkstra = O((m+n)log n) Fibonacci Heap: amortisiert • TDeleteMin(n)=TInsert(n)=O(log n) • TdecreaseKey(n)=O(1) • Damit TDijkstra = O(n log n + m) 08.02.2010 Kapitel 4 30 Monotone Priority Queues Einsicht: Dijkstras Algorithmus braucht keine allgemeine Priority Queue, sondern nur eine monotone Priority Queue. Monotone Priority Queue: Folge der gelöschten Elemente hat monoton steigende Werte. Effiziente Implementierungen von monotonen Priority Queues möglich, falls Kantenkosten ganzzahlig. 08.02.2010 Kapitel 4 31 Bucket Queue Annahme: alle Kantenkosten im Bereich [0,C]. Konsequenz: zu jedem Zeitpunkt enthält q Distanzen im Bereich [d,d+C] für ein d. d+3 d+1 d C=8 d+2 d+1 d+8 d+5 08.02.2010 Kapitel 4 32 Bucket Queue Annahme: alle Kantenkosten im Bereich [0,C]. Konsequenz: zu jedem Zeitpunkt enthält q Distanzen im Bereich [d,d+C] für ein d. Bucket Queue: Array B aus C+1 Listen und Variable dmin für aktuell minimale Distanz (mod C+1) 0 08.02.2010 1 2 3 …. Kapitel 4 C 33 Bucket Queue 0 1 2 3 …. C • Jeder Knoten v mit momentaner Distanz d[v] wird in Liste B[d[v] mod (C+1)] gespeichert • Da momentane d[v]´s im Bereich [d,d+C] für ein d sind, haben alle v in einem B[d] dasselbe d[v]. 08.02.2010 Kapitel 4 34 Bucket Queue 0 1 2 3 …. C • Insert(v): fügt v in B[d[v] mod (C+1)] ein. Laufzeit O(1). • decreaseKey(v): entfernt v aus momentaner Liste und fügt v in B[d[v] mod (C+1)] ein. Falls in v Position in der Liste speichert, Laufzeit O(1). • deleteMin(): solange B[dmin]=∅, setze dmin:=(dmin+1) mod (C+1). Nimm dann einen Knoten u aus B[dmin] heraus. Laufzeit O(C). 08.02.2010 Kapitel 4 35 Bucket Queue 0 1 2 3 …. C • Insert(v), decreaseKey(v): Laufzeit O(1). • deleteMin(): Laufzeit O(C). • Laufzeit von Dijkstras Algo mit Bucket Queue: O(n⋅C+m) 08.02.2010 Kapitel 4 36 Radix-Heap Annahmen: • alle Elemente haben eine maximale Differenz von C zueinander • Insert(e) fügt nur Elemente e ein mit key(e)≥kmin (kmin: min. Schlüssel) 08.02.2010 Kapitel 4 37 Radix-Heap Array B mit Listen B[-1] bis B[K], K=1+⌊log C⌋. -1 0 1 2 …. K Regel: Element e in B[min(msd(kmin,key(e)),K)] msd(kmin,key(e)): höchstes Bit, in dem sich Binärdarstellungen von kmin und key(e) unterscheiden (-1: kein Unterschied) 08.02.2010 Kapitel 4 38 Radix-Heap Beispiel für msd(kmin,k): • sei kmin=17 oder binär 10001 • k=17: msd(kmin,k)=-1 • k=18: binär 10010, also msd(kmin,k)=1 • k=21: binär 10101, also msd(kmin,k)=2 • k=52: binär 110100, also msd(kmin,k)=5 Berechnung von msd für a≠b: msd(a,b)=⌊log(a⊕b)⌋ Zeit O(1) (mit entspr. Maschinenbefehlen) 08.02.2010 Kapitel 4 39 Radix-Heap -1 0 1 2 …. K min(): • gib kmin in B[-1] zurück Laufzeit: O(1) 08.02.2010 Kapitel 4 40 Radix-Heap insert(e): ( key(e)≥kmin ) • i:=min{msd(kmin,key(e)), K} • speichere e in B[i] Laufzeit: O(1) delete(e): ( key(e)>kmin ) • lösche e aus seiner Liste B[j] raus Laufzeit: O(1) decreaseKey(e,∆): ( key(e) - ∆ ≥ kmin ) • rufe delete(e) und insert(e) mit key(e):=key(e) - ∆ auf Laufzeit: O(1) 08.02.2010 Kapitel 4 41 Radix-Heap deleteMin(): • Falls B[-1] besetzt, entnehme ein e aus B[-1] (sonst kein Element mehr in Heap und fertig) • finde minimales i, so dass B[i]≠∅ ∅ (falls kein solches i oder i=-1, dann fertig) • bestimme kmin in B[i] (in O(1) Zeit möglich, falls z.B. kmin-Werte in extra Feld min[-1..K] gehalten) • verteile Knoten in B[i] über B[-1],…,B[i-1] gemäß neuem kmin Entscheidend: für alle e in B[j], j>i, gilt nach wie vor msd(kmin,key(e))=j, d.h. sie müssen nicht verschoben werden. 08.02.2010 Kapitel 4 42 Radix-Heap -1 2 0 1 2 3 4 5 6 7 8 4 9 260 5 11 381 6 14 Wir betrachten Sequenz von deleteMin Operationen 08.02.2010 Kapitel 4 43 Radix-Heap -1 9 0 1 2 11 14 3 4 5 6 7 8 260 381 Wir betrachten Sequenz von deleteMin Operationen 08.02.2010 Kapitel 4 44 Radix-Heap Lemma 4.1: Sei B[i] die minimale nichtleere Liste, i≥0. Sei xmin der kleinste Schlüssel in B[i]. Dann ist msd(xmin,x)<i für alle Schlüssel x in B[i].Alle Elemente in B[i] nach links Beweis: • x=xmin: klar • x≠xmin: wir unterscheiden zwei Fälle: 1) i<K, 2) i=K 08.02.2010 Kapitel 4 45 Radix-Heap Fall i<K: Bitposition: i altes kmin a 0 xmin a 1 a 1 x 0 Also muss msd(xmin,x)<i sein. 08.02.2010 Kapitel 4 46 Radix-Heap Fall i=K: Bitposition: j≥K h altes kmin a 0 xmin a 1 b 0 a 1 b 1 x 0 • Für alle x: kmin < xmin ≤ x ≤ kmin+C • j = msd(kmin,xmin), h = msd(xmin,x) 08.02.2010 Kapitel 4 47 Radix-Heap Fall i=K: Bitposition: j≥K h altes kmin a 0 xmin a 1 b 0 a 1 b 1 x 0 • Wegen j≥K hat Binärdarstellung von jedem übrigbleibenden x dasselbe Präfix a1b bis runter zu Bitstelle j‘≤K, d.h. h<K 08.02.2010 Kapitel 4 48 Radix-Heap -1 0 1 2 …. K Konsequenz: • jeder Knoten nur maximal K-mal verscho-ben in Radix Heap • Potenzial für amortisierte Analyse: Summe der Positionen der Elemente im Radix-Heap • insert(): amortisierte Laufzeit O(log C). 08.02.2010 Kapitel 4 49 Laufzeitvergleich Laufzeit Fibonacci-Heap Radix-Heap insert O(1) O(log C) amor. min O(1) O(1) deleteMin O(log n) amor. O(1) amor. delete O(log n) amor. O(1) merge O(1) O(n) decreaseKey O(1) O(1) 08.02.2010 Kapitel 4 50 Radix Heap -1 0 1 2 …. K Amortisierte Laufzeiten: • deleteMin(), decreaseKey(v): O(1). • insert(v): O(log C). Laufzeit von Dijkstras Algo mit Radix Heap: O(m + n log C) 08.02.2010 Kapitel 4 51 Bellman-Ford Algorithmus Nächster Schritt: Kürzeste Wege für beliebige Graphen mit beliebigen Kantenkosten. Problem: besuche Knoten eines kürzesten Weges in richtiger Reihenfolge s w 0 d1 d2 d3 d4 v Dijkstra Algo kann nicht mehr verwendet werden, da er im Allgemeinen nicht mehr Knoten in der Reihenfolge ihrer Distanz zu s besucht. 08.02.2010 Kapitel 4 52 Bellman-Ford Algorithmus Beispiel für Problem mit Dijkstra Algo: v 2 ∞ 2 0 -1 1 s 3 3 ∞ ∞ -1 1 -4 Knoten v hat falschen Distanzwert! 08.02.2010 Kapitel 4 53 Bellman-Ford Algorithmus Lemma 4.2: Für jeden Knoten v mit µ(s,v) > -∞ zu s gibt es einfachen Weg (ohne Kreis!) von s nach v der Länge µ(s,v). Beweis: • Weg mit Kreis mit Kantenkosten ≥0: Kreisentfernung erhöht nicht die Kosten • Weg mit Kreis mit Kantenkosten <0: Distanz zu s ist -∞ ! 08.02.2010 Kapitel 4 54 Bellman-Ford Algorithmus Folgerung: (Graph mit n Knoten) Für jeden Knoten v mit µ(s,v)> -∞ gibt es kürzesten Weg der Länge <n zu v. Strategie: Durchlaufe (n-1)-mal sämtliche Kanten in Graph und aktualisiere Distanz. Dann alle kürzeste Wege berücksichtigt. s 0 Durchlauf 08.02.2010 d1 1 d2 2 d3 3 Kapitel 4 d4 v 4 55 Bellman-Ford Algorithmus Problem: Erkennung negativer Kreise -2 1 s ∞ 1 0 ∞ 1 -1 ∞ -1 1 1 2 0 ∞ -1 Einsicht: in negativem Kreis erniedrigt sich Distanz in jeder Runde bei mindestens einem Knoten 08.02.2010 Kapitel 4 56 Bellman-Ford Algorithmus Problem: Erkennung negativer Kreise -2 1 s 1 0 -1 -1 1 0 -1 Zeitpunkt: kontinuierliche Distanzerniedrigung startet spätestens in n-ter Runde (dann Kreis mindestens einmal durchlaufen) 08.02.2010 Kapitel 4 57 Bellman-Ford Algorithmus Keine Distanzerniedrigung möglich: • Angenommen wir erreichen Zeitpunkt mit d[v]+c(v,w)≥ ≥d[w] für alle Kanten (v,w). • Dann gilt (über Induktion) für jeden Weg p, dass d[s]+c(p)≥d[w] für alle Knoten w. • Falls sichergestellt ist, dass für den ≥c(p) zu kürzesten Weg p nach w, d[w]≥ jedem Zeitpunkt ist, dann gilt am Ende d[w]=µ(s,w). 08.02.2010 Kapitel 4 58 Bellman-Ford Algorithmus Zusammenfassung: • Keine Distanzerniedrigung mehr möglich (d[v]+c(v,w)≥d[w] für alle w): Fertig, d[w]=µ(s,w) für alle w • Distanzerniedrigung möglich selbst noch in n-ter Runde (d[v]+c(v,w)<d[w] für ein w): Dann gibt es negative Kreise, also Knoten w mit Distanz µ(s,w)=-∞. Ist das wahr für ein w, dann für alle von w erreichbaren Knoten. 08.02.2010 Kapitel 4 59 Bellman-Ford Algorithmus Procedure BellmanFord(s: NodeId) d=<∞,…,∞>: NodeArray of ℝ∪{-∞, ∞} parent=<⊥,…, ⊥>: NodeArray of NodeId d[s]:=0; parent[s]:=s for i:=1 to n-1 do // aktualisiere Kosten für n-1 Runden forall e=(v,w)∈E do if d[w] > d[v]+c(e) then // bessere Distanz möglich? d[w]:=d[v]+c(e); parent[w]:=v forall e=(v,w) ∈E do // in n-ter Runde noch besser? if d[w] > d[v]+c(e) then infect(w) Procedure infect(v) // setze -∞-Kosten von v aus if d[v]>-∞ then d[v]:=-∞ forall (v,w)∈E do infect(w) 08.02.2010 Kapitel 4 60 Bellman-Ford Algorithmus Laufzeit: O(n⋅m) Verbesserungsmöglichkeiten: • Überprüfe in jeder Aktualisierungsrunde, ob noch irgendwo d[v]+c[v,w]<d[w] ist. Nein: fertig! • Besuche in jeder Runde nur die Knoten w, für die Test d[v]+c[v,w]<d[w] sinnvoll (d.h. d[v] hat sich in letzter Runde geändert). 08.02.2010 Kapitel 4 61 All Pairs Shortest Paths Annahme: Graph mit beliebigen Kantenkosten, aber keine negativen Kreise Naive Strategie für Graph mit n Knoten: lass n-mal Bellman-Ford Algorithmus (einmal für jeden Knoten) laufen Laufzeit: O(n2 m) 08.02.2010 Kapitel 4 62 All Pairs Shortest Paths Bessere Strategie: Reduziere n BellmanFord Anwendungen auf n Dijkstra Anwendungen Problem: wir brauchen dazu nichtnegative Kantenkosten Lösung: Umwandlungsstrategie in nichtnegative Kantenkosten, ohne kürzeste Wege zu verfälschen (nicht so einfach!) 08.02.2010 Kapitel 4 63 All Pairs Shortest Paths Gegenbeispiel zur Erhöhung um Wert c: Vorher 2 v Kosten +1 überall 3 1 s v 2 s 1 -1 2 0 : kürzester Weg 08.02.2010 Kapitel 4 64 All Pairs Shortest Paths • Sei φ:V→ℝ eine Funktion, die jedem Knoten ein Potenzial zuweist. • Die reduzierten Kosten von e=(v,w) sind: r(e) := φ(v) + c(e) - φ(w) Lemma 4.3: Seien p und q Wege in G. Dann gilt für jedes Potenzial φ: r(p)<r(q) genau dann wenn c(p)<c(q). 08.02.2010 Kapitel 4 65 All Pairs Shortest Paths Lemma 4.3: Seien p und q Wege in G. Dann gilt für jedes Potenzial φ: r(p)<r(q) genau dann wenn c(p)<c(q). Beweis: Sei p=(v1,…,vk) ein beliebiger Weg und ei=(vi,vi+1) für alle i. Es gilt: r(p) = ∑i r(ei) = ∑i (φ(vi) + c(e) - φ(vi+1)) = φ(v1) + c(p) - φ(vk) 08.02.2010 Kapitel 4 66 All Pairs Shortest Paths Lemma 4.4: Angenommen, G habe keine negativen Kreise und dass alle Knoten von s erreicht werden können. Sei φ(v)=µ(s,v) für alle v∈V. Mit diesem φ ist r(e)≥0 für alle e. Beweis: • nach Annahme ist µ(s,v)∈ℝ für alle v • wir wissen: für jede Kante e=(v,w) ist µ(s,v)+c(e)≥µ(s,w) (Abbruchbedingung!) • also ist r(e) = µ(s,v) + c(e) - µ(s,w) ≥ 0 08.02.2010 Kapitel 4 67 All Pairs Shortest Paths 1. Füge neuen Knoten s und Kanten (s,v) für alle v hinzu mit c(s,v)=0 (alle erreichbar!) 2. Berechne µ(s,v) nach Bellman-Ford und setze φ(v):=µ(s,v) für alle v 3. Berechne die reduzierten Kosten r(e) 4. Berechne für alle Knoten v die Distanzen µ(v,w) mittels Dijkstra Algo mit reduzierten Kosten auf Graph ohne Knoten s 5. Berechne korrekte Distanzen µ(v,w) durch µ(v,w)=µ(v,w)+φ(w)-φ(v) 08.02.2010 Kapitel 4 68 All Pairs Shortest Paths a Beispiel: 2 2 b b 1 a 1 d 1 c 1 -1 c -1 d 08.02.2010 Kapitel 4 69 All Pairs Shortest Paths Schritt 1: künstliche Quelle a 2 0 b 0 s 1 0 0 1 c -1 d 08.02.2010 Kapitel 4 70 All Pairs Shortest Paths Schritt 2: Bellman-Ford auf s a 2 0 0 s φ(a)=0 1 b φ(b)=0 c φ(c)=-1 0 0 1 -1 d 08.02.2010 Kapitel 4 φ(d)=0 71 All Pairs Shortest Paths Schritt 3: r(e)-Werte berechnen a 2 Die reduzierten Kosten von e=(v,w) sind: r(e) := φ(v) + c(e) - φ(w) 1 φ(a)=0 0 b φ(b)=0 c φ(c)=-1 0 d 08.02.2010 Kapitel 4 φ(d)=0 72 All Pairs Shortest Paths Schritt 4: berechne alle Distanzen µ(v,w) via Dijkstra 2 µ a b c d 08.02.2010 a 0 1 0 0 b 2 0 2 2 c 3 1 0 0 d 3 1 3 0 Kapitel 4 1 a φ(a)=0 0 b φ(b)=0 c φ(c)=-1 0 d φ(d)=0 73 All Pairs Shortest Paths Schritt 5: berechne korrekte Distanzen durch die Formel µ(v,w)=µ(v,w)+φ(w)-φ(v) µ a b c d 08.02.2010 a 0 1 1 0 b 2 0 3 2 c 2 0 0 -1 d 3 1 4 0 Kapitel 4 a 2 1 φ(a)=0 1 b φ(b)=0 c φ(c)=-1 -1 d φ(d)=0 74 All Pairs Shortest Paths Laufzeit des APSP-Algorithmus: O(TBellman-Ford(n,m) + n⋅TDijkstra(n,m)) = O(n⋅m + n(n log n + m)) = O(n⋅m ⋅ + n2 log n) unter Verwendung von Fibonacci Heaps. 08.02.2010 Kapitel 4 75 Transitive Hülle Problem: Konstruiere für einen gerichteten Graphen G=(V,E) eine Datenstruktur, die die folgende Operation (speicher- und zeit-)effizient unterstützt: • Reachable(v,w): liefert 1, falls es einen gerichteten Weg von v nach w in G gibt und sonst 0 08.02.2010 Kapitel 4 76 Transitive Hülle Lösung 1: verwende APSP Algorithmus • Laufzeit zur Erstellung der DS: O(n⋅m + n2 log n) • Speicheraufwand: O(n2) • Laufzeit von Reachable(v,w): O(1) (nachschauen in Tabelle, ob µ(v,w)<∞ ) 08.02.2010 Kapitel 4 77 Transitive Hülle Einsicht: Kantenkosten jetzt egal. Daher können wir alle Kantenkosten auf 1 setzen. Lösung 2: • verwende als APSP Algorithmus einfach n-mal Breitensuche (1x von allen Knoten) • Laufzeit: O(n(n+m)) 08.02.2010 Kapitel 4 78 Transitive Hülle Einsicht: Alle Knoten in einer starken ZHK haben dieselbe Menge erreichbarer Knoten. Daher reicht es, sie durch Repräsentanten zu vertreten. v w ZHK ZHK ZHK 08.02.2010 Kapitel 4 79 Transitive Hülle Lösung 3: verwende ZHK-Algorithmus • bestimme starke ZHKs e d i h g f c a 08.02.2010 b Kapitel 4 80 Transitive Hülle Lösung 3: verwende ZHK-Algorithmus • bestimme ZHK-Graph (Repräsentanten) e i c a 08.02.2010 b Kapitel 4 81 Transitive Hülle Lösung 3: verwende ZHK-Algorithmus • Wende APSP-Algo auf ZHK-Graph an e i c a 08.02.2010 b Kapitel 4 82 Transitive Hülle Reachable(v,w): • Bestimme Repräsentanten rv und rw von v und w • rv=rw: gib 1 aus • sonst gib Reachable(rv,rw) für ZHK-Graph zurück 08.02.2010 Kapitel 4 83 Transitive Hülle • Graph G=(V,E): n=|V|, m=|E| • ZHK-Graph G’=(V’,E’): n’=|V’|, m’=|E’| Datenstruktur: • Berechnungszeit: O(n + m + n’⋅(m’ + n’)) • Speicher: O(n + (n’)2) Reachable(v,w): Laufzeit O(1) 08.02.2010 Kapitel 4 84 Transitive Hülle Lösung 4: mit Matrixmultiplikation (auf ZHK-Graph) (Siehe auch die DuA Vorlesung.) • Erstelle Adjazenzmatrix A∈{0,1}n×n von G (mit 1-Einträgen entlang Diagonale) • Verwende für die Matrixmultiplikation das Boolesche Produkt, d.h. für C=A⋅B gilt ci,j= Vk(ai,k∧bk,j) (statt ci,j = ∑k (ai,k⋅bk,j) ) • Berechne A*=An-1. Es gilt dann: a*i,j = 1 ⇔ es gibt gerichteten Weg von i nach j • Zur Berechnung von An-1 sind nur O(log n) Matrixmultiplikationen notwendig. • Zeit für Matrixmultiplikation nach Strassen: O(n2,81) • Besser als Lösung 2, falls m´≈n´2. 08.02.2010 Kapitel 4 85 Ausblick Matchingalgorithmen… 08.02.2010 Kapitel 4 86