Powerpoint-Präsentation

Werbung
Graphen und ihre Verarbeitung
Klaus Becker
2010
2
Graphen
3
Teil 1
Vernetzte Strukturen
4
Routenplanung
Typisches Routenproblem:
Wie kommt man am besten mit dem Auto von Worms nach Speyer?
5
Routenplanung mit dem Computer
Modellierungsproblem:
Wie wird das
Verkehrsnetz im
Computer
repräsdentiert?
Berechnungsproblem:
Wie wird die optimale
Route ermittelt?
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:
7
Fachkonzept Graph
Ein Graph besteht aus einer Menge von
Knoten und einer Menge von Kanten (die
jeweils zwei Knoten miteinander verbinden).
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.
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.
8
Graph-Editor
siehe: http://www.yworks.com/en/products_yed_about.html
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/europaeisch
es-buchungsportal-fuer-faehren/
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
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?
12
Graphen in Anwendungssituationen
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 ...
Aufgabe
(a) Beschreibe die Struktur des folgenden
(siehe rechts Mitte) wer-kennt-wenNetzwerks 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."
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 Martin
Anna liebt Ben
Ben liebt Clara
Clara liebt Daniel
Daniel liebt Anna
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-LiterWassermenge durch Umfüllen zu
erzeugen.
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.
Graphenterminologie
15
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.
E
B
E
B
5
12
8
F
A
11
F
A
D
D
17
G
C
gerichteter, unbewerteter Graph
3
H
C
6
8
G
5
ungerichteter, bewerteter Graph
H
16
Graphenterminologie
In einem Multigraphen können Knoten über mehrere Kanten miteinander verbunden werden.
Multigraph
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.
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?
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.
20
Teil 2
Implementierung von Graphen
Graphen als Daten
21
Darstellen
Deuten
Verarbeiten
>>> g =
>>> sucheWeg(g, 'A', 'C')
['A', 'B', 'C']
def sucheWeg(graph, start, ziel):
...
return ...
22
Graphen als Daten
Aufgabe
Betrachte den folgenden (gerichteten) Graphen. Wie könnte man diesen Graphen in
Tabellenform / mit Hilfe von Listen beschreiben? Entwickle hierzu selbst Ideen.
Darstellen
>>> g =
Nachbarschaftstabelle
23
Sämtliche Informationen eines Graphen lassen sich in einer Nachbarschaftstabelle darstellen.
Nachbarschaftstabelle
Darstellen
A
B
C
D
A
0
1
0
0
0
1
0
0
B
0
1
1
1
0
1
1
1
C
1
1
0
0
1
1
0
0
D
0
0
0
0
0
0
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
Adjazenzmatrix
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:
>>> existiertKante(testgraph, 'A', 'D')
False
Tipp: Mit knotenliste.index('A') kann man den Index des übergebenen Bezeichners in der
Knotenliste bestimmen.
(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']
Nachbarschaftslisten
25
Sämtliche Informationen eines Graphen lassen sich in einer Nachbarschaftstabelle darstellen.
Darstellen
Nachbarschaftslisten
Adjazenzlisten
testgraph
[
['A',
['B',
['C',
['D',
]
= \
['B']],
['B', 'C', 'D']],
['A', 'B']],
[]]
A:
B
B:
B
C
D
C:
B
1
0
D:
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:
>>> getAlleNachbarn(testgraph, 'B')
['B', 'C', 'D']
(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:
>>> existiertKante(testgraph, 'A', 'D')
False
Aufgabe:
(c) (offen) Entwickle weitere Funktionen zur Verwaltung und Verarbeitung von Graphen, z.B.:
addKnoten(...)
delKnoten(...)
addKante(...)
...
# fügt einen neuen Knoten hinzu
# löscht einen Knoten
# fügt eine neue Kante hinzu
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.
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.
Implementierung der Klasse Graph
29
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
# ...
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-Objekts
g = Graph()
# Hinzufügen von Knoten und Kanten
g.addKnoten('A')
g.addKnoten('B')
g.addKante('A', 'B')
# Ausgabe der Nachbarschaftslisten
for 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
31
Erweiterung der Klasse Graph
Erweiterung: Verwaltung
zusätzlicher Daten
Zunä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 GeoKoordinaten 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 GeoInformationen eingetragen.
32
Erweiterung der Klasse Graph
Erweiterung: Speicherung
der Daten in einer externen
Datei
Die 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 XMLbasiertes 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>
33
Erweiterung der Klasse Graph
Die Klasse Graph wird um
geeignete Operationen
erweitert.
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.
35
Teil 3
Kürzeste Wege in Graphen
36
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 Startund 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.
Das Problem
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?
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 ...
Adriana kennt Clara, Erik, Greta
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.
Erik kennt Dominik, Greta
Aufgabe:
Versuche (ohne den
Bekanntschaftsgraphen zu
zeichnen), die gesuchten
Bekannheitsabstände systematisch
zu ermitteln. Beschreibe dein
Vorgehen.
Betül kennt Clara, Dominik
Clara kennt Adriane, Dominik, Erik
Dominik kennt Betül, Erik
Fabian kennt Hannah
Greta kennt Dominik, Hannah
Hannah kennt Fabian
39
Lösungsverfahren - Abstand
40
Ein Lösungsverfahren
# Vorbereitung
für alle Knoten knoten des Graphen:
knoten.abstand = 'u'
startKnoten.abstand = 0
füge startKnoten in eine Liste zuVerarbeiten ein (hier grün)
41
Ein Lösungsverfahren
# Verarbeitung der Knoten
SOLANGE 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
42
Ein Lösungsverfahren
# Verarbeitung der Knoten
SOLANGE 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
43
Ein Lösungsverfahren
# Verarbeitung der Knoten
SOLANGE 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
44
Ein Lösungsverfahren
# Verarbeitung der Knoten
SOLANGE 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
45
Lösungsverfahren - Abstand / Herkunft
46
Algorithmus von Moore
ALGORITHMUS # von Moore
Übergabedaten: Graph, startKnoten, zielKnoten
# Vorbereitung des Graphen
für alle knoten des Graphen:
setze abstand auf 'u'
setze herkunft auf None
setze abstand von startKnoten.abstand auf 0
füge startKnoten in eine Liste zuVerarbeiten ein
# Verarbeitung der Knoten
SOLANGE 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 ausgewaehlterKnoten
weglaenge = abstand von zielKnoten
# Erzeugung des Weges zum zielKnoten
weg = []
knoten = zielKnoten
SOLANGE knoten != startKnoten und herkunft von knoten != None:
weg = [(herkunft von knoten, knoten)] + weg
knoten = herkunft von knoten
Rückgabedaten: (weg, weglaenge)
47
Exkurs "Graph durchlaufen"
{Eingabe: Graph G; Startknoten s des Graphen}
für alle Knoten w
markiere w als nicht besucht
fü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}
Quelle: http://www.matheprisma.uni-wuppertal.de/Module/Graphen/index.htm
Beispiel
48
B
0
F
D
C
0
B
D
C
E
A
S
Vorbereitungsschritt
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
0
B
F
D
C
1
0
0
0
0
A
0
0
1
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
Wiederholungsschritt
0
1
B
F
D
C
E
S
0
E
S
0
F
0
E
A
S
0
1
1
A
0
0
Beispiel
49
0
1
B
F
D
C
0
0
0
1
B
D
C
E
S
1
A
S
0
1
B
F
D
C
1
1
1
B
1
1
B
D
C
A
S
0
1
F
D
C
S
0
1
1
0
1
1
A
1
1
Auswahlstrategie
Last In
First Out
-> Tiefensuche
1
0
1
B
F
D
C
E
A
F
E
1
0
0
E
S
1
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
Auswahlstrategie
First In
First Out
-> Breitensuche
1
0
0
E
1
0
F
1
E
A
S
1
1
1
A
1
0
Beispiel
50
1
1
B
F
D
C
1
0
1
1
B
D
C
E
S
F
0
1
E
1
1
A
S
1
1
A
1
1
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
1
1
B
F
D
C
1
1
0
1
1
1
F
D
C
E
S
B
Ergebnis:
Von S aus gibt es Wege zu
den folgenden Knoten:
A, B, C, D, E.
1
E
A
S
1
1
1
A
1
0
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.
52
Lösungsverfahren
Aufgabe: Benutze das Simulationsprogramm "Shortest Path Animation", um die Grundidee des
Lösungsverfahrens von Dijkstra herauszufinden.
53
Lösungsverfahren - Abstand / Herkunft
54
Ein Lösungsverfahren
# Verarbeitung der Knoten
SOLANGE 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
55
Algorithmus von Dijkstra
Übergabedaten: Graph, startKnoten, zielKnoten
# Vorbereitung des Graphen
für alle knoten des Graphen:
setze abstand auf 'u'
setze herkunft auf None
setze abstand von startKnoten.abstand auf 0
füge startKnoten in eine Liste zuVerarbeiten ein
# Verarbeitung der Knoten
SOLANGE 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 minKnoten
weglaenge = abstand von zielKnoten
# Erzeugung des Weges zum zielKnoten
weg = []
knoten = zielKnoten
SOLANGE knoten != startKnoten und herkunft von knoten != None:
weg = [(herkunft von knoten, knoten)] + weg
knoten = herkunft von knoten
# Rückgabedaten: (weg, weglaenge)
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):
# ...
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)
58
Implementierung des Moore-Alg.
# Erzeugung des Testgraphen
testgraph_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-Algorithmus
start = '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.
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-Objekts
g = GraphMoore()
# Erzeugung der Knoten und Kanten aus einer GraphML-Datei
datei = open("graph_ohne_gewichte.xml", "r")
xml_quelltext = datei.read()
g.graphmlToGraph(xml_quelltext)
# Kontrollausgabe des Graphen
print('Graph:')
for knoten in g.getAlleKnoten():
print(knoten, ':', g.getAlleNachbarn(knoten))
print()
# Test des Moore-Algorithmus
start = '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)
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 Testgraphen
testgraph_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-Algorithmus
start = '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)
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-Objekts
g = GraphDijkstra()
# Erzeugung der Knoten und Kanten aus einer GraphML-Datei
datei = open("graph_mit_gewichten.xml", "r")
xml_quelltext = datei.read()
g.graphmlToGraph(xml_quelltext)
# Kontrollausgabe des Graphen
print('Graph:')
for knoten in g.getAlleKnoten():
print(knoten, ':', g.getAlleNachbarn(knoten))
print()
# Test des Dijkstra-Algorithmus
start = '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)
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).
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 infschule).
Quelle:
http://de.wikipedia.org/wiki/Autobahn_%28Deutschland%29
Autor der Karte: M. Stadthaus
64
Routenplanung mit dem Dijkstra-Alg.
Aufgabe:
Teste auch die GUI-Version des
Routenplanerprogramms (siehe infschule).
Vergleiche auch die vom
Simulationsprogramm gelieferten Daten
auch mit den Ergebnissen realer
Routenplaner.
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.
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)
...
67
Teil 4
Rundreisen in Graphen
68
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.
Das Problem
Das Problem
69
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
Bonn
0
Paris
401
Rom
1066
Den Ha. 245
Brüssel 195
Luxemb. 145
Paris
401
0
1108
383
262
287
Rom
1066
1108
0
1289
1174
989
Den Ha.
244
383
1289
0
137
302
Brüssel
195
262
1174
137
0
187
Luxemb.
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.
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-erGemeinschaft, 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?
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.
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 Rundreise
startRouteOhneStartKnoten = Liste aller Knotennamen ohne den startKnoten
startRoute = [startKnoten] + startRouteOhneStartKnoten + [startKnoten]
routeOhneStartKnoten = Kopie von startRouteOhneStartKnoten
route = startRoute
minLaenge = Länge von route
minRoute = route
endePermutationen = False
while not endePermutationen:
routeOhneStartKnoten = naechste_permutation(routeOhneStartKnoten)
route = [startKnoten] + routeOhneStartKnoten + [startKnoten]
if self.laenge(route) < minLaenge:
minLaenge = self.laenge(route)
minRoute = route
endePermutationen = (routeOhneStartKnoten == startRouteOhneStartKnoten)
73
Erzeugung von Permutationen
def 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
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.
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-Objekts
g = GraphMitDaten()
# Erzeugung der Knoten und Kanten aus einer GraphML-Datei
datei = 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)
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.
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 ! = 1
1 ! = 1
2 ! = 2
3 ! = 6
4 ! = 24
5 ! = 120
6 ! = 720
7 ! = 5040
8 ! = 40320
9 ! = 362880
10 ! = 3628800
11 ! = 39916800
12 ! = 479001600
13 ! = 6227020800
14 ! = 87178291200
15 ! = 1307674368000
16 ! = 20922789888000
17 ! = 355687428096000
18 ! = 6402373705728000
19 ! = 121645100408832000
20 ! = 2432902008176640000
21 ! = 51090942171709440000
22 ! = 1124000727777607680000
23 ! = 25852016738884976640000
24 ! = 620448401733239439360000
25 ! = 15511210043330985984000000
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 ! = 1
1 ! = 1
2 ! = 2
3 ! = 6
4 ! = 24
5 ! = 120
6 ! = 720
7 ! = 5040
8 ! = 40320
9 ! = 362880
10 ! = 3628800
11 ! = 39916800
12 ! = 479001600
13 ! = 6227020800
14 ! = 87178291200
15 ! = 1307674368000
16 ! = 20922789888000
17 ! = 355687428096000
18 ! = 6402373705728000
19 ! = 121645100408832000
20 ! = 2432902008176640000
21 ! = 51090942171709440000
22 ! = 1124000727777607680000
23 ! = 25852016738884976640000
24 ! = 620448401733239439360000
25 ! = 15511210043330985984000000
79
Aufgabe:
Überlege dir eine
Strategie, wie man "mit
Köpfchen" statt der
"Holzhammermethode"
bei der Suche nach der
kürzesten Rundreise
vorgehen könnte.
Näherungsverfahren
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?
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.
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.
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.
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?
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
Methode: Integration entfernter Knoten
Methode: Erzeugung aller Rundreisen
Länge der Rundreise: 10444.6
Länge der Rundreise: 9012.6
Länge der Rundreise: 8945.1
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: Graphen
http://www.matheprisma.uni-wuppertal.de/Module/Graphen/index.htm
D. Jonietz: Graphen
http://informatik.bildung-rp.de/fileadmin/user_upload/informatik.bildungrp.de/Weiterbildung/pdf/WB-VIII-6-Graphen.pdf
...
Die Darstellung hier orientiert sich an den Materialien auf den Webseiten:
http://www.inf-schule.de
Herunterladen