Seminararbeit Tobias Jülg - Laufzeitoptimierung Des Dijkstra

Werbung
Der Dijkstra Algorithmus
Laufzeitoptimierung für den Einsatz in
Navigationssystemen
Seminararbeit am
Ignaz Kögler Gymnasium Landsberg am Lech
Rahmenthema des Wissenschaftspropädeutischen Seminars:
Vermessung und Navigation
Leitfach: Mathematik
von
Tobias Jülg
Kursleiter:
Matthias Müller, OStR
Laufzeitoptimierung des Dijkstra Algorithmus
Inhaltsverzeichnis
1
Einleitung ....................................................................................... 3
2
Der Dijkstra Algorithmus ............................................................... 4
2.1 Einführung in die Graphentheorie ....................................................................... 4
2.2 Überlegungen zur Problemstellung ..................................................................... 5
2.2.1 Der Dijkstra-Algorithmus und dessen Funktionsweise ........................................ 7
3
Wieso sind Änderungen notwendig? ........................................... 9
3.1 Laufzeitbeweis am Quellcode ............................................................................. 9
3.2 Laufzeitversuch mittels eines Java Programms ................................................ 10
4
Laufzeitoptimierung des Dijkstra Algorithmus .......................... 12
4.1 Bidirektionale Suche ......................................................................................... 13
4.2 A* Algorithmus .................................................................................................. 14
4.2.1 Funktionsweise des A* Algorithmus ................................................................. 15
4.3 Contraction Hierarchy ....................................................................................... 16
5
Anwendung in Navigationssystemen ......................................... 18
6
Zusammenfassung ...................................................................... 20
7
Anhänge ....................................................................................... 21
7.1 Bedienung des selbsterstellten Programmes .................................................... 21
7.2 Laufzeitbeweis am Quellcode ........................................................................... 25
8
Abbildungsverzeichnis ................................................................ 26
9
Literaturverzeichnis ..................................................................... 27
10 Erklärung des Verfassers ............................................................ 29
Laufzeitoptimierung des Dijkstra Algorithmus
3
Einleitung
1 EINLEITUNG
Routenplanung ist mittlerweile ein großer Bestandteil unserer heutigen Gesellschaft.
Vor allem im industriellen Sektor sind elektronische Navigationssysteme kaum noch
wegzudenken, da man mit ihnen in sehr kurzer Zeit den optimalsten, also in den
meisten Fällen den effizientesten Pfad von A nach B berechnen kann. Gerade in
unserer heutigen Zeit der Globalisierung ist der Warentransport sehr wichtig.
Innerhalb Europas wird hauptsächlich mit dem Lastkraftwagen oder der Bahn
transportiert. Weltweit fließen die Warenströme dagegen eher über den See- oder
Luftweg.
Hier spielt oft der monetäre Faktor eine große Rolle. Denn durch unnötig lange
Strecken entstehen mehr Kosten für Treibstoff, Personal und die Abnutzung des
Transportmittels. Deshalb ist in der Regel die schnellste Route auch die beste.
Andererseits ist aber auch das Benutzen von großen, ausgebauten Wegen, wie zum
Beispiel einer Autobahn, von Vorteil, da dort auch bei längeren Wegen, durch die
höhere Geschwindigkeit, Zeit eingespart werden kann. Bei größeren Transporten mit
dem Flugzeug kann eine falsche Route dramatische Kostenauswirkungen haben.
Diese Faktoren muss eine Navigationssoftware berücksichtigen. Zusätzlich spielt die
benötigte Laufzeit des Algorithmus auch eine wichtige Rolle. Bei laufenden
Transportprozessen, wie zum Beispiel im LKW-Verkehr, ist es oft durch Staus
erforderlich, schnell eine passende alternative Route zu finden.
Somit liegt es nahe, Navigationsgeräte und dessen Funktionsweise näher zu
analysieren. Dabei stößt man zunächst einmal auf grundlegende aber sehr
interessante Fragen: Wie kann ein Routenplaner überhaupt eine Strecke berechnen?
Und wie ist es möglich, dass die Algorithmen bei einem großen Straßennetz, mit
mehreren Millionen Kreuzungen und entsprechend vielen Weg-Möglichkeiten, das
Ergebnis in wenigen Sekunden finden? Für die Beantwortung dieser Fragen wird in
der Seminararbeit zunächst ein passender Algorithmus gesucht, welcher dann an die
Anforderungen der Straßennavigation angepasst wird. Die dabei verwendeten
Methoden
zur
Laufzeitoptimierung
werden
in
ähnlicher
Weise
auch
bei
professioneller Navigationssoftware verwendet, siehe (OpenStreetMap Wiki 2015,
Abs. 4).
Laufzeitoptimierung des Dijkstra Algorithmus
4
Der Dijkstra Algorithmus
2 DER DIJKSTRA ALGORITHMUS
2.1
EINFÜHRUNG IN DIE GRAPHENTHEORIE
Für die Verwendung von Kartendaten in Navigationsprogrammen, ist es sinnvoll die
Navigationsdaten in ein Format, beziehungsweise Modell zu bringen, mit dem ein
Computer arbeiten kann. Wichtig dabei ist, dass alle Ortsbeziehungen enthalten sind.
Ein mathematischer Graph erfüllt genau diese Anforderungen, deshalb wird dieses
Modell in den meisten Fällen für die Beschreibung von Karten benutzt. Dem
folgenden Inhalt liegen (Gallenbacher 2007, S. 3–7) und (Wikipedia 2015c, Abs.
Betrachteter Gegenstand) zugrunde.
Ein Graph ist eine Art Netzwerk, das aus Knoten besteht, welche die vernetzten
Objekte darstellen und Kanten, welche die Verbindungen der Knoten bilden. Wenn
eine Kante zwischen zwei Knoten besteht, sind diese verbunden und es ist ein
direkter Weg vorhanden. Man muss dabei allerdings zwischen gerichteten und
ungerichteten Graphen unterscheiden. Bei ungerichteten steht eine Kante immer für
eine beidseitige Verbindung. Bei gerichteten Graphen enthält die Kante auch noch
die Eigenschaft der Richtung, somit kann jede Kante nur in eine Richtung genutzt
werden. Bei beidseitigen Verbindungen werden deshalb immer zwei Kanten benötigt.
Das Kantengewicht ist eine Zahl, welche die Wegkosten beschreibt, die notwendig
sind, um über die jeweilige Kante zu reisen. Jede Kante hat ein Gewicht. Bei
gerichteten Graphen kann es vorkommen, dass es zwischen zwei Knoten abhängig
von der Richtung zwei unterschiedliche Gewichte gibt. Falls nicht direkt darauf
hingewiesen wird, werden in dieser Seminararbeit ungerichtete Graphen benutzt. Für
die verwendeten Algorithmen macht das keinen Unterschied, jedoch ist ein
ungericheter Graph leichter zu generieren.
Damit ein Straßennetz in einem Graphen modellieren werden kann, werden
Kreuzungen als Knoten und Straßen als Kanten des Graphen beschrieben, siehe
Bild 2-1. Die Länge einer Straße stellt in der Regel das Kantengewicht dar. Die
Kantenkosten können aber auch Fahrzeit, Verkehr oder Mautgebühren sein,
vergleiche (Velden 2014b, Abs. 1). Würde man gerichtete Graphen verwenden,
könnte man jeweils noch zwischen Einbahn- und normalen Straßen unterscheiden.
Laufzeitoptimierung des Dijkstra Algorithmus
5
Der Dijkstra Algorithmus
Bild 2-1:
Vom Straßennetz zum mathematischen Graphen. Die ursprünglichen
Abbildungen stammen aus (Gallenbacher 2007, S. 2 und 7, Abb. 1.1
und 1.4)
Echte Verkehrsnetzte können mithilfe des Graphen-Modells beschrieben werden. Ein
Graph kann wiederum durch die Verwendung einer Adjazenzmatrix, einer Matrix in
der alle Knotenbeziehungen gespeichert sind, implementiert werden. Somit ist eine
digitale Kartenspeicherung möglich. Im nächsten Schritt wird ein „shortes path“
Algorithmus gesucht, welcher an einem Graphen arbeitet. Dabei ist es erforderlich,
dass die folgenden Bedingungen erfüllt werden: Der Algorithmus sollte in
annehmbarer Zeit den kürzesten Pfad zwischen Start- und Zielknoten liefern, falls es
überhaupt einen gibt. Falls nicht, sollte er terminieren und eine entsprechende
Fehlermeldung ausgeben.
2.2
ÜBERLEGUNGEN ZUR PROBLEMSTELLUNG
Eine Möglichkeit, den kürzesten Pfad vom Start- zum Zielknoten zu finden, wäre
einfach alle Wege zu testen. Diese Methode wird „Brute Force“, zu deutsch „Rohe
Laufzeitoptimierung des Dijkstra Algorithmus
6
Der Dijkstra Algorithmus
Gewalt“, genannt, da sie keinerlei Intelligenz benutzt und auch bereits gefundene
Informationen nicht mit einbezieht. Es werden stupide alle möglichen Wege
hintereinander verglichen, worin auch das Problem dieser Methode besteht: Bei
einem großen Graphen gibt es sehr viele Kanten, welche eine hohe Anzahl an
möglichen Wegen verursachen.
Bild 2-2:
Anzahl der Kanten, beziehungsweise die aller Wege von A aus bei
vollständigen Graphen mit 3, 4 und 5 Knoten. Bei der Anzahl der Wege
sind auch Pfade enthalten, welche nicht zum Zielknoten führen. Diese
Daten können mit der Wege-Formel aus (Gallenbacher 2007, S. 30)
berechnet werden.
Besteht ein Graph aus 3 Knoten und jeweils alle Knoten sind untereinander
verbunden, dann gibt es genau 2 mögliche Wege von A nach B. Bei einem Graphen
mit gleicher Konstellation, aber mit 4 Knoten, sind es bereits 5 Wege. Bei einem mit 5
Knoten sind es 9 Wege. Ein Brute Force Algorithmus betrachtet allerdings nicht nur
alle Wege die bei dem Zielknoten enden, sondern alle die überhaupt möglich sind.
Somit kommt eine sehr schnell wachsende Anzahl an zu vergleichenden Pfaden
zustande, siehe Bild 2-2. Im schlimmsten Fall, dem „Worst Case“, ist der Zielgraph
ein vollständiger Graph, was bedeutet, dass alle Knoten untereinander verbunden
sind (Gallenbacher 2007, S. 29). Für diesen Fall gibt es eine Formel, mit der die
ungefähre Anzahl der Rechenschritte eines „Brute Force“ Algorithmus berechnet
werden kann (Gallenbacher 2007, S. 30). Hierbei steht
𝑛c für die Anzahl der Rechenschritte und
Laufzeitoptimierung des Dijkstra Algorithmus
7
Der Dijkstra Algorithmus
𝑛 für die Anzahl der im Graph enthaltenden Knoten.
( 2.1 )
𝑛c ≈ (𝑛 − 1)! ∗ (𝑛 − 1)
( 2.2 )
Bei 10 beziehungsweise 20 Knoten erhält man durch diese Formel bereits folgende
Werte (Gallenbacher 2007, S. 30).
𝑛c (10) = 3265920
( 2.3 )
18
𝑛c (20) ≈ 2,3 ∗ 10
Aus diesem Beispiel ist erkenntlich, dass der Berechnungsaufwand mit der Anzahl
der Knoten sehr schnell extrem hoch wird. Diese Methode kann für einen großen
Graphen mit mehreren Millionen Knoten in annehmbarer Zeit kein Ergebnis liefern,
weil bei jedem Ausführen alle möglichen Verbindungen untersucht werden müssen.
Die Laufzeit, abhängig von der Anzahl der möglichen Wege, ist dann unannehmbar
hoch.
Wesentlich besser wäre es, wenn die Laufzeit von der Anzahl der Knoten abhängig
wäre und nicht exponentiell wachsen würde. Für das klassische kürzeste Wege
Problem existiert bereits ein solcher Algorithmus, der Dijkstra-Algorithmus. Dieser
Algorithmus wird im Folgenden genauer beschrieben.
2.2.1
DER DIJKSTRA-ALGORITHMUS UND DESSEN FUNKTIONSWEISE
In dem folgenden Grundlagen-Kapitel werden (Velden 2014b) und (Wikipedia 2015b,
Abs. Informelle Darstellung) des Öfteren als Quellen verwendet. Für die
Implementierung des Algorithmus an einem normalen Graphen, benötigt die
Knotenklasse drei weitere Attribute:
1. Eine Distanz zum Startknoten, welche immer wieder aktualisiert wird, falls ein
noch kürzerer Weg existiert.
2. Eine Art Marker, welcher Knoten zu denen bereits der kürzeste Weg vom
Startknoten gefunden wurde, markiert.
Laufzeitoptimierung des Dijkstra Algorithmus
8
Der Dijkstra Algorithmus
3. Und ein Speicherfeld, in das, falls ein neuer Knoten entdeckt wird, oder es
einen kürzeren Weg zu diesem gibt, sein Vorgänger hineingeschrieben wird.
Dadurch kann am Ende die Kette der Knoten, die den kürzesten Weg bilden,
vom Zielknoten rekursiv zurückverfolgt werden.
Die einzigen Informationen die der Algorithmus benötigt, um an einem gegeben
Graphen zu arbeiten sind
der Startknoten 𝑠
und der Zielknoten 𝑡.
( 2.4 )
( 2.5 )
Diese werden am Anfang dem Algorithmus übergeben. Zur Initialisierung vor dem
Start gehören außerdem folgende Arbeitsschritte:

Die Markierungen von allen Knoten entfernen.

Die Distanzen aller Knoten auf Unendlich setzten, da man diese noch nicht
kennt.

Die Vorgänger aller Knoten entfernen.

Der Startknoten wird von Anfang an markiert und seine eigene Distanz wird
auf 0 gesetzt, da dies die Distanz zu ihm selbst ist.
Der folgende Teil ist Kern des Algorithmus und wird solange wiederholt, bis alle
Knoten markiert sind. Zunächst werden alle unmarkierten Nachbarn des
aktuellen Knotens 𝑥
( 2.6 )
untersucht und deren Distanzen aktualisiert. Diese ergeben sich aus der Summe der
Länge des kürzesten Weges vom aktuellen Knoten zum Startknoten 𝑔(𝑥) und des
Kantengewichtes zum neuen Knoten 𝑑(𝑥, 𝑥neu ):
𝑔(𝑥neu ) = 𝑑(𝑥, 𝑥neu ) + 𝑔(𝑥).
( 2.7 )
Dabei steht xneu für einen Nachbarn von x, g(xneu ) für die Distanz des neuen
Knotens zu s, d(x, xneu ) für eine Funktion, welche die Wegkosten zwischen 2 Knoten
ausgibt und g(x) für die Distanz des Knotens x zu s.
Diese Aktion wird aber nur dann ausgeführt, wenn der alte Abstand größer als der
neue ist, was bei einem unbesuchten Knoten immer der Fall ist, da seine Distanz auf
Unendlich steht. Anschließend wird der nächste zu markierende Knoten aus der
Laufzeitoptimierung des Dijkstra Algorithmus
9
Wieso sind Änderungen notwendig?
Warteschlange ausgewählt. Die Warteschlange beinhaltet alle nicht markierten
Knoten, also alle zu denen es noch einen kürzeren Weg geben kann und alle die
noch nicht entdeckt wurden. Der Knoten mit der geringsten Distanz wird ausgewählt
und markiert, er ist jetzt der aktive Knoten von dem aus weiter gesucht wird.
Falls der Zielknoten markiert wurde, aber es immer noch unmarkierte Knoten gibt,
wird der obige Block solange wiederholt bis dies nicht mehr der Fall ist.
3 WIESO SIND ÄNDERUNGEN NOTWENDIG?
Durch die Themenstellung ergibt sich die folgende Frage: Sind Änderungen am
Dijkstra Algorithmus überhaupt notwendig oder kann dieser unverändert in den zu
untersuchenden Applikationen, den Navigationssystemen, eingesetzt werden?
Die Beantwortung dieser Frage erfolgt mit zwei separaten Methoden. Die erste
Untersuchung besteht aus einem Beweis, bei dem der Laufzeit-Zuwachs, bei
steigender Knotenanzahl 𝑛, über den Quellcode ermittelt wird. Dabei kommt eine
gängige Methode der Quellcodebetrachtung entsprechend (Brichzin et al. 2010, S.
148–149) zur Anwendung.
Die zweite Methode ist ein Laufzeitversuch, bei dem das Ergebnis der Ersten
experimentell überprüft wird. Bei der Durchführung dieses Versuches wird 𝑛 linear
gesteigert und dabei die Laufzeit des Algorithmus gemessen.
3.1
LAUFZEITBEWEIS AM QUELLCODE
Im Folgenden wird ein Laufzeitbeweis am Quellcode durchgeführt, welcher die
Laufzeit-Knoten-Abhängigkeit veranschaulichen soll, vergleiche dazu Bild 7-5 im
Anhang.
Bei der Laufzeitbetrachtung erhält man für den Zeitzuwachs, abhängig von der
Knotenanzahl 𝑛, die folgende Funktion. Hierbei ist 𝑡𝑖 die Laufzeit des jeweiligen
Codeabschnittes und 𝑡𝑔𝑒𝑠 die Gesamtlaufzeit des Programmes:
𝑡𝑔𝑒𝑠 (n) = 𝑛² ∗ (𝑡5 + 𝑡7 ) + 𝑛 ∗ (𝑡2 + 𝑡4 + 𝑡6 + 𝑡9 ) + 𝑡1 + 𝑡3 + 𝑡8 .
( 3.1 )
Laufzeitoptimierung des Dijkstra Algorithmus
10
Wieso sind Änderungen notwendig?
Diese „Worstcase“-Schleifenbetrachtungsfunktion kann dabei entsprechend der
folgenden Vorgehensweise ermittelt werden: Man muss jeweils den Faktor, den ein
Codefragment maximal wiederholt wird, mit dessen Laufzeit multiplizieren. Da es
zwei Codeabschnitte, mit den Laufzeiten 𝑡5 und 𝑡7 gibt, welche im vorliegenden
Beispielcode von zwei ineinander liegenden Schleifen durchlaufen werden, liegt hier
eine quadratische Laufzeitzunahme vor. Diese Zunahme ist abhängig von 𝑛, weil 𝑛
die maximale Anzahl der Durchläufe beider Schleifen ist und somit der Code
maximal 𝑛²-mal ausgeführt wird.
Bei der Grenzwertbetrachtung von Funktionen ist allgemein bekannt, dass der Term
mit der höchsten Potenz den größten Einfluss auf das Ergebnis hat. Somit haben 𝑡5
und 𝑡7 das größte Gewicht bei der Laufzeitzunahme.
3.2
LAUFZEITVERSUCH MITTELS EINES JAVA PROGRAMMS
Zur experimentellen Überprüfung des Beweises von 3.1 wird der Dijkstra Algorithmus
hinsichtlich seines Laufzeitwachstums untersucht. Dabei kommt die galileische
Methode zum Einsatz. Eine Durchführungsbeschreibung für Experimente, bei der
eine Hypothese aufgestellt werden muss, welche dann mittels des Versuchs
überprüft und angepasst wird, siehe (Hermann-Rottmair et al. 2009, S. 55).
Die Hypothese dieses Experiments ist, dass die Laufzeit des
Algorithmus von der Knotenanzahl des Graphen abhängt.
( 3.2 )
Für den Versuch wurde ein Programm erstellt, welches die Knotenanzahl 𝑛 möglichst
linear von 100 Knoten bis auf 10000 bei jedem Iterationsschritt erhöht.
Die Funktion für die Knotenanzahl des aktuellen Programmdurchlaufs ist:
𝑛 = 100 ∗ 𝑖 + 100; 𝑖 ∈ {0, 1, 2, … , 99}.
( 3.3 )
Der Messwert jedes Schrittes wird dann mit der jeweiligen Knotenanzahl in einem
𝑛 − Δt-Diagramm eingetragen, siehe Bild 3-1.
Laufzeitoptimierung des Dijkstra Algorithmus
11
Wieso sind Änderungen notwendig?
Laufzeit des Dijkstra
600
y = (0,0516x2 + 0,1334x)/10000
R² = 0,9948
Laufzeit in ms
500
400
300
Laufzeit des Dijkstra
200
Poly. ( Laufzeit des Dijkstra)
100
100
676
1296
1849
2500
3025
3600
4225
4900
5476
6084
6561
7225
7744
8464
9025
9604
0
Anzahl der Knoten
Bild 3-1:
Ergebnis des Laufzeitexperiments
Da sich bei der Änderung nur eines Parameters, nämlich der Knotenanzahl 𝑛, die
Laufzeit verändert, ist die Hypothese ( 3.2 ) bestätigt. Die Trendlinie, welche den
Verlauf der Messwerte mit einem Bestimmtheitsmaß von 99,48 % beschreibt, zeigt
den „optimalen“ Verlauf.
Aufgrund der großen Anzahl an Messwerten, kann man mit hoher Wahrscheinlichkeit
annehmen,
dass
sich
die
Wachstumszunahme
auch
bei
noch
höheren
Knotenanzahlen nicht mehr ändert. Die prognostizierte Funktion für die Laufzeit Δ𝑡 in
Sekunden, lautet dabei wie folgt:
Δ𝑡 = 10−7 ∗ (0,0516 𝑛2 + 0,1334 𝑛).
( 3.4 )
Anhand dieser Gleichung sieht man, dass die Laufzeit quadratisch wächst.
Um einen Eindruck zu bekommen, ob der Dijkstra bei größeren Straßennetzen
unverändert eingesetzt werden kann, wird die Knotenanzahl eines üblichen Graphen
probehalber in die Funktion eingesetzt. Die exakte Anzahl an Kreuzungen lässt sich
nur mit einer gewissen Unschärfe bestimmen, da sie sehr stark von der jeweiligen
Definition abhängt. Laut (Ruopp 2012, S. 37)1 gibt es im deutschen Straßennetz circa
1
Für diese Quelle wurde Herr Anton Donner angeschrieben, ein Navigationsexperte welcher im
deutschen Zentrum für Luft und Raumfahrt am Institut für Kommunikation und Navigation arbeitet.
Er zeigte mir einige nützliche Informationen, welche mir im Laufe der Seminararbeit hilfreich waren.
Dafür möchte ich ihm herzlich danken.
Laufzeitoptimierung des Dijkstra Algorithmus
12
Laufzeitoptimierung des Dijkstra Algorithmus
15 ∗ 106 Kreuzungen. Im Folgenden soll jede dieser Kreuzungen einem Knoten
entsprechen.
Für 𝑛 = 15 ∗ 106 erhält man den Wert Δ𝑡 = 1.2 ∗ 106 s, also circa 14 Tage! Wollte
man mit Hilfe eines Routenplaners, welcher den normalen Dijkstra Algorithmus
benutzt, durch ganz Deutschland fahren, müsste man etwa 2 Wochen auf das
Ergebnis warten. Dieser Wert übersteigt jegliche tolerierbare Dauer einer
Routenberechnung. Schon bei Kurzstrecken müsste mehrere Minuten auf das
Ergebnis gewartet werden. Außerdem wären Routenänderungen, zum Beispiel auf
Grund eines Staus, wenn eine schnelle alternative Route benötigt wird, rein zeitlich
nicht möglich.
Aus diesem Grund sind „shortest path“-Berechnungen, die in wenigen Sekunden ein
Ergebnis liefern, wie es bei den heutigen Navigationssystemen der Fall ist, nicht
ohne
weitere
Zeitoptimierungen
des
Dijkstra
Algorithmus
bei
größeren
Straßennetzen möglich.
Zusammenfassend lässt sich sagen, dass der Dijkstra Algorithmus durchaus für das
Routing-Problem in der Navigation zum Einsatz kommen kann. Vorteile sind eine
relativ einfache Umsetzung, da lediglich das Straßennetz als Graph modelliert
werden muss. Außerdem lässt sich der Algorithmus sehr gut implementieren.
Allerdings
benötigt
er
aufgrund
des
bereits
bewiesenen
quadratischen
Laufzeitwachstums sehr viel Zeit bei großen Graphen. Deshalb ist er in seiner
normalen Form für Navigationssysteme, welche ein Ergebnis in wenigen Sekunden
benötigen, eher ungeeignet. Um den Dijkstra Algorithmus aber trotzdem einsetzten
und damit alle Vorteile nutzen zu können, sind einige Optimierungen, speziell im
Hinblick
auf
die
Laufzeit,
notwendig.
Im
folgenden
Kapitel
sollen
diese
Optimierungsmöglichkeiten benannt und genauer darauf eingegangen werden.
4 LAUFZEITOPTIMIERUNG DES DIJKSTRA ALGORITHMUS
Um Optimierungsmöglichkeiten zu finden, muss man den Algorithmus hinsichtlich
seiner Schwachstellen untersuchen. Er berechnet zum Beispiel oft Werte, welche im
weiteren Verlauf nicht mehr benötigt werden.
Laufzeitoptimierung des Dijkstra Algorithmus
13
Laufzeitoptimierung des Dijkstra Algorithmus
Bild 4-1:
Suchraum des Dijkstra Algorithmus, im Bild links, verglichen mit einer
bidirektionalem
Variante.
Der
Graph
ist
dabei
das
deutsche
Straßennetz. Der Startknoten ist Rot und der Zielknoten grün markiert.
Kanten welche während dieses Vorgangs untersucht wurden, sind fett
gedruckt. Diese Abbildung stammt aus (Schütz 2004, S. 15 Fig. 5).
Eine Stelle an der dies passiert fällt sofort auf, wenn man sich nach einer
Berechnung einmal alle, während des Suchvorgangs durchlaufenen Kanten
anschaut. Diese bilden in der Regel eine Art Kreis um den Startknoten, siehe Bild
4-1.
Zur Minimierung dieses Suchaufwandes in die falsche Richtung, wäre es sinnvoll ein
Kriterium einzuführen, welches die Suche bevorzugt in die Richtung des Zielknotens
laufen lässt. Die einfachste und am wenigsten aufwendigste Lösung für dieses
Problem ist die bidirektionale Suche, welche im folgenden Kapitel erklärt wird.
4.1
BIDIREKTIONALE SUCHE
Bei dieser Methode wird der Dijkstra nicht nur von Startknoten 𝑠 aus gestartet,
sondern
auch
von
Zielknoten
𝑡.
So
erhält
man
zwei
parallel
laufende
Suchprogramme, welche sich in der Mitte treffen, falls es einen Weg von 𝑠 nach 𝑡
Laufzeitoptimierung des Dijkstra Algorithmus
14
Laufzeitoptimierung des Dijkstra Algorithmus
gibt. Da der Weg nun halbiert ist, dringt der Algorithmus auch weniger weit in falsche
Richtungen vor, siehe Bild 4-1. Dadurch sinkt der Suchaufwand und die Laufzeit wird
geringer.
Bei der Umsetzung dieser Variante gibt es jedoch einiges zu beachten. Jeder Knoten
benötigt zwei Markerattribute, für jeden Dijkstra ein eigenes. Außerdem braucht man
eine zusätzliche Codesequenz, welche beim Zusammentreffen zweier Suchpfade,
also immer dann wenn ein Knoten zweimal markiert wurde, die minimale Summe des
kürzesten Weges von Start zu Ziel aktualisiert (Schütz 2004, S. 15). Dies ist
notwendig, da der erste Knoten, welcher von beiden Richtungen gekennzeichnet
wurde, nicht unbedingt Teil des kürzesten Weges ist (Schütz 2004, S. 14).
Es muss jedoch beachtet werden, dass bei einem gerichteten Graphen alle
Kantenrichtungen für den Algorithmus, welcher bei t startet, umgedreht werden
müssen. Da wir hier aber immer von ungerichten Graphen ausgehen, ist das an
dieser Stelle zu vernachlässigen.
Die Implementation kann zwar durch die zwangsweise erforderliche genaue
Parallelität der Algorithmen erschwert werden, trotzdem wird diese Methode sehr
häufig benutzt, da der originale Graph unverändert eingesetzt werden kann. Somit
kann diese Methode gut in Verbindung mit weiteren Optimierungsmöglichkeiten
verwendet werden. So wird der Algorithmus beispielsweise in wissenschaftlichen
Arbeiten, wie bei (Ruopp 2012, S. 7), als Grundlage für weitere Forschungen
benutzt. Gerade wegen des hohen Multithread-Aufwandes macht die Verwendung
eines bidirektionalen Dijkstra aber erst mit einem großen Graphen Sinn. Bei der
eigenen Implementation ist erst ab circa 2000 Knoten ein Laufzeitunterschied
erkennbar, zu sehen in Bild 5-1 im Kapitel 5.
4.2
A* ALGORITHMUS
Diese Verbesserungsmethode setzt, ähnlich wie der bidirektionale Dijkstra, an dem
großen Suchbereich des Dijkstra Algorithmus an. Sie versucht durch heuristische
Schätzungen speziell in Richtung des Ziels zu suchen.
Der A* Algorithmus, gesprochen „A Stern“, ist im Prinzip ein Dijkstra-Algorithmus mit
ein paar kleinen Erweiterungen und Verbesserungen. Zunächst sucht er priorisiert in
Laufzeitoptimierung des Dijkstra Algorithmus
15
Laufzeitoptimierung des Dijkstra Algorithmus
die Richtung in der sich das Ziel befindet, um somit unnötigen Suchaufwand zu
vermeiden. Diese Art von Optimierungen wird auch „goal-directed search“ (Wagner
und Willhalm 2007, S. 5) oder informiertes Suchverhalten genannt (Velden 2014a,
Abs. 1). Um diese Methode durchzuführen, benutzt der Algorithmus für die
Erkennung der Distanz zwischen dem untersuchten und dem Zielknoten, eine
heuristische Schätzungsfunktion.
4.2.1
FUNKTIONSWEISE DES A* ALGORITHMUS
Diesem Kapitel werden die folgenden zwei Quellen zugrunde gelegt: (Wikipedia
2015a) und (Velden 2014a). Der Algorithmus benötigt, außer den Listen welche vom
Graphen bei der Implementierung bereits benötigt werden, noch zwei zusätzliche:
Eine „Open List“ und eine „Closed List“.
In der Open List werden alle neugefunden Knoten, zu denen noch keine Information
über dem Abstand bekannt ist, hineingeschrieben. Um anschließend den kürzesten
Weg zurückverfolgen zu können wird, ähnlich wie beim Dijkstra, bei jedem neuen
Knoten der jeweilige Vorgänger gesetzt.
Die Knotenklasse benötigt ein neues Attribut, welches den geschätzten Abstand 𝑓(𝑥)
zum Ziel speichert, wobei 𝑥 für den jeweiligen Knoten steht, siehe ( 2.6 ). 𝑓(𝑥) wird
einmal beim Eintragen in die Open List berechnet und jedes Mal, wenn ein noch
kürzerer Weg zu 𝑥 gefunden wurde. Der Abstand wird dabei wie folgt berechnet:
𝑓(𝑥) = 𝑔(𝑥) + ℎ(𝑥).
( 4.1 )
Dabei steht 𝑔(𝑥), entsprechend wie beim Dijkstra in ( 2.7 ), für die Summe aus der
Distanz des aktuellen Knotens und dem Abstand zum neuen Knoten. Zum aktuellen
Knoten wurde der kürzeste Weg bereits gefunden, er befindet sich in der Closed List.
ℎ(𝑥) ist der heuristisch geschätzte Abstand von Knoten 𝑥 zum Zielknoten 𝑡. Dieser
darf den echten Abstand allerdings nicht überschreiten, da es sonst passieren
könnte, dass der Algorithmus den Zielknoten zu weit hinten einreiht und keine
korrekte Lösung findet. Als Schätzfunktion wird dabei häufig, aufgrund der einfachen
Umsetzung die Luftlinie als monotone Heuristik benutzt, beziehungsweise im 2
Laufzeitoptimierung des Dijkstra Algorithmus
16
Laufzeitoptimierung des Dijkstra Algorithmus
Dimensionalen der euklidische Abstand. Außerdem ist die Open List gleichzeitig
auch Prioritätsliste: Der nächste zu untersuchende Knoten ist immer der mit dem
geringsten 𝑓(𝑥).
Die Closed List beinhaltet alle Knoten zu denen bereits der kürzester Weg gefunden
wurde. Sie dient vor allem zur Vermeidung von der mehrmaligen Untersuchung eines
Knotens. Wird ein Knoten zu dieser Liste hinzugefügt, dann werden seine
unbesuchten Nachfolgeknoten in die Open List geschrieben. Ein Knoten wird immer
dann zur Closed List hinzugefügt, wenn dieser besucht wurde. Die zwei Listen
müssen aber nicht zwingend implementiert werden. Es reichen auch zwei boolesche
Knotenattribute die den Zustand des Knotens speichern.
Am Anfang ist die Closed List komplett leer, lediglich in der Open List befindet sich
der Startknoten. Der Algorithmus endet wenn der Zielknoten den geringsten Wert
𝑓(𝑥) hat, dann wurde der kürzeste Weg gefunden. Er kann, genau wie beim Dijkstra
in 2.2.1, durch die in den Knoten gespeicherten Vorgänger zurückverfolgt werden.
Andererseits kann es auch passieren, dass sich an einem Punkt keine Knoten mehr
in der Open List befinden. Dann existiert kein Weg von Start- zu Zielknoten und der
Algorithmus sollte terminieren.
Abschließend kann man sagen, dass der A* Algorithmus durch die Einbeziehung von
zusätzlichen heuristischen Informationen eine gute Alternative zum Dijkstra ist. Man
muss aber berücksichtigen, dass beim Anwenden, auch gerade durch das
Einbeziehen von nicht sicheren geschätzten Daten, Fehler entstehen können (Ruopp
2012, S. 12). Deshalb wird in manchen Fällen trotzdem der Dijkstra bevorzugt.
4.3
CONTRACTION HIERARCHY
Die als Contraction Hierachy bekannte Optimierungsmethode untersucht den
Graphen und bewertet die Wichtigkeit der Knoten, um ihn damit hierarchisch so
aufzubauen, dass der Dijkstra Algorithmus weniger Knoten zu untersuchen hat.
Dadurch wird der Zeitaufwand geringer. Die folgende Beschreibung des Contraction
Hierachy Verfahren orientiert sich vor allem an (Ruopp 2012, S. 14-18 und 25).
Laufzeitoptimierung des Dijkstra Algorithmus
17
Laufzeitoptimierung des Dijkstra Algorithmus
Jeder Knoten wird mit einem neuen Attribut, der eigenen hierarchischen Gewichtung,
beziehungsweise der eigenen Ordnungsnummer ausgestattet. Die Gewichtung
orientiert sich gewöhnlicher Weise an der Größe der Straßen an der die Kreuzung
liegt und wird häufig mittels einer Heuristik festgelegt, vergleiche (Ruopp 2012, S.
17). So erhalten Autobahnen eine relativ große Zahl und Dorfstraßen eine sehr
geringe. Der Algorithmus versucht nun bei der Auswahl des nächsten Knoten, immer
einen mit einer höheren Ordnung zu wählen. Dabei ist es günstig eine bidirektionale
Version zu nutzen, da der Zielknoten meist auch niederpriorisiert ist. Somit muss
man in der Regel bei der Auswahl des nächsten Knoten nie eine Hierarchiestufe
tiefer gehen. Der Lösungspfad ist hierbei wieder in der Schnittmenge der beiden
Algorithmen zu finden.
Bild 4-2:
Kontraktion des Knotens b in Teilbild (a). Da der Weg von a nach c über
b 1+1=2 Einheiten lang war, muss eine Kante dieser Länge von a nach
c eingefügt werden, zu sehen in (c). Quelle der Abbildung: (Ruopp
2012, S. 15 Abb. 2.3)
Um den Prioritätsgraphen zu erhalten, benutzt man das Kontraktionsverfahren für
Knoten. Dabei werden ein bestimmter Knoten und alle seine Kanten komplett aus
dem Graph entfernt. Wenn allerdings ein Weg über diesen möglich war, wird eine
neue Kante mit dem Gewicht der Summe der beiden, die den Weg bildeten
eingefügt, siehe Bild 4-2. Somit werden die Kosten des kürzesten Weges nicht
verändert, aber die Knotenanzahl verringert, wodurch der Suchaufwand für den
nachfolgenden „shortest path“ Algorithmus reduziert wird.
Die Reihenfolge der Knoten bei der Kontraktion richtet sich dabei an die gegebene
Knotenordnung. Das bedeutet, dass Knoten mit kleinerer Ordnung früher als andere
Laufzeitoptimierung des Dijkstra Algorithmus
18
Anwendung in Navigationssystemen
mit
größerer
kontrahiert
werden.
Außerdem
ist
es
nach
experimentellen
Beobachtungen für den späteren Dijkstra Algorithmus laufzeittechnisch von Vorteil,
Knoten zu entfernen, bei denen danach die Gesamtkantenanzahl kleiner als davor
ist, vergleiche (Ruopp 2012, S. 17).
Der bidirektionale Dijkstra wird dann für den so entstandenen reduzierten Graphen
ausgeführt. Nach dem ein Weg im reduzierten Graphen gefunden wurde muss dieser
allerdings noch auf den ursprünglichen Graphen zurückgeführt werden. Dies wird
nach (Ruopp 2012, S. 17) auch unfolding genannt.
5 ANWENDUNG IN NAVIGATIONSSYSTEMEN
In
der
Regel
unterliegt
der
verwendete
Algorithmus
bei
Herstellern
von
Navigationssystemen der Geheimhaltung. Allerdings gibt es auch die OpensourceSoftware (OpenStreetMap Wiki 2015, Abs. 4). Hier wird angegeben, dass neben
anderen Verfahren auch der A* Algorithmus mit einem Contraction Hierachy
Graphen als Optimierung implementiert ist. Außerdem wird dort geschrieben, dass
die Entwickler zuerst den normalen Dijkstra benutzten wollten, dieser aber bei
größeren Graphen zu lange Berechnungszeiten aufwies.
In vielen wissenschaftlichen Arbeiten über dieses Thema wird meist eine der
vorgestellten Methoden benutzt. Zum Beispiel in (Ruopp 2012, S. 7), bei der eine
erweiterte bidirektionale Version verwendet wurde. Deshalb liegt der Schluss nahe,
dass die beschriebenen Methoden tatsächlich in Navigationssystemen zum Einsatz
kommen.
Für die Seminararbeit wurde zur Überprüfung ein weiteres Beispielprogramm erstellt,
welches die Laufzeit des normalen Dijkstra Algorithmus, des A* und des
bidirektionalen Dijkstra unter gleichen Bedingungen bei steigender Knotenanzahl
misst.
Das
„Contraction
Hierarchy“-Verfahren
konnte
aufgrund
der
hohen
Komplexität und der Änderungen welche am Graphen vorgenommen werden
müssen, nicht implementiert werden.
Laufzeitoptimierung des Dijkstra Algorithmus
19
Anwendung in Navigationssystemen
Laufzeitvergleich des Dijkstra, A* und
bidirektionalem Dijkstra
1000
900
Laufzeit in ms
800
700
600
500
Dijkstra
400
A*
300
bidirektionaler Dijkstra
200
100
1936
2304
2601
2916
3249
3600
3844
4225
4489
4761
5184
5476
5776
6084
6400
6724
7056
7396
7744
0
Anzahl der Knoten
Bild 5-1:
Ergebnis des Laufzeitvergleichs der Algorithmen Dijkstra, A* und
bidirektionaler Dijkstra.
Die Laufzeitmessungen wurden dabei speziell erst ab einer hohen Knotenanzahl
durchgeführt, weil sich zum Beispiel beim bidirektionalen Dijkstra infolge des ThreadAufwands erst dann ein bemerkbarer Unterschied zeigt.
In der Graphik Bild 5-1 kann man erkennen, dass beide Optimierungsvarianten
schneller als der Dijkstra sind und auch langsamer steigen. Durch Kombinieren der
beiden Methoden könnte man also schon eine enorme Verbesserung in dem
Laufzeit-Knoten-Zuwachs erreichen. Hieraus ist ersichtlich, dass aus einem
langsamen Algorithmus durch Optimierung ein schnelles alltagstaugliches System
entstehen kann. Das Programm welches für den Versuch verwendete wurde, wird in
7.1 hinsichtlich der Bedienung genauer beschrieben.
Zum Bau eines kommerziellen Navigationssystems benötigt es aber weitaus mehr.
Neben der Navigationssoftware muss auch die gesamte Hardware designt,
entwickelt und produziert werden. Zusätzlich wird noch wesentlich mehr Software,
zum
Beispiel für
ein
Userinterface
oder
die
Ansteuerung
eines
mobilen
Datenempfängers für aktuelle Verkehrsdaten, benötigt. Daraus ist erkennbar, dass
die Entwicklung von solchen Geräten aufwendiger ist als vielleicht vermutet. Erst
Laufzeitoptimierung des Dijkstra Algorithmus
20
Zusammenfassung
eine intensive Beschäftigung mit der Funktionsweise eines modernen technischen
Systems gibt einen Einblick in die Komplexität und den damit zusammenhängenden
Realisierungsaufwand.
6 ZUSAMMENFASSUNG
Zusammenfassend lässt sich sagen, dass der Dijkstra Algorithmus durchaus für den
Einsatz in Navigationssystemen geeignet ist. Allerdings ist er für die Anwendung auf
größeren Straßennetzten nicht optimal, da seine Laufzeit quadratisch zur Anzahl der
Kreuzungen steigt und daraus eine sehr hohe Rechenzeit resultiert.
Zur Minimierung dieser wurden folgende Optimierungsmethoden verwendet:

Der „Bidirektionale Dijkstra Algorithmus“, welcher die Suche von Start- und
Zielknoten
ansetzt.
Durch
den
verringerten
Suchraum
wird
eine
Geschwindigkeitssteigerung erreicht.

Der „A* Algorithmus“, welcher durch heuristische Schätzfunktionen eine
informierte Suche speziell in Richtung des Zielknotens laufen lässt.

Das „Contraction Hierachy“ Verfahren, welches durch das Kontrahieren von
nieder priorisierten Knoten die Knotenanzahl und somit den Suchaufwand
verringert.
Mithilfe der genannten Methoden lässt sich der Laufzeitzuwachs minimieren. Dann
erfüllt der Dijkstra die Anforderungen eines Bedieners und er kann für den
Echtzeiteinsatz in Navigationssystemen verwendet werden.
Laufzeitoptimierung des Dijkstra Algorithmus
21
Anhänge
7 ANHÄNGE
7.1
BEDIENUNG DES SELBSTERSTELLTEN PROGRAMMES
Bild 7-1:
Hauptfenster
der
Bedienoberfläche.
Hier
können
alle
für
den
Laufzeitversuch nötigen Parameter eingestellt werden.
Das Bild 7-1 zeigt das Hauptfenster der Bedienoberfläche. Hier können die zu
vergleichenden Algorithmen ausgewählt, sowie die Funktion der Knotenanzahl
bestimmt werden. Dementsprechend wurde bei dem Laufzeitversuch aus 3.2 bei der
verwendeten Knotenfunktion ( 3.3 ) der Startwert 100, der Endwert 10000 und die
Schrittgröße 100 gewählt.
Laufzeitoptimierung des Dijkstra Algorithmus
22
Anhänge
Bild 7-2:
Konsolen-Tab des Graphical-User-Interfaces (GUI). Hier werden die
Zwischenergebnisse ausgegeben.
Das Bild 7-2 zeigt den Konsolen-Tab des GUI. Während des Laufzeitversuches
werden hier die entsprechenden Zwischenergebnisse ausgegeben. Darunter
befinden sich die Laufzeit der Algorithmen, die Zielknotenkette, die Länge des
berechneten Weges und die echte Anzahl der Knoten im Graphen. Die Anzahl der
Knoten weicht leicht ab, da für die Implementation ein quadratischer Graph besser
geeignet war. Für die Berechnung der echten Knotenanzahl 𝑛real wurde deshalb
folgende Formel benutzt.
𝑛real = (round(√𝑛 ))2
( 7.1 )
Hierbei steht round() für eine Funktion, welche die übergebene reelle Zahl zu einer
Ganzzahl rundet.
Laufzeitoptimierung des Dijkstra Algorithmus
Anhänge
Bild 7-3:
Konsolen-Tab am Ende des Versuchs
23
Laufzeitoptimierung des Dijkstra Algorithmus
24
Anhänge
Am Ende des Versuchs werden alle Teilergebnisse noch einmal in einer Tabelle
ausgegeben, welche in Bild 7-3 zu sehen ist. Diese Werte können jetzt, für die
weitere Verwendung der Ergebnisse, in gleicher Form, im Haupt-Tab in Bild 7-1, in
eine Textdatei gespeichert werden. Alternativ kann man das Ergebnis aber auch
gleich in einem vorläufigen Diagramm im Graphen-Tab betrachten, siehe Bild 7-4.
Bild 7-4:
Der Graphen-Tab des Programmes ist gut geeignet um einen
vorläufigen Überblick der Messwerte zu erhalten.
Laufzeitoptimierung des Dijkstra Algorithmus
25
Anhänge
7.2
LAUFZEITBEWEIS AM QUELLCODE
Bild 7-5:
Laufzeitbeweis am eigenen Java Code nach dem Beispiel von (Brichzin
et al. 2010, S. 148–149).
Laufzeitoptimierung des Dijkstra Algorithmus
26
Abbildungsverzeichnis
8 ABBILDUNGSVERZEICHNIS
Bild 2-1:
Vom Straßennetz zum mathematischen Graphen. Die
ursprünglichen Abbildungen stammen aus (Gallenbacher
2007, S. 2 und 7, Abb. 1.1 und 1.4) ............................................... 5
Bild 2-2:
Anzahl der Kanten, beziehungsweise die aller Wege von A
aus bei vollständigen Graphen mit 3, 4 und 5 Knoten. Bei der
Anzahl der Wege sind auch Pfade enthalten, welche nicht
zum Zielknoten führen. Diese Daten können mit der WegeFormel aus (Gallenbacher 2007, S. 30) berechnet werden............ 6
Bild 3-1:
Ergebnis des Laufzeitexperiments ............................................... 11
Bild 4-1:
Suchraum des Dijkstra Algorithmus, im Bild links, verglichen
mit einer bidirektionalem Variante. Der Graph ist dabei das
deutsche Straßennetz. Der Startknoten ist Rot und der
Zielknoten grün markiert. Kanten welche während dieses
Vorgangs untersucht wurden, sind fett gedruckt. Diese
Abbildung stammt aus (Schütz 2004, S. 15 Fig. 5). ..................... 13
Bild 4-2:
Kontraktion des Knotens b in Teilbild (a). Da der Weg von a
nach c über b 1+1=2 Einheiten lang war, muss eine Kante
dieser Länge von a nach c eingefügt werden, zu sehen in (c).
Quelle der Abbildung: (Ruopp 2012, S. 15 Abb. 2.3) ................... 17
Bild 5-1:
Ergebnis des Laufzeitvergleichs der Algorithmen Dijkstra, A*
und bidirektionaler Dijkstra. .......................................................... 19
Bild 7-1:
Hauptfenster der Bedienoberfläche. Hier können alle für den
Laufzeitversuch nötigen Parameter eingestellt werden. ............... 21
Bild 7-2:
Konsolen-Tab des Graphical-User-Interfaces (GUI). Hier
werden die Zwischenergebnisse ausgegeben. ............................ 22
Bild 7-3:
Konsolen-Tab am Ende des Versuchs ......................................... 23
Bild 7-4:
Der Graphen-Tab des Programmes ist gut geeignet um
einen vorläufigen Überblick der Messwerte zu erhalten. .............. 24
Laufzeitoptimierung des Dijkstra Algorithmus
27
Abbildungsverzeichnis
Bild 7-5:
Laufzeitbeweis am eigenen Java Code nach dem Beispiel
von (Brichzin et al. 2010, S. 148–149). ........................................ 25
9 LITERATURVERZEICHNIS
Bauer, Reinhard; Delling, Daniel; Sanders, Peter; Schieferdecker, Dennis; Schultes,
Dominik; Wagner, Dorothea (2008): Combining Hierarchical and Goal-Directed
Speed-Up Techniques for Dijkstra’s Algorithm. In: Catherine C. McGeoch (Hg.):
Experimental Algorithms, Bd. 5038. Berlin, Heidelberg: Springer Berlin Heidelberg
(Lecture Notes in Computer Science), S. 303–318. Online verfügbar unter
http://algo2.iti.kit.edu/schultes/hwy/combine.pdf, zuletzt geprüft am 01.11.2015.
Brichzin, Peter; Freiberger, Ulrich; Reinold, Klaus; Wiedemann, Albert (2010):
Informatik. Oberstufe 2. 1. Aufl. München: Oldenbourg.
Gallenbacher, Jens (2007): Abenteuer Informatik. IT zum Anfassen von
Routenplaner bis Online-Banking. 1. Aufl. München: Elsevier, Spektrum Akad. Verl.
Hermann-Rottmair, Ferdinand; Hoche, Detlef; Meyer, Lothar; Reichwald, Rainer;
Schwarz, Oliver (2009): Physik. Bayern Gymnasium Lehrbuch für die 11. Klasse. 1.
Aufl. Berlin, Mannheim: Duden-Schulbuchverl.
OpenStreetMap Wiki (Hg.) (2015): OpenTripPlanner – OpenStreetMap Wiki. Online
verfügbar unter http://wiki.openstreetmap.org/wiki/OpenTripPlanner, zuletzt
aktualisiert am 02.10.2015, zuletzt geprüft am 03.10.2015.
Ruopp, Manuel (2012): Contraction Hierarchies für komplexe Kostenmaße.
Diplomarbeit. Universität Stuttgart, Stuttgart. Institut für Formale Methoden der
Informatik Abteilung Algorithmik. Online verfügbar unter ftp://ftp.informatik.unistuttgart.de/pub/library/medoc.ustuttgart_fi/DIP-3232/DIP-3232.pdf, zuletzt geprüft
am 01.11.2015.
Schmidt, Thorsten; Fuchs, David (2004): A-Stern Algorithmus. Hg. v. Geosimulation.
Online verfügbar unter
http://www.geosimulation.de/methoden/a_stern_algorithmus.htm, zuletzt aktualisiert
am 12.11.2004, zuletzt geprüft am 17.08.2015.
Laufzeitoptimierung des Dijkstra Algorithmus
28
Abbildungsverzeichnis
Schütz, Birk (2004): Partition-Based Speed-Up of Dijkstra's Algorithm. Studienarbeit.
Universität Karlsruhe (TH), Karlsruhe. Institut für Logik, Komplexität und
Deduktionssysteme. Online verfügbar unter http://i11www.iti.unikarlsruhe.de/_media/teaching/theses/files/studienarbeit-schuetz-05.pdf, zuletzt
geprüft am 01.11.2015.
Velden, Lisa (2014a): Der A*-Algorithmus. Hg. v. TU München. Online verfügbar
unter https://www-m9.ma.tum.de/graph-algorithms/spp-a-star/index_de.html, zuletzt
aktualisiert am 08.07.2015, zuletzt geprüft am 17.08.2015.
Velden, Lisa (2014b): Der Dijkstra-Algorithmus. Hg. v. TU München. Online verfügbar
unter https://www-m9.ma.tum.de/graph-algorithms/spp-dijkstra/index_de.html, zuletzt
aktualisiert am 08.07.2015, zuletzt geprüft am 17.08.2015.
Wagner, Dorothea; Willhalm, Thomas (2007): Speed-Up Techniques for ShortestPath Computations. Universität Karlsruhe (TH), Karlsruhe. Institut für Theoretische
Informatik. Online verfügbar unter http://i11www.iti.unikarlsruhe.de/extra/publications/ww-sutsp-07.pdf, zuletzt geprüft am 01.11.2015.
Wikipedia (Hg.) (2015a): A*-Algorithmus. Online verfügbar unter
https://de.wikipedia.org/w/index.php?oldid=146613207, zuletzt aktualisiert am
02.10.2015, zuletzt geprüft am 06.10.2015.
Wikipedia (Hg.) (2015b): Dijkstra-Algorithmus. Online verfügbar unter
https://de.wikipedia.org/w/index.php?oldid=146740393, zuletzt aktualisiert am
23.10.2015, zuletzt geprüft am 26.10.2015.
Wikipedia (Hg.) (2015c): Graphentheorie. Online verfügbar unter
https://de.wikipedia.org/w/index.php?oldid=145232211, zuletzt aktualisiert am
23.10.2015, zuletzt geprüft am 26.10.2015.
Wikiversity (Hg.) (2011): Projekt:Mathematik in Natur und Technik/dijkstra. Online
verfügbar unter
http://de.wikiversity.org/wiki/Projekt:Mathematik_in_Natur_und_Technik/dijkstra,
zuletzt aktualisiert am 16.01.2015, zuletzt geprüft am 16.02.2015.
Laufzeitoptimierung des Dijkstra Algorithmus
Erklärung des Verfassers
10 ERKLÄRUNG DES VERFASSERS
Ich habe diese Seminararbeit ohne fremde Hilfe angefertigt und nur die im
Literaturverzeichnis angeführten Quellen und Hilfsmittel benutzt.
Finning den 09.11.2015
____________________
____________________
Ort, Datum
Unterschrift
29
Herunterladen