0/2/2

Werbung
Gliederung
5. Compiler
1.
2.
3.
4.
Struktur eines Compilers
Syntaxanalyse durch rekursiven Abstieg
Ausnahmebehandlung
Arrays und Strings
6. Sortieren und Suchen
1. Grundlegende Datenstrukturen
2. Bäume
3. Hash-Verfahren (Streuspeicherung)
7. Graphen
1. Darstellung von Graphen
2. Algorithmen auf Graphen
1. Kürzeste Wege
2. Fluß- und Zuordnungsprobleme
3. Topologisches Sortieren
Kürzeste Wege mit negativen Kantengewichten
• Graphen können negative Kantengewichte enthalten:
Beispiel: Verbindungen, die mit negativen Kosten versehen sind (also
Gewinnen) bevorzugt gewählt werden
• Dijkstras Algorithmus funktioniert nur, wenn die Kantengewichte keine
negative Werte annehmen können
Beispiel: Eine lokal ungünstige nächste Kante kann durch eine darauf
folgende negativ gewichtete Kante nachträglich zu einer besseren
Verbindung führen
• Lösung: Bellman-Ford-Algorithmus
Vorgehensweise:
– In mehreren Durchläufen wird jeweils die beste bisher mögliche Verbindung
bestimmt
– Im i-ten Durchlauf werden alle Pfade der Länge i berücksichtigt
– Der längste Pfad ohne Zyklus hat eine Länge von |V|-1: Der Prozess kann
nach |V|-1 Durchläufe abgeschlossen werden
Graph mit negativen Kantengewichten
u
v
1
10
-2
s
3
-5
6
7
5
x
2
y
• Merke: Falls es einen negativen Zyklus auf einem Pfad gibt, dann ist der
kürzeste Pfad nicht wohldefiniert, da man durch Hinzufügen weiterer
Zyklusrunden das Pfadgewicht beliebig klein machen kann. In diesem Fall
existiert kein kürzester Pfad
Bellman-Ford-Algorithmus (1)
Vorüberlegungen
• Das Gewicht einer Kante e wird in der Kantenvariablen
e.weight gespeichert
• Das Gewicht eines (aktuellen) kürzesten Pfades zum Knoten
v wird in der Knotenvariablen v.weight gespeichert
• Den Vorgänger u von v auf dem kürzesten Pfad von s nach v
speichert man in der Knotenvariablen v.parent = u
• Mit Hilfe der Parent-Variablen kann man den kürzesten Pfad
zu einem Knoten v bestimmen
Bellman-Ford-Algorithmus (2)
•
Initialisierung
Initialize-BFA (G,s):
1. Für jeden Knoten v ∈ V: Setze v.weight = ∞ und v.parent = -1
2. s.weight = 0
•
Operation „Relaxation“:
– Solange man den kürzesten Pfad von s zu einem Knoten v noch nicht
gefunden hat, speichert man in v.weight eine obere Schranke für die
Länge des kürzesten pfades von s nach v
– Eine Kante (u,v) zu „entspannen“, bedeutet, dass man testet, ob
man einen neuen kürzesten Pfad von s nach v bekommt, wenn man
den aktuellen kürzesten Pfad von s nach u betrachtet und die Kante
(u,v) hinzufügt
Relax(e=(u,v)):
1. Falls v.weight > u.weight + e.weight :
2. Setze v.weight = u.weight + e.weight und v.parent = u
Bellman-Ford-Algorithmus (1)
• Der Algorithmus gibt einen booleschen Wert zurück. Der
Wert ist TRUE, falls es keinen negativen Zyklus gibt und der
Algorithmus dann erfolgreich alle kürzesten Pfade zu den von
s aus erreichbaren Knoten bestimmt hat
• Gibt es einen negativen Zyklus, der von s aus erreichbar ist,
so gibt der Algorithmus FALSE zurück
Bellman-Ford(G,w,s):
Initialize-Single-Source(G,s)
Für i = 1, ... , n-1 :
Für alle Kanten e = (u,v) ∈ E: Relax(e)
Für alle Kanten e = (u,v):
IF v.weight > u.weight + e.weight THEN
Gib FALSE zurück
Gib TRUE zurück.
• Aufwand des Bellman-Ford-Algorithmus: Der Bellman-FordAlgorithmus hat Laufzeit O(nm), wobei n die Zahl der Knoten
in V und m die Zahl der Kanten in E ist
Bellman-Ford-Algorithmus: Beispiel (1)
u
1
∞
v
u
∞
10
1
∞
10
10
-2
s 0
v
3
-5
6
7
5
∞
2
-2
s 0
3
x
y
Graph nach der Initialisierung
6
7
5
∞
-5
5
2
∞
x
1. Iteration (i=1)
Merke:
• Nach der ersten Iteration hat der Knoten u einen vorläufigen Wert von
10 bekommen, da er direkt vom Startknoten s aus mit einer Kante des
Gewichtes 10 erreicht werden kann
• Der Wert 10 stellt nur einen Zwischenergebnis dar: Mit einem Pfad der
Länge 2 über x kann eine billigere Verbindung mit Kosten 5+3=8
aufgebaut werden
y
Bellman-Ford-Algorithmus: Beispiel (1)
u
2. Iteration (i=2)
v
1
8
u
s 0
3
-5
6
5
x
3
s 0
3
9
-5
6
7
5
5
x
2
4
y
2
3. Iteration (i=3)
10
-2
-5
6
7
v
1
8
s 0
5
x
7
y
2
u
-2
5
7
5
9
10
10
-2
1
8
11
v
4. Iteration (i=4)
7
y
Maximaler Durchfluss (1)
• Motivation: Lösung logistischer Aufgaben
• Beispiele:
– Anzahl der Autos, die durch ein Kanalnetz fahren können
– Strommenge, die durch ein Leitungsnetz fließen kann
– Paketvermittlung in Computernetzwerken: Sollen vom Rechner Quelle
möglichst (oder gar in Echtzeit) viele Pakete zum Rechner Ziel
übertragen werden, stellt sich die Frage nach der maximalen Anzahl
übertragbarer Pakete
Quelle
Ziel
Maximaler Durchfluss (2)
• Aufgabenbeschreibung
1. Menge von Computern (=Knoten eines Graphen), einer bildet die
Quelle einer zu übermittelnden Datenmenge, einer die Senke
2. Zwei verschiedene Computer sind über Einzelverbindungen
(=Kanten) verknüpft und können Daten über diese Verbindung
übertragen
• Daten werden als Pakete fester Länge übertragen
• Jede Verbindung hat eine Kapazität (Maximale Menge pro Zeiteinheit zu
übertragender Datenpakete)
3. Die Vernetzung ist derart, dass verschiedene Pfade bestehen, über
die Daten von der Quelle zur Senke transportiert werden können.
• Fragestellung: wie viele Datenpakete können pro Zeiteinheit
maximal von der Quelle bis zur Senke übertragen werden?
Maximaler Durchfluss (3)
• Ein Netzwerk ist ein gerichteter Graph G = (V, E, c) mit ausgezeichneten
Knoten q (Quelle) und s (Senke), sowie einer Kapazitätsfunktion
c: E -> R+
• Ein Fluss für das Netzwerk ist eine Funktion f: E -> R, mit so dass gilt:
- Kapazitätsbeschränkung
∀u,v∈V: f(u,v) ≤ c(u,v)
- Konsistenz des Flusses
∀u,v∈V: f( (u,v) ) = -f( (v,u) )
- Flusserhaltung:
∀u,v∈V\{q,s}: Σu ∈ V f(u,v) =0
• Der Wert f(u,v) kann positiv oder negativ sein
• Der Wert eines Flusses wird als w(f)=Σu ∈ V f(s,v) definiert
• Der maximale Fluss ist folgendermaßen definiert:
max{val(G, f, q) | f ist ein zulässiger Fluss in G bezüglich q und s}
Der Ford-Fulkerson-Algorithmus
• Ein „erweiternder (zunehmender) Weg“ in G ist eine
Folge von Knoten beginnend bei s und endend bei q wobei
der Fluss entlang dieses Weg vergrößert wird
• Ford-Fulkerson: Generischer Algorithmus
Pseudo-Code-Notation
Finde einen zulässigen Fluss f in G
REPEAT
erhöhe diesen Fluss f
UNTIL eine Erhöhung von f ist nicht möglich
Der Ford-Fulkerson-Algorithmus
Sei f ein zulässiger Fluss für G = (V,E).
• Die Restkapazität einer Kante (u,v) wird folgendermaßen
definiert:
rest(u,v)= c(u,v)-f(u,v)
• Der Restgraph von G (bzgl. f) wird mit Gf=(V, Ef)
bezeichnet, wobei gilt:
Ef ={(u,v) ∈ V X V: r(u,v)>0 }
• Jeder gerichtete Pfad von q nach s im Restgraphen heißt
zunehmender Weg
• Ein Schnitt (A,B) eines Netzwerks ist eine Zerlegung von V in
disjunkte Teilmengen A und B, so dass q ∈ A und s ∈ B.
Die Kapazität des Schnitts ist
c(A,B) = Σu∈A,v∈B c(u,v)
Theorem (Max-Flow- Min-Cut)
Sei f zulässiger Fluß für G. Folgende Aussagen sind äquivalent:
1. f ist maximaler Fluss in G.
2. Der Restgraph von f enthält keinen zunehmenden Weg.
3. w(f) = c(A,B) für einen Schnitt (A,B) von G
Ford-Fulkerson: verbesserter Algorithmus
for (alle (u,v) in E ) f(u,v) = 0; // Initialisierung
while ( es gibt zunehmenden Weg p im Restgraphen Gf )
{
r = min{rest(u,v) | (u,v) liegt in p};
for (alle (u,v) auf Pfad p ){
f(u,v) = f(u,v) + r(u,v) ;
f(v,u) = f(v,u) - r;
}
}
Ford-Fulkerson-Algorithmus: Beispiel (1)
1. Schritt: Graph wird mit Fluss=0 initialisiert
Kantenbeschriftung: f/c/r
f: Fluss
c: Vorgegebene Kapazität
r: Restkapazität
0/2/2
a
0/3/3
q
b
0/1/1
0/4/4
c
0/2/2
0/1/1
0/2/2
0/2/2
e
0/2/2
0/2/2
0/3/3
d
0/1/1
0/3/3
s
Ford-Fulkerson-Algorithmus: Beispiel (2)
1. Iteration: Auswahl des ersten Pfades:
Pfad q->c->e->s mit r = min{rest(u,v) | (u,v) liegt in p}=2
wird ausgewählt
0/2/2
a
0/3/3
q
b
0/1/1
0/4/4
c
0/2/2
0/1/1
0/2/2
0/2/2
e
0/2/2
0/2/2
0/3/3
d
0/1/1
0/3/3
s
Ford-Fulkerson-Algorithmus: Beispiel (3)
2. Iteration: Anpassung der Kantenbeschriftungen und
Auswahl des zweiten Pfades q->e->d->s mit
r = min{rest(u,v) | (u,v) liegt in p}=1
Merke: Restkapazität von (c,e) ist nach der ersten Iteration
erschöpft
0/2/2
a
0/3/3
q
b
0/1/1
2/4/2
c
0/2/2
0/1/1
0/2/2
2/2/0
e
0/2/2
0/2/2
0/3/3
d
0/1/1
2/3/1
s
Ford-Fulkerson-Algorithmus: Beispiel (4)
3. Iteration: Anpassung der Kantenbeschriftungen und
Auswahl des dritten Pfades q->a->b->s mit
r = min{rest(u,v) | (u,v) liegt in p}=2
Merke:
• Restkapazität von (e,d) ist nach der zweiten Iteration
aufgebraucht
• Bei der Anpassung der Kantenbeschriftung (e,d) muss die
Rückkante (d,e) mitbehandelt werden:
f(v,u) = f(v,u) – r (Siehe Algorithmus)
0/2/2
a
0/3/3
q
b
0/1/1
2/4/2
c
0/2/2
-1/1/2
1/2/1
2/2/0
e
0/2/2
0/2/2
1/3/2
d
1/1/0
2/3/1
s
Ford-Fulkerson-Algorithmus: Beispiel (4)
4. Iteration: Anpassung der Kantenbeschriftungen und
Auswahl des vierten Pfades q->a->d->e->s mit
r = min{rest(u,v) | (u,v) liegt in p}=1
Merke:
Restkapazität von (e,d) und (b,s) sind nach der dritten
Iteration aufgebraucht
2/2/0
a
2/3/1
q
b
0/1/1
2/4/2
c
0/2/2
-1/1/2
1/2/1
2/2/0
e
2/2/0
0/2/2
1/3/2
d
1/1/0
2/3/1
s
Ford-Fulkerson-Algorithmus: Beispiel (4)
5. Iteration: Anpassung der Kantenbeschriftungen und
Auswahl des fünften Pfades q->c->d->s mit
r = min{rest(u,v) | (u,v) liegt in p}=2
Merke:
• Restkapazität von (a,d) und (e,s) sind nach der vierten
Iteration aufgebraucht
• Bei der Anpassung der Beschriftung für die Kante (d,e)
muss die Rückkante behandelt werden
2/2/0
a
3/3/0
q
b
1/1/0
2/4/2
c
0/2/2
0/1/1
1/2/1
2/2/0
e
2/2/0
0/2/2
1/3/2
d
0/1/1
3/3/0
s
Ford-Fulkerson-Algorithmus: Ergebnis
• Es sind keine weitere Pfade möglich
• Die Berechnung des maximalen Flusses ist damit beendet!
• Merke:
– Welcher Pfad in jedem Iterationsschritt gewählt wird bleibt offen!
– Die Anzahl der Iterationen hängt von der Wahl der Pfade ab
2/2/0
•a
3/3/0
•q
•b
4/4/0
•c
2/2/0
0/1/1
1/2/1
2/2/0
1/1/0
2/2/0
•e
0/2/2
•d
3/3/0
0/1/1
3/3/0
•s
Weitere Algorithmen für Graphen
Topologisches Sortierung
• Gegeben: Gerichteter azyklischer Graph G
• Gesucht: Reihenfolge der Knoten derart, dass jeder Knoten
nach all seinen Vorgängern kommt (d.h. es sollte keine
Rückkante geben)
Falls die gerichtete Kanten kausale oder zeitliche
Abhängigkeiten darstellen, so spricht man von scheduling-
Problemen
Eine topologische Sortierung eines DAG ist eine (lineare)
Ordnung aller Knoten, so dass für alle Kanten (u,v) des
Graphen gilt: Der Knoten u erscheint in der Ordnung vor v
Topologische Sortierung: Beispiel
Beliebtes Beispiel aus Lehrbüchern: Ein zerstreuter Professor
hat Probleme, morgens seine Kleidungsstücke in der richtigen
Reihenfolgen anzulegen. Daher legt er die
Reihenfolgebedingungen beim Ankleiden fest:
–
–
–
–
–
–
–
–
–
Unterhose vor Hose
Hose vor Gürtel
Hemd vor Gürtel
Gürtel vor Jackett
Hemd vor Krawatte
Krawatte vor Jackett
Socken vor Schuhen
Hose vor Schuhen
Uhr: Egal
Socken
Unterhose
Uhr
Schuhe
Hose
Hemd
Gürtel
Krawatte
Jackett
Topologische Sortierung: Algorithmus
1. Starte die Methode Tiefendurchlauf und berechne die
„finishing-time“ für alle Knoten (Zeit an der der Knoten mit
dem Tiefendurchlauf besucht wurde)
2. Wenn ein Knoten abgearbeitet ist, dann füge ihn am Anfang
der (Ordnungs-)Liste ein
3. Die Ordnungsliste stellt die topologische Sortierung dar
Ergebnis mit finishing Time
18 Socken
16 Unterhose
15 Hose
14 Schuhe
10 Uhr
8 Hemd
7 Gürtel
5 Krawatte
4 Jackett
Traveling Salesman Problem
• Ein Handlungsreisender muss eine Reihe von Orten
besuchen.
• Er möchte seine Tour so planen, dass der zurückzulegende
Weg (ein Zyklus, der alle Orte enthält) minimal ist.
• Dies ist ein Problem über einen bewerteten Graphen.
• Die Knoten sind die zu besuchenden Orte, die (bewerteten)
Kanten stellen die Entfernung (oder Fahrtkosten) zwischen
den Orten dar.
• Das Graphenproblem lautet also :
Finde einen Zyklus minimaler Länge,
in einem vorgegebenen Graphen,
der alle Knoten enthält.
Traveling Salesman : Beispiel 1
Finden Sie eine TSP-Tour in dem unten stehenden Graphen
rund um das Schloss von Marburg
Köln 5
174
Marburg
Bonn
224
106
3
Gießen
66
181
1
88
6
Mannheim
4 Kassel
96
7
30
34
0
104
2 Fulda
104
Frankfurt
136
93
8 Würzburg
Eigenschaften des TSP
• Unser Beispielproblem lässt sich offenbar intuitiv auf
einfache Weise (und eindeutig!) lösen. Grundsätzlich ist das
jedoch keineswegs der Fall.
- (a)
Oft gibt es überhaupt keine Lösung.
Beispiel: Wenn ein weiterer Knoten "Mainz" zwischen Bonn und
Frankfurt aufgenommen wird, ist das TSP nicht lösbar.
- (b)
Oft gibt es mehrere Zyklen, die alle zu besuchenden Knoten
enthalten. Dann kann der kürzeste Zyklus nur durch Ausprobieren
gefunden werden.
Beispiel: Wenn zusätzlich eine Verbindung Mainz Mannheim
aufgenommen wird, gibt es mehrere Zyklen.
Traveling Salesman : Problem bei Beispiel 1
Problem 1: Wenn ein weiterer Knoten "Mainz" zwischen Bonn und
Frankfurt aufgenommen wird, ist das TSP nicht lösbar.
Problem 2: Wenn zusätzlich eine Verbindung Mainz Mannheim
aufgenommen wird, gibt es mehrere Zyklen.
Köln 5
Marburg
174
30
34
Bonn
0
104
Gießen
181
140
41
224 Mainz 9
71
6
Mannheim
96
7
106
3
66
1
2 Fulda
104
Frankfurt
136
88
4 Kassel
93
8 Würzburg
Lösungen des TSP
• Bis heute ist keine effiziente Lösung des TSP bekannt.
Alle bekannten Lösungen sind von der Art :
Allgemeiner TSP-Algorithmus:
Erzeuge alle möglichen Touren;
Berechne die Kosten für jede Tour;
Wähle die kostengünstigsteTour aus.
• Folgerung : Die Komplexität aller bekannten TSPAlgorithmen ist O(2N), wobei N die Anzahl der Kanten
ist. Das heißt: Wenn wir eine einzige Kante
hinzunehmen, verdoppelt sich der Aufwand zur Lösung
des TSP!
• Beispiel: Hinzunahme einer neuen Verbindung
Mannheim-Würzburg im obenstehenden Graphen.
Varianten des TSP
• Eine Verallgemeinerung des TSP besteht darin, auf die Rückkehr zum
Ausgangspunkt zu verzichten:
- TSP (u,v): Finde einen einfachen Weg von Knoten u nach Knoten v,
der alle Knoten von G enthält.
• Offenbar stellt TSP(u,u) das ursprüngliche TSP-Problem dar.
• Beispiel: TSP(Marburg, Gießen) ist (im ursprünglichen Graphen)
eindeutig lösbar, TSP (Marburg, Köln) ist nicht lösbar, für TSP (Marburg,
Würzburg) müssen im erweiterten Graphen mehrere mögliche Wege
verglichen werden.
• In einer weiteren Verallgemeinerung werden Mehrfachbesuche einzelner
Knoten bis zu einer Schranke AriMax (= Maximalzahl zulässiger Besuche)
zugelassen.
- TSP (u,v,AriMax): Finde einen Weg von Knoten u nach Knoten v, der
alle Knoten von G mindestens einmal und höchstens AriMax-mal
enthält.
• Mit dieser Verallgemeinerung (und geeignetem AriMax) ist das TSP
immer lösbar - allerdings mit noch erheblich gesteigerten Aufwand!
TSP-Algorithmus: Erläuterung (1)
• Der folgende Algorithmus für das Problem TSP (u,v,AriMax)
verfolgt eine Tiefendurchlauf-Strategie (depth first) mit
Zurücksetzen (backtracking).
Er verwendet
- ein int-Array Marken zum Markieren der bereits besuchten Knoten,
- ein int-Array MinWeg zum Speichern des (bisher) minimalen Weges
- eine rekursive Prozedur besuche, die einen begonnenen Weg der
Tiefe t an der Stelle k mit dem Ziel z fortsetzt. Ist der Weg noch keine
vollständige Tour, und existiert zu k ein Nachbarknoten k', der noch
weniger als AriMax-mal besucht wurde und bei dessen Besuch die
gesamte Weglänge unterhalb der Weglängen-Schranke MinWegLen
bleibt, wird der Weg bei k' mit Tiefe t+1 fortgesetzt (rekursiver Aufruf).
TSP-Algorithmus: Erläuterung (2)
- Weiter wird durch eine boolesche Funktion testeWeg geprüft,
- ob k bereits der Zielknoten v ist,
- ob alle Knoten besucht wurden.
- Ist ein Weg gefunden, so wird seine Länge (AktWegLaenge) mit der
von MinWeg (MinWegLen) verglichen. Falls er kürzer ist, wird er zum
neuen MinWeg und seine Länge wird als neue MinWegLen
festgehalten. Der Besuch wird abgebrochen.
- Beim Abbruch eines Besuchs wird zum vorherigen Knoten
zurückgekehrt (backtrack) und der nächste mit diesem verbundene
Knoten besucht. Wurden alle Wege durchprobiert und mindestens eine
Tour gefunden, so wird MinWeg, ansonsten eine Fehlermeldung
ausgegeben.
TSP-Algorithmus: Programm (1)
class Graph{
...
private final int AriMax = 2;
private int Schranke;
private int WegeMax = 5*KnotenZahl;
private int[] MinWeg = new int[WegeMax];
private int AktWegLaenge;
...
private int wegLaenge(int[] Weg, int maxIndex){
int erg = 0;
for (int w = 0; w < maxIndex; w++)
erg += Kanten[Weg[w]][Weg[w+1]];
return erg;
}
TSP-Algorithmus: Programm (2)
private boolean testeWeg(int[] Weg, int[] Marken,
int maxIndex, int Ziel){
if (Weg[maxIndex] != Ziel) return false;
int Max = KnotenZahl;
if (maxIndex < (Max-1)) return false;
for (int k = 0; k < Max; k++)
if (Marken[k] == 0) return false;
return true;
}
private void besuche(int k, int[] Weg, int maxIndex,
int Ziel, int[] Marken){
int Max = KnotenZahl;
maxIndex++;
if (maxIndex >= (WegeMax-2)){
System.out.println("Der Weg wurde zu lang ...");
return;
}
...
TSP-Algorithmus: Programm (3)
...
Weg[maxIndex] = k;
int BisherigeLaenge = 0;
if (maxIndex == 0) AktWegLaenge = 0;
else {
BisherigeLaenge = AktWegLaenge;
AktWegLaenge += Kanten[Weg[maxIndex-1]][Weg[maxIndex]];
}
Marken[k]++;
if (AktWegLaenge < Schranke){
if (TesteWeg(Weg, Marken, maxIndex, Ziel )){
System.arraycopy(Weg, 0, MinWeg, 0, maxIndex+2);
Schranke = AktWegLaenge;
}
else{
...
TSP-Algorithmus: Programm (4)
...
for (int n = 0; n < Max; n++)
if (Kanten[k][n] > 0)
if (Marken[n] < maxB)
Besuche(n, Weg, maxIndex, Ziel, Marken);
}
}
Besuch wieder rückgängig machen:
AktWegLaenge = BisherigeLaenge;
Weg[maxIndex] = -1;
Marken[k]--;
}
TSP-Algorithmus: Programm (5)
Hauptprogramm:
Aufruf z.B.: MeinGraph.TSP(0,1);
void TSP(int u, int v){
int Max = KnotenZahl;
//int s = 0;
// Automatisches Abschätzung für Schranke
//for (int x=0; x < Max; x++)
//for (int y=0; y < Max; y++) s += Kanten[x][y];
// Bzw. Experimentelles Setzen der Schranke
int s =370;
Schranke = s;
int[] Weg = new int[WegeMax];
for (int i = 0; i < WegeMax; i++) Weg[i] = -1;
System.arraycopy(Weg, 0, MinWeg, 0, WegeMax);
...
TSP-Algorithmus: Programm (6)
...
int[] Marken = { 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0 };
int maxIndex = -1;
long Zeit1 = System.currentTimeMillis();
besuche(u, Weg, maxIndex, v, Marken);
long Zeit2 = System.currentTimeMillis();
System.out.println("LaufZeit: "+(Zeit2-Zeit1));
if ( s == Schranke){
System.out.println("Kein Weg gefunden !!!");
return;
}
...
TSP-Algorithmus: Programm (7)
...
System.out.println("Länge des kürzesten Weges: "
+ Schranke);
System.out.println("Der kürzeste Weg ist: ");
int KnotenNr = MinWeg[0];
int WegIndex = 1;
while (KnotenNr >= 0){
for (int i=0; i < (2*WegIndex+10); i++)
System.out.print(' ');
System.out.println(Knoten[KnotenNr]);
KnotenNr = MinWeg[WegIndex];
WegIndex++;
}
}
}
TSP für Beispiel 2 (1)
•
TSP Ausgangsknoten: San Francisco
Zielknoten: San Rafael
Länge des kürzesten Weges: 342
Der kürzeste Weg ist:
San Francisco
Pacifica
Half Moon Bay
San Mateo
Eine Lösung des TSP
Palo Alto
von San Francisco nach
Santa Clara
Scotts Valley
San Rafael ist mit einem
Santa Cruz
einfachen Weg möglich.
Watsonville
San Jose
Fremont
Hayward
Oakland
Richmond
San Rafael
TSP für Beispiel 2 (1)
•
TSP Ausgangsknoten: San Francisco
Zielknoten: San Mateo
Länge des kürzesten Weges: 364
Der kürzeste Weg ist:
San Francisco
San Rafael
Richmond
Oakland
San Francisco
Eine Lösung des TSP
Pacifica
von San Francisco nach
Half Moon Bay
Santa Cruz
San Mateo gelingt nur mit
Scotts Valley
Mehrfachbesuchen.
Santa Cruz
Watsonville
San Jose
Santa Clara
Palo Alto
Fremont
Hayward
San Mateo
TSP-Algorithmus: Anmerkungen (1)
• Die Suche nach einer Lösung des TSP gelingt bei 15 Städten in nicht
messbarer Zeit, wenn wir höchstens einen Besuch für jede Stadt zulassen.
• Wenn wir zulassen, dass jede Stadt bis zu zweimal besucht werden darf,
wächst der Rechenaufwand ganz erheblich.
• Die Zahl der zu generierenden Wege steigt in diesem Fall dramatisch an.
Für die Suche nach der Lösung des ersten Beispiels wurden 483 Wege
generiert, beim zweiten Beispiel waren 3.832.913 Wege erforderlich.
• Dies liegt an einer Vielzahl von unsinnigen Doppelbesuchen, die der
Algorithmus nicht als unsinnig erkennt. Man müsste ihm eine Hilfestellung
geben, welche Städte einmal und welche zweimal besucht werden sollen.
• Die oben genannte Anzahl der generierten Wege ergibt sich, wenn man
die Schranke automatisch abschätzen lässt. Mit einer kleineren Schranke
erniedrigt sich die Zahl der generierten Wege erheblich.
TSP-Algorithmus: Anmerkungen (2)
•
Offensichtlich kann man sehr viel Laufzeit sparen, wenn man die Suche auf
einfache Wege beschränkt. Trotzdem kann man nicht hoffen, umfangreiche
Travelling Salesman Probleme mit diesem Programm berechnen zu können.
•
Die Laufzeit L ist nämlich exponentiell, also L=c×2N mit einer geeigneten
Konstanten c. Dies ist leicht einzusehen, denn selbst wenn jeder Knoten nur zwei
Nachbarn hätte, verdoppelt sich jedes Mal die Anzahl der möglichen Wege.
•
Unter der Annahme, die Laufzeit im Falle N=15 sei eine Millisekunde gewesen,
wenn wir höchstens einen Besuch für jede Stadt zulassen, finden wir
c= 1/30 000 000
•
Im Falle eines Graphen mit N=40 Knoten müssen wir mit einer Laufzeit von etwa
240/30 000 000 ≈ 10004/30 000 000 ≈ 30 000 Sekunden
rechnen. Mit einem 10fach schnelleren Rechner könnten wir zwar die Aufgabe in
nur 3000 Sekunden erledigen. Wenn wir dann allerdings die Zahl der Städte um
zehn erhöhen, ergibt sich sofort eine tausendmal größere Laufzeit.
•
Aus diesen Gründen kann eine punktuelle Optimierung des Algorithmus keinen
nennenswerten Einfluss auf die Laufzeit haben, solange nicht mindestens ein
polynomialer Algorithmus gefunden wird – doch das ist höchst unwahrscheinlich.
Literatur
• Die Folien zum Traveling Salesman Problem wurden aus der
Vorlesung aus der Vorlesung „Informatik II a, SS 2002“ von
Prof. Sommer (Uni-Marburg) übernommen
Herunterladen