Implementierung
Implementierung des Algorithmus von Moore
Hier noch einmal der 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 Schlange zuVerarbeiten ein
# Verarbeitung der Knoten
SOLANGE die Schlange zuVerarbeiten nicht leer ist:
ausgewaehlterKnoten ist das erste Element aus zuVerarbeiten
entferne ausgewaehlterKnoten aus zuVerarbeiten
für alle nachbarKnoten von ausgewaehlterKnoten:
wenn abstand von nachbarKnoten == 'u':
füge nachbarKnoten hinten in die Schlange zuVerarbeiten ein
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)
Die folgende Implementierung dieses Algorithmus beruht auf einer Darstellung von Graphen mit Nachbarschaftlisten.
def existiertKnoten(graph, knoten):
ergebnis = False
for eintrag in graph:
if eintrag[0] == knoten:
ergebnis = True
return ergebnis
def getAlleKnoten(graph):
knotenListe = []
for eintrag in graph:
knotenListe = knotenListe + [eintrag[0]]
return knotenListe
def getAlleNachbarn(graph, knoten):
nachbarListe = []
for eintrag in graph:
if eintrag[0] == knoten:
nachbarListe = eintrag[1]
return nachbarListe
def getAbstand(erweiterterGraph, knoten):
ergebnis = None
for eintrag in erweiterterGraph:
if eintrag[0] == knoten:
ergebnis = eintrag[1]
return ergebnis
def getHerkunft(erweiterterGraph, knoten):
ergebnis = None
for eintrag in erweiterterGraph:
if eintrag[0] == knoten:
ergebnis = eintrag[2]
return ergebnis
def setAbstand(erweiterterGraph, knoten, wert):
erweiterterGraphNeu = []
for eintrag in erweiterterGraph:
if eintrag[0] == knoten:
eintragNeu = [eintrag[0], wert, eintrag[2], eintrag[3]]
erweiterterGraphNeu = erweiterterGraphNeu + [eintragNeu]
else:
erweiterterGraphNeu = erweiterterGraphNeu + [eintrag]
return erweiterterGraphNeu
def setHerkunft(erweiterterGraph, knoten, wert):
erweiterterGraphNeu = []
for eintrag in erweiterterGraph:
if eintrag[0] == knoten:
eintragNeu = [eintrag[0], eintrag[1], wert, eintrag[3]]
erweiterterGraphNeu = erweiterterGraphNeu + [eintragNeu]
else:
erweiterterGraphNeu = erweiterterGraphNeu + [eintrag]
return erweiterterGraphNeu
def initErweiterterGraph(graph, startKnoten):
erweiterterGraph = []
for eintrag in graph:
if eintrag[0] == startKnoten:
eintragNeu = [eintrag[0], 0, None, eintrag[1]]
erweiterterGraph = erweiterterGraph + [eintragNeu]
else:
eintragNeu = [eintrag[0], 'u', None, eintrag[1]]
erweiterterGraph = erweiterterGraph + [eintragNeu]
return erweiterterGraph
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)
# 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 1
(a) Teste zunächst separat die Funktion initErweiterterGraph. Was leistet diese Funktion?
Teste auch die Funktionen getAbstand, getHerkunft,
setAbstand und setHerkunft?
(b) Ergänze Ausgaben in der Funktion kuerzesterWegMoore so, dass die Verarbeitung
des Graphen Schritt für Schritt (wie in den Abbildungen im Abschnitt
Der Algorithmus von Moore)
nachvollzogen werden kann.
(c) Führe weitere Tests der Funktion kuerzesterWegMoore aus.
Aufgabe 2
Eine weitere Implementierung des Algorithmus von Moore findest du in der Klasse GraphMoore
(siehe graph_moore.txt).
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 des Algorithmus von Moore.
Das folgende Testprogramm
verdeutlicht die Verwendung der Klasse GraphMoore
am Demo-Graphen graph_ohne_gewichte.xml.
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)
Implementierung des Algorithmus von Dijkstra
Der Algorithmus von Dijkstra lässt sich so formulieren:
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)
Aufgabe 3
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)
Aufgabe 4
Eine weitere Implementierung des Algorithmus von Dijkstra findest du in der Klasse GraphDijkstra
(siehe graph_dijkstra.txt).
Objekte der Klasse GraphDijkstra stellen die Operation kuerzesterWegDijkstra
zur Verfügung, mit der man Wege mit geringster Anzahl von Zwischenknoten in Graphen bestimmen kann.
Teste auch diese Implementierung des Algorithmus von Dijkstra.
Das folgende Testprogramm
verdeutlicht die Verwendung der Klasse GraphDijkstra
am Demo-Graphen graph_mit_gewichten.xml.
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)