Kürzeste Wege in gewichteten Graphen 1 Gewichtete

Werbung
Prof. Thomas Richter
Institut für Analysis und Numerik
Otto-von-Guericke-Universität Magdeburg
[email protected]
1. Juni 2017
Material zur Vorlesung Algorithmische Mathematik II am 31.05.2017
Kürzeste Wege in gewichteten Graphen
1 Gewichtete Graphen + kürzeste Wege
Oft macht es Sinn, den Knoten und Kanten in einem Graph ein Gewicht zuzuordnen.
Wir betrachten als Graphen das Netz zwischen Städten (die Knoten) und Bahnlinien
(die Kanten) welche die Städte verbinden. Ein mögliches Kantengewicht c(e) ∈ R für
eine Kante e = (x, y) kann z.B. die Länge es verbindenden Bahnstrecke von x nach y
sein, etwa in Kilometer oder aber in Zeit. Ein Knotengewicht c(x) ∈ R könnte z.B. die
durchschnittliche Zeit sein, die ein Zug an diesem Bahnhof verbringt.
Im Folgenden betrachten wir zunächst nur Kantengewichte.
Folie 1
Definition 1 (Gewichteter Graph). Ein Tripel G = (V, E, fW ) bestehend aus Knoten
V ⊂ N, Kanten E ⊂ V × V und einer Gewichtsfunktion fW : E → R heißt gewichteter
Graph.
Die Unterscheidung zwischen gerichteten und ungerichteten Graphen, vollständigen Graphen, Bäumen und Wäldern wird durch das zusätzliche Gewicht nicht geändert.
1
Folie 2
Zur Speicherung von gewichteten Graphen wird zusätzlich zur Adjazenzliste eine
Gewichtsliste gespeichert.
Algorithmus 1: Gewichteter Graph
1
2
3
4
5
6
7
8
9
10
c l a s s GraphGewichtet
{
public :
/ / A d j a z e n z l i s t e . a d j [ i ] s p e i c h e r t a l l e Knoten a d j [ i ] [ j ] ,
/ / d i e m i t Knoten i d u r c h e i n e K a n t e v e r b u n d e n s i n d .
vector <vector <int > > adj ;
/ / G e w i c h t s l i s t e . wgt [ i ] [ j ] s p e i c h e r t d a s G e w i c h t z u r
/ / K a n t e z w i s c h e n Knoten i und Knoten a d j [ i ] [ j ]
v e c t o r < v e c t o r <double> > wgt ;
};
Wir definieren nun das wesentliche Problem, welches wir in dieser Stunde untersuchen
werden.
Folie 3
8
Definition 2 (Kürzester Weg). Gegeben sei ein gewichteter Graph G sowie
zwei Knoten x, y ∈ V(G). Gesucht ist
der Weg P = (V 0 , E 0 , fW ) ⊂ G
P := (V 0 , E 0 ) =
({x = x0 , . . . , xk = y}, {e1 , . . . , ek })
6
7
1
5
6
2
5
8
5
4
9
mit kleinstem summierten Kantengewicht
X
fW (e) → min!
5
1
3
3
e∈P
2
0
2
7
Wir suchen z.B. den kürzesten Weg
von Knoten 0 nach Knoten 8.
2
Kantengewichte fW (e) können im Allgemeinen negativ oder positiv sein. Wir beschränken uns hier auf den einfachen Fall von ausschließlich positiven Kantengewichten fW :
E → R>0 . Angenommen, ein Graph (mit auch negativen Kantengewichten) hätte einen
Kreis mit negativer Kantengewichtsumme. Durch mehrfaches durchlaufen dieses Kreises können wir Wege mit beliebig kleiner Gewichtssumme erzeugen. Dieses Beispiel ist
extrem, es zeigt jedoch bereits, dass dieser allgemeine Fall schwerer ist.
2
2 Suche kürzester Wege - Dijkstra’s Algorithmus
Bei der Suche nach kürzesten Wegen haben wir Landkarten vor Augen. Diese beinhalten
zusätzlich zu den Knoten und Kanten - also Städten und Bahnlinien - auch geometrische
Informationen, die uns beim Problem stark helfen: Wollen wir von Hamburg nach Kiel
fahren, so werden wir nicht in einen Zug nach Berlin oder Hannover steigen. Wir suchen
hier nach einfachen Algorithmen, die ohne solche Zusatzinformationen auskommen.
Starten wir in einem Punkt x ∈ V, so können wir also nicht zielgerichtet in Richtung
y ∈ V loslegen sonder werden den Graphen - ähnlich der Durchmusterung - allgemein
durchlaufen. Hierbei werden wir für alle Knoten xk ∈ V jeweils kürzeste Wege von x
berechnen. Treffen wir bei dieser Suche auf den Knoten y, so sind wir fertig.
Ein Algorithmus zum Lösen des Problems (bei positiven Kantengewichten) heißt Dijkstra’s Algorithmus.
Folie 4
Algorithmus 2: Dijkstra’s Algorithmus
Gegeben ein gewichteter Graph G = (V, E, fW ) sowie ein Knoten x ∈ V
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Setze R = ∅
Setze Q = {x}
Setze l(v) = 0
Solange Q 6= ∅
Wä hle v ∈ Q mit l(v) minimal
Setze Q = Q \ {v}
Setze R = R ∪ {v}
Für e = (v, w) ∈ E mit w 6∈ R
Setze ŵ = l(v) + fW (e)
F a l l s w 6∈ Q oder ŵ < l(w)
Setze l(w) = ŵ
Setze Q = Q ∪ {w}
Setze P(w) = e
Setze T = {P(v) | v ∈ R \ {x}}
Ausgabe (R, T )
Der Algorithmus erzeugt einen gerichteten Graphen (R, T ), der zu jedem Knoten v ∈ R
den kürzesten Weg beinhaltet. Der Graph ist eine sogenannte Arboreszenz. Eine Arboreszenz ist ein zusammenhängendes Branching. Dabei ist ein Branching ein gerichteter Graph,
dessen zugehöriger ungerichteter Graph ein Wald ist (Kreisfrei) und für den jeder Knoten nur eine eingehende Kante besitzt. Was ist wichtig für uns? Zu jedem Knoten v ∈
R \ {x} gibt es nur eine Kante e ∈ T mit e = (v 0 , x). Wollen wir nun den kürzesten Weg
von x nach y bestimmen, so durchlaufen wir die entsprechenden Kanten von y aus einfach rückwärts. Anstelle von Zeile 13 speichern wir im Algorithmus daher keine Kanten
sondern zu jedem Knoten w ∈ R den Knoten v ∈ R von dem aus wir w mit e = (v, w)
erreicht haben.
3
13
Setze P[w] = v
Suchen wir nur den Weg von x nach y so kann der Algorithmus abgebrochen werden,
falls in Zeile 5 v = y gilt.
Folie 5
Satz 1 (Dijkstr’as Algorithmus). Der Dijkstra Algorithmus löst das kürzeste-WegeProblem. Der Algorithmus kann in
O(|V|2 + |E|)
Operationen durchgeführt werden.
Beweis. Der Beweis der Korrektheit, dass also kürzeste Wege von x ∈ V zu jedem erreichbaren Knoten y ∈ V gefunden werden findet sich z.B. in Hougardy, Vygen “Algorithmische Mathematik”.
Wir gehen kurz auf den Aufwand ein. Wir speichern Q in einer Liste, also einem vector.
R speichern wir in einem Vektor vom Typ vector<bool> R mit dem Wert true falls v ∈ R
sonst false .
Die Solange-Schleife wird höchstens |V| mal durchgeführt, da nur |V| Knoten der Menge
Q hinzugefügt werden können.
In jedem Durchgang werden die folgenden Schritte durchgeführt:
• Suche des Elements v ∈ Q mit l(v) minimal. Bei Speicherung von Q als Liste kann
dies in O(|Q|) = O(|V|) Operationen erfolgen.
• Löschen von v ∈ Q erfordert bei einer Liste das Suchen (bereits erfolgt) ein Umkopieren des letzten Elements an die Stelle von v und ein Verkürzen, somit O(1)
Operationen.
• Hinzufügen von v an R erfolgt in O(1) Operationen.
• Ebenso benötigt die Abfrage w 6∈ R in Schritt 8 nur O(1) Operationen
• In Schritt 8 werden alle Kanten von v aus durchlaufen. Da dieser Schritt maximal
für alle Knoten des Graphen durchlaufen wird wird die innere Schleife 8-13 somit maximal O(|E|) mal durchlaufen. Die Schritte 11-13 können jeweils in O(1)
Operationen durchgeführt werden. Die Abfrage w 6∈ Q in Schritt 14 kann durch
Auswertung des Gewichtes l(w) erfolgen, falls dieses vor Durchlauf des Verfahrens z.B. mit den Werten −1 initialisiert wird.
Insgesamt ergibt sich somit der Aufwand O(|V|2 + |E|).
4
Folie 6
Zu einer effizienten Umsetzung des Algorithmus müssen mehrere Teilaufgaben
schnell gelöst werden. Die Solange-Schleife ab Zeile 4 hat maximal n = |V| Iterationen. Die wesentlichen Bestandteile sind:
• Suche des Elements v ∈ Q mit kleinstem Gewicht
• Suche des Elementes w ∈ R (erledigt, wenn wir R als vector schreiben)
• Hinzufügen in Q sowie entfernen aus Q
• Hinzufügen in R (erledigt, bei R als vector)
Kritisch in Bezug auf die Laufzeit ist die Suche in Q und R. Sind diese Mengen nicht
günstig strukturiert, so kann die Suche jeweils O(n) Operationen benötigen, in denen
die gesamte Liste durchlaufen wird. Die Gesamtllaufzeit wäre dann O(n2 ).
Die Suche in der Menge R kann einfach gestaltet werden. Wird der Algorithmus komplett durchgeführt und ist der Graph G zusammenhängend, so hat R nach Beeindigung
die gleiche Anzahl an Elementen. Statt einer Menge R kann zur Speicherung ein Vektor
gewählt werden mit dem Wert 1, falls ein Knoten Teil von R ist, ansonsten Null.
5
Herunterladen