Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes...

38
Praktikum aus Operations Research Algorithmen zur Lösung des „Travelling Salesman Problem” Paul Niel, 9705566 Thomas Ledl, 9702223

Transcript of Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes...

Page 1: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus Operations Research

Algorithmen zur Lösung des „Travelling Salesman Problem”

Paul Niel, 9705566 Thomas Ledl, 9702223

Page 2: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 2 Thomas Ledl, 9702223

INHALT: Vorwort...................................................................................... 3

1 Datensätze ............................................................................. 4 1.1 Praktische Beispiele.........................................................................4

1.2 Fraktale ...........................................................................................6 2 Verteilung von Zufallslösungen ........................................ 8

3 Vorstellung der Algorithmen ............................................. 9 3.1 Nearest Neighbour mit Teilstreckenoptimierung ..............................9

3.2 Local Search ....................................................................................11

3.3 Simulated Annealing ........................................................................13

4 Graphische Lösungen ..................................................... 15

5 Fazit ................................................................................. 22

Appendix 1: Source Code......................................................................... 25

Appendix 2 : Erklärung der Source Codes................................................ 34

Appendix 3 : Screenshots......................................................................... 38

Appendix 4 : Quellenangabe .................................................................... 38

Appendix 5 : Hardware ............................................................................. 38

Page 3: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 3 Thomas Ledl, 9702223

VORWORT Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe

verschiedener Algorithmen das Travelling-Salesman Problem löst.

Aufgabe dieses Problems der kombinatorischen Optimierung ist es, den

kürzesten Weg oder den einer angemessenen Laufzeit angepassten

suboptimalen Weg durch eine gewisse Anzahl von Punkten zu finden.

Zur Lösung des Problems sollten drei verschiedene Algorithmen

verwendet werden. Neben dem Nearest-Neighbour (mit

Teilstreckenoptimierung)- und dem Local Search- Verfahren wurde auch

der Simulated Annealing Algorithmus implementiert . Das komplette Tool

wurde mit einer Graphical User Interface versehen, das eine leichte

Handhabung erlaubt. Als Programmierumgebung wurde dabei S-PLUS

benutzt. Generell gliederte sich das Projekt in zwei Phasen: In einer

ersten erfolgte einerseits die Programmierung des Tools und des GUI,

ferner wurden verschiedene Testdatensätze aufgespürt und diese dann

Zufallslösungen ausgesetzt. In der zweiten Phase wurde vor allem die

Lösungseffizienz der einzelnen Algorithmen überprüft. Es zeigte sich

dabei, dass handelsübliche Personal-Computer mit den verwendeten

Algorithmen aufgrund der grossen Routenanzahl sehr lange zu kämpfen

hatten (Details s.u.). Neben der Analyse des Laufzeitverhaltens wurde

auch die richtige Wahl der Parametereinstellungen kritisch untersucht,

leider nur mit mässigem Erfolg.

Page 4: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 4 Thomas Ledl, 9702223

1. Datensätze 1.1 Praktische Beispiel Der erste Teil der Beispiel wurde in der TSP-Library der Universität Heidelberg gefunden die von Gerhard Reinelt betreut wird. Es handelt sich hierbei um 2 Städterundreisen, die dem ursprünglichen Charakter des TSP entsprechen, sowie um ein Leiterplatinenproblem. Als erstes Problem stellte sich hierbei schon die richtige Konvertierung der Koordinatenmatrizen heraus. So musste der Datensatz Ulysseus 22, der leider nur in geografischen Längen- und Breitengraden vorlag, zuerst konvertiert werden um eine euklidische Abstandsmatrix zu erhalten, und damit mit den anderen Datensätzen vergleichbar zu sein. Im folgenden sollen nun die einzelnen Datensätze kurz grafisch vorgestellt werden: 1.1.1 ULYSSEUS22 Dieser Datensatz beruht auf der historischen Irrfahrt des Odysseus, die in der griechischen Klassik von Homer beschrieben wurde. Es handelt sich dabei um 22 Wegpunkte rund um das Mittelmeer. Die optimale Lösung die bisher für dieses TSP-Problem gefunden wurde umfasst dabei.

Ulysseus 22

25

30

35

40

45

-10 -5 0 5 10 15 20 25 30

Page 5: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 5 Thomas Ledl, 9702223

1.1.2 CITY51 Der City51 Datensatz behandelt 51 Städteproblem in den USA, die in den 60er Jahren im Rahmen eines Gewinnspieles von Procter&Gamble ausgeschrieben. Einer der Gewinner (mehrere Teilnehmer errieten die richtige Lösung) war übrigens ein Mathematiker.

0

10

20

30

40

50

60

70

80

0 10 20 30 40 50 60 70

Page 6: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 6 Thomas Ledl, 9702223

1.1.3 PLATINE280 Beim Platine Datensatz handelt sich um das Problem den günstigsten Weg durch 280 Bohrlöcher auf einer Leiterplatine zu finden. Solche Probleme existieren überall dort wo es um die effektive Ausnutzung von Maschinen in Fertigungsbetrieben geht. Der optimale Weg ist dabei bei diesem Problem .

0

20

40

60

80

100

120

140

160

180

0 50 100 150 200 250 300 350

1.2 Fraktale Im Gegensatz zu den praktischen Beispielen wurden auch Fraktale TSP- Beispiele verwendet. Diese entstammen vor allem den Arbeiten von Pablo Mascato, der via Internet einen Algorithmus zur Verfügung stellt um solche Fraktale verschiedenster Ordnung zu generieren. Die beiden dabei hauptsächlich verwendeten Algorithmen sind Mpeano und Davidstern. 1.2.1 Mpeano44 Der Mpeano44 Datensatz ist ein TSP-Problem das mit dem MPeano-Algorithmus 3. Ordnung erstellt wurde. Für alle Mpeano generierten TSP-Probleme konnte dabei nachgewiesen werden, dass der Greedy-Algorithmus (Nearest Neighbour) eine optimale Lösung findet.

0

100

200

300

400

500

600

700

800

900

1000

0 200 400 600 800 1000

Page 7: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 7 Thomas Ledl, 9702223

1.2.2 Mpeano92 Ein Mpeano-Fraktal 4. Ordnung mit bereits 92 Datenpunkten.

1.2.3 David 162 Im Gegensatz zu dem mit MPeano generierten Fraktalen, konnte bis jetzt für den Davidstern Algorithmus keine optimale Tour gezeigt werden. Der folgende Datensatz stellt dabei einen Davidstern 4.Ordnung mit 162 Datenpunkten dar.

0

100

200

300

400

500

600

700

800

900

1000

0 200 400 600 800 1000

Page 8: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 8 Thomas Ledl, 9702223

2. Verteilung von Zufallslösungen Um festzustellen, ob die verwendeten Algorithmen eine bessere Lösung liefern, als durch die einfache Erzeugung von Zufallslösungen, und falls ja um wieviel besser diese Lösungen sind, wurde die Verteilung der Zielfunktionswerte der konkreten Beispieldatensätze anhand der Erzeugung von jeweils 1000 Zufallsrouten geschätzt. Die Vorgangsweise war folgende: 1. Es wurden für jeden Datensatz 1000 Zufallsrouten mit der Funktion „tspperm“

erzeugt und die jeweiligen Zielfunktionswerte berechnet. 2. In SPSS wurde dann mit diesen 1000 ZF-Werten ein Test auf

Normalverteilung gerechnet, um die Verteilung approximativ durch 2 Parameter (Mittelwert, Varianz) definieren zu können. Dies gelang wirklich, da bei keinem Datensatz die Normalverteilungshypothese abgelehnt werden konnte, die p-Werte sogar immer ziemlich hoch waren (0,7 und größer).

3. Daher plotteten wir im nächsten Schritt die jeweilige geschätzte Dichtefunktion, um einen Überblick über die Verteilung zu bekommen.

4. Interessant war nur, wenn man n Zufallslösungen erzeugt, wie das Minimum aussieht. Da wir nun die Verteilung wussten (annähern konnten), waren wir nicht auf das Minimum der ZZ-Werte aus der einen Stichprobe angewiesen, sondern konnten uns die Verteilung des Minimums ausrechnen

X N i i d Min X Y F y p p pi i yi n

i

n

~ ( , ), . . ., ( ) ( ) ( ) ( )µ σ 2 1

11 1 1= ⇒ = − = − −−

=∑

,wobei p gerade jene Wahrscheinlichkeit ist mit der Xi kleiner gleich y ist.

5. Die Dichtefunktion dieser Verteilung wurde nun neben die ursprüngliche Dichtefunktion geplottet. Um n (Anzahl der Zufallslösungen) variabel gestalten zu können und im speziellen Fall mit einem Algorithmus verglichen werden kann (Anzahl der getesteten Routen wird bei jedem Algorithmus ausgegeben), wurde ein Schieberegler verwendet, mit dem man die Dichtefunktion der Verteilung des Minimums interaktiv verändern kann.

Zum Beispiel sieht so die Dichtefunktion der ZF-Werte bzw. die Dichtefunktion des Minimums von 100 ZF-Werten im „David“-Datensatz aus:

00,000050,0001

0,000150,0002

0,000250,0003

0,000350,0004

6500

066

40067

80069

20070

60072

00073

40074

80076

20077

60079

00080

40081

80083

20084

60086

000

f_X(x)f_MIN(x)

Page 9: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 9 Thomas Ledl, 9702223

3 Lösungsalgorithmen 3.1 Nearest Neighbour mit Teilstreckenoptimierung Der „Nearest-Neighbour“-Algorithmus erhält als Input eine Distanzmatrix, sowie die Anzahl der aufeinanderfolgenden Kanten einer Stelle im Zyklus, die mittels Teilstreckenoptimierung verändert werden (=Umgebung (umg)). Es soll also nicht nur die einfache „Nearest-Neigbour“-Lösung gefunden, sondern, es soll auch eine bestimmte Umgebung durchsucht werden, die eventuell noch bessere Lösungen liefern könnte. Im GUI ist für die Umgebung ein Wert von 3 bis 20 vorgesehen. Umgebung=2 würde keinen Sinn machen, weil dazwischen nur ein Knoten permutiert werden könnte (also würde gar nichts geschehen). Wünscht man nur eine Optimierung nach der „Nearest-Neigbour“-Methode ohne Teilstreckenoptimierung, muss man den Quellcode dahingehend verändern, daß in der Funktion „tspsolver“ nicht nn1(...), sondern nn(...) aufgerufen wird. Da diese Variante von vornherein nicht vorgesehen war, wir jedoch aufgrund der Optimierungsresultate den Verdacht hatten, dass schon die ursprüngliche „Nearest-Neighbour“-Lösung das Optimum liefert, wollten wir das natürlich überprüfen. Daher die umständliche Programmierung. Im folgenden wird nur dieFunktion „nn1“ (mit Teilstreckenoptimierung) erklärt. Die Funktion beginnt mit dem ermitteln der ZF-Werte des herkömmlichen „Nearest-Neighbour“-Verfahrens ausgehend von jedem der möglichen Punkte. Das passiert so: Vor der „Repeat“-Schleife wird der erste „verfügbar“-Vektor aufgebaut, der alle Knoten enthält, die noch für die weitere Route ausgewählt werden können. repeat { min<-verfuegbar[(min(D[i,verfuegbar])==D[i,verfuegbar])] min<-min[1] In diesem Schritt werden in der betreffenden Zeile (Zeile, die dem letzten Punkt in der Route entspricht) jene Stellen ermittelt, wo das Minimum auftritt. Da ein Minimum an mehreren Stellen auftreten kann und das zu einem Absturz des Algorithmus führen könnte, wird einfach der erste Wert genommen. loesung[start,i]<-min verfuegbar<-verfuegbar[-(1:length(verfuegbar))[verfuegbar==min]] Der ermittelte Knoten wird nun an die Stelle des vorangegangenen geschrieben. Falls zB. zuletzt Knoten Nr.3 dran war, und jetzt Knoten Nr. 8, dann wird x[3]<-8 gesetzt. Aus dem „verfügbar“-Vektor wird diese Stelle gestrichen. Dies wird solange wiederholt, solange im „verfügbar“-Vektor noch Zahlen stehen. Im letzten Schritt wird an die Stelle des letzten Knotens der Anfangsknoten geschrieben, um wieder zurückzugelangen. Danach wird der beste Zielfunktionswert ermittelt und der Variable „x.stern“ zugewiesen.

Page 10: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 10 Thomas Ledl, 9702223

Im anschliessenden Schritt (Optimierung durch Veränderung von zusammenhängenden Teilstrecken) wird nun an jeder Stelle die Umgebung durchsucht. Für eine konkrete Stelle im Zyklus sieht das so aus: x<-loesung[i,] knoten<-i k<-i for (j in 1:(umg)) { knoten<-c(knoten,x[k]) k<-x[k] } mittl.knoten<-knoten[2:umg]

p.matrix<-matrix(mittl.knoten[allperm(umg-1,F)],fakt(umg-1)-1,(umg-1)) An der betreffenden Stelle wird die ermittelte „Nearest-Neighbour“-Route dem Vektor x zugewiesen. Des weiteren merkt man sich in „knoten“, von welcher Stelle man ausgeht. Im folgenden wird in „knoten“ ein Vektor aufgebaut, der die Knoten entlang der Route angibt. Wenn „knoten“ nun fertig aufgebaut ist, beschreiben die Knoten genau jenen Weg, den man geht, wenn man beginnend von der Startstelle genau soviele Kanten weitergeht, wie in „umg“ angegeben. Wurde zB. eine Umgebung von 4 gewählt befindet sich das zu verändernde Stück der Route (die „Umgebung“ eben) zwischen dem Startknoten und jenem Knoten, der 4 aufeinanderfolgende Kanten weiter liegt. Da die zwei äußeren Knoten dieses Vektors ja nicht verändert werden, werden in „mittl.knoten“ gerade die mittleren Knoten, die permutiert werden sollen, herausgeschält. Was in „p.matrix“ steht, soll nun das folgende Beispiel zeigen. Umfasst die Teilstrecke 4 aufeinanderfolgende Kanten (von Pkt. 47 zu 35, zu 22, zu 24, und zu 16), dann dürften die Knoten 35, 22 und 24 beliebig permutiert werden. „p.matrix“ sieht dann so aus: A B [1,] 24 22 35 [2,] 24 35 22 [3,] 22 24 35 [4,] 35 24 22 [5,] 22 35 24 Mit dem Parameter „F“ in allperm wird wieder auf die triviale Permutation 35,33,24 verzichtet, da man hier den ZF-Wert ja schon kennt. In den folgenden Zeilen wird nun für jede Knotenpermutation wieder die zugehörige TSP-Route ermittelt. Das passiert folgendermaßen: x[p.matrix[j,][umg-1]]<-knoten[umg+1] x[i]<-p.matrix[j,][1] for (k in (umg-2):1) { x[p.matrix[j,][k]]<-p.matrix[j,][k+1]

Page 11: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 11 Thomas Ledl, 9702223

} Sei p.matrix[1,] die erste Zeile der p.matrix im vorigen Beispiel, also 24,22,35 und „knoten“ war 47,35,22,24,16. Dann heißt die erste Zeile: x[35]<-16. Die zweite Zeile heißt x[47]<-24. In der Schleife steht dann x[22]<-35 und x[24]<-22 und somit wurde die Knotenreihenfolge in der Permutation in eine TSP-Route „übersetzt“. Statt: Gehe von 47 nach 35, nach 22, nach 24, nach 16 heißt es jetzt: Gehe von 47 nach 24, nach 22, nach 35 und nach 16. In der Schleife mit j als Zählvariable geschieht das für alle Permutationen, die in „p.matrix“ angegeben sind. In den restlichen Zeilen werden einfach immer nur die Zielfunktionswerte mit dem besten verglichen und x.stern wird gegebenenfalls modifiziert. Der Zielfunktionswert einer Lösung x wird immer mit der etwas seltsamen aussehenden Berechnungsvorschrift sum(diag(D[,x]). Mit D[,x] wird die Distanzmatrix so umgeschichtet, daß die relevanten Streckenlängen alle in der Hauptdiagonale zu finden sind. „diag()“ liefert die Hauptdiagonale als Vektor und „sum()“ summiert drüber. Erwähnenswert ist auch noch, dass zur Kontrolle ein Routenzähler eingefügt wurde, anhand dessen man überprüfen kann, ob alle Routen getestet wurden. Die Formel dafür lautet:

#Routen = #Punkte*(umg-1)! Ergebnistabelle: Datensatz Parameter Lösungen Name Umgebung Methode AnzRouten Lösungswert Ulysseus22 8 nn 110880 8092,308 Mpeano44 Keine *) nn 44 4914,459 City51 keine*) nn 51 505,774 Mpeano92 keine*) nn 92 6062,101 David162 keine*) nn 162 7153,727 Platine280 keine*) nn 280 3094,278 *) grössere Umgebungen erbrachten keine Steigerung 3.2 Local Search Im Gegensatz zum „Nearest-Neigbour“-Algorithmus kommt man hier bei mehrmaligen Anwenden der Funktion mit gleichen Einstellungen im allgemeinen nicht auf die gleichen Optima, da dieser Algorithmus bekannterweise auf dem Erstellen von Zufallslösungen beruht. Das Absuchen der Umgebung funktioniert jedoch genauso wie bei „Nearest Neighbour“.

Page 12: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 12 Thomas Ledl, 9702223

if (!verbessert) { x<-tspperm(n) Anfangsloesung<-x Zufallerz<-Zufallerz+1 } else x<-x.stern Im ersten Schritt wird also eine Zufallslösung erzeugt, bei weiteren Iterationsschritten wird nicht notwendigerweise jedesmal eine Zufallslösung erzeugt. Ein Iterationsschritt besteht nur aus dem Vorgang, beginnend von einer konkreten Route die gesamten Umgebung zu durchsuchen und den besten ZF-Wert zu wählen. Bei der nächsten Iteration wird dann, wenn verbessert wurde, die selbe Prozedur wieder gestartet, oder falls nicht verbessert wurde, das lokale Minimum in x.stern gespeichert und eine neue Zufallslösung generiert. Die Zahl der Iterationen ist daher nicht gleich der Anzahl der erzeugten Zufallslösungen. Um festzustellen, wieviele Zufallslösungen tatsächlich erzeugt wurden, zählt „Zufallerz“ diese Anzahl. Das Absuchen der Umgebung funktioniert nun genauso wie bei der Teilstreckenoptimierung des „Nearest-Neigbour“-Algorithmus. Solang man bei im gleichen Iterationsschritt verbleibt, wird bei Verbesserungen „Fx“ (der beste ZF-Wert) und „x.stern“ neu gesetzt. Gemerkt wird auch, ob irgendwann in der Umgebung eine Verbesserung stattgefunden hat (verbessert=T,F). if (!verbessert) { x.stern<-Anfangsloesung Fx<-sum(diag(D[,x.stern])) } if (Fx<M) {M<-Fx ;bishbestx<-x.stern} Die Abfrage, ob verbessert wurde, oder nicht, ist am Ende des Iterationsschritts noch einmal wichtig, denn wenn keine Verbesserung stattgefunden hat, muss „x.stern“ auf die Anfangslösung des Iterationsschrittes gesetzt und der zugehörige ZF-Wert berechnet werden. Am Ende jedes Iterationsschrittes muss dann natürlich auch noch festgestellt werden, ob das gefundene lokale Minimum kleiner oder größer als das bisherige Minimum ist, und es muss gegebenenfalls eine neue kleinste untere Schranke („M“) und ein absolut bester Minimierer („bishbestx“) modifiziert werden. Wieder ist hier die Zahl der getesteten Routen eine Kontrolle dafür, ob alle Routen überprüft wurden. In jeder Iteration werden pro Punkt (Stadt) (umg-1)!-1 Lösungen plus eine Lösung für die Zufallslösung überprüft. Die Gesamtanzahl errechnet sich daher so: #Routen=#Iterationen*[1+#Punkte*((umg-1)!-1)] Jedoch sind bei diesem Algorithmus einige Lösungen dabei, die doppelt berechnet werden. Wird nämlich bei einem Iterationsschritt keine Zufallslösung erzeugt, dann ist

Page 13: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 13 Thomas Ledl, 9702223

die Startlösung ja schon in der Umgebung der Startlösung im vorhergehenden Iterationsschritt zu finden. Außerdem ist nicht auszuschließen, dass wenn mehrmals in der Umgebung eines Punktes gesucht wird, einige Routen öfters berechnet werden. Ergebnistabelle: Datensatz Parameter Lösungen Name Umgebung Iterationen dav. Zufallslsg. AnzRouten Lösungswert Ulysseus22 6 50 5 130950 7640,861 Mpeano44 5 200 11 202600 9370,84

City51 6 30 2 182100 831.370 Mpeano92 5 50 1 105850 20444,6 David162 4 50 1 40550 48670,29 Platine280 4 5 28020 27685,38

3.3 Simulated Annealing Der „Simulated-Annealing“-Algorithmus, der von den drei Algorithmen die meisten Parametrisierungsmöglichkeiten hat, ist von Quellcode her am kürzesten, da jeweils nicht die gesamte Umgebung durchgesucht wird, sondern nach erzeugen einer Zufallslösung zu einer weiteren zufälligen Lösung in der Umgebung weitergegangen wird, jetzt aber nicht ausschließlich wenn eine Verbesserung des Zielfunktionswertes stattgefunden hat, sondern eventuell auch dann, wenn er etwas schlechter ist. Die Wahrscheinlichkeit hängt von der sogenannten Temperatur „c“ ab. Im S-Plus wird diese Aufgabe zunächst folgendermaßen gelöst: Vor der ersten Schleife wird eine erste Zufallslösung dem Vektor „x“ zugewiesen. for(l in 1:L) { getestete.routen<-getestete.routen+1 x.neu<-matperm(x,umg) # neue Umgebung f.loes.alt<-sum(diag(D[x])) f.loes.neu<-sum(diag(D[x.neu])) In der inneren Schleife wird der schon bekannte Routenzähler aktiviert. In „x.neu“ wird nun eine Lösung aus der Umgebung von „x“ gewählt. Von dieser und von der ursprünglichen Lösung werden nun die ZF-Werte ermittelt. diff<-f.loes.neu-f.loes.alt if(diff<-c*log(runif(1))) {x<-x.neu}

Page 14: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 14 Thomas Ledl, 9702223

Die Wahrscheinlichkeit, zu einer schlechteren Lösung weiterzugehen, berechnet sich nun folgendermaßen:

p yF y F x

cdiff

cx c, ( ) exp(( ) ( )

) exp( )= −−

= −

Es wird also dann die schlechtere Lösung gewählt, wenn exp( )− >diff

cZZ ist, wobei

ZZ eine gleichverteilte Zufahlszahl zwischen 0 und 1 ist. Anders ausgedrückt muss gelten: diff c ZZ< * ln( ) Dies als Kriterium zu verwenden, ob zu einer Lösung weitergegangen werden soll oder nicht, benötigt keine Fallunterscheidung, ob die neue Lösung jetzt besser, oder schlechter ist, denn falls die neue Lösung besser sein sollte, dann ist „diff“ negativ und sicher immer kleiner als der rechte Ausdruck.

L<-L*beta c<-alpha*c if(c<breakv) break In den letzten Zeilen der inneren Schleife wird einerseits die Kettenlänge „L“ (=Anzahl der zu überprüfenden Zufallslösungen mit konstanter Temperatur) schrittweise um den Faktor „beta“ gesteigert. Außerdem wird die Temperaur gesenkt (um den Faktor „alpha“). Die äußere Schleife (repeat{ }) läuft nun solange, bis die Temperatur unter den vorgegebenen Wert „breakv“ fällt. Die gesamte Anzahl an durchlaufenen Routen kann hier nicht exakt berechnet werden schätzt sich aber so: Sei m die Anzahl der äußeren Schleifendurchläufe

m

breakvc

alpha*

ln( )

ln( )= m ist die aufgerundete Zahl von m*

Dann ist #Routen ungefähr gleich L*(1+beta+beta2+beta3+...+betam-1) Ergebnistabelle:

Datensatz Parameter Lösungen Name c alpha breakv L beta AnzRouten Lösungswert Ulysseus22 2000 0,9 10 10 1,15 87377 7639,94 Mpeano44 1000 0,8 10 20 1,4 58451 8128,91 City51 100 0,9 0,5 70 1,1 89797 613,71 Mpeano92 3000 0,9 30 70 1,1 45740 15324,98 David162 5000 0,9 10 15 1,1 40644 27727,76 Platine280 2000 0,9 20 70 1,05 10577 17562,65

Page 15: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 15 Thomas Ledl, 9702223

4 Graphische Lösungen für Datensätze ulysseus22

Ulysseus22Nearest Neighbour

30

32

34

36

38

40

42

-10 -5 0 5 10 15 20 25 30

Ulysseus22

Local Search

30

32

34

36

38

40

42

-10 -5 0 5 10 15 20 25 30

Ulysseus22

Simulated Annealing

30

32

34

36

38

40

42

-10 -5 0 5 10 15 20 25 30

Page 16: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 16 Thomas Ledl, 9702223

mpeano44 Mpeano44

Nearest Neighbour

0100200300400500600700800900

1000

0 200 400 600 800 1000

Mpeano44

Local Search

0100200300400500600700800900

1000

0 200 400 600 800 1000

Mpeano44

Simulated Annealing

0100200300400500600700800900

1000

0 200 400 600 800 1000

Page 17: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 17 Thomas Ledl, 9702223

City 51

City 51Nearest Neighbour

0102030405060

7080

0 10 20 30 40 50 60 70

City 51Local Search

0102030405060

7080

0 10 20 30 40 50 60 70

City 51

Simulated Annealing

0102030405060

7080

0 10 20 30 40 50 60 70

Page 18: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 18 Thomas Ledl, 9702223

Mpeano92

Mpeano92Nearest Neigbour

0100200300400500600700800900

1000

0 200 400 600 800 1000

Mpeano92

Local Search

0

100

200

300

400

500

600

700

800

900

1000

0 200 400 600 800 1000

Mpeano92

Simulated Annealing

0

100

200

300

400

500

600

700

800

900

1000

0 200 400 600 800 1000

Page 19: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 19 Thomas Ledl, 9702223

David 162

David162Nearest Neighbour

0

100

200

300

400

500

600

700

800

900

1000

0 200 400 600 800 1000

David162Local Search

0

100

200

300

400

500

600

700

800

900

1000

0 200 400 600 800 1000

Page 20: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 20 Thomas Ledl, 9702223

David162Simulated Annealing

0

100

200

300

400

500

600

700

800

900

1000

0 200 400 600 800 1000

Platine 280

Platine 280Nearest Neigbour

0

20

40

60

80

100

120

140

160

180

0 50 100 150 200 250 300 350

Page 21: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 21 Thomas Ledl, 9702223

Platine 280Local Search

0

20

40

60

80

100

120

140

160

180

0 50 100 150 200 250 300 350

Platine 280Simulated Annealing

0

20

40

60

80

100

120

140

160

180

0 50 100 150 200 250 300 350

Page 22: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 22 Thomas Ledl, 9702223

Platine 280Optimale Lösung

0

20

40

60

80

100

120

140

160

180

0 50 100 150 200 250 300 350

5 Fazit Im wesentlichen haben wir die gestellten Aufgaben erfüllt. Sowohl die Programmierung der Algorithmen nach den Vorgaben aus der Vorlesung, sowie die der Bedienung durch das Graphical User Interface (GUI) funktionierte einwandfrei. Dass die bestehenden Aufgaben effizienter programmiert werden können, ist ebenso gewiss, wie die Tatsache, dass die konkret implementierten Algorithmen ebenfalls teilweise unnötige Rechnungen produzieren (des öfteren werden Routen doppelt überprüft). Um solche Verbesserungen durchzuführen, müssten die Algorithmen wesentlich trickreicher programmiert werden. Da im Rahmen dieses Praktikums aber nicht die Programmierung der Algorithmen alleine im Vordergrund stand, sondern ein mindestens ebenso großer Teil die Gestaltung der graphischen Benutzerschnittstelle bzw. die Testläufe mit den Testdatensätzen betroffen hat, erachten wir unseren Aufwand diesbezüglich als ausreichend. Das Programmieren in S-Plus betreffend, haben wir festgestellt, dass diese Programmiersprache eine ziemlich kompakte Handhabung von Vektoren und Matrizen ermöglicht und damit bei solchen und ähnlichen Aufgabenstellungen sicher eine ideale Programmierumgebung darstellt. Nachteilig jedoch befanden wir das Laufzeitverhalten. Wie auch schon aus vorhergehenden Vergleichen mit den Programmiersprachen PASCAL und C bekannt, ist S-Plus wohl nicht gerade das „Schnellste“. Der Grund, warum wir uns trotzdem für S-Plus entschieden haben, war, dass es schnell ein fertiges Programm gibt, mit dem man experimentieren kann. Im Nachhinein wäre es vielleicht doch auch interessant gewesen, eventuell etwas mehr Zeit für die Programmierung aufzuwenden und dafür einen leistungsfähigeren Algorithmus auf wenige (2-3) Datensätze anzuwenden.

Page 23: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 23 Thomas Ledl, 9702223

Um trotzdem halbwegs brauchbare Ergebnisse zu bekommen, führten wir sämtliche Testläufe auf dem PC der Studienrichtungsvertretung Statistik durch, da dieser der schnellste uns zugängliche Rechner war (Pentium 800MHz). Der Vergleich zwischen den drei verwendeten Verfahren brachte folgendes ziemlich eindeutige Ergebnis:

1. Nearest Neighbour mit Teilstreckenoptimierung 2. Simulated Annealing 3. Local Search

Dazu ist folgendes zu sagen: Es wurden ursprünglich 7 Testdatensätze verwendet. Der kleinste hatte 22 Punkte, der größte 666 Punkte. Vier Datensätze hatten weniger als 100 Punkte. Der größte Datensatz wurde im Laufe der Zeit wieder verworfen, weil ein Vergleich der drei Verfahren kaum möglich war, da nur wenige Lösungen berechnet werden konnten und dadurch zB zwischen „Simulated Annealing“ und „Local Search“ kaum Unterschiede aufgefallen wären. Eigentlich sind die beiden anderen Datensätze (162 bzw. 280 Punkte) auch schon ziemlich problematisch. Das Problem ist, dass bei größer werdenden Datensätzen immer mehr Routen überprüft werden müßten, um auf verhältnismäßig gleichgute Lösungen zu kommen, wie bei kleineren Datensätzen, jedoch immer weniger Lösungen überprüft werden können. Da diese „Schere“ ziemlich schnell auseinandergeht, ist die Situation bei so großen Datensätzen hoffnungslos. Der einzige Datensatz, bei denen „Local Search“ und „Simulated Annealing“ mithalten können, ist der 22-Punkte-Datensatz (der kleinste). Hier sind die Lösungen sogar besser als jene der „Nearest Neighbour“-Methode. Der 44- und der 92-Punkte-Datensatz sind künstlich erzeugte Datensätze, für die bewiesen ist, daß der „Nearest Neighbour“-Algorithmus optimal ist. Daher ist hier von vornherein jeder Versuch, den Zielfunktionswert anderweitig zu verbessern zum Scheitern verurteilt. Daß bei dem 51-Punkte-Datensatz der „Simulated Annealing“-Algorithmus eine Chance habe könnte, sieht man dadurch, dass der ZF Wert (614) wesentlich näher an der „Nearest Neighbour“-Lösung (507), als an der „Local Search“-Lösung (831) liegt. Bei den zwei größten Datensätzen zeigt sich jeweils ein klares Bild. Hier gilt die oben beschriebene Reihung einwandfrei. Grundsätzlich ist zu sagen, dass die Teilstreckenoptimierung in den meisten Fällen keine weitere Verbesserung bringt, sondern bereits die „Nearest Neighbour“-Methode alleine reicht. Dies ist deswegen interessant, weil die „Nearest Neighbour“- Methode ja nur n Routen überprüft (wenn n die Anzahl der Punkte ist). Zum „Simulated Annealing“-Algorithmus ist noch zu bemerken, dass wir lange Zeit einen Fehler im Algorithmus hatten und dass einige Zeit verloren ging, ehe wir erkannten, dass die Lösungen die wir herausbekommen hatten nichts anderes als reine Zufallslösungen waren. Das Finden solcher Fehler wird ebenfalls durch die Programmmiersprache S-Plus nicht gerade erleichtert, da S-Plus in den meisten Fällen nur Warning Messages, nicht aber Fehlermeldungen bringt. Die Parameterwahl beim „Simulated Annealing“ wurde in etwa an die Standardabweichung beim Erstellen von Zufallslösungen angebunden. Die

Page 24: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 24 Thomas Ledl, 9702223

Starttemperatur c wurde meist etwas größer als diese Standardabweichung gewählt. Das heißt, dass zu Beginn des Algorithmus zu Lösungen, die um die Differenz einer Standardabweichung zum optimalen ZF-Wert größer sind, mit Wahrscheinlichkeit 1/e=37% gegangen wird. Die Abbruchbedingung war zumeist, dass die Temperatur einen Wert von 1/100 der ursprünglichen Temperatur unterschreitet. Die Anzahl der Temperaturänderungen wurde mit dem Parameter alpha in einem uns sinnvoll erscheinenden Rahmen verändert. Schließlich wurde mit beta noch eingestellt, wie stark die Kettenlänge bei jeder Temperaturveränderung vergrößert wird. Bei 20 oder mehr Temperaturveränderungen ist klar, dass beta nicht wesentlich höher als 1,2 angenommen werden konnte. Die Kettenlänge L bei der ersten Temperatur wurde dann so gewählt, dass die Laufzeit einen sinnvollen Wert erreicht.

Page 25: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 25 Thomas Ledl, 9702223

6 Appendix 1: Sorce Code

laden<-function(Pfad) { source(paste(Pfad,"\\tsp.txt")) source(paste(Pfad,"\\haupt.txt")) source(paste(Pfad,"\\matperm.txt")) source(paste(Pfad,"\\tspperm.txt")) source(paste(Pfad,"\\locsearch.txt")) source(paste(Pfad,"\\allperm.txt")) source(paste(Pfad,"\\simann.txt")) source(paste(Pfad,"\\change.txt")) source(paste(Pfad,"\\fakt.txt")) source(paste(Pfad,"\\nn.txt")) source(paste(Pfad,"\\nn1.txt")) invisible() }

tsp<-function() # Aufbau der Benutzerschnittstelle # Definition der Dialogobjekte und abfangen von Falscheingaben { obj4<-radiobutton.control(label="Distanzmatrix:",begin.group=T,position=c(20,10)) obj5<-radiobutton.control(label="Koordinatenmatrix:",begin.group=F,position=c(20,25)) obj6<-editfield.control(label="",position=c(140,10),size=c(35,10)) obj7<-editfield.control(label="",position=c(140,25),size=c(35,10)) obj10<-statictext.control(value="by Ledl and Niel 2000",position=c(10,190)) obj11<-button.control(label="OK",position=c(20,160),size=c(45,25)) obj21<-radiobutton.control(label="Nearest Neighbour mit Teilstreckenoptimierung",begin.group=T,position=c(20,75)) obj22<-radiobutton.control(label="Local Search",begin.group=F,position=c(20,100)) obj23<-radiobutton.control(label="Simulated Annealing",begin.group=F,position=c(20,125)) obj23a<-editfield.control(label="breakv= ",value="0.1",position=c(170,170),size=c(25,10)) obj31<-slider.control(label="Umgebung: ",boxvalue=5,range=c(3,20),incr=1,vertical=F,size=c(50,10),position=c(20,55)) obj32<-editfield.control(label="alpha= ",value="0.9",position=c(200,140),size=c(25,10)) obj33<-editfield.control(label="c= ",value="10",position=c(140,140),size=c(25,10)) obj34<-editfield.control(label="L= ",value="50",position=c(140,155),size=c(25,10)) obj35<-editfield.control(label="beta= ",value="1.1",position=c(200,155),size=c(25,10)) obj40<-listbox.control(label="Iterationen:",listvalues=c("5","10","20","30","50","100","150","200"),selected=1,hscroll=T,size=c(30,30),position=c(125,100)) obj<-dialogbox(title="TSP-Solver",controls=list(obj4,obj5,obj6,obj7,obj10,obj11,obj21,obj22,obj23,obj

Page 26: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 26 Thomas Ledl, 9702223

23a,obj31,obj32,obj33,obj34,obj35,obj40),size=c(260,200),buttons=character(0)) # Definition der Dialogobjekte a<-dialogbox.display(obj)$values a<-unlist(a) iterationen<-NA;alpha<-NA;beta<-NA;c<-NA;L<-NA;breakv<-NA # Abfangen von Falscheingaben if (a["Distanzmatrix:"]=="Koordinatenmatrix:") index<-3 else index<-2 if (!is.matrix(eval(parse(text=a[index])))) stop ("Das ist keine gueltige Matrix !!!!!") else { D<-eval(parse(text=a[index])) quadratisch<-dim(D)[[1]]==dim(D)[[2]] if (!(((index==2) & (quadratisch) & (dim(D)[1]>5)) | ((index==3) & (dim(D)[[1]]>5) & (sum(c(2,3)==dim(D)[[2]])==1)))) stop ("Die Matrix-Dimension ist ungeeignet !!!!!") else D<-eval(parse(text=a[index])) } if (index==3) D<-change(D) # Umwandlung von Koordinaten in Distanzmatrix if (!(sum(diag(D))==0)) stop ("Die Inputmatrix kann keine Distanzmatrix sein !!!") if (a["Nearest Neighbour mit Teilstreckenoptimierung"]=="Nearest Neighbour mit Teilstreckenoptimierung") welche.methode<-1 else if (a["Nearest Neighbour mit Teilstreckenoptimierung"]=="Local Search") welche.methode<-2 else welche.methode<-3 #as.numeric(a["alpha= "]) tspsolver(welche.methode,D,eval(parse(text=a["Umgebung: "])),as.numeric(a["Iterationen:"]),as.numeric(a["alpha= "]),as.numeric(a["beta= "]),as.numeric(a["c= "]),as.numeric(a["L= "]),as.numeric(a["breakv= "])) # Übergabe an die Berechnungsfunktion } tspsolver<-function(welche.methode,D,umg,iterationen,alpha,beta,c,L,breakv)

Page 27: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 27 Thomas Ledl, 9702223

# Die eigentliche Berechnung findet in dieser # Funktion statt. # #Die NN-Routine mit Teilstrecken-Optimierung benötigt eine #Distanzmatrix D und einen Umgebungsparameter umg # #Die Local-Search-Routine benötigt eine Distanzmatrix D #und einen Parameter umg, der die Größe der Umgebung #festlegt, sowie eine Iterationszahl # #Die Simulated-Annealing-Routine benötigt eine Distanzmatrix D, #einen Umgebungsparameter umg, eine Starttemperatur c und #einen weiteren Parameter alpha (regelt die Abkühl-Geschw.) # und die Kettenlänge L, und break (Wahrschkeit, bei der der #Algorithmus endet { #list(welche.methode=welche.methode,D=D,umg=umg,iterationen=iterationen,alpha=alpha,beta=beta,c=c,L=L,breakv=breakv) if (welche.methode==1) loesung<-nn1(D,umg) else if (welche.methode==2) loesung<-locsearch(D,umg,iterationen) else loesung<-simann(D,umg,alpha,beta,c,L,breakv) } matperm<-function(x,umg) # Teil-Funktion des Simulated-Annealing-Algorithmus # findet zufällig eine geeignete Nachbarschaftslösung { n<-length(x) i<-round(n*runif(1)+0.5) knoten<-i k<-i for (j in 1:(umg)) { knoten<-c(knoten,x[k]) k<-x[k] } mittl.knoten<-knoten[2:umg] tour.neu<-mittl.knoten[sample(umg-1)] x[tour.neu[umg-1]]<-knoten[umg+1] x[i]<-tour.neu[1] for (k in (umg-2):1) {x[tour.neu[k]]<-tour.neu[k+1]} x } tspperm<-function(n) # liefert eine zufaellige Permutation,

Page 28: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 28 Thomas Ledl, 9702223

# die eine zulaessige Loesung des TSP darstellt { perm<-numeric(n) verfuegbar<-2:n i<-1 for (j in 1:(n-1)) { perm[i]<-verfuegbar[trunc(runif(1)*(n-j)+1)] # wählt aus den restlichen Zahlen eine aus verfuegbar<-sort(replace(verfuegbar,(1:(n-j))[verfuegbar==perm[i]],NA)) # nimmt das verw. Element heraus i<-perm[i] } perm[i]<-1 perm } matperm<-function(x,umg) # Teil-Funktion des Simulated-Annealing-Algorithmus # findet zufällig eine geeignete Nachbarschaftslösung { n<-length(x) i<-round(n*runif(1)+0.5) knoten<-i k<-i for (j in 1:(umg)) { knoten<-c(knoten,x[k]) k<-x[k] } mittl.knoten<-knoten[2:umg] tour.neu<-mittl.knoten[sample(umg-1)] x[tour.neu[umg-1]]<-knoten[umg+1] x[i]<-tour.neu[1] for (k in (umg-2):1) {x[tour.neu[k]]<-tour.neu[k+1]} x } allperm<-function(n,origin=T) # liefert alle Permutationen { if (n>2) {

Page 29: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 29 Thomas Ledl, 9702223

Block<-cbind(rep(n,fakt(n-1)),allperm(n-1)) for (j in 2:(n-1)) { A<-allperm(n-1)[,1:(j-1)] B<-allperm(n-1)[,j:(n-1)] Block<-rbind(Block,cbind(A,rep(n,fakt(n-1)),B)) } Block<-rbind(Block,cbind(allperm(n-1),rep(n,fakt(n-1)))) allperm<-Block } if (n==2) allperm<-matrix(c(2,1,1,2),2,2) if (n==1) allperm<-1 if (dim(allperm)[[2]]==n) allperm<-allperm[c(rep(T,fakt(n)-1),origin),] # löscht, falls gewünscht, die elementare Permutation 1:n heraus allperm } simann<- function(D, umg, alpha=0.9, beta=1.1, c=10, L=5, breakv=0.1) # Simulated Annealing-Algorithmus für das TSP (Travelling Salesman Problem) # D ist die nxn-Distanzmatrix { n<-dim(D)[[1]] x<-tspperm(n) # Startlösung getestete.routen<-0 repeat { for(l in 1:L) { getestete.routen<-getestete.routen+1 x.neu<-matperm(x,umg) # neue Umgebung f.loes.alt<-sum(diag(D[x])) f.loes.neu<-sum(diag(D[x.neu])) diff<-f.loes.neu-f.loes.alt if(diff<-c*log(runif(1))) {x<-x.neu} # Vergleich der Lösungen } L<-L*beta c<-alpha*c # neue Temperatur if(c<breakv) break # Abbruchbedingung }

Page 30: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 30 Thomas Ledl, 9702223

list(Methode="Simulated Annealing",D=D,umg=umg,AnzRouten=getestete.routen,Minimum=sum(diag(D[x])),Minimierer=x) } # Ausgabe change<-function(koordinaten) # diese Funktion wandelt Koordinaten in # eine Distanzmatrix um (euklid. Distanz) # koordinaten ist eine nx2- bzw. nx3- Matrix # Output ist eine Distanzmatrix D der Dimension nxn { if (!((dim(koordinaten)[[2]]==2) | (dim(koordinaten)[[2]]==3))) stop("Inputdimension ist nicht 2 oder 3 !!!!!") if (!(dim(koordinaten)[[1]]>1)) stop("Zu wenige Punkte angegeben") if (!(is.numeric(koordinaten))) stop("Das sind keine numerischen Inputwerte !!!!") n<-dim(koordinaten)[[1]] D<-matrix(0,n,n) for (i in 1:(n-1)) for (j in (i+1):n) D[i,j]<-sqrt(sum((koordinaten[i,]-koordinaten[j,])^2)) D<-D+t(D) } fakt<-function(n) # Faktorielle { fakt<-1 for (i in 1:n) fakt<-fakt*i fakt } nn<-function(D,umg) { n<-dim(D)[[1]] verfuegbar<-1:n loesung<-matrix(0,n,n) for (start in 1:n) { i<-start verfuegbar<-(1:n)[-i] #"start" gibt an, von wo die Tour gestartet wird repeat { min<-verfuegbar[(min(D[i,verfuegbar])==D[i,verfuegbar])] min<-min[1]

Page 31: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 31 Thomas Ledl, 9702223

#nimmt das erste Minimum einer Zeile der Distanzmatrix (falls mehrere vork.) loesung[start,i]<-min verfuegbar<-verfuegbar[-(1:length(verfuegbar))[verfuegbar==min]] #löscht die verwendete Zahl aus dem Vektor i<-min if (length(verfuegbar)==0) break #Abbruchbedingung } loesung[start,i]<-start } # Die NN-Lösungen wurden von jedem möglichen Startpunkt ermittelt # Jetzt erfolgt die Teilstreckenoptimierung innerhalb der Umgebung getestete.routen<-n zielfunktionsvektor<-rep(0,n) for (i in 1:n) zielfunktionsvektor[i]<-sum(diag(D[,loesung[i,]])) zahl<-(1:n)[zielfunktionsvektor==min(zielfunktionsvektor)][1] x.stern<-loesung[zahl,] M<-sum(diag(D[,loesung[zahl,]])) # Finden des Minimums für die ersten n Routen #for (i in 1:n) # wähle eine Stelle im Zyklus # { # x<-loesung[i,] # knoten<-i # k<-i # for (j in 1:(umg)) # { # knoten<-c(knoten,x[k]) # k<-x[k] # } # mittl.knoten<-knoten[2:umg] # p.matrix<-matrix(mittl.knoten[allperm(umg-1,F)],fakt(umg-1)-1,(umg-1)) # # bestimme die darauffolgenden Punkte in der konkreten Tour # und alle Permutationen, die dieses Teilstück verändern # in p.matrix stehen alle relevanten Knotenpermutationen # # for (j in 1:(fakt(umg-1)-1)) # { # getestete.routen<-getestete.routen+1 # x<-loesung[i,] # x[p.matrix[j,][umg-1]]<-knoten[umg+1] # x[i]<-p.matrix[j,][1] # for (k in (umg-2):1) # { # x[p.matrix[j,][k]]<-p.matrix[j,][k+1] # }

Page 32: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 32 Thomas Ledl, 9702223

# neue Permutation wird produziert # if (sum(diag(D[,x])) < M) # { # M<-sum(diag(D[,x])) # x.stern<-x # } # } von einem Punkt wurde die gesamte Umgebung durchsucht # } an allen Punkten wurde die Umgebung durchsucht list(Methode="NN mit Teilstreckenoptimierung",umg=umg,AnzRouten=getestete.routen,Minimum=M,Minimierer=x.stern) } nn1<-function(D,umg) { n<-dim(D)[[1]] verfuegbar<-1:n loesung<-matrix(0,n,n) for (start in 1:n) { i<-start verfuegbar<-(1:n)[-i] #"start" gibt an, von wo die Tour gestartet wird repeat { min<-verfuegbar[(min(D[i,verfuegbar])==D[i,verfuegbar])] min<-min[1] #nimmt das erste Minimum einer Zeile der Distanzmatrix (falls mehrere vork.) loesung[start,i]<-min verfuegbar<-verfuegbar[-(1:length(verfuegbar))[verfuegbar==min]] #löscht die verwendete Zahl aus dem Vektor i<-min if (length(verfuegbar)==0) break #Abbruchbedingung } loesung[start,i]<-start } # Die NN-Lösungen wurden von jedem möglichen Startpunkt ermittelt # Jetzt erfolgt die Teilstreckenoptimierung innerhalb der Umgebung getestete.routen<-n zielfunktionsvektor<-rep(0,n) for (i in 1:n) zielfunktionsvektor[i]<-sum(diag(D[,loesung[i,]])) zahl<-(1:n)[zielfunktionsvektor==min(zielfunktionsvektor)][1] x.stern<-loesung[zahl,] M<-sum(diag(D[,loesung[zahl,]]))

Page 33: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 33 Thomas Ledl, 9702223

# Finden des Minimums für die ersten n Routen for (i in 1:n) # wähle eine Stelle im Zyklus { x<-loesung[i,] knoten<-i k<-i for (j in 1:(umg)) { knoten<-c(knoten,x[k]) k<-x[k] } mittl.knoten<-knoten[2:umg] p.matrix<-matrix(mittl.knoten[allperm(umg-1,F)],fakt(umg-1)-1,(umg-1)) # bestimme die darauffolgenden Punkte in der konkreten Tour # und alle Permutationen, die dieses Teilstück verändern # in p.matrix stehen alle relevanten Knotenpermutationen for (j in 1:(fakt(umg-1)-1)) { getestete.routen<-getestete.routen+1 x<-loesung[i,] x[p.matrix[j,][umg-1]]<-knoten[umg+1] x[i]<-p.matrix[j,][1] for (k in (umg-2):1) { x[p.matrix[j,][k]]<-p.matrix[j,][k+1] } # neue Permutation wird produziert if (sum(diag(D[,x])) < M) { M<-sum(diag(D[,x])) x.stern<-x } }# von einem Punkt wurde die gesamte Umgebung durchsucht }# an allen Punkten wurde die Umgebung durchsucht list(Methode="NN mit Teilstreckenoptimierung",umg=umg,AnzRouten=getestete.routen,Minimum=M,Minimierer=x.stern) }

Page 34: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 34 Thomas Ledl, 9702223

Appendix 2: Erklärung der Source-Codes

1) Hilfsfunktionen, die weder mit der eigentlichen Berechnung, noch mit der Benutzerschnittstelle zu tun haben

Funktion „laden“ Diese Funktion dient nur zum automatischen Laden aller relevanten Funktionen ins S-Plus-Programmfenster. Funktion „fakt“ Da keinen Funktion bekannt war, die Fakultät einer Zahl ausrechnet, wurde diese programmiert. Funktion „tspperm“ Diese Funktion liefert eine gültige Zufallslösung für das TSP-Problem. Da es ja bei der Anordnung von n Elementen nur (n-1)! gültige Permutationen gibt, ist immer nur ein ganz kleiner Teil der n! Lösungen zulässig. Beispielsweise wäre bei einer Menge von 5 Punkten und der herkömmlichen Interpretation von TSP-Routen die Permutation (4,1,5,2,3) nicht zulässig. (Man würde von Stadt 1 zu Stadt 4 gehen, von dort zu Stadt 2 und dann wieder zu Stadt 1 zurück → geht nicht; genauso darf an Stelle i der Permutation nicht i stehen, da man nicht von einer Stadt zur selben Stadt gehen kann.) Gelöst wurde dieses Problem folgendermaßen: Es wird jeweils beginnend bei Stadt 1 aus einem Zahlenvorrat der Größe n-1, n-2, n-3, usw. eine Zufallszahl ermittelt und die entsprechende Stelle im Vektor mit den noch zur Verfügung stehenden Zahlen als nächste Stadt gewählt. Beispiel: Es soll eine Route über 16 Städte gelegt werden und 11 Städte sind schon in der Route. Der Vektor der noch verfügbaren Städte sieht zB so aus: (3,9,10,14)........es sind nur mehr 4 Städte über, weil man im letzten Schritt zu Stadt 1 wieder zurück gehen muß (determiniert). Wenn im folgenden nun eine diskrete Zufallszahl von 1 bis 4 ermittelt wird, dann wird nun die entsprechende Stadt (bei ZZ=3 → Stadt Nr. 10) in den Routenvektor an die Stelle jener Stadt geschrieben, von der man im vorherigen Schritt gekommen ist, geschrieben. War zB die letzte Stadt in der Route Stadt Nr. 8, dann würde x[8]=10 gesetzt werden und im nächsten Schritt die nächste Zahl (gewählt aus den verbleibenden Zahlen (3,9,14) auf die Stelle x[10] geschrieben, usw.. Funktion „allperm“ Diese Funktion ist ebenfalls eine Hilfsfunktion und erzeugt rekursiv nach Eingabe einer „Integer“-Zahl (n) alle Permutationen von n Elementen in Matrixform

Page 35: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 35 Thomas Ledl, 9702223

Das sieht so aus: > allperm(3) A B [1,] 3 2 1 [2,] 3 1 2 [3,] 2 3 1 [4,] 1 3 2 [5,] 2 1 3 [6,] 1 2 3 Mit einem optionalen Parameter (typ boolean) kann man noch angeben, ob man die triviale Permutation (1,2,...,n), die immer an letzter Stelle steht, auch haben will. Funktion „matperm“ Diese Funktion wird nur im „Simulated Annealing“-Berechnungsalgorithmus (in der Funktion „simann“) verwendet und dient dazu, eine zufällige „Nachbarschaftslösung“ zu finden. Dies passiert so, dass eine gültige tsp-Permutation , sowie die Größe der „Umgebung“(=Anzahl der aufeinanderfolgenden Kanten die an einer Stelle der Tour verändert werden dürfen) angegeben wird. Dies sei auch anhand eines Beispiels beschrieben: Es existiert die „tsp“-Permutation (4,5,2,3,6,7,1). Man geht also von 1 nach 4, nach 3, nach 2, nach 5, nach 6, nach 7, und wieder zurück nach 1. Die Umgebung sei mit 4 gewählt (dh 4 aufeinanderfolgene Kanten an einer beliebigen Stelle im Zyklus dürfen herausgetrennt und irgendwie anders wieder eingefügt werden). Man entscheidet sich zB (Zufallszahl) bei Stadt Nr. 6 die darauffolgenden 4 Kanten anders anzuordnen. Man muss also nach 4 Kanten wieder bei Stadt 3 ankommen und die Punkte 7, 1 und 4 passieren. Daher wird eine der folgenden Permutationen zufällig gewählt: A B [1,] 4 1 7 [2,] 4 7 1 [3,] 1 4 7 [4,] 7 4 1 [5,] 1 7 4 Die letzte Permutation, die ja genau die gleiche Route liefern würde, wird weggelassen. Zuletzt wird der Routenvektor so modifiziert, dass die Route der gewählten Permutation entspricht. Funktion „change“ Da uns die Wahl unserer Beispieldatensätze dazu zwang, Koordinatenmatrizen, und nicht Distanzmatrizen einzulesen, mußten wir eine Funktion schreiben die solche Koordinatenmatrizen umwandelt. Hierbei beschränkten wir die Umwandlung auf

Page 36: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 36 Thomas Ledl, 9702223

Koordinatenmatrizen aus dem R2 oder R3. Für höhere Dimensionen funktioniert die Funktion genauso. Input ist hier also eine nx2- (bzw. nx3-) Matrix, in der zeilenweise die Punktkoordinaten stehen. Output ist die symmetrische nxn-Distanzmatrix (mit lauter Nullen in der Hauptdiagonale). 2) Die drei Berechnungs-Algorithmen (Details siehe Kapitel 3)

Funktion „nn“ Details siehe Kapitel 3.1 Der „Nearest-Neighbour-Algorithmus“ Funktion „nn1“ source(paste(Pfad,"\\nn1.txt")) Funktion „locsearch“ Details siehe Kapitel 3.2 Hier steht der „Local Search“-Algorithmus drinnen. source(paste(Pfad,"\\locsearch.txt")) Funktion „simann“ Details siehe Kapitel 3.3 Der „Simulated Annealing“-Algorithmus“ source(paste(Pfad,"\\simann.txt")) 3) Die Benutzerschnittstelle (rufendes Hauptprogramm) Funktion "tsp" Die Funktion „tsp“ beinhaltet alle Angaben über die graphische Benutzerschnittstelle (Dialogelemente) sowie einige Plausibilitätsabfragen über Eingabeparameter, die falsch gewählt wurden. „tsp“ ist die Funktion, die beim Start des Programmes aufgerufen wird. Die Funktion erklärt sich eigentlich selbst und verwendet die in Windows üblichen Dialogelemente. Das Abfangen von Falscheingaben betrifft die Dimension der Koordinatenmatrix (nur nx2-, nx3 erlaubt), die Prüfung ob die Distanzmatrix quadratisch (S-Plus hat die Eigenheit, unvollständige Matrizen und Vektoren gelegentlich mit der „Recycling Rule“ aufzufüllen, ohne eine Fehlermeldung zu bringen; das wurde hier unterbunden) und numerisch ist, bzw. ob überhaupt etwas eingegeben wurde.

Page 37: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 37 Thomas Ledl, 9702223

In der Variable „Index“ steht, an wievielter Stelle des Ausgabevektors der Benutzerschnittstelle die für die Berechnung notwendige Matrix zu finden ist. Diese Zahl dient auch zur Unterscheidung ob die Matrix transformiert werden muß (Koordinatenmatrix) oder direkt übernommen werden kann (Distanzmatrix). An „tspsolver“ werden schließlich folgende Variablen übergeben: welche.methode . . . . . . . =1, wenn „Nearest Neigbour“ gewählt wurde, =2 bei „Local Search“ =3 bei Simulated Annealing“ D . . . . . . . . . . . . . . . . . . . die Distanzmatrix umg . . . . . . . . . . . . . . . . . die Größe der Umgebung (auch „integer“) iterationen . . . . . . . . . . . die Anzahl der Iterationen (nur falls „Local Search“

gewählt wurde, ansonsten „NA“ und folgende Variablen, die nur den „Simulated-Annealing“-Algorithmus betreffen und sonst auf „NA“ gesetzt werden: alpha. . . . . . . . . . . . . . . . jener Faktor mit dem die „Temperatur“ gesenkt wird beta. . . . . . . . . . . . . . . . . der Faktor, mit dem die Kettenlänge (L) erhöht wird

(ändert sich immer dann, wenn sich die Temperatur verändert

c. . . . . . . . . . . . . . . . . . . . Starttemperatur L. . . . . . . . . . . . . . . . . . . . Kettenlänge: Die Anzahl der Zufallslösungen in der

„Umgebung“ einer Route, die gesucht werden, und bei denen die Temperatur konstant ist. Die Kettenlänge ändert sich nach jeder Temperaturänderung durch Multiplikation mit dem Faktor beta

breakv. . . . . . . . . . . . . . . die Schranke, die dann den Algorithmus beendet, wenn c

unter diesen Wert gesunken ist Funktion“tspsolver“ Diese Funktion wird direkt am Ende von „tsp“ aufgerufen und bekommt die eben erwähnten Parameter als Inputs. Die einzige Aufgabe dieser Funktion ist es, die eigentliche Berechnungsfunktion des gewählten Algorithmus aufzurufen. Eine eigene Funktion wäre hier zwar nicht notwendig, der Übersichtlichkeit wegen, beziehungsweise weil wir die einzelnen eigentlichen Berechnungs-Algorithmen vom rufenden Programm trennen wollten, sind wir so vorgegangen.

Page 38: Algorithmen zur Lösung des „Travelling Salesman Problem” · 2001-01-13 · Ziel des Projektes sollte die Erstellung eines Tools sein, das mithilfe verschiedener Algorithmen das

Praktikum aus DS WS 2000/01

Paul Niel, 9705566 Seite 38 Thomas Ledl, 9702223

Appendix 3: Screenshot

Appendix 4 Quellenverzeichnis Literatur: Steiner, G. “Simulated Anneling und die Lösung eines verallgemeinerten TSP”, 1995 W.Gutjahr, „Skriptum zur Vorlesung aus Opertions Research“ M.Padberg, M.Grötschel „Die optimierte Odysse“, Spektrum der Wissenschaft, 4/1999 World Wide Web: TSPLIB: http://www.iwr.uni-heidelberg.de/iwr/comopt/TSPLIB95 TSPBIB: http://www.ing.unlp.edu.ar/cetad/mos/TSPBIB_home.html Fractal Instances of the Traveling Salesman Problem: http://www.densis.fee.unicamp.br/~moscato/FRACTAL_TSP_home.html History of TSP: http://www.keck.caam.rice.edu/tsp/history.html Appendix 5 Hardware Benutzte Workstations : - Pentium 3- 700, 128 MB RAM, Win NT - Celeron 466, 64 MB RAM, Win 98 - AMD K6-2 450, 128 MB RAM, Win 98 - Pentium 100, 64 MB RAM, Win 95