Grundlagen: Graphen Wie rechnet man mit Landkarten? Melanie Herzog∗ Wolfgang Ferdinand Riedl† Lehrstuhl M9 für Angewandte Geometrie und Diskrete Mathematik Technische Universität München 1 Motivation Ein wichtiges Gebiet der Kombinatorischen Optimierung sind Routing Probleme aller Art, d.h. Probleme bei denen es darum geht, möglichst gute Routen für Verkehrsmittel zu nden. Beispiele sind die Bestimmung kürzester Wege in Auto-Navigationsgeräten (zum Beispiel der kürzeste Weg von München nach Berlin, wie in Abbildung 1a), die Bestimmung von kürzesten Rundreisen beim Problem des Handlungsreisenden (Traveling Salesman Problem) (in Abbildung 1b zu sehen für eine Rundreise durch 80 Städte in Deutschland) oder die Bestimmung von kürzesten Touren für eine Flotte von Lieferwagen (Vehicle Routing Problem). All diese Probleme setzen voraus, dass die Verkehrsinfrastruktur in einer für die zur Lösung verwendeten Algorithmen lesbarer Form dargestellt ist. Diese Darstellung sind die hier vorgestellten Graphen. (a) Kürzester Weg von München nach Berlin1 (b) Rundreise in Deutschland2 Abbildung 1: Beispiele für Routing Probleme ∗ [email protected] † [email protected] 1 2 Quelle: © OpenRouteService.org, Creative Commons BY-SA 2.0 Quelle: TSP Spiel des Lehrstuhl M9 der Technische Universität München (siehe [1]) 1 2 Denition Die einfachsten Graphen bestehen aus Knoten und Kanten, wobei jede Kante genau zwei Knoten verbindet: G = (V, E), wobei V die Menge der Knoten (vertices) und E die Menge der Kanten (edges) bezeichnet. Ein Beispielgraph ist in Abbildung 2 dargestellt. v2 v4 v1 v6 v3 Abbildung 2: v5 G = (V, E) mit V = {v1 , . . . , v6 } und E = {{v1 , v2 }, {v1 , v3 }, {v2 , v4 }, {v3 , v4 }, {v3 , v5 }, {v4 , v5 }, {v4 , v6 }, {v5 , v6 }} Sind die Kanten gerichtet, spricht man von einem gerichteten Graphen. Die Kantenmenge bezeichnet man dann oft mit A (arcs) statt E. Für ein Beispiel für einen gerichteten Graphen siehe Abbildung 3. v2 v4 v1 v6 v3 Abbildung 3: v5 G = (V, A) mit V = {v1 , . . . , v6 } und A = {(v1 , v2 ), (v1 , v3 ), (v2 , v4 ), (v3 , v4 ), (v3 , v5 ), (v4 , v5 ), (v4 , v6 ), (v5 , v6 )} In vielen Anwendungen sind nicht alle Kanten gleichwertig. Daher werden Gewichte eingeführt: G = (V, E, w), dabei ist w:E→R die Gewichtsfunktion. Sind die Kanten eines Graphen gewichtet, spricht man von einem gewichteten Graphen (siehe Abbildung 4). 1.2 v3 Abbildung 4: 0.7 0.3 v4 2.0 v1 v2 1.5 0.5 0.8 1.0 v6 v5 G = (V, A, w) mit V = {v1 , . . . , v6 }, A = {(v1 , v2 ), (v1 , v3 ), (v2 , v4 ), (v3 , v4 ), (v3 , v5 ), (v4 , v5 ), (v4 , v6 ), (v5 , v6 )} und w(v1 , v2 ) = 0.5, w(v1 , v3 ) = 1.2, w(v2 , v4 ) = 0.7, w(v3 , v4 ) = 1.5, w(v3 , v5 ) = 0.3, w(v4 , v5 ) = 2.0, w(v4 , v6 ) = 0.8, w(v5 , v6 ) = 1.0 2 3 Anwendung Das Übersetzen der Verkehrsinfrastruktur in einen Graphen wird im Folgenden am Beispiel eines Straÿennetzes dargestellt. Oft liegen dafür eine Straÿenkarte wie in Abbildung 5a oder entsprechende Geodaten vor. Daraus wird in einem ersten Schritt eine Entfernungskarte berechnet, siehe Abbildung 5b, um diese abschlieÿend in einen Graphen, siehe Abbildung 5c umzuwandeln. (a) Straÿenkarte3 (b) Entfernungskarte4 74 v7 79 10 1 v4 v9 50 v1 105 68 82 v3 162 95 98 v5 111 v2 86 v6 65 v8 (c) Graph Abbildung 5: Von der Straÿenkarte zum Graph 4 Strukturen Häug beschäftigt man sich mit bestimmten Strukturen von Graphen. Die wichtigsten werden im Folgenden vorgestellt. 4.1 Pfade, Wege und Kreise Denition 4.1 (Weg): Sei G = (V, E) ein Graph, s, t ∈ V ein Start- und Zielknoten. Ein s-t-Weg ist eine Folge W = (w1 , . . . , wk ), k ∈ N, mit w1 = s, wk = t, wi ∈ V für alle i ∈ {1, . . . , k} und 3 4 Quelle: © OpenStreetMap.org Mitwirkende, Creative Commons BY-SA 2.0 Quelle: Eigene Darstellung 3 {wi , wi+1 } ∈ E für alle i ∈ {1, . . . , k − 1}. Ist G = (V, E, w) ein gerichteter Graph, so ist die Länge des Weges W w(W ) := k−1 X w({wi , wi+1 }). i=1 Denition 4.2 (Pfad): Sei G = (V, E) ein Graph, s, t ∈ V ein Start- und Zielknoten. Ein s-t-Pfad ist ein s-t-Weg bei dem alle Knoten paarweise verschieden sind. Abbildung 6 illustriert den Unterschied zwischen Pfaden und Wegen. v2 v4 v1 v6 v3 (a) v2 v4 v1 v5 v6 v3 W = (v1 , v2 , v4 , v3 , v5 , v4 , v6 ) ist ein Weg, aber (b) v5 P = (v1 , v2 , v4 , v6 ) ist ein Pfad kein Pfad Abbildung 6: Unterschied zwischen Wegen und Pfaden Denition 4.3 (Zykel): Sei G = (V, E) ein Graph. Ein Zykel ist ein geschlossener Weg, d.h. eine Folge C = (w1 , . . . , wk ), k ∈ N, mit w1 = wk , wi ∈ V und {wi , wi+1 } ∈ E für alle i ∈ {1, . . . , k}. Denition 4.4 (Kreis): Sei G = (V, E) ein Graph. Ein Kreis ist ein Zykel bei dem alle Knoten paarweise verschieden sind. In Abbildung 7 ist der Unterschied zwischen Zykeln und Kreisen dargestellt. Für alle in diesem Unterabschnitt vorgestellten Strukturen gibt es Analoga auf gerichteten Graphen. v2 v4 v1 v6 v3 (a) v2 v1 v5 Z = (v1 , v2 , v4 , v6 , v5 , v4 , v3 , v1 ) v4 v6 v3 ist ein Zykel, (b) v5 C = (v1 , v2 , v4 , v3 , v1 ) ist ein Kreis aber kein Kreis Abbildung 7: Unterschied zwischen Zykeln und Kreisen 4.2 Bäume, Spannbäume Denition 4.5 (Baum): Sei G = (V, E) ein Graph. Die Kantenmenge T ⊂ E heiÿt Baum, wenn sie zusammenhängend ist und keine Kreise enthält. 4 Denition 4.6 (Spannbaum): Sei G = (V, E) ein Graph. Die Kantenmenge T ⊂ E heiÿt Spannbaum, wenn sie ein Baum ist und alle Knoten enthält. Abbildung 8 illustriert die Denition der Struktur Baum und Spannbaum. v2 v4 v1 v6 v3 (a) v5 {{v1 , v2 }, {v2 , v4 }, {v3 , v4 }, {v4 , v5 }} ist ein Baum, aber kein Spannbaum, da v6 nicht enthalten ist v2 v4 v1 v6 v3 (b) v5 {{v1 , v2 }, {v3 , v4 }, {v4 , v5 }} ist kein Baum, da die Kantenmenge nicht zusammenhängend ist v2 v4 v1 v6 v3 (c) v5 {{v2 , v4 }, {v3 , v4 }, {v3 , v5 }, {v4 , v5 }} ist kein Baum, da die Kantenmenge einen Kreis enthält v2 v4 v1 v6 v3 (d) v5 {{v1 , v2 }, {v2 , v4 }, {v3 , v4 }, {v4 , v5 }, {v5 , v6 }} ist ein Spannbaum, da die Kantenmenge alle Knoten enthält Abbildung 8: Denition Baum 5 Einfache und grundlegende Algorithmen Es gibt einige grundlegende Algorithmen, welche häug auf Graphen ausgeführt werden. Zwei dieser Algorithmen sind die Breiten- und Tiefensuche. Diese besuchen die Knoten eines Graphen in einer bestimmten Reihenfolge und können verwendet werden, wann immer man die Knoten eines Graphen in einer systematischen Reihenfolge besuchen will. 5 Will man einen minimalen Spannbaum eines Graphen berechnen, so kann man dazu beispielsweise den Algorithmus von Kruskal verwenden. Dieser berechnet einen minimalen Spannbaum, das heiÿt einen Baum, welcher alle Knoten enthält und der zugleich eine möglichst kleine Summe von Kantengewichten hat. 5.1 Breitensuche Bei der Breitensuche werden die Knoten des Graphen ausgehend von einem Startknoten schichtweise besucht, das heiÿt erst werden die direkten Nachbarn des Startknoten besucht, dann deren Nachbarn und so weiter. Die Breitensuche ist in Algorithmus 1 dargestellt. Algorithmus 1 Breitensuche Eingabe: G = (V, E, w), s ∈ V Ausgabe: Besuchsreihenfolge der Knoten 1: for v ∈ V do 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: Besuchsnr(v) ← ∞ end for Q ← {s} nr ← 1 while Q 6= ∅ do v ← Q.f irst Besuchsnr(v) ← nr nr ← nr + 1 for w ∈ V : w ist Nachbar von v Q ← Q ∪ {w} . Füge noch end for end while . Füge Startknoten in Warteschlange ein . . und Entferne ersten Knoten aus Q Merke Besuchsnummer des Knoten Besuchsnr(w) = ∞ do nicht besuchte Nachbarn von Zu Beginn ist in der Warteschlange der noch zu besuchenden Knoten ten. So lange noch Knoten besucht werden müssen (das heiÿt Q v zu Warteschlange Q nur der Startkno- nicht leer ist) wird immer Q entfernt und mit seiner Besuchsnummer markiert. Danach werden zu Q hinten hinzugefügt, sofern sie nicht schon besucht wurden. der erste Knoten aus alle seine Nachbarn Dadurch, dass die Knoten hinten zu Q hinzugefügt, aber von vorne weggenommen werden, werden die Knoten wie oben dargelegt schichtweise abgearbeitet. 5.2 Tiefensuche Im Gegensatz zur Breitensuche werden die Knoten bei der Tiefensuche nicht schichtweise besucht. Vielmehr sucht man zuerst in die Tiefe und versucht, so weit wie möglich in den Graphen vorzudringen. Dennoch funktioniert die Tiefensuche ähnlich zur Breitensuche, wie in Algorithmus 2 zu erkennen ist. Der einzige Unterschied zur Breitensuche ist, dass nun immer der letzte Knoten (das heiÿt der zuletzt eingefügte) Knoten aus der Warteschlange Q entfernt und benutzt wird. Hier- durch arbeitet man nicht zuerst alle Nachbarn des Startknoten und dann deren Nachbarn usw. ab, sondern entfernt sich immer weiter von ihm, bis man keine unbesuchten Knoten mehr erreichen kann. 6 Algorithmus 2 Tiefensuche Eingabe: G = (V, E, w), s ∈ V Ausgabe: Besuchsreihenfolge der Knoten 1: for v ∈ V do 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: Besuchsnr(v) ← ∞ end for Q ← {s} nr ← 1 while Q 6= ∅ do v ← Q.last Besuchsnr(v) ← nr nr ← nr + 1 for w ∈ V : w ist Nachbar von v Q ← Q ∪ {w} . Füge noch end for end while . Füge Startknoten in Warteschlange ein . . und Entferne letzten Knoten aus Q Merke Besuchsnummer des Knoten Besuchsnr(w) = ∞ do nicht besuchte Nachbarn von v zu Warteschlange 5.3 Vergleich von Breiten- und Tiefensuche Wir wollen die beiden vorgestellten Algorithmen nun an Hand des Graphen aus Abbildung 9a vergleichen. Hierzu wählen wir als Startknoten den Knoten v1 . Das Ergebnis der Breitensuche ist in Abbildung 9b zu sehen. Es ist klar zu erkennen, dass alle Nachbarn von Nachbarn von man von v1 v2 v1 zuerst besucht werden (v2 , v3 und v4 besucht, danach die Nachbarn von v4 ). Anschlieÿend werden alle v5 (also alle Knoten, welche und mit zwei Kanten erreichen kann). Zuletzt kommen die noch weiter entfernten Knoten (hier nur noch v6 ). Die fett gedruckten Kanten zeigen an, von welchem Knoten aus ein weiterer Knoten besucht wurde. Bei der Tiefensuche sieht man sofort, dass die Knoten in einer anderen Reihenfolge besucht wurden. Die Suche geht von besucht also anschlieÿend v5 , v1 zu v2 und von dort immer weiter, so lange es geht. Sie geht dann weiter zu v7 und schlussendlich zu v4 . Von dort aus kann sie keine neuen Knoten mehr besuchen, sie macht also an der letzten Möglichkeit weiter, was heiÿt dass sie von v2 weiter zu v8 und v6 geht. 5.4 Algorithmus von Kruskal Der Algorithmus von Kruskal berechnet für einen zusammenhängenden gewichteten Graphen einen minimalen Spannbaum P e∈M c(e). M, Das Vorgehen ist in Algorithmus 3 beschrieben. Der Algorithmus fügt also Kanten zu (solange M das heiÿt einen Spannbaum mit minimalen Kosten M hinzu, solange dadurch kein Kreis geschlossen wird also noch ein Baum ist). Es ist klar, dass dadurch am Ende ein Spannbaum entsteht. Um zu zeigen, dass dieser Spannbaum auch minimal ist, braucht man etwas mehr Hintergrundwissen, weshalb hier darauf verzichtet wird. Beispiel 5.1: Suchen wir für den Graphen aus Abbildung 10a einen minimalen Spannbaum, so können wir diesen mit den Algorithmus von Kruskal nden. Ein mögliches Ergebnis ist dann der in Abbildung 10b gezeigte Spannbaum. 7 v3 v5 v7 v1 v2 v8 v6 v4 (a) Was ist das Ergebnis von Breiten- und Tiefensuche mit Startknoten v1 ? v3 4 v5 v3 4 v5 5 v7 3 v7 7 5 1 v1 3 v4 8 v6 1 v2 2 v1 6 v8 v4 6 (b) Ergebnis der Breitensuche mit Startpunkt v1 8 v6 v2 2 v8 7 (c) Ergebnis der Tiefensuche mit Startpunkt v1 Abbildung 9: Vergleich von Breiten- und Tiefensuche 6 Übungsaufgaben Aufgabe 6.1: Betrachte den Graphen aus Abbildung 2 und W = (v1 , v3 , v4 , v3 , v5 , v6 ). Ist W ein Weg? ein Pfad? ein Baum? Aufgabe 6.2: Betrachte den Graphen aus Abbildung 4 und W = (v1 , v3 , v4 , v5 , v6 ). Was ist die Länge dieses Pfades? Aufgabe 6.3: Begründe: Ein Weg, der keine Zykel enthält, ist ein Pfad. Aufgabe 6.4: Ist jeder Pfad ein Baum? Ist jeder Weg ein Baum? Aufgabe 6.5: Führe Breiten- und Tiefensuche auf dem Graphen aus Abbildung 5c aus. 8 Algorithmus 3 Algorithmus von Kruskal Eingabe: G = (V, E, w) Ausgabe: Minimaler Spannbaum M 1: Sortiere Kanten E so, dass M ←∅ for i ∈ {1, . . . , m} do if M ∪ {ei } ist kreisfrei M ← M ∪ {ei } 2: 3: 4: 5: c(e1 ) ≤ c(e2 ) ≤ . . . c(em ) then end if end for 6: 7: 6 v3 5 v5 4 v5 v7 v3 3 v7 3 2 4 3 6 3 4 v1 v2 v1 v2 1 1 v4 4 3 v8 v8 v6 v4 (a) Wie sieht ein minimaler Spannbaum auf diesem gewichteten Graphen aus? v6 (b) Ein minimaler Spannbaum Abbildung 10: Der Algorithmus von Kruskal Aufgabe 6.6: Eine häuge Anwendung von Breiten- oder Tiefensuche ist der Test, ob ein Graph zusammenhängend ist. Woran erkennt man am Ergebnis des Algorithmus, ob der Graph zusammenhängend ist? Aufgabe 6.7: Finde einen Graphen, auf welchem Breiten- und Tiefensuche die Knoten in der selben Reihenfolge besuchen. Aufgabe 6.8: Informiere Dich über Algorithmus von Prim und führe ihn auf dem Graphen von Abbildung 10a aus. Was gilt für die Ergebnisse der beiden Algorithmen? Die erhaltenen Graphen sind immer Spannbäume. Die erhaltenen Graphen haben das gleiche Gewicht. Die erhaltenen Graphen sind immer gleich. Aufgabe 6.9: Finde auf dem Graphen aus Abbildung 5c einen minimalen Spannbaum. 9 Literatur [1] M9 Lehrstuhl für Angewandte Geometrie und Diskrete Mathematik, TU München. TSP Spiel. Juli 2012. url: http://www-m9.ma.tum.de/Allgemeines/TSPStarten. 10