Aufgabenblatt

Werbung
Institut für Mathematische Optimierung
Fortgeschrittenenpraktikum - WS2006/07
Vorbereitungsaufgabe: Einfache Heuristiken für das TSP
Dennis Egbers
06.10.2006
Theoretischer Hintergrund
Rundreiseprobleme sind jedem von uns bekannt, da sie in vielfältiger Weise im
eigenen Leben auftauchen. In mathematischer Hinsicht modelliert man Rundreiseprobleme meist durch Graphen G = (V, E). Dabei ist jede Kante (i, j) ∈ E
(i, j ∈ V ) mit einem Gewicht cij versehen, das z.B. die Länge der Strecke zwischen den beiden Orten symbolisiert, die durch die mit der Kante inzidierenden
Knoten repräsentiert werden. Man kann grundsätzlich unterscheiden zwischen solchen Rundreiseproblemen, bei denen alle Kanten eines Graphen durchlaufen werden
müssen, und solchen, bei denen alle Knoten durchlaufen werden müssen.
Wir wollen uns im folgenden mit Rundreiseproblemen des zweiten Types beschäftigen. Ein einfaches und sicher bekanntes Problem dieser Art ist das Hamilton-KreisProblem, bei dem entschieden werden soll, ob ein Graph G hamiltonsch ist.
Definition. Sei G = (V, E) ein (zusammenhängender) Graph. Ein HamiltonKreis ist ein geschlossener Zug von Kanten aus E, der alle Knoten aus V genau einmal enthält. Analog ist ein Hamilton-Pfad ein (gegebenenfalls nicht geschlossener) Zug von Kanten aus E, der alle Knoten aus V genau einmal berührt.
Man nennt einen Graphen hamiltonsch, wenn er einen Hamilton-Kreis enthält,
und semi-hamiltonsch, wenn er einen Hamilton-Pfad enthält, nicht aber einen
Hamilton-Kreis.
Man kann zeigen, dass das Hamilton-Kreis-Problem N P-vollständig ist - im Gegensatz zum Problem, ob es einen Kreis in einem Graphen gibt, der alle Kanten
genau einmal berührt. Dieses Problem, das sogenannte Euler-Tour-Problem, ist
effektiv lösbar.
In praktischen Anwendungen ist man meist nicht nur daran interessiert, einen Hamiltonschen Kreis in einem Graphen zu finden, sondern auch daran, unter allen
solchen Kreisen einen günstigsten zu ermitteln. Auf dieser Fragestellung basiert
das Problem des Handelsreisenden, bei dem man versucht mit möglichst geringen
Gesamtkosten alle Knoten eines Graphen genau einmal zu besuchen.
Definition. Es sei ein vollständiger Graph Kn = (V, E) gegeben mit einer Gewichtsfunktion c : E → R+ . Das Problem des Handlungsreisenden (Traveling-Salesman-Problem, kurz TSP) besteht nun darin, eine Permutation
n
P
π = (π1 , . . . , πn ) der Knoten zu finden, so dass die Gesamtkosten c(π) =
cπi πi+1
(πn+1 = π1 ) der entsprechenden Tour minimal werden.
Man kann verschiedene Typen von TSPs unterscheiden:
i=1
• Wie man einfach sieht, ist das Hamilton-Kreis-Problem ein Spezialfall des
TSP.
• Beim metrischen TSP (∆TSP) erfüllen die Kanten des Graphen stets die
Dreiecksungleichung, d.h. es gilt cij ≤ cih + chj für alle i, j, h ∈ V . Man kann
zeigen, dass das metrische TSP N P-schwierig ist.
• Beim asymmetrischen TSP (ATSP) liegen asymmetrische Kantenkosten
vor, d.h. es gibt Knoten i, j ∈ V , so dass cij 6= cji .
Da das TSP N P-vollständig ist, sind zumindest bei größeren Problemen exakte
Lösungsverfahren kaum praktikabel. Daher ist eine Beschäftigung mit Näherungsverfahren sinnvoll, wobei wir als erstes einige einfache Heuristiken betrachten wollen. Bei allen vorgestellten Verfahren hat die Einfachheit der Algorithmen ihren
Preis: Eine Gütegarantie für die Qualität der Lösungen, die man mit ihnen erhält,
kann man nicht geben.
Nearest-Neighbor-Heuristik: Diese Heuristik ist ein einfaches Greedy-Verfahren.
Man startet mit einem beliebigen Knoten i1 ∈ V und fügt dann sukzessive den noch
nicht besuchten Knoten ein, der zum vorher zur Tour hinzugefügten Knoten die
geringste Distanz aufweist. Ist also eine Teiltour (i1 , . . . , ik ) gegeben, so fügt man
nach ik den Knoten ik+1 ∈ V \ {i1 , . . . , ik } mit minimalen Kosten cik ik+1 zur Tour
hinzu. Der große Nachteil dieses Verfahrens ist, dass man zum Ende häufig Kanten
mit sehr hohen Kosten einfügen muss.
Double-Nearest-Neighbor-Heuristik: Das Verfahren ist eine Erweiterung der
Nearest-Neighbor-Heuristik. Statt den nächsten Knoten nur über die günstigsten
Kosten der Kante vom zuletzt hinzugefügten Knoten zu ermitteln, sucht man einen
Knoten ik , bei dem der Wert min{cik+1 i1 , cik ,ik+1 } minimal ist, und fügt ihn entsprechend vor i1 oder nach ik in die Tour ein.
Nearest-Insertion-Heuristik: Wiederum startet man mit einem beliebigen Knoten i1 . In jedem Schritt fügt man anschließend den Knoten hinzu, der den geringsten
Abstand zur bereits konstruierten Teiltour aufweist. Das Einfügen geschieht an der
Stelle, an der es am günstigsten ist. Genauer: Ist bereits eine Teiltour (i1 , . . . , ik )
k ©
ª
konstruiert, so ermittelt man den Knoten ik+1 , für den der Wert min ciν ik+1
ν=1
minimal ist. Anschließend fügt man ik+1 hinter einem Knoten il ein, so dass die
Einfügekosten cil ik+1 + cik+1 il+1 − cil il+1 minimal sind.
Farthest-Insertion-Heuristik: In dieser Heuristik kümmert man sich zuerst um
die schwierigen Fälle“ d.h. die Knoten, die sehr weit von der bisher konstruierten
”
Teiltour entfernt liegen. Man startet auch hier mit einem beliebigen Knoten und
fügt in jedem Schritt den Knoten ik+1 zur bereits ermittelten Teiltour (i1 , . . . , ik )
ª
k ©
hinzu, bei dem die Kosten max ciν ik+1 maximal sind. Das Einfügen selber geν=1
schieht analog zur Nearest-Insertion-Heuristik.
Cheapest-Insertion-Heuristik: Startend mit einem beliebigen Knoten bestimmt
man sukzessive den Knoten, der sich am günstigsten in die bereits konstruierte
Teiltour einfügen lässt und fügt ihn an der entsprechenden Stelle ein. Ist also die
Teiltour (i1 , . . . , ik ) konstruiert, so bestimmt man einen Knoten ik+1 , der minimale
k ©
ª
Kosten min ciν ik+1 + cik+1 iν+1 − ciν iν+1 aufweist. Anschließend fügt man ik+1 hinν=1
ter dem Knoten l in die Tour ein, für den das entsprechende Minimum angenommen
wird.
Programmieraufgabe
Besuchen Sie die Internetseite
http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/.
Dort findet man diverse Instanzen für unterschiedliche Varianten des TSP. Laden
Sie sich die Dokumentation herunter und lesen sie die FAQ und die Dokumentation
sorgfältig durch, im Verlaufe des Semesters wird stets auf Instanzen aus dieser
Bibliothek oder weitere Instanzen im gleichen Format zurückgegriffen werden.
Schreiben Sie anschließend ein C-Programm, das mittels einer Funktion readdata()
explizit durch untere Dreiecksmatrizen mit Diagonalelementen vorgegebene TSPProbleme korrekt einlesen kann. Dies entspricht in den TSPLIB-Instanzen einem
EDGE WEIGHT FORMAT von LOWER DIAG ROW. Mit Hilfe separater Funktionen sollen
die Nearest-Neighbor, die Farthest-Insertion- und die Cheapest-Insertion-Heuristik
implementiert werden, die Ansteuerung sowohl dieser Methoden als auch der
readdata-Methode soll über eine Methode main() geschehen. Testen sie anschließend Ihr Programm mit den auf der Internetseite der Voranstaltung verfügbaren
Instanzen rheinland.tsp und degbers1.tsp, die dem bekannten Rheinlandproblem und einem fiktiven Urlaub entsprechen, in dem der Praktikumsleiter einen
Großteil seiner Freunde besuchen möchte. Geben sie die Ergebnisse in sinnvoller
Form entweder in eine Datei oder auf die Kommandezeile aus.
Sowohl der Dateiname der zu verarbeitenden Instanz als auch die zu verwendende Heuristik sollen nicht fest in den Programmcode geschrieben werden, sondern
als Kommandozeilenargument oder über die Standardeingabe eingelesen werden.
Gleiches gilt für die Ausgabedatei, wenn die Ergebnisse in eine solche geschrieben
werden. Für die Ansteuerung der Heuristiken überlege man sich dabei sinnvolle
Übergabeparameter, die bei Fehleingabe durch eine Funktion help() angezeigt
werden, die aus der main-Methode automatisch aufgerufen wird.
Der Speicherplatz für die verwendeten Datenstrukturen soll per calloc() oder
malloc() automatisch vom Betriebssystem angefordert werden und zum Ende per
free() freigegeben werden.
Hinweis: Es ist empfehlenswert, zur Speicherung des TSP-Problems eine eigene
Struktur zu verwenden.
Herunterladen