Graphen und ihre Verarbeitung

86
Graphen und ihre Verarbeitung Klaus Becker 2010

description

Graphen und ihre Verarbeitung. Klaus Becker 2010. Graphen. Teil 1. Vernetzte Strukturen. Routenplanung. Typisches Routenproblem: Wie kommt man am besten mit dem Auto von Worms nach Speyer?. Routenplanung mit dem Computer. Modellierungsproblem: - PowerPoint PPT Presentation

Transcript of Graphen und ihre Verarbeitung

Page 1: Graphen und ihre Verarbeitung

Graphen und ihre Verarbeitung

Klaus Becker

2010

Page 2: Graphen und ihre Verarbeitung

2 Graphen

Page 3: Graphen und ihre Verarbeitung

3 Teil 1

Vernetzte Strukturen

Page 4: Graphen und ihre Verarbeitung

4 Routenplanung

Typisches Routenproblem: Wie kommt man am besten mit dem Auto von Worms nach Speyer?

Page 5: Graphen und ihre Verarbeitung

5 Routenplanung mit dem Computer

Modellierungsproblem:Wie wird das Verkehrsnetz im Computer repräsdentiert?

Berechnungsproblem:Wie wird die optimale Route ermittelt?

Page 6: Graphen und ihre Verarbeitung

6

Beschreibung vernetzter Strukturen

Modellierung: Will man die Information über ein solches Straßennetz beschreiben, so konzentriert man sich auf die relevanten Fakten und lässt alles andere erst einmal weg. Ist man z.B. nur an den Autobahnverbindungen um Ludwigshafen / Mannheim interessiert, so könnte eine abstrahierende Beschreibung des Autobahnnetzes wie folgt aussehen:

Page 7: Graphen und ihre Verarbeitung

7 Fachkonzept Graph

Ein Graph besteht aus einer Menge von Knoten und einer Menge von Kanten (die jeweils zwei Knoten miteinander verbinden).

Graphen dienen dazu, vernetzte Strukturen zu beschreiben. Die Knoten repräsentieren die Objekte des Anwendungsbereichs, die Kanten die Beziehungen zwischen den Objekten.

Graphen sind ein wichtiges und häufig benutztes Modellierungsmuster in der Informatik (und Mathematik), das in ganz unterschiedlichen Anwendungsbereichen zum Einsatz kommt.

Mathematisch: G = (V, E)

V = {WO, KR-FR, ..., SP, ...} ist die Menge der Knoten.

E = {{WO, KR-FR}, ... {SP, HO}, ...} ist die Menge der Kanten.

Page 8: Graphen und ihre Verarbeitung

8 Graph-Editor

siehe: http://www.yworks.com/en/products_yed_about.html

Page 9: Graphen und ihre Verarbeitung

9 Graphen in Anwendungssituationen

Aufgabe

(a) Wie sind die Verbindungslinien zwischen den Fährhäfen hier zu deuten? Warum beschreiben sie nicht die tatsächlichen Schifffahrsrouten? Warum reicht hier eine abstrahierende Darstellung der Fährverbindungen?

(b) Man möchte zusätzlich die Streckenlängen der Fährverbindungen angeben. Wie könnte man solche Informationen in der gezeigten Darstellung integrieren?

siehe auch: http://www.ferrylines.com/de/europaeisches-buchungsportal-fuer-faehren/

Page 10: Graphen und ihre Verarbeitung

10 Graphen in Anwendungssituationen

Aufgabe

Wie kommt man über Land von Deutschland nach Finnland? Wie viele Ländergrenzen muss man dabei mindestens passieren?

(a) Der (noch unfertige Graph) zeigt Deutschland und seine Nachbarländer. Trage erst einmal sämtliche noch fehlenden Nachbarländer in die bereits vorgegebenen Knoten ein.

(b) Wie würde man die Kanten in der gezeigten Darstellung deuten?

(c) Erweitere das Diagramm um die Nachbarländer von Polen usw., bis du das oben beschriebene Problem mit Hilfe des Graphen lösen kannst.

(d) Wie kommt man über Land von Finnland nach Irland? Wie würde man das am Graphen erkennen?

siehe auch: http://moritz.stefaner.eu/projects/relation-browser/relationViewer.swf

Page 11: Graphen und ihre Verarbeitung

11 Graphen in Anwendungssituationen

Aufgabe

In Königsberg (heute Kaliningrad) teilt der Fluss Pregel die Stadt in mehrere Stadtteile auf. Der Stadtplan hebt die Brücken hervor, die die Stadtteile miteinander verbinden. Der Mathematiker Euler beschäftigte sich mit der Frage, ob es einen Rundgang durch Königsberg gibt, der jede der sieben Brücken über den Fluss Pregel genau einmal benutzt.

(a) Versuche erst einmal, das Problem von Euler zu lösen.

(b) Der folgende Graph zeigt die Brückensituation in Königsberg in einer abstrahierenden Darstellung. Was stellen die Knoten des Graphen, was die Kanten dar?

(c) Wie viele Kanten gehen von den jeweiligen Knoten aus? Was hat das mit der Lösung des Problems von Euler zu tun?

Page 12: Graphen und ihre Verarbeitung

12 Graphen in Anwendungssituationen

Aufgabe

(a) Beschreibe die Struktur des folgenden (siehe rechts Mitte) wer-kennt-wen-Netzwerks mit Hilfe eines Graphen.

(b) Noch ein soziales Netzwerk (siehe rechts unten). Wie würde man hier die Vernetzungungsstruktur darstellen?

(c) Bist du Mitglied in einem sozialen Netzwerk? Wie hoch ist dein Mitgliedsbeitrag? Nimm Stellung zu folgender Aussage: "Die Mitglieder zahlen mit ihren Daten."

An: Daniel

Hallo Daniel, Rebekka hat dich als Freund/Freundin auf ... hinzugefügt. Wir benötigen deine Bestätigung, dass du Rebekka kennst, damit ihr Freunde/Freundinnen auf ... sein könnt.

Viele Grüße vom ...

Rebekka kennt Daniel, Florian, Lisa, Greta, Sophie, Maria

Daniel kennt Tim, Rebekka, Jonas

Florian kennt Rebekka, Sophie

Lisa kennt Rebekka, Sophie, Jonas

Greta kennt Rebekka, Sophie, Tim

Sophie kennt Rebekka, Florian, Lisa, Greta

Maria kennt Rebekka

Tim kennt Daniel, Greta

Jonas kennt Daniel, Lisa

Martin kennt Markus

Markus kennt MartinAnna liebt Ben

Ben liebt Clara

Clara liebt Daniel

Daniel liebt Anna

Page 13: Graphen und ihre Verarbeitung

13 Graphen in Anwendungssituationen

Aufgabe

Zum Nudelkochen im Ferienlager werden genau 2 Liter Wasser benötigt. Zum Abmessen stehen nur ein kleiner Eimer, der 3 Liter fasst, und einen etwas größerer Eimer, der 4 Liter fasst, zur Verfügung. Kann das funktionieren?

Um systematisch alle durch Umfüllen erzeugbaren Wassermengen zu bestimmen, kann man einen Zustandsgraphen erstellen. Die Knoten des Graphen sind die aktuellen Füllinhalte der beiden Eimer. Die Kanten des Graphen stellen die Umfüllvorgänge dar.

Vervollständige den bereits begonnenen Graphen. Ermittle mit diesem Graphen verschiedene Möglichkeiten, eine 2-Liter-Wassermenge durch Umfüllen zu erzeugen.

Page 14: Graphen und ihre Verarbeitung

14 Graphen in Anwendungssituationen

Aufgabe

Am Flussufer befinden sich ein Wolf, eine Ziege, ein Kohlkopf und ein Fährmann. Der Fährmann soll Wolf, Ziege und Kohlkopf auf die andere Seite des Flusses bringen. Er kann aber immer nur einn der drei mit an das andere Ufer nehmen und muss die beiden anderen so lange allein lassen. Da nun der Wolfe gerne die Ziege frisst und die Ziege auf den Kohlkopf scharf ist, kann der Fährmann diese Paarungen nicht allein lassen. Kann der Fährmann das Transportproblem lösen?

Versuche, das Transportproblem systematisch zu lösen, indem du den bereits begonnenen Transport-Graphen vervollständigst.

Page 15: Graphen und ihre Verarbeitung

15 Graphenterminologie

Je nach Anwendung ist es sinnvoll, Kanten gerichtet oder ungerichtet zu modellieren. Bei gerichteten Graphen werden in der Regel auch sog. Schlingen zugelassen. Werden die Kanten mit zusätzlichen Gewichten versehen, so spricht man von gewichteten oder bewerteten Graphen.

A

B

C

D

E

F

G H

A

B

C

D

E

F

G H

128

17

11

5

3

5

68

gerichteter, unbewerteter Graph

ungerichteter, bewerteter Graph

Page 16: Graphen und ihre Verarbeitung

16 Graphenterminologie

In einem Multigraphen können Knoten über mehrere Kanten miteinander verbunden werden.

Multigraph

Page 17: Graphen und ihre Verarbeitung

17 Graphenterminologie

Ist in einem gerichteten Graphen ein Knoten über eine Kante mit einem anderen Knoten verbunden, so heißen dieser andere knoten Nachbar des Ausgangsknoten. In ungerichteten Graphen sind zwei Knoten Nachbarn, wenn sie über eine Kante miteinander verbunden sind.

Ein Knoten, der keine Nachbarn hat, wird auch isolierter Knoten genannt.

Ein Weg innerhalb eines Graphen ist eine Folge von Knoten des Graphen, die sukzessive über eine Kante miteinander verbunden sind.

Ein einfacher Weg ist ein Weg, in dem - außer gegebenenfalls Startknoten und Endknoten - kein Knoten mehrfach vorkommt.

Ein einfacher Weg heißt Kreis oder Zyklus, wenn der Startknoten des Weges gleichzeitig Endknoten ist.

Page 18: Graphen und ihre Verarbeitung

18 Übungen

Aufgabe

(a) Welche Nachbarn hat Knoten 1 (Knoten 2) im Beispielgraphen?

(b) Gibt es im Beispielgraphen einen isolierten Knoten?

(c) Verdeutliche am Beispielgraphen den Weg [1,4,1,3,2,2].

(d) Gib einen möglichst langen Weg im Beispielgraphen an.

(e) Gib es Kreise im Beispielgraphen? Wenn ja, welche?

Page 19: Graphen und ihre Verarbeitung

19 Übungen

Aufgabe

"Die Leute vom Planeten Chator schreiben gern Schlechtes übereinander.Wer vielen über andere Schlechtes schreibt, gilt als besonders charmant. Aber natürlich nur, wenn die Kompromittierten nichts davon erfahren. Chatonen schreiben nur an Leute, die ihnen sympathisch sind. Doch die können den Tratsch weitertragen, und eventuell genau an den Falschen. Ein Chatone muss also gut aufpassen, dass er keinen Charmefehler macht. Dieses Missgeschick passierte unlängst Ator, als er Btor Schlechtes über Dtor schrieb. Zu dumm: Dtor ist dem Ctor sympathisch, der wiederum Btor sympathisch ist. Und so landete der Tratsch bei Dtor, der über Ator verständlicherweise sehr verärgert war. Dies hätte Ator mit ein wenig Übersicht vermeiden können, denn schließlich wissen alle Chatonen voneinander, wer wem sympathisch ist." (Quelle: Bundeswettbewerb Informatik 2004/2005 - 1. Runde)

(a) Stelle die Sympathiebeziehungen der Chatonen mit einem gerichteten Graphen dar.

(b) Welches Problem muss hier gelöst werden. Beschreibe es mit Hilfe der Graphenterminologie.

Page 20: Graphen und ihre Verarbeitung

20 Teil 2

Implementierung von Graphen

Page 21: Graphen und ihre Verarbeitung

21 Graphen als Daten

Darstellen

Verarbeiten

def sucheWeg(graph, start, ziel): ... return ...

>>> sucheWeg(g, 'A', 'C')['A', 'B', 'C']

Deuten

>>> g =

Page 22: Graphen und ihre Verarbeitung

22 Graphen als Daten

Darstellen

>>> g =

Aufgabe

Betrachte den folgenden (gerichteten) Graphen. Wie könnte man diesen Graphen in Tabellenform / mit Hilfe von Listen beschreiben? Entwickle hierzu selbst Ideen.

Page 23: Graphen und ihre Verarbeitung

23 Nachbarschaftstabelle

Sämtliche Informationen eines Graphen lassen sich in einer Nachbarschaftstabelle darstellen.

Adjazenzmatrix

A

B

C

D

0

0

1

0

A

1

1

1

0

B

0

1

0

0

C

0

1

0

0

D

0

0

1

0

1

1

1

0

0

1

0

0

0

1

0

0

knotenliste = ['A', 'B', 'C', 'D']kantenmatrix = [[0, 1, 0, 0],[0, 1, 1, 1],[1, 1, 0, 0],[0, 0, 0, 0]]testgraph = (knotenliste, kantenmatrix)

Kantenmatrix

Nachbarschaftstabelle

Darstellen

Page 24: Graphen und ihre Verarbeitung

24 Nachbarschaftstabelle

Aufgabe:

(a) (einfach) Entwickle eine Funktion existiertKante(graph, vonKnoten, nachKnoten), die überprüft, ob es eine Kante zwischen den übergebenen Knoten gibt. Ein möglicher Testfall sollte so verlaufen:

Tipp: Mit knotenliste.index('A') kann man den Index des übergebenen Bezeichners in der Knotenliste bestimmen.

>>> existiertKante(testgraph, 'A', 'D')False

(b) (etwas schwieriger) Entwickle eine Funktion getAlleNachbarn(graph, knoten), die sämtliche Nachbarn eines vorgegebenen Knotens ermittelt. Ein möglicher Testfall sollte so verlaufen:>>> getAlleNachbarn(testgraph, 'B')['B', 'C', 'D']

Page 25: Graphen und ihre Verarbeitung

25 Nachbarschaftslisten

Sämtliche Informationen eines Graphen lassen sich in einer Nachbarschaftstabelle darstellen.

A:

B:

C:

D:

B

B

B

C

1

D

0

testgraph = \[ ['A', ['B']], ['B', ['B', 'C', 'D']], ['C', ['A', 'B']], ['D', []]]

Nachbarschaftslisten

Darstellen

Adjazenzlisten

Page 26: Graphen und ihre Verarbeitung

26 Nachbarschaftslisten

Aufgabe:

(a) (einfach) Entwickle eine Funktion getAlleNachbarn(graph, knoten), die sämtliche Nachbarn eines vorgegebenen Knotens ermittelt. Ein möglicher Testfall sollte so verlaufen:

>>> existiertKante(testgraph, 'A', 'D')False

(b) (etwas schwieriger) Entwickle eine Funktion existiertKante(graph, vonKnoten, nachKnoten), die überprüft, ob es eine Kante zwischen den übergebenen Knoten gibt. Ein möglicher Testfall sollte so verlaufen:

>>> getAlleNachbarn(testgraph, 'B')['B', 'C', 'D']

Aufgabe:

(c) (offen) Entwickle weitere Funktionen zur Verwaltung und Verarbeitung von Graphen, z.B.:

addKnoten(...) # fügt einen neuen Knoten hinzudelKnoten(...) # löscht einen KnotenaddKante(...) # fügt eine neue Kante hinzu...

Page 27: Graphen und ihre Verarbeitung

27 Graph als Objekt

Bisher wurde gezeigt, dass man Graphen auf unterschiedliche Weise mit Hilfe elementarer Datenstrukturen repräsentieren kann. Für die Verarbeitung von Graphen ist die gewählte Darstellung durchaus wichtig. Noch wichtiger ist es aber, über geeignete Operationen zur Verwaltung und Veränderung von Graphen zu verfügen, die - unabhängig von der zu Grunde liegenden Darstellung - die erforderiche Verarbeitung der Daten durchführen. Günstig ist es, hier objektoerientiert vorzugehen und eine Klasse Graph zu konzipieren, die die benötigten Operationen bereitstellt.

Page 28: Graphen und ihre Verarbeitung

28 Modellierung der Klasse Graph

Ein Objekt der Klasse Graph soll die Knoten und Kanten eines Graphen verwalten.

Zum einen soll es geeignete Operationen bereit stellen, um einen Graphen aufzubauen und zu verändern. Mit diesen Operationen soll man z.B. neue Knoten hinzufügen oder bereits vorhandene Knoten entfernen können.

Zum anderen soll es Operationen bereit stellen, um an Informationen über den Graphen zu gelangen. So soll man mit einer geeigneten Operation ermitteln können, ob es den Knoten ... gibt oder ob es eine Kante von Knoten ... zu Knoten ... gibt.

Aufgabe:

Erstelle zunächst eine Liste mit den Operationen, die ein Objekt der Klasse Graph zur Verfügung stellen sollte.

Ergänze dann das Klassendiagramm. Beschreibe die gewünschten Operationen möglichst genau.

Page 29: Graphen und ihre Verarbeitung

29 Implementierung der Klasse Graph

Aufgabe:

Ergänze die Implementierung der Klasse Graph. Du kannst auch eine Nachbarschaftstabelle zur Repräsentation des Graphen benutzen.

Teste natürlich auch deine Implementierung der Klasse Graph.

class Graph(object): def __init__(self): self.knotenMitNachbarn = []

def getAlleKnoten(self): knotenListe = [] for eintrag in self.knotenMitNachbarn: knotenListe = knotenListe + [eintrag[0]] return knotenListe

def existiertKnoten(self, nameKnoten): if nameKnoten in self.getAlleKnoten(): return True else: return False # ...

Page 30: Graphen und ihre Verarbeitung

30 Nutzung der Klasse Graph

Das Testprogramm unten zeigt, wie man eine (gegebene) Implementierung der Klasse Graph nutzen kann.

from graph import *# Erzeugung des Graph-Objektsg = Graph()# Hinzufügen von Knoten und Kanteng.addKnoten('A')g.addKnoten('B')g.addKante('A', 'B')# Ausgabe der Nachbarschaftslistenfor knoten in g.getAlleKnoten(): print(knoten, ':', g.getAlleNachbarn(knoten))

Aufgabe:

Nutze die Implementierung der Klasse Graph, um den Graphen in der Abbildung zu erstellen.

Nimm anschließend folgende Veränderungen am Graphen vor und kontrolliere die Ergebnisse: (1) Kante von B nach C löschen (2) Kante von C nach B löschen (3) Kante von C nach C hinzufügen (4) Knoten B löschen (5) Knoten C löschen

Page 31: Graphen und ihre Verarbeitung

31 Erweiterung der Klasse Graph

Erweiterung: Verwaltung zusätzlicher DatenZunächst einmal sind hier alle Kanten mit Gewichten versehen. Die Zahlen an den Kanten repräsentieren die Entfernung zwischen den Autobahnknotenpunkten.

An einer der Kanten ist zusätzlich die Autobahnbezeichnung eingetragen. Auch diese Information ist für praktische Anwendungen oft wichtig.

Interessant könnten auch die Geo-Koordinaten von Autobahnknotenpunkten sein. Diese würde man benötigen, wenn eine Darstellung auf einer Landkarte angestrebt würde. An einem der Knoten sind solche zusätzlichen Geo-Informationen eingetragen.

Page 32: Graphen und ihre Verarbeitung

32 Erweiterung der Klasse Graph

Erweiterung: Speicherung der Daten in einer externen DateiDie Daten von Graphen werden während der Verarbeitung von einem Objekt der Klasse Graph verwaltet. Nach der Verarbeitung (wenn das Programm beendet ist) wird das Objekt vernichtet. Danach sind sämtliche Daten des verwalteten Graphen nicht mehr zugänglich. Wünschenswert ist eine Möglichkeit, die Daten eines Graphen in einer externen Datei abspeichern zu können und Daten einer externen Datei wieder einlesen zu können.

Als externes Speicherformat benutzen wir im Folgenden GraphML, ein XML-basiertes Standardformat zur Repräsentation von Graphen.

<?xml version="1.0" encoding="iso-8859-1"?><graph id="bundesautobahnen Lu Ma"><!--Knoten--><node id="Kreuz Frankenthal"> <data key="lat">49.5534891</data> <data key="lon">8.3199207</data></node>...<!--Kanten--><edge source="Kreuz Frankenthal" target="Viernheimer Dreieck"> <data key="A">A 6</data> <data key="entfernung">19</data></edge>...</graph>

Page 33: Graphen und ihre Verarbeitung

33 Erweiterung der Klasse Graph

Die Klasse Graph wird um geeignete Operationen erweitert.

Page 34: Graphen und ihre Verarbeitung

34 Erweiterung der Klasse Graph

Aufgabe

Teste die erweiterte Klasse mit den Daten zum Autobahnnetz (siehe inf-schule).

Aufgabe

Teste die Klasse GraphMitDaten. Erzeuge ein Objekt, mit dem der folgende gewichtete Graph verwaltet wird. Die Daten des Graphen sollen auch in einer externen Datei gespeichert werden.

Page 35: Graphen und ihre Verarbeitung

35 Teil 3

Kürzeste Wege in Graphen

Page 36: Graphen und ihre Verarbeitung

36 Das Problem

Viele Wege führen vom Kreuz Frankenthal zum Kreuz Heidelberg. Aber welcher dieser Wege ist der kürzeste?

allgemein:Gegeben ist ein (gerichteter oder ungerichtetet, gewichteter) Graph. Gegeben ist zusätzlich ein Start- und ein Zielknoten. Welcher Weg des Graphen vom Startknoten zum Zielknoten ist der kürzeste. Dabei soll die Länge des Weges durch die Summe der Gewichte der Kanten längs des Weges erfasst werden.

Page 37: Graphen und ihre Verarbeitung

37 Ein vereinfachtes Problem

Viele Wege führen vom Kreuz Frankenthal zum Kreuz Heidelberg. Aber welcher dieser Wege benötigt die wenigsten "Hops"?

allgemein:Gegeben ist ein (gerichteter oder ungerichtetet) Graph. Gegeben ist zusätzlich ein Start- und ein Zielknoten. Welcher Weg des Graphen vom Startknoten zum Zielknoten führt über die geringste Anzahl an Zwischenknoten?

Page 38: Graphen und ihre Verarbeitung

38

Lösung des vereinfachten Problems

Im Alltag kommt es gelegentlich vor, dass jemand sagt: "Den kenne ich um mehrere Ecken". Das heißt dann wohl, dass derjenige jemanden kennt, der wiederum jemanden kennt, der ...

Ziel ist es, den "Bekanntheitsabstand" von Adriana zu Betül, Clara, Dominik, ..., Hannah zu bestimmen. Dabei soll direkte Bekanntschaft durch den Bekanntheitsabstand 1 beschrieben werden.

Aufgabe:

Versuche (ohne den Bekanntschaftsgraphen zu zeichnen), die gesuchten Bekannheitsabstände systematisch zu ermitteln. Beschreibe dein Vorgehen.

Adriana kennt Clara, Erik, Greta

Betül kennt Clara, Dominik

Clara kennt Adriane, Dominik, Erik

Dominik kennt Betül, Erik

Erik kennt Dominik, Greta

Fabian kennt Hannah

Greta kennt Dominik, Hannah

Hannah kennt Fabian

Page 39: Graphen und ihre Verarbeitung

39 Lösungsverfahren - Abstand

Page 40: Graphen und ihre Verarbeitung

40 Ein Lösungsverfahren

# Vorbereitungfür alle Knoten knoten des Graphen: knoten.abstand = 'u'startKnoten.abstand = 0füge startKnoten in eine Liste zuVerarbeiten ein (hier grün)

Page 41: Graphen und ihre Verarbeitung

41 Ein Lösungsverfahren

# Verarbeitung der KnotenSOLANGE die Liste zuVerarbeiten nicht leer ist: bestimme ausgewaehlterKnoten aus zuVerarbeiten entferne ausgewaehlterKnoten aus zuVerarbeiten (hier blau) für alle Nachbarn nachbarKnoten von ausgewaehlterKnoten: wenn nachbarKnoten.abstand == 'u': füge nachbarKnoten in die Liste zuVerarbeiten ein nachbarKnoten.abstand = ausgewaehlterKnoten.abstand + 1

Page 42: Graphen und ihre Verarbeitung

42 Ein Lösungsverfahren

# Verarbeitung der KnotenSOLANGE die Liste zuVerarbeiten nicht leer ist: bestimme ausgewaehlterKnoten aus zuVerarbeiten entferne ausgewaehlterKnoten aus zuVerarbeiten (hier blau) für alle Nachbarn nachbarKnoten von ausgewaehlterKnoten: wenn nachbarKnoten.abstand == 'u': füge nachbarKnoten in die Liste zuVerarbeiten ein nachbarKnoten.abstand = ausgewaehlterKnoten.abstand + 1

Page 43: Graphen und ihre Verarbeitung

43 Ein Lösungsverfahren

# Verarbeitung der KnotenSOLANGE die Liste zuVerarbeiten nicht leer ist: bestimme ausgewaehlterKnoten aus zuVerarbeiten entferne ausgewaehlterKnoten aus zuVerarbeiten (hier blau) für alle Nachbarn nachbarKnoten von ausgewaehlterKnoten: wenn nachbarKnoten.abstand == 'u': füge nachbarKnoten in die Liste zuVerarbeiten ein nachbarKnoten.abstand = ausgewaehlterKnoten.abstand + 1

Page 44: Graphen und ihre Verarbeitung

44 Ein Lösungsverfahren

# Verarbeitung der KnotenSOLANGE die Liste zuVerarbeiten nicht leer ist: bestimme ausgewaehlterKnoten aus zuVerarbeiten entferne ausgewaehlterKnoten aus zuVerarbeiten (hier blau) für alle Nachbarn nachbarKnoten von ausgewaehlterKnoten: wenn nachbarKnoten.abstand == 'u': füge nachbarKnoten in die Liste zuVerarbeiten ein nachbarKnoten.abstand = ausgewaehlterKnoten.abstand + 1

Page 45: Graphen und ihre Verarbeitung

45

Lösungsverfahren - Abstand / Herkunft

Page 46: Graphen und ihre Verarbeitung

46 Algorithmus von MooreALGORITHMUS # von MooreÜbergabedaten: Graph, startKnoten, zielKnoten# Vorbereitung des Graphenfür alle knoten des Graphen: setze abstand auf 'u' setze herkunft auf Nonesetze abstand von startKnoten.abstand auf 0füge startKnoten in eine Liste zuVerarbeiten ein# Verarbeitung der KnotenSOLANGE die Liste zuVerarbeiten nicht leer ist: bestimme einen Knoten ausgewaehlterKnoten aus zuVerarbeiten (z.B. den ersten in der Liste) entferne ausgewaehlterKnoten aus zuVerarbeiten für alle nachbarKnoten von ausgewaehlterKnoten: wenn abstand von nachbarKnoten == 'u': füge nachbarKnoten in die Liste zuVerarbeiten ein (z.B. am Listenende) neuerAbstand = (abstand von ausgewahlterKnoten) + 1 setze abstand von nachbarKnoten auf neuerAbstand setze herkunft von nachbarKnoten auf ausgewaehlterKnotenweglaenge = abstand von zielKnoten# Erzeugung des Weges zum zielKnotenweg = []knoten = zielKnoten SOLANGE knoten != startKnoten und herkunft von knoten != None: weg = [(herkunft von knoten, knoten)] + weg knoten = herkunft von knotenRückgabedaten: (weg, weglaenge)

Page 47: Graphen und ihre Verarbeitung

47 Exkurs "Graph durchlaufen"

Quelle: http://www.matheprisma.uni-wuppertal.de/Module/Graphen/index.htm

{Eingabe: Graph G; Startknoten s des Graphen}

für alle Knoten w      markiere w als nicht besuchtfüge s in eine (zunächst leere) Datenstruktur D ein solange D nicht leer ist      entnimm einen Knoten w aus D      für alle Kanten {w,u}   falls u nicht markiert ist     markiere u    füge u in D ein

{Ausgabe: Markierungen für alle Knoten w von G; ein Knoten ist genau dann als 'besucht' markiert, wenn er üben einen Weg mit s verbindbar ist}

Page 48: Graphen und ihre Verarbeitung

48 Beispiel

S

C

EA

D

B F

markiere alle Knot. als nicht besucht (hier 0) markiere S als besucht (hier 1) füge s in e. Datenstruktur D (hier grün) ein

S

C

EA

D

B F

1

0

0 0

0

00

S

C

EA

D

B F

1

0

0 0

0

00

entnimm einen Knoten w (hier blau) aus D für alle Kanten {w,u} falls u nicht markiert ist     markiere u    füge u in D ein

S

C

EA

D

B F

1

1

0 0

0

01

Vorbereitungsschritt

Wiederholungsschritt

Page 49: Graphen und ihre Verarbeitung

49 Beispiel

S

C

EA

D

B F

1

1

0 0

1

01

entnimm einen Knoten w (hier blau) aus D für alle Kanten {w,u} falls u nicht markiert ist     markiere u    füge u in D ein

S

C

EA

D

B F

1

1

0 0

0

01 S

C

EA

D

B F

1

1

0 0

1

01

S

C

EA

D

B F

1

1

0 0

1

11

S

C

EA

D

B F

1

1

0 0

1

11

S

C

EA

D

B F

1

1

1 0

1

11

Auswahlstrategie

First InFirst Out

-> Breitensuche

Auswahlstrategie

Last InFirst Out

-> Tiefensuche

Page 50: Graphen und ihre Verarbeitung

50 Beispiel

entnimm einen Knoten w (hier blau) aus D für alle Kanten {w,u} falls u nicht markiert ist     markiere u    füge u in D ein

S

C

EA

D

B F

1

1

1 0

1

11

S

C

EA

D

B F

1

1

1 0

1

11

S

C

EA

D

B F

1

1

1 0

1

11

S

C

EA

D

B F

1

1

1 0

1

11

Ergebnis:Von S aus gibt es Wege zu den folgenden Knoten: A, B, C, D, E.

Page 51: Graphen und ihre Verarbeitung

51 Das verallgemeinerte Problem

Gegeben ist ein (gerichteter oder ungerichtetet, gewichteter) Graph. Gegeben ist zusätzlich ein Startknoten (z.B. A) und ein Zielknoten (z.B. C). Welcher Weg des Graphen vom Startknoten zum Zielknoten ist der kürzeste. Dabei soll die Länge des Weges durch die Summe der Gewichte der Kanten längs des Weges erfasst werden.

Page 52: Graphen und ihre Verarbeitung

52 Lösungsverfahren

Aufgabe: Benutze das Simulationsprogramm "Shortest Path Animation", um die Grundidee des Lösungsverfahrens von Dijkstra herauszufinden.

Page 53: Graphen und ihre Verarbeitung

53

Lösungsverfahren - Abstand / Herkunft

Page 54: Graphen und ihre Verarbeitung

54 Ein Lösungsverfahren

# Verarbeitung der KnotenSOLANGE die Liste zuVerarbeiten nicht leer ist: bestimme e. Knoten minKnoten a. zuVerarbeiten mit min. Abstand entferne minKnoten aus zuVerarbeiten (hier blau) für alle Nachbarn nachbarKnoten von minKnoten: wenn nachbarKnoten.abstand == 'u': füge nachbarKnoten in zuVerarbeiten ein nachbarKnoten.abstand = minKnoten.abstand+gewicht((minknoten, nachbarKnoten)) nachbarKnoten.herkunft = minKnoten sonst: wenn nachbarKnoten in zuVerarbeiten liegt: wenn minKnoten.abstand+ gewicht((minknoten, nachbarKnoten)) < nachbarKnoten.abstand: aktualisiere nachbarKnoten.abstand aktualisiere nachbarKnoten.herkunft

Page 55: Graphen und ihre Verarbeitung

55 Algorithmus von DijkstraÜbergabedaten: Graph, startKnoten, zielKnoten# Vorbereitung des Graphenfür alle knoten des Graphen: setze abstand auf 'u' setze herkunft auf Nonesetze abstand von startKnoten.abstand auf 0füge startKnoten in eine Liste zuVerarbeiten ein# Verarbeitung der KnotenSOLANGE die Liste zuVerarbeiten nicht leer ist: bestimme einen Knoten minKnoten aus zuVerarbeiten mit minimalem Abstand entferne minKnoten aus zuVerarbeiten für alle nachbarKnoten von minKnoten: gewicht = Gewicht der Kante von minKnoten zu nachbarKnoten neuerAbstand = (abstand von minKnoten) + gewicht WENN abstand von nachbarKnoten == 'u': füge nachbarKnoten in die Liste zuVerarbeiten ein (z.B. am Listenende) setze abstand von nachbarKnoten auf neuerAbstand setze herkunft von nachbarKnoten auf minKnoten SONST: WENN nachbarKnoten in zuVerarbeiten liegt: WENN abstand von nachbarKnoten > neuerAbstand: setze abstand von nachbarKnoten auf neuerAbstand setze herkunft von nachbarKnoten auf minKnotenweglaenge = abstand von zielKnoten# Erzeugung des Weges zum zielKnotenweg = []knoten = zielKnoten SOLANGE knoten != startKnoten und herkunft von knoten != None: weg = [(herkunft von knoten, knoten)] + weg knoten = herkunft von knoten# Rückgabedaten: (weg, weglaenge)

Page 56: Graphen und ihre Verarbeitung

56 Implementierung des Moore-Alg.

Aufgabe:

Die folgende Implementierung dieses Algorithmus beruht auf einer Darstellung von Graphen mit Nachbarschaftlisten. Sie benutzt eine Reihe von Hilfsfunktionen (siehe inf-schule). Teste zunächst die Hilfsfunktionen. Was leisten sie jeweils?

def existiertKnoten(graph, knoten): # ...

def getAlleKnoten(graph): # ...

def getAlleNachbarn(graph, knoten): # ...

def getAbstand(erweiterterGraph, knoten): # ...

def getHerkunft(erweiterterGraph, knoten): # ... def setAbstand(erweiterterGraph, knoten, wert): # ...

def setHerkunft(erweiterterGraph, knoten, wert): # ...

def initErweiterterGraph(graph, startKnoten): # ...

Page 57: Graphen und ihre Verarbeitung

57 Implementierung des Moore-Alg.def kuerzesterWegMoore(graph, startKnoten, zielKnoten): if existiertKnoten(graph, startKnoten) and existiertKnoten(graph, zielKnoten): # Vorbereitung erweiterterGraph = initErweiterterGraph(graph, startKnoten) zuVerarbeiten = [startKnoten] # Verarbeitung der Knoten while zuVerarbeiten != []: # bestimme einen Knoten ausgewaehlterKnoten aus zuVerarbeiten ausgewaehlterKnoten = zuVerarbeiten[0] # entferne ausgewaehlterKnoten aus zuVerarbeiten zuVerarbeiten = zuVerarbeiten[1:] # bearbeite die Nachbarn von ausgewaehlterKnoten for nachbarKnoten in getAlleNachbarn(graph, ausgewaehlterKnoten): if getAbstand(erweiterterGraph, nachbarKnoten) == 'u': zuVerarbeiten = zuVerarbeiten + [nachbarKnoten] neuerAbstand = getAbstand(erweiterterGraph, ausgewaehlterKnoten)+ 1 erweiterterGraph = setAbstand(erweiterterGraph, nachbarKnoten, neuerAbstand) erweiterterGraph = setHerkunft(erweiterterGraph, nachbarKnoten, ausgewaehlterKnoten) weglaenge = getAbstand(erweiterterGraph, zielKnoten) # Erzeugung des Weges zum zielKnoten weg = [] knoten = zielKnoten while knoten != startKnoten and getHerkunft(erweiterterGraph, knoten) != None: weg = [(getHerkunft(erweiterterGraph, knoten), knoten)] + weg knoten = getHerkunft(erweiterterGraph, knoten) else: weg = [] weglaenge = 'u' return (weg, weglaenge)

Page 58: Graphen und ihre Verarbeitung

58 Implementierung des Moore-Alg.# Erzeugung des Testgraphentestgraph_ohne_gewichte = \[['A', ['C', 'E', 'G']],['B', ['C', 'D']],['C', ['A', 'D', 'E']],['D', ['B', 'E']],['E', ['D', 'G']],['F', ['B', 'D', 'H']],['G', ['D']],['H', ['F', 'G']]]

# Test des Moore-Algorithmusstart = 'A'ziel = 'B'print('kürzester Weg von', start, 'nach', ziel, ':')(weg, laenge) = kuerzesterWegMoore(testgraph_ohne_gewichte, start, ziel)for w in weg: print(w)print('Weglänge:', laenge)

Aufgabe:

Ergänze Ausgaben in der Funktion kuerzesterWegMoore so, dass die Verarbeitung des Graphen Schritt für Schritt (wie in den Abbildungen zum Algorithmus von Moore ) nachvollzogen werden kann. Führe auch weitere Tests der Funktion kuerzesterWegMoore aus.

Page 59: Graphen und ihre Verarbeitung

59 Implementierung des Moore-Alg.

Aufgabe:

Eine weitere Implementierung des Algorithmus von Moore findest du in der Klasse GraphMoore (siehe inf-schule). Objekte der Klasse GraphMoore stellen die Operation kuerzesterWegMoore zur Verfügung, mit der man Wege mit geringster Anzahl von Zwischenknoten in Graphen bestimmen kann. Teste auch diese Implementierung.

from graph_moore import *

# Erzeugung des Graph-Objektsg = GraphMoore()# Erzeugung der Knoten und Kanten aus einer GraphML-Dateidatei = open("graph_ohne_gewichte.xml", "r")xml_quelltext = datei.read()g.graphmlToGraph(xml_quelltext) # Kontrollausgabe des Graphenprint('Graph:')for knoten in g.getAlleKnoten(): print(knoten, ':', g.getAlleNachbarn(knoten))print()# Test des Moore-Algorithmusstart = 'A'ziel = 'B'print('kürzester Weg von', start, 'nach', ziel, ':')(weg, laenge) = g.kuerzesterWegMoore(start, ziel)for w in weg: print(w)print('Weglänge:', laenge)

Page 60: Graphen und ihre Verarbeitung

60 Implementierung des Dijkstra-Alg.

Aufgabe:

Mit den Hilfsfunktionen initErweiterterGraph, getAbstand, getHerkunft, setAbstand, setHerkunft, ... lässt sich auch der Algorithmus von Dijkstra implementieren. Du kannst dich an der Implementierung des Algorithmus von Moore orientieren. Zum Testen kannst du das folgende Testprogramm nutzen und variieren.

# Erzeugung des Testgraphentestgraph_mit_gewichten = \[['A', [('C', 20), ('E', 2), ('G', 9)]],['B', [('C', 1), ('D', 8)]],['C', [('A', 20), ('D', 10), ('E', 13)]],['D', [('B', 8), ('E', 16)]],['E', [('D', 16), ('G', 5)]],['F', [('B', 3), ('D', 4), ('H', 5)]],['G', [('D', 2)]],['H', [('F', 5), ('G', 7)]]]

# Test des Dijkstra-Algorithmusstart = 'A'ziel = 'B'print('kürzester Weg von', start, 'nach', ziel, ':')(weg, laenge) = kuerzesterWegDijkstra(testgraph_mit_gewichten, start, ziel)for w in weg: print(w)print('Weglänge:', laenge)

Page 61: Graphen und ihre Verarbeitung

61 Implementierung des Dijkstra-Alg.

Aufgabe:Eine weitere Implementierung des Algorithmus von Dijkstra findest du in der Klasse GraphDijkstra (siehe inf-schule). Objekte der Klasse GraphDijkstra stellen die Operation kuerzesterWegDijkstra zur Verfügung, mit der man kürzeste Wege in gewichteten Graphen bestimmen kann. Teste auch diese Implementierung.

from graph_dijkstra import *

# Erzeugung des Graph-Objektsg = GraphDijkstra()# Erzeugung der Knoten und Kanten aus einer GraphML-Dateidatei = open("graph_mit_gewichten.xml", "r")xml_quelltext = datei.read()g.graphmlToGraph(xml_quelltext) # Kontrollausgabe des Graphenprint('Graph:')for knoten in g.getAlleKnoten(): print(knoten, ':', g.getAlleNachbarn(knoten))print()# Test des Dijkstra-Algorithmusstart = 'A'ziel = 'B'print('kürzester Weg von', start, 'nach', ziel, ':')(weg, laenge) = g.kuerzesterWegDijkstra(start, ziel)for w in weg: print(w)print('Weglänge:', laenge)

Page 62: Graphen und ihre Verarbeitung

62

Routenplanung mit dem Dijkstra-Alg.

Aufgabe:

Zunächst betrachten wir das vereinfachte Autobahnnetz rund um Ludwigshafen und Mannheim.

Benutze die Implementierung des Algorithmus von Dijkstra, um den kürzesten Weg vom Kreuz Frankenthal zum Kreuz Heidelberg zu ermitteln. Die Daten zum Autobahnnetz findest du in der Datei graph_bab_lu_ma.xml (siehe inf-schule).

Page 63: Graphen und ihre Verarbeitung

63

Routenplanung mit dem Dijkstra-Alg.

Aufgabe:

Benutze die Daten zum Autobahnnetz in Deutschland, um den kürzesten Weg vom 'KREUZ FRANKENTHAL' zum 'KREUZ HEIDELBERG' bzw. von 'TRIER - VERTEILERKREIS (A 602)' nach 'KREUZ MÜNCHEN - WEST' zu bestimmen. Vergleiche die Ergebnisse auch mit denen, die ein professioneller Routenplaner liefert.

Die Daten zum Autobahnnetz findest du in der Datei graph_bab.xml (siehe inf-schule).Quelle:http://de.wikipedia.org/wiki/Autobahn_%28Deutschland%29Autor der Karte: M. Stadthaus

Page 64: Graphen und ihre Verarbeitung

64

Routenplanung mit dem Dijkstra-Alg.

Aufgabe:

Teste auch die GUI-Version des Routenplanerprogramms (siehe inf-schule).

Vergleiche auch die vom Simulationsprogramm gelieferten Daten auch mit den Ergebnissen realer Routenplaner.

Page 65: Graphen und ihre Verarbeitung

65

Routenplanung mit dem Dijkstra-Alg.

Aufgabe:

Die Bestimmung kürzester Wege mit dem Algorithmus von Dijstra in der bisher gezeigten Form dauert bei einer großen Datebasis sehr lange. Woran liegt das? Entwickle Ideen, wie man den Suchaufwand verringern könnte. Versuche eventuell auch, diese Ideen umzusetzen.

Page 66: Graphen und ihre Verarbeitung

66

Routenplanung mit dem Dijkstra-Alg.

Aufgabe:

Die Aufbereitung der Ergebnisse (Auflistung der Stationen der Route) kann ebenfalls noch verbessert werden.

('TRIER - VERTEILERKREIS (A 602)', 'TRIER - EHRANG (A 602)') ('A 602', 5.0)('TRIER - EHRANG (A 602)', 'TRIER - RUWER (A 602)') ('A 602', 2.0)('TRIER - RUWER (A 602)', 'SCHWEICH (A 602)') ('A 602', 2.0)('SCHWEICH (A 602)', 'DREIECK MOSELTAL') ('A 602', 1.0)('DREIECK MOSELTAL', 'MEHRING (A 1)') ('A 1', 8.0)('MEHRING (A 1)', 'REINSFELD (A 1)') ('A 1', 14.0)('REINSFELD (A 1)', 'HERMESKEIL (A 1)') ('A 1', 2.0)('HERMESKEIL (A 1)', 'BIERFELD (A 1)') ('A 1', 7.0)('BIERFELD (A 1)', 'DREIECK NONNWEILER') ('A 1', 2.0)('DREIECK NONNWEILER', 'OTZENHAUSEN (A 62)') ('A 62', 0.3)('OTZENHAUSEN (A 62)', 'NOHFELDEN - TÜRKISMÜHLE (A 62)') ('A 62', 8.0)('NOHFELDEN - TÜRKISMÜHLE (A 62)', 'BIRKENFELD (A 62)') ('A 62', 6.0)('BIRKENFELD (A 62)', 'FREISEN (A 62)') ('A 62', 9.0)('FREISEN (A 62)', 'REICHWEILER (A 62)') ('A 62', 4.0)('REICHWEILER (A 62)', 'KUSEL (A 62)') ('A 62', 7.0)('KUSEL (A 62)', 'GLAN - MÜNCHWEILER (A 62)') ('A 62', 9.0)('GLAN - MÜNCHWEILER (A 62)', 'HÜTSCHENHAUSEN (A 62)') ('A 62', 6.0)('HÜTSCHENHAUSEN (A 62)', 'KREUZ LANDSTUHL - WEST') ('A 62', 3.0)...

Page 67: Graphen und ihre Verarbeitung

67 Teil 4

Rundreisen in Graphen

Page 68: Graphen und ihre Verarbeitung

68 Das Problem

Wenn ein neuer Außenminister im Amt ist, dann versucht er (oder sie), möglichst rasch Antrittsbesuche bei den wichtigsten Bündnispartnern zu machen. Zu diesen Partner gehören natürlich auch die Länder der Europäischen Union (EU).

Wir werden hier folgende Situation durchspielen: Nach einer Bundestagswahl soll der neue Außenminister alle Hauptstädte der EU besuchen. Die Reihenfolge soll sich nicht nach der Bedeutung der Länder oder anderen Kriterien richten. Sie soll so gewählt werden, dass der gesamte Reiseweg für den Minister möglichst gering wird.

Page 69: Graphen und ihre Verarbeitung

69 Das Problem

Als Willy Brand 1966 Außenminister wurde, bestand die EU (damals EWG) aus nur 6 Ländern: Deutschland, Frankreich, Italien, Niederlande, Belgien und Luxemburg. Die Tabelle zeigt die Entfernungen der jeweiligen Hauptstädte.

Bonn Paris Rom Den Ha. Brüssel Luxemb.Bonn 0 401 1066 244 195 145Paris 401 0 1108 383 262 287Rom 1066 1108 0 1289 1174 989Den Ha. 245 383 1289 0 137 302Brüssel 195 262 1174 137 0 187Luxemb. 145 287 989 302 187 0

Aufgabe:Versuche, eine möglichst kurze Rundreise mit Start- und Zielort Bonn zu finden. Bestimme auch die Gesamtlänge der Rundreise.

Page 70: Graphen und ihre Verarbeitung

70 Das Problem

Die EU (bzw. EWG bzw. EG) ist seit ihrer Gründung 1957 mehrfach erweitert worden. Zu Beginn bestand sie aus 6 Mitgliedsstaaten. Diese 6-er-Gemeinschaft ist 1973 zu einer 9-er-Gemeinschaft, 1981 bis 1986 zu einer 12-er-Gemeinschaft, 1995 zu einer 15-er-Gemeinschaft, 2004 zu einer 25-er-Gemeinschaft und 2007 zu einer 27-er-Gemeinschaft gewachsen. Weitere Staaten warten auf den baldigen Beitritt zu dieser Gemeinschaft.

Aufgabe:Welche Schwierigkeiten sind bei der Bestimmung der kürzesten Rundreise zu erwarten?

Page 71: Graphen und ihre Verarbeitung

71 Ein einfacher Lösungsalgorithmus

Idee:

Erzeuge alle möglichen Rundreisen und bestimme jeweils die Länge der Rundreise. Ermittle aus den erzeugten Längenwerten die optimale Route.

Aufgabe:

Teste das beschriebene Verfahren mit dem Simulationsprogramm (siehe inf-schule) und bestimme den kürzesten Rundweg bei den vorgegebenen Hauptstädten.

Page 72: Graphen und ihre Verarbeitung

72 Ein einfacher Lösungsalgorithmus

Idee:

Erzeuge alle möglichen Rundreisen und bestimme jeweils die Länge der Rundreise. Ermittle aus den erzeugten Längenwerten die optimale Route.

ALGORITHMUS RundreisestartRouteOhneStartKnoten = Liste aller Knotennamen ohne den startKnotenstartRoute = [startKnoten] + startRouteOhneStartKnoten + [startKnoten]routeOhneStartKnoten = Kopie von startRouteOhneStartKnotenroute = startRouteminLaenge = Länge von routeminRoute = routeendePermutationen = Falsewhile not endePermutationen: routeOhneStartKnoten = naechste_permutation(routeOhneStartKnoten) route = [startKnoten] + routeOhneStartKnoten + [startKnoten] if self.laenge(route) < minLaenge: minLaenge = self.laenge(route) minRoute = route endePermutationen = (routeOhneStartKnoten == startRouteOhneStartKnoten)

Page 73: Graphen und ihre Verarbeitung

73 Erzeugung von Permutationendef naechste_permutation(L): # best. max. Index i mit L[i] < L[i+1] i = len(L)-2 gefunden = False while not gefunden: if i < 0: gefunden = True else: if L[i] < L[i+1]: gefunden = True else: i = i-1 if i >= 0: # best. max. Index j mit L[j] > L[i] j = i+1 m = j while j < len(L)-1: j = j+1 if L[j] > L[i]: m = j j = m ...

... # vertausche L[i] und L[j] h = L[i] L[i] = L[j] L[j] = h # kehre Restliste ab Position i+1 um i = i+1 j = len(L)-1 while i < j: h = L[i] L[i] = L[j] L[j] = h i = i+1 j = j-1 else: # Liste ist absteigend sortiert # kehre Liste um i = 0 j = len(L)-1 while i < j: h = L[i] L[i] = L[j] L[j] = h i = i+1 j = j-1 return L

Page 74: Graphen und ihre Verarbeitung

74 Erzeugung von Permutationen

Aufgabe:

Teste die Funktion naechste_permutation durch Funktionsaufrufe wie die folgenden. Versuche auch zu verstehen, wie die jeweils nächste Permutation gebildet wird.>>> naechste_permutation(['A', 'B', 'C', 'D', 'E'])['A', 'B', 'C', 'E', 'D']>>> naechste_permutation(['A', 'B', 'C', 'E', 'D'])['A', 'B', 'D', 'C', 'E']

Aufgabe:

Entwickle ein Testprogramm, mit dem man ermitteln kann, wie viele verschiedene Permutationen bei einer Liste mit 5 (bzw. 6, ...) verschiedenen Elementen möglich sind.

Page 75: Graphen und ihre Verarbeitung

75

Suche nach der kürzesten Rundreisen

from graph import *

def naechste_permutation(L): # siehe oben

def laenge(g, rundreise): weglaenge = 0 anzahlKnoten = len(rundreise) i = 1 while i < anzahlKnoten: weglaenge = weglaenge + float(g.getGewichtKante(rundreise[i-1], rundreise[i])) i = i+1 return weglaenge def minRundreise(g, startKnoten): # siehe nächste Seite

# Erzeugung des Graph-Objektsg = GraphMitDaten()# Erzeugung der Knoten und Kanten aus einer GraphML-Dateidatei = open("graph_eu_6.xml", "r")xml_quelltext = datei.read()g.graphmlToGraph(xml_quelltext) # Test des Rundreise-Algorithmus(minRoute, minLaenge) = minRundreise(g, 'Bonn')print('Route:', minRoute)print('Länge:', minLaenge)

Page 76: Graphen und ihre Verarbeitung

76

Suche nach der kürzesten Rundreisen

def minRundreise(g, startKnoten): startRouteOhneStartKnoten = [] for knoten in g.getAlleKnoten(): if knoten != startKnoten: startRouteOhneStartKnoten = startRouteOhneStartKnoten + [knoten] startRoute = [startKnoten] + startRouteOhneStartKnoten + [startKnoten] routeOhneStartKnoten = startRouteOhneStartKnoten[:] route = startRoute minLaenge = laenge(g, route) minRoute = route endePermutationen = False while not endePermutationen: routeOhneStartKnoten = naechste_permutation(routeOhneStartKnoten) route = [startKnoten] + routeOhneStartKnoten + [startKnoten] if laenge(g, route) < minLaenge: minLaenge = laenge(g, route) minRoute = route endePermutationen = (routeOhneStartKnoten == startRouteOhneStartKnoten) return (minRoute, minLaenge)

Aufgabe:

Führe das Testprogramm aus. Ändere es auch wie folgt ab: Es sollen alle erzeugten Routen mit ihren Längen ausgegeben werden. Es soll zusätzlich mitgezählt werden, wie viele Routen erzeugt werden (zur Kontrolle: 120).

Bevor du anfängst, bei 27 (bzw. 25) Hauptstädten alle Rundreisen zu erzeugen, berechne erst einmal, wie viele das sind.

Page 77: Graphen und ihre Verarbeitung

77 Aufwandsanalyse

Die Problemgröße wird durch die Anzahl n der Mitgliedsländer der EU (Knoten des Graphen) festgelegt. Je größer n ist, desto größer ist auch der Aufwand zur Berechnung der Problemlösung.

Als Kostenmaß für den Berechnungsaufwand wählen wir die Anzahl der zu erzeugenden und verarbeitenden Rundreisen R(n). Wir gehen dabei davon aus, dass jede zu erzeugende und verarbeitende Rundreise in etwa den gleichen Berechnungsaufwand hat.

Für R(n) kann man einen recht einfachen Berechnungsterm entwickeln:

Bei n Knoten gibt es vom Startknoten aus n-1 Möglichkeiten, den nächsten Knoten zu wählen. Von jedem dieser n-1 Knoten gibt es dann noch n-2 Möglichkeiten, den nächsten Knoten zu wählen, usw.. Insgesamt erhält man die folgende Formel:

R(n) = (n-1)*(n-2)*...*2*1 = (n-1)!

0 ! = 11 ! = 12 ! = 23 ! = 64 ! = 245 ! = 1206 ! = 7207 ! = 50408 ! = 403209 ! = 36288010 ! = 362880011 ! = 3991680012 ! = 47900160013 ! = 622702080014 ! = 8717829120015 ! = 130767436800016 ! = 2092278988800017 ! = 35568742809600018 ! = 640237370572800019 ! = 12164510040883200020 ! = 243290200817664000021 ! = 5109094217170944000022 ! = 112400072777760768000023 ! = 2585201673888497664000024 ! = 62044840173323943936000025 ! = 15511210043330985984000000

Page 78: Graphen und ihre Verarbeitung

78 Anwendbarkeit des Algorithmus

Aufgabe:

Man kann recht einfach ermitteln, wie lange ein Rechner zur Erzeugung und Verarbeitung einer Rundreise benötigt: Ergänze hierzu einen Zähler und eine Ausgabe des Zählers nach z.B. 1000 oder 10000 oder 100000 Zählschritten. Aus der grob gemessenen Zeit kann man dann die gesuchte Zeit abschätzen. Wir gehen im folgenden davon aus, dass man für 1000 Rundreisen etwa 1 Sekunde benötigt.

Schätze mit den oben gezeigten Daten ab, wie lange es dauert, bis die kürzeste Rundreise mit dem vorliegenden Algorithmus bei 25 Knoten gefunden ist. Beurteile mit dem Ergebnis die praktische Anwendbarkeit des Algorithmus.

0 ! = 11 ! = 12 ! = 23 ! = 64 ! = 245 ! = 1206 ! = 7207 ! = 50408 ! = 403209 ! = 36288010 ! = 362880011 ! = 3991680012 ! = 47900160013 ! = 622702080014 ! = 8717829120015 ! = 130767436800016 ! = 2092278988800017 ! = 35568742809600018 ! = 640237370572800019 ! = 12164510040883200020 ! = 243290200817664000021 ! = 5109094217170944000022 ! = 112400072777760768000023 ! = 2585201673888497664000024 ! = 62044840173323943936000025 ! = 15511210043330985984000000

Page 79: Graphen und ihre Verarbeitung

79 Näherungsverfahren

Aufgabe:

Überlege dir eine Strategie, wie man "mit Köpfchen" statt der "Holzhammermethode" bei der Suche nach der kürzesten Rundreise vorgehen könnte.

Page 80: Graphen und ihre Verarbeitung

80

Stategie: zum am nächst lieg. Knoten

Aufgabe:

Eine naheliegende Strategie besteht darin, vom jeweils aktuellen Knoten zum am nächst liegenden Knoten zu gehen.

Die Abbildung zeigt die Route, die nach der Strategie "zum am nächst liegenden Knoten" berechnet wurde. Versuche, die Route / Strategie zu bewerten: Gibt es kürzere Routen? Welche Nachteile hat die Strategie?

Page 81: Graphen und ihre Verarbeitung

81

Stategie: Integration entfernter Knoten

In einem ersten Schritt wird die Stadt gesucht, die am weitesten von Berlin entfernt ist. Im vorliegenden Fall ist es die Hauptstadt Nikosia von Zypern. Das Rundreisegerüst besteht jetzt aus Berlin - Nikosia - Berlin.

Page 82: Graphen und ihre Verarbeitung

82

Stategie: Integration entfernter Knoten

In einem nächsten Schritt wird die Stadt gesucht, die zu den Knoten des aktuellen Rundreisegerüsts den größten Abstand hat. Im vorliegenden Fall ist es die Hauptstadt Lissabon von Portugal. Diese Stadt wird jetzt so in das Rundreisengerüst eingebaut, dass das neue Rundreisegerüst eine möglichst geringe Länge hat. Es ergibt sich Berlin - Nikosia - Lissabon - Berlin.

Page 83: Graphen und ihre Verarbeitung

83

Stategie: Integration entfernter Knoten

Es wird die Stadt gesucht, die zu den Knoten des aktuellen Rundreisegerüsts den größten Abstand hat. Im vorliegenden Fall ist es Dublin, die die Hauptstadt von Irland. Diese Stadt wird jetzt so in das Rundreisengerüst eingebaut, dass das neue Rundreisegerüst eine möglichst geringe Länge hat. Es ergibt sich Berlin - Nikosia - Valetta - Lissabon - Dublin - Berlin.

Page 84: Graphen und ihre Verarbeitung

84

Stategie: Integration entfernter Knoten

Wenn man auf diese Weise weiterverfährt, ergibt sich insgesamt die folgende Rundreise.

Aufgabe:

Vergleiche das Ergebnis der Stategie "Integration der am weitesten entfernten Knoten" mit dem Ergebnis der Strategie "zum am nächst liegenden Knoten". Kann man mit Sicherheit behaupten, dass die Strategie "Integration der am weitesten entfernten Knoten" die kürzeste Rundreise liefert?

Page 85: Graphen und ihre Verarbeitung

85

Näherungslösungen statt exakter Lös.

Bei 27 Hauptstädten ist es unmöglich, die exakte Lösung nach der Holzhammer-Methode in der zur Verfügung stehenden Zeit zu bestimmen. In vertretbarem Aufwand (mehrere Stunden) geht das noch bei 12 Hauptstädten. Hier ist dann ein Vergleich der exakten Lösung mit Näherungslösungen möglich.

Methode: zum am nächst lieg. Knoten

Länge der Rundreise: 10444.6

Methode: Integration entfernter Knoten

Länge der Rundreise: 9012.6

Methode: Erzeugung aller Rundreisen

Länge der Rundreise: 8945.1

Page 86: Graphen und ihre Verarbeitung

86 Literaturhinweise

U. Schöning: Ideen der Informatik. Oldenbourg Verlag 2002.

P. Gritzmann, R. Brandenburg: Das Geheimnis des kürzesten Weges. Springer 2002.

Mathe-Prisma: Graphenhttp://www.matheprisma.uni-wuppertal.de/Module/Graphen/index.htm

D. Jonietz: Graphen http://informatik.bildung-rp.de/fileadmin/user_upload/informatik.bildung-rp.de/Weiterbildung/pdf/WB-VIII-6-Graphen.pdf

...

Die Darstellung hier orientiert sich an den Materialien auf den Webseiten:

http://www.inf-schule.de