• Keine Ergebnisse gefunden

Optimierung von Routingproblemen mit Genetischen Algorithmen auf Apache Spark

N/A
N/A
Protected

Academic year: 2021

Aktie "Optimierung von Routingproblemen mit Genetischen Algorithmen auf Apache Spark"

Copied!
109
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Bachelorarbeit

Minh Duc Nguyen

Optimierung von Routingproblemen mit Genetischen

Algorithmen auf Apache Spark

(2)

Algorithmen auf Apache Spark

Bachelorarbeit eingereicht im Rahmen der Bachelorpr ¨ufung

im Studiengang Bachelor of Science Angewandte Informatik am Department Informatik

der Fakult¨at Technik und Informatik

der Hochschule f ¨ur Angewandte Wissenschaften Hamburg

(3)

Minh Duc Nguyen

Thema der Arbeit

Optimierung von Routingproblemen mit Genetischen Algorithmen auf Apache Spark Stichworte

Traveling Salesman Problem, genetische Algorithmen, Apache Spark Kurzzusammenfassung

Das Traveling Salesman Problem, welches ein typisches Beispiel f ¨ur ein Routingproblem darstellt, wurde aufgrund seiner Anwendung in der realen Welt bereits in vielen Bereichen weitgehend untersucht. In dieser Arbeit wird eine L ¨osung f ¨ur dieses Problem untersucht, die auf einem genetischen Algorithmus mit dem Parallelverarbeitungs-Framework Apache Spark aufbaut. Die Performance der L ¨osung wird anschließend durch verschiedene Benchmarks analysiert und bewertet.

Minh Duc Nguyen

Title of the paper

Optimization of Routing Problems with Genetic Algorithms on Apache Spark Keywords

Traveling Salesman Problem, Genetic Algorithms, Apache Spark Abstract

The Traveling Salesman Problem, which is a typical example of a routing problem, was already largely studied in many areas because of its applications in the real world. In this thesis, a solution to this problem is proposed, which implements a genetic algorithm with the parallel processing framework Apache Spark. The performance of the solution is then evaluated with various benchmarks.

(4)

1. Einleitung 1

1.1. Ziel der Arbeit . . . 1

1.2. Aufbau der Arbeit . . . 1

2. Grundlagen 3 2.1. Traveling Salesman Problem . . . 3

2.1.1. Definition . . . 3

2.1.2. Formen des Problems . . . 4

2.2. Genetische Algorithmen . . . 5 2.2.1. Kodierung . . . 6 2.2.2. Crossover . . . 7 2.2.3. Mutation . . . 11 2.3. Apache Spark . . . 12 2.3.1. Der Spark-Stack . . . 13

2.3.2. Resilent Distributed Dataset - RDD . . . 14

2.3.3. Architektur . . . 16

3. L¨osungsvorstellung und Umsetzung 18 3.1. Der genetische Algorithmus als L ¨osung f ¨ur das TSP . . . 18

3.1.1. Improved Genetic Algorithm - IGA . . . 18

3.1.2. Umsetzung des IGAs . . . 26

3.2. Genetischer Algorithmus auf dem Cluster mit Apache Spark . . . 31

3.2.1. Multi-Island-Modell . . . 31

3.2.2. Umsetzung des Multi-Island-Modells mit Apache Spark . . . 32

4. Auswertung 38 4.1. Aufbau der Benchmarks . . . 38

4.1.1. Hardware und Software . . . 38

4.1.2. Testdaten . . . 38

4.1.3. Aspekte der Benchmarks . . . 39

4.1.4. Ablauf der Benchmarks . . . 39

4.2. Die Benchmarks . . . 40

4.2.1. Genetischer Algorithmus mit verschiedenen Einstellungen . . . 40

4.2.2. Genetischer Algorithmus auf Cluster mit verschiedenen Gr ¨oßen . . . 50

(5)

Inhaltsverzeichnis

5. Bewertung der Ergebnisse 62

5.1. Einstellungen f ¨ur genetische Algorithmen auf dem Cluster . . . 62

5.2. Die Gr ¨oße des Clusters . . . 64

5.3. Standalone-IGA und IGA auf dem Cluster . . . 65

6. Zusammenfassung und Ausblick 66

6.1. Zusammenfassung . . . 66

6.2. Ausblick . . . 67

Anhang 68

A. Rohdaten der Benchmark-Ergebnisse 69

A.1. Genetischer Algorithmus mit verschiedenen Einstellungen . . . 69

A.2. Genetischer Algorithmus auf Cluster mit verschiedenen Gr ¨oßen . . . 82

(6)

2.1. Bin¨are Kodierung, Quelle:Kumar(2013), S. 4 . . . 6

2.2. Wertskodierung, Quelle:Kumar(2013), S. 5 . . . 7

2.3. Baumskodierung, Quelle:Kumar(2013), S. 5 . . . 7

2.4. Permutationskodierung, Quelle:Kumar(2013), S. 5 . . . 7

2.5. Apache Spark Stack, Quelle:Scott(2015a), S. 17 . . . 13

2.6. RDD von Strings und RDD von Paare, Quelle:Laskowski(a) . . . 15

2.7. Abh¨angigkeiten von RDDs, Quelle:Zaharia u. a.(2012) . . . 16

2.8. Spark-Cluster, Quelle:Spark(b) . . . 17

3.1. Entit¨aten vom Improved Genetic Algorithm (IGA) . . . 27

3.2. Multi-Island-Modell, Quelle:Shrestha und Mahmood(2016), S. 32 . . . 33

3.3. Architektur f ¨ur die Umsetzung desIGAs mit Apache Spark . . . 34

4.1. Performancevergleich verschiedener Einstellungen f ¨ur rd100 nach Tourenl¨ange 42 (a). Zeitraum zwischen 10. Sekunde und 50. Sekunde . . . 42

(b). Zeitraum zwischen 10. Sekunde und 40. Sekunde . . . 42

4.2. Performancevergleich verschiedener Einstellungen f ¨ur rd100 nach Generationen 43 4.3. Performancevergleich verschiedener Einstellungen f ¨ur qa194 nach Tourenl¨ange 45 (a). Zeitraum zwischen 10. Sekunde und 140. Sekunde . . . 45

(b). Zeitraum zwischen 20. Sekunde und 100. Sekunde . . . 45

4.4. Performancevergleich verschiedener Einstellungen f ¨ur qa194 nach Generationen 46 4.5. Performancevergleich verschiedener Einstellungen f ¨ur pcb442 nach Tourenl¨ange 48 (a). Zeitraum zwischen 20. Sekunde und 600. Sekunde . . . 48

(b). Zeitraum zwischen 100. Sekunde und 450. Sekunde . . . 48

4.6. Performancevergleich verschiedener Einstellungen f ¨ur pcb442 nach Generationen 49 4.7. Performancevergleich verschiedener Einstellungen f ¨ur lu980 nach Tourenl¨ange 51 (a). Zeitraum zwischen 500. Sekunde und 4000. Sekunde . . . 51

(b). Zeitraum zwischen 1400. Sekunde und 2800. Sekunde . . . 51

4.8. Performancevergleich verschiedener Einstellungen f ¨ur lu980 nach Generationen 52 4.9. Performancevergleich verschiedener Cluster f ¨ur rd100 nach Tourenl¨ange . . . 53

4.10. Performancevergleich von verschiedenen Cluster f ¨ur qa194 nach Tourenl¨ange 55 4.11. Performancevergleich verschiedener Cluster f ¨ur pcb442 nach Tourenl¨ange . . 57

(a). Zeitraum zwischen 20. Sekunde und 300. Sekunde . . . 57

(b). Zeitraum zwischen 50. Sekunde und 300. Sekunde . . . 57

(7)

Abbildungsverzeichnis

B.1. Vergleich der besten Tour und der bisher bekannten optimalen Tour vom rd100-Problem . . . 92

(a). Die beste Tour . . . 92

(b). Bisher bekannte optimale Tour . . . 92

B.2. Vergleich der besten Tour und der bisher bekannten optimalen Tour vom qa194-Problem . . . 93

(a). Die beste Tour . . . 93

(b). Bisher bekannte optimale Tour . . . 93

B.3. Vergleich der besten Tour und der bisher bekannten optimalen Tour vom pcb442-Problem . . . 94

(a). Die beste Tour . . . 94

(b). Bisher bekannte optimale Tour . . . 94

B.4. Vergleich der besten Tour und der bisher bekannten optimalen Tour vom lu980-Problem . . . 95

(a). Die beste Tour . . . 95

(8)

3.1. Eigenschaften des genetischen Algorithmus’ beim TSP . . . 19

4.1. Performancevergleich verschiedener Einstellungen f ¨ur rd100 . . . 41

4.2. Performancevergleich verschiedener Einstellungen f ¨ur qa194 . . . 44

4.3. Performancevergleich verschiedener Einstellungen f ¨ur pcb442 . . . 47

4.4. Performancevergleich verschiedener Einstellungen f ¨ur lu980 . . . 50

4.5. Performancevergleich verschiedener Cluster f ¨ur rd100 . . . 54

4.6. Performancevergleich von verschiedenen Cluster f ¨ur qa194 . . . 54

4.7. Performancevergleich verschiedener Cluster f ¨ur pcb442 . . . 56

4.8. Performancevergleich verschiedener Cluster f ¨ur lu980 . . . 59

4.9. Ergebnisvergleich von rd100 . . . 59

4.10. Ergebnisvergleich von qa194 . . . 59

4.11. Ergebnisvergleich von pcb442 . . . 60

(9)

Listings

3.1. Pseudocode f ¨urIGA . . . 20 3.2. Pseudocode f ¨ur SwapInvertedCrossover-Operation . . . 22 3.3. Pseudocode f ¨ur Multi-Mutation-Operation . . . 24 3.4. Pseudocode f ¨ur Reformulate-Operation . . . 25 3.5. Pseudocode f ¨ur Rearrangement-Operation . . . 26 3.6. Java-Kode f ¨ur evolvePopulation()-Methode . . . 27 3.7. Java-Kode f ¨ur swapInvertedCrossover()-Methode . . . 28 3.8. Java-Kode f ¨ur reformulate()-Methode . . . 28 3.9. Java-Kode f ¨ur mutate()-Methode . . . 29 3.10. Java-Kode f ¨ur rearrange()-Methode . . . 30

3.11. Java-Kode f ¨ur Methoden von der Packet-Klasse vgl.Dommerholt(b) . . . 35

3.12. Java-Kode f ¨ur Methoden von der PacketFactory-Klasse . . . 35

3.13. Scala-Kode f ¨ur die Organiser-Klasse vgl.Dommerholt(a) . . . 37

A.1. Performancetest f ¨ur rd100-Problem bei der Einstellung 10 x 1600 . . . 69

A.2. Performancetest f ¨ur rd100-Problem bei der Einstellung 80 x 200 . . . 69

A.3. Performancetest f ¨ur rd100-Problem bei der Einstellung 125 x 128 . . . 70

A.4. Performancetest f ¨ur rd100-Problem bei der Einstellung 200 x 80 . . . 70

A.5. Performancetest f ¨ur rd100-Problem bei der Einstellung 1600 x 10 . . . 71

A.6. Performancetest f ¨ur qa194-Problem bei der Einstellung 20 x 2000 . . . 72

A.7. Performancetest f ¨ur qa194-Problem bei der Einstellung 80 x 500 . . . 72

A.8. Performancetest f ¨ur qa194-Problem bei der Einstellung 200 x 200 . . . 73

A.9. Performancetest f ¨ur qa194-Problem bei der Einstellung 500 x 80 . . . 74

A.10. Performancetest f ¨ur qa194-Problem bei der Einstellung 2000 x 20 . . . 74

A.11. Performancetest f ¨ur pcb442-Problem bei der Einstellung 25 x 3000 . . . 75

A.12. Performancetest f ¨ur pcb442-Problem bei der Einstellung 150 x 500 . . . 76

A.13. Performancetest f ¨ur pcb442-Problem bei der Einstellung 250 x 300 . . . 77

A.14. Performancetest f ¨ur pcb442-Problem bei der Einstellung 500 x 150 . . . 77

A.15. Performancetest f ¨ur pcb442-Problem bei der Einstellung 3000 x 25 . . . 78

A.16. Performancetest f ¨ur lu980-Problem bei der Einstellung 50 x 2500 . . . 79

A.17. Performancetest f ¨ur lu980-Problem bei der Einstellung 250 x 500 . . . 79

A.18. Performancetest f ¨ur lu980-Problem bei der Einstellung 350 x 357 . . . 80

A.19. Performancetest f ¨ur lu980-Problem bei der Einstellung 500 x 250 . . . 80

A.20. Performancetest f ¨ur lu980-Problem bei der Einstellung 2500 x 25 . . . 81

(10)

A.22. Performancetest f ¨ur rd100-Problem auf 2-Nodes-Cluster . . . 82

A.23. Performancetest f ¨ur rd100-Problem auf 4-Nodes-Cluster . . . 82

A.24. Performancetest f ¨ur qa194-Problem auf 1-Node-Cluster . . . 83

A.25. Performancetest f ¨ur qa194-Problem auf 2-Nodes-Cluster . . . 83

A.26. Performancetest f ¨ur qa194-Problem auf 4-Nodes-Cluster . . . 84

(11)

1. Einleitung

Das Traveling Salesman Problem (TSP) ist ein klassischer Fall eines kombinatorischen Op-timierungsproblems. TSP wurde in den Bereichen k ¨unstliche Intelligenz, Graphentheorie, Mathematik und Informatik aufgrund seiner Anwendungen in der realen Welt weitgehend untersucht. Genaue, ungef¨ahre und sehr intelligente Methoden sind weitgehend f ¨ur TSP kon-zipiert. Die genauen Methoden verschwenden Zeit und Memory und sind in der Regel nicht erreichbar, da der Suchraum von TSP mit der Fakult¨at von der Problemgr ¨oße w¨achst. Ge-netischer Algorithmus (GA) ist ein globaler Suchalgorithmus, der f ¨ur Probleme mit großem Suchraum sehr geeignet ist, in unserem Fall: TSP. Inspiriert durch die Evolutionsbiologie, setzt der GA Selektions-, Crossover- und Mutationsoperationen ein, um den L ¨osungs-Suchraum zu durchqueren. Diese Algorithmen basieren in Wesentlichen auf den zuf¨alligen Werte um die Mutanten zu finden, die m ¨oglicherweise Verbesserungen f ¨ur n¨achsten Generationen bringen k ¨onnen. Dabei ist die Anzahl der Versuche zu dem Erfolg des Algorithmus’ theoretisch sehr relevant.

1.1. Ziel der Arbeit

In dieser Arbeit versuchen wir das Problem in der Richtung einer Umsetzung von einem genetischen Algorithmus auf einem verteilten System anzun¨ahern. Mithilfe von Apache Spark Framework und das bekannte Multi-Island-Modell, wo Instanzen des GAs getrennt laufen und die besten Ergebnisse periodisch ausgetauscht werden, wird ein verbesserter GA implementiert. Die Performance der zu implementierenden L ¨osung werden wir in dieser Arbeit durch mehrere Benchmarks ausgewertet und bewertet.

1.2. Aufbau der Arbeit

In Kapitel 2 werden die theoretischen Grundlagen besprochen. Dabei werden die grundlegenden Aspekte von Traveling Salesman Problem untersucht und es wird insbesondere dabei auf die genetischen Algorithmen eingegangen. Dazu ist die Vorstellung von Apache Spark als Hilfe f ¨ur die Umsetzung des genetischen Algorithmus’ auf verteiltem System. In Kapitel 3 wird

(12)

der L ¨osungsansatz f ¨ur die Umsetzung erleuchten sowie die Implementierung im Details (mit Pseudocode und echtem Kode) beschrieben. Kapitel 4 wertet die Ergebnisse des umgesetzten Algorithmus’ auf Apache-Spark-Cluster in Form von Benchmarks aus, um die Aspekte der Benchmarks zu kl¨aren. Abschließend erfolgt eine Bewertung der Ergebnisse in Kapitel 5 gefolgt von einer Zusammenfassung mit Ausblick in Kapitel 6.

(13)

2. Grundlagen

F ¨ur das Verst¨andnis dieser Forschungsarbeit ist Wissen aus unterschiedlichen Fachdisziplinen notwendig. Der Schwerpunkt der Arbeit liegt auf der Untersuchung einer neuen Methode zum L ¨osen des Traveling Salesman Problems (TSPs). Zuerst wird das Traveling Salesman Problem vorgestellt. Die Elemente, auf denen die neue Methode basiert, werden auch in diesem Kapitel begrifflich eingegangen, n¨amlich genetische Algorithmen und Apache Spark.

2.1. Traveling Salesman Problem

In diesem Abschnitt wird zuerst in die Definition des TSPs eingegangen. Anschließend werden einige der Formen des TSPs vorgestellt.

2.1.1. Definition

Das Traveling Salesman Problem beschreibt folgendes Szenario: Zu finden ist eine Tour mit einer bestimmten Anzahl von St¨adten, jede Stadt genau einmal zu besuchen und am Ende in die erste Stadt zur ¨uckzukehren (diese Stadt wird folglich zweimal besucht). Gleichzeitig soll seine Tour durch alle St¨adte m ¨oglichst kurz sein. [vgl.Bryant(2000), S. 20]

In das Buch ”

Der Handlungsreisende, wie er sein soll und was er zu thun hat, um Auftr¨age zu erhalten und eines gl ¨ucklichen Erfolgs in seinen Gesch¨aften gewiss zu sein. Von einem alten Commis-Voyageur“ von BF Voigt im Jahr 1832 wurde Traveling Salesman Problem zum ersten Mal vorgestellt. Obwohl das Problem nicht unter dem Namen TSP, wurde das Wesen des Problems in diesem Buch erreicht, indem es betont wird, dass um so viele Orte wie m ¨oglich zu decken, ohne irgendeinen Ort zweimal zu besuchen, der wichtigste Aspekt der Planung einer Tour. [vgl.Lawler u. a.(1985), S. 5]

Das Traveling Salesman Problem kann man mathematisch wie folgt beschreiben: Angenommen es gibtn durch den Salesman zu besuchende St¨adte. ci,jsei die Entfernung von Stadti und Stadt j. Zu suchen ist eine Tour durch alle St¨adte genau einmal, sodass die Summer der Entfernung

(14)

m ¨oglichst klein ist. Jede m ¨ogliche Tour ist eine Permutation von123. . . n, also die Anzahl der m ¨oglichen Touren istn!. Wenn n groß wird, wird es unm¨oglich, die Kosten f¨ur jede Tour in der Polynomialzeit zu finden, also wir konfrontieren hier ein NP-Hard Problem. [vgl.Bryant

(2000), S. 20 f.] In [Lawler u. a.(1985), S. 11 ] wurde behauptet: Obwohl die H¨arte des TSPs nicht impliziert, dass exponentielle Worst-Case-Laufzeiten f ¨ur seine L ¨osungen unvermeidbar sind, dient es dazu, den Glauben zu verst¨arken, dass die Existenz eines Polynomialalgorithmus f ¨ur das TSP ¨außerst unwahrscheinlich ist: Die Konsequenzen eines solchen Algorithmus sind Dramatisch jenseits des Glaubens. F ¨ur TSP wurden seit Jahren mehreren L ¨osungen entwickelt, nat ¨urlich mit gem¨aßen Kompromissen.

2.1.2. Formen des Problems

MitVehicle-Routing bezeichnen wir das Problem der Bestimmung f¨ur eine Fahrzeugflotte, wel-che Kunden von welwel-chen Fahrzeugen bedient werden sollten und in welwel-cher Reihenfolge jedes Fahrzeug seine Kunden besuchen sollte. Hierbei m ¨ussen die Einschr¨ankung der Anzahl von Fahrzeugen sowie die Zeitfenster der Kunden eingehalten werden. [vgl.Lawler u. a.(1985), S. 18] Es gibt verschiedene Variationen dieses Problems, bei denen z. B. die den Zeitraum, in dem die Kundenanforderungen erf ¨ullt werden m ¨ussen. Mit den L ¨osungen f ¨ur TSP k ¨onnen einigen dieser Probleme gel ¨ost werden.

Das Problem der Computer-Wiring kann auch als TSP modelliert werden. Ein System be-steht aus einer Anzahl von Modulen und mehreren Pins sind auf jedem Modul angeordnet. Die physische Position jedes Moduls wurde bestimmt. Eine Teilmenge dieser Pins mit Kabel m ¨ussen so verbunden werden, dass h ¨ochstens zwei Kabel an beliebigen Pins befestigt werden sollen und die Gesamtl¨ange der Kabel minimiert wird (Um Signal ¨uberquerung zu vermeiden) [vgl.Lawler u. a.(1985), S. 18]. Wenn wir die Pins als St¨adten betrachten und die L¨ange jedes Kabels die ihre Entfernung, erhalten wir ein TSP-¨ahnliches Problem.

DieJob-Sequenzierung ist auch ein TSP-¨ahnliches Problem. Angegeben sind n auszuf¨uhrende Jobs. Die Reihenfolge der Ausf ¨uhrungen sind frei zu entscheiden und das Ziel ist es, alle in k ¨urzester Zeit fertigzustellen. [vgl.Lawler u. a.(1985), S. 19] Dass die Ausf ¨uhrungszeiten von aller Jobs sind Konstanze, variieren hierbei nur noch die Vorbereitungsaufwandci,jzwischen zwei Jobsi und j. Wenn wir nun die Jobs als St¨adte ansehen und die Vorbereitungszeiten als den Abstand zwischen den St¨adten, handelt es hier um ein TSP-Problem.

(15)

2. Grundlagen

2.2. Genetische Algorithmen

Genetische Algorithmen (GA) sind Optimierungsmethoden, die auf der nat ¨urlichen Evolution basieren. In der Natur sind die St¨arksten am ehesten zu ¨uberleben und zu paaren. Deshalb sollte die n¨achste Generation fitter und ges ¨under sein, weil sie von gesunden Eltern geboren wurden. [vgl. Bryant(2000), S. 2] Genetische Algorithmen wurden von dem biologischen Genetik-Modell inspiriert. Aus diesem Grund stammt der Großteil seiner Terminologie aus der Genetik. Nach genetische Theorie sind Genotyp und Ph¨anotyp zwei Arten von R¨aumen, auf denen genetische Algorithmen arbeiten. Genotyp heißt kodierungsraum und Ph¨anotyp beschreibt das ¨

außere Erscheinungsbild eines Individuums. Eine Transformation existiert zwischen Genotyp und Ph¨anotyp (auch Mapping genannt), die die genotypischen Informationen verwendet, um den Ph¨anotyp zu konstruieren. Ein Chromosom, also ein Individuum in kodierungsraum, bezieht sich auf einen String von bestimmter L¨ange, wo alle genetischen Informationen eines Individuums gespeichert sind. [vgl.Kumar(2013), S. 2]

Ein genetisches Algorithmus besteht aus folgenden Schritten:

Kodierung ⇒ Auswertung ⇒ Crossover ⇒Mutation ⇒ Dekodierung

Eine geeignete Kodierungsmethode soll f ¨ur die L ¨osung unseres Problems gefunden werden, sodass jede m ¨ogliche L ¨osung eine eindeutige Kodierung hat […]. Die initiale Population wird meist zuf¨allig ausgew¨ahlt, obwohl auch alternative Techniken mit Heuristiken genutzt werden k ¨onnen. […] Unter Auswertung versteht man in diesem Zusammenhang die Berechnung der Fitness eines Individuums. Die Fitness beschreibt, wie gut sich das Individuum dem Problem anpasst und ob es in der N¨ahe des Optimums im Vergleich zu den anderen Individuen in der Population ist. Diese Fitness wird verwendet, um zu entscheiden, ob das Individuum der Fitness qualifiziert f ¨ur Crossover ist. Je h ¨oher die Fitness, desto besser ist die Chance. Ein Crossover beschreibt die Rekombination zweier Individuen, aus der ein neues Individuum einer neuen Generation entsteht. Darauf folgt die Mutation. Einige Individuen werden zuf¨allig ausgew¨ahlt, um an einem zuf¨allig ausgew¨ahlten Punkt zu mutieren. Die Reihenfolge des entsprechenden Individuums wird mit Tauschen der Positionen ver¨andert. Sobald dies geschehen ist, wurde eine neue Generation gebildet und der Prozess wird wiederholt, bis gewisse STOPP-Kriterien erf ¨ullt sind. An dieser Stelle wird das dem Optimum am n¨achsten liegende Individuum decodiert und der Vorgang abgeschlossen. [vgl.Bryant(2000) S. 2 f.]

(16)

Abbildung 2.1.: Bin¨are Kodierung, Quelle:Kumar(2013), S. 4

2.2.1. Kodierung

In diesem Abschnitt werden wir m ¨ogliche Schema zur Kodierung verschiedener Probleme untersuchen. Abh¨angig von der Struktur der Kodierung k ¨onnen sie in 1-dimensional und 2- dimensional klassifiziert werden. 1-dimensionale Schema sind: Bin¨ar, Oktal, Hexadezimal, Permutation.

2.2.1.1. Bin¨are Kodierung

Bin¨are Kodierung ist die h¨aufigste und einfachste Form der Kodierung. Bei diesem Kodie-rungsschema werden Nullen und Einsen verwendet, um Chromosomen zu konstruieren. Jeder bin¨are String repr¨asentiert einen Wert (Siehe Abbildung2.1). Dabei bestehen viele m ¨ogliche Chromosomen auch aus einer kleinen Anzahl von Allelen (hier Nullen und Einsen). Dieses Kodierungsschema kann zum Beispiel beim Knappsack Problem verwendet werden, wo die Kodierung das Vorhandensein der Elemente andeutet, also mit 1 gekennzeichnet ist. Diese Kodierung ist oft nicht nat ¨urlich f ¨ur viele Probleme und manchmal m ¨ussen Korrekturen nach Crossover und / oder Mutation erfolgen. [vgl.Kumar(2013), S. 3 f.]

2.2.1.2. Wertskodierung

Bei Problemen, bei denen komplexe Werte existieren wie z. B. reelle Zahlen, w¨are die Ver-wendung einer bin¨aren Kodierung sehr schwierig. Direkte Wertkodierungen setzen Werte als Allelen ein. Dabei ist jedes Chromosom ein String von einigen Werten. Diese Werte k ¨onnen Zahlen, reale Zahlen, Zeichen oder auch komplizierte Objekte sein (Siehe Abbildung2.2). Beim Finden von Gewichten f ¨ur ein neuronales Netz kann dieses Kodierungsschema sehr effizient eingesetzt werden. [vgl.Kumar(2013), S. 5]

2.2.1.3. Baumskodierung

Die Baum-Kodierung wird haupts¨achlich f ¨ur die Entwicklung von Programmen oder Aus-dr ¨ucken f ¨ur die genetische Programmierung verwendet. In der Baum-Kodierung ist jedes

(17)

2. Grundlagen

Abbildung 2.2.: Wertskodierung, Quelle:Kumar(2013), S. 5

Abbildung 2.3.: Baumskodierung, Quelle:Kumar(2013), S. 5

Chromosom ein Baum mit Objekten wie Funktionen oder Befehlen einer Programmiersprache (Siehe Abbildung2.3). [vgl.Obitko]

2.2.1.4. Permutationskodierung

Die Permutationskodierung ist f ¨ur Reihenfolgeprobleme (insbes. Traveling Salesman Problem, Task-Ordering) sehr geeignet. Bei der Permutationskodierung ist jedes Chromosom eine Zeichenfolge, das Elemente in einer Sequenz darstellt. [vgl.Obitko] Zum Beispiel repr¨asentiert beim Traveling Salesman Problem die Zeichenfolge von Zahlen die Reihenfolge der St¨adte, die besucht werden sollen (Siehe Abbildung2.4).

2.2.2. Crossover

Die Motivation f ¨ur den Einsatz von Crossover wurde in [Heistermann(1994), S. 107] beleuchtet:

Der wesentliche Vorteil eines genetischen Algorithmus gegen ¨uber anderen Verfahren ist die

(18)

horizontale Informations ¨ubertragung. Eine Population von Individuen arbeitet zusammen, indem jeweils zwei dieser Individuen gemeinsame Nachkommen zeugen. [. . . ] Die Aufgabe der Rekombination besteht aus der Erzeugung eines neuen Individuums durch geeignete Kombination zweier Individuen“. Hierbei kann man

Rekombination“ als eine andere Aus-drucksm ¨oglichkeit von Crossover verstehen. Typ und Implementierung des Crossover h¨angt von dem Kodierungsverfahren und auch von der Problemstellung ab. In diesem Kapitel sind nur einige Beispiele und Anregungen f ¨ur mehrere Kodierungen genannt.

2.2.2.1. Crossover f ¨ur bin¨are Kodierung

F ¨ur diese Kodierungsform stehen typischerweiseSingle-Point- und Two-Points-Crossover zur Verf ¨ugung.

Der Single-Point-Crossover zielt darauf ab, Bit-Strings zwischen zwei Eltern-Chromosomen zu tauschen. Durch Zufall wird eine Position zwischen 1 undn-1 entlang einer der Eltern-chromosomen gew¨ahlt, wobein die L¨ange des Chromosoms ist. Diese Position nennt man Crossover-Punkt. Von diesem Crossover-Punkt werden die Elternchromosomen jeweils in zwei Teile geschnitten, um zwei nachkommende Chromosomen zu erzeugen. [vgl.Potvin(1996), S. 346] Der Bin¨arstring vom Beginn eines Chromosoms bis zum Crossover-Punkt wird jeweils von einem Elternteil kopiert, der Rest wird aus dem anderen Elternteil kopiert [vgl.Obitko]. In der Figur ist der Crossover-Punkt in der Position 3:

parent1 = 110|001 parent2 = 010|111

Erhalten wir:

child1 = 110|111 child2 = 010|001

Two-Points-Crossover hat die gleiche Arbeitsweise wie Single-Point-Crossover. Der wesentliche Unterschied besteht darin, dass dieses Mal zwei Crossover-Punkte ausgew¨ahlt werden: Die Zeichenfolge vom Beginn des Chromosoms zum ersten Crossover-Punkt (und vom zweiten Crossover-Punkt zum Ende) wird kopiert und die bin¨are Zeichenfolge vom ersten zum zweiten

(19)

2. Grundlagen

Crossover-Punkt dient als Austausch-Komponente mit dem jeweils anderen Elternteil. [vgl.

Obitko] parent1 = 11|00|01 parent2 = 01|01|11 Erhalten wir: child1 = 11|01|01 child2 = 01|00|11 2.2.2.2. Crossover f ¨ur Permutationskodierung

Bei dieser Form steht die Reihenfolge im Zentrum der Kodierung. ¨Anderungen an einer Stelle k ¨onnen zu ung ¨ultigen Chromosomen f ¨uhren. Hierbei sind reineSingle-Point-Crossover und Two-Points-Crossover nicht mehr geeignet. Daf¨ur wurden erweiterte Crossover-Verfahren ent-wickelt, die auf den beiden vorgestellten Crossover-Varianten basieren.

Partially Matches Crossover (PMX) versucht, Kinder so ¨ahnlich wie Eltern zu erhalten. Die-ser Operator w¨ahlt zuerst zuf¨allig zwei Crossover-Punkte auf beiden Elternteilen aus. Um ein Kind zu erzeugen, ersetzt der Teilstring zwischen den beiden Crossover-Punkten im ers-ten Elternteil den entsprechenden Teilstring im zweiers-ten Elternteil. Dann wird der inverse Ersatz außerhalb der Crossover-Punkten angewendet, um Duplikate zu eliminieren und alle St¨adte wiederherzustellen. [vgl.Potvin(1996), S. 351] Als Beispiel verwenden wir diese zwei ganzzahligen Darstellungen zur Kodierung des TSPs:

parent1 = 123|4567|89 parent2 = 169|8473|25

Angenommen, die Positionen 4 bis 7 sind f ¨ur dasTwo-Points-Crossover ausgew¨ahlt. Nach der Ausf ¨uhrung desTwo-Points-Crossovers erhalten wir:

child1 = 123|8473|89 child2 = 169|4567|25

(20)

Die beiden Kinderchromosomen sind offensichtlich ung ¨ultig da child1 die St¨adte 5 und 6 verpasst und zugleich zweimal die St¨adte 8 und 3 besucht. Solche Probleme existieren auch beimchild2. In dieser Situation bietet PMX eine Erweiterung, um diese Fehler zu beheben. Die beiden Nachkommen sind wie folgt gegeben, wenn wir jeweils eine der widerspr ¨uchlichen Positionen durch * ersetzen:

child1 = 12 ∗ |8473| ∗ 9 child2 = 1 ∗ 9|4567|2∗

Jetzt nehmen wir die widerspr ¨uchlichen Positionen und tauschen diese mit dem ¨Uberschuss des anderen Nachkommen aus:

child1 = 126|8473|59 child2 = 139|4567|28

Order Crossover (OX) basiert auf dem Prinzip, dass die Reihenfolge der St¨adte im Vergleich zu ihren Positionen in der Tour wichtiger ist. ¨Ahnlich wie bei PMX tauscht OX zwei ausgerichtete Teilstrings aus. Anstatt das Chromosom zu reparieren, indem man die Wiederholungen eines jeden Knotens austauscht, ordnen wir einfach den Rest der Gene so an, dass sie eine juristische Tour ergeben. [vgl.Bryant(2000), S. 14] Wir betrachten die obigen Beispiele wie f ¨ur PMX:

parent1 = 123|4567|89 parent2 = 169|8473|25

Wir fangen damit an, die Teilstrings zwischen den beiden Crossover-Punkten zu ersetzen:

child1 = ∗ ∗ ∗|8473| ∗ ∗ child2 = ∗ ∗ ∗|4567| ∗ ∗

Dann schreiben wie die Gene aus jedem Elternchromosom ab dem zweiten Crossover-Punkt auf.

parent1 = 891234567 parent2 = 251698473

(21)

2. Grundlagen

ann werden die Gene, die zwischen den Crossover-Punkten waren, gel ¨oscht. Z. B. bei parent1 die St¨adte 8, 4, 7, 3:

of f spring1 = 91256 of f spring2 = 21983

Jetzt f ¨ugen wir diese Liste inoffspring1 und offspring2 beginnend ab der zweiten Crossover-Position ein:

child1 = 256|8473|91 child2 = 983|4567|21

Nicht jedes Chromosom wird im Crossover verwendet. Die Auswertungsfunktion gibt jedem Chromosom eine

Punktzahl“, die verwendet wird, um zu entscheiden, wie hoch die Chro-mosomenwahrscheinlichkeit nach einem Crossover ist. Die Chromosomen werden nach dem Zufallsprinzip ausgew¨ahlt, wobei Chromosomen mit hohen Werten bevorzugt gew¨ahlt werden. Wir verwenden die kumulative Verteilung, die in der Auswertungsstufe erstellt wurde, um die Chromosomen zu w¨ahlen. Wir generieren eine zuf¨allige Zahl zwischen null und eins und w¨ahlen dann aus, welchem Chromosom dies in unserer Verteilung entspricht. Wir wiederholen dies, um ein Paar zu bekommen und f ¨uhren anschließend das Crossover durch, sodass die beiden neuen Chromosomen in die neue Generation verlegt werden. Das f ¨uhrt hoffentlich zu dem Ergebnis, dass die n¨achste Generation besser sein wird als die letzte - denn nur die besten Chromosomen aus der vorherigen Generation wurden verwendet, um diese Generation zu schaffen. Das Crossover geht weiter, bis die neue Generation voll ist. [vgl.Bryant(2000), S. 6]

2.2.3. Mutation

Die Rolle der Mutation in der Natur besteht in der Erzeugung neuen Erbmaterials, indem die Erbinformation der Eltern zuf¨allig ver¨andert wird [vgl.Heistermann(1994), S. 142]. Die Rolle des Mutationsoperators in GA ist es, zuf¨allige St ¨orungen in den Suchprozess einzuf ¨uhren. Es ist insbesondere sinnvoll, Vielfalt in homogenen Populationen einzuf ¨uhren und Werte wieder-herzustellen, die nicht ¨uber Crossover wiederhergestellt werden k ¨onnen […] [vgl.Heistermann

(1994), S. 347]. Mutation wird verwendet, damit wir nicht in einem lokalen Optimum gefangen werden. […] Die Mutation wird nach Crossover an einem zuf¨allig ausgew¨ahlten Chromosom der neuen Generation durchgef ¨uhrt. So ist die Mutation ein v ¨ollig zuf¨alliges Verfahren, um

(22)

zu m ¨oglichen L ¨osungen zu gelangen, die sich andernfalls außerhalb der m ¨oglichen L ¨osungen befinden w ¨urden. [vgl.Bryant(2000), S. 7]

2.2.3.1. Mutation f ¨ur Permutation-Kodierung

Bei der Swap-Mutation w¨ahlen wir zwei Positionen auf dem Chromosom zuf¨allig aus und tauschen die Werte aus. Dies ist bei permutationsbasierten Kodierungen ¨ublich. [vgl. Tutorials-point]

123456789 ⇒ 127456389. (2.1)

Inversion-Mutation wird f¨ur Chromosomen mit Permutationskodierung verwendet. Um eine Inversion durchzuf ¨uhren, w¨ahlen wir Allele zuf¨allig aus und invertiere dann den Teilstring dazwischen. [vgl.Tutorialspoint]

123456789 ⇒ 126543789. (2.2)

2.2.3.2. Mutation f ¨ur Bin¨are Kodierung

Flip Mutation: In dieser Bit-Flip-Mutation w¨ahlen wir ein oder mehrere zuf¨allige Bits aus und drehen sie um [vgl.Tutorialspoint], also 1 zu 0 und 0 zu 1:

010011101011000 ⇒ 010001100111010 (2.3)

2.3. Apache Spark

Apache Spark ist ein Open-Source-Parallelverarbeitungs-Framework f ¨ur den Betrieb von Big-Data-Anwendungen ¨uber Cluster-Computer. Es wurde urspr ¨unglich im Jahr 2009 in UC Berke-ley’s AMPLab entwickelt und im Jahr 2010 open-sourced als Apache-Projekt ver ¨offentlicht. [vgl.

Penchikala(2015)] Apache Spark bietet eine benutzerfreundliche Programmierschnittstelle f ¨ur verschiedene Sprache wie Java, Scala, Python oder R [vgl.Spark(d)]. Dieses Framework wird h¨aufig neben Hadoops Datenspeichermodul-HDFS verwendet – aber es l¨asst sich glei-chermaßen in andere popul¨are Datenspeichersubsysteme wie HBase, Cassandra, MapR-DB, MongoDB und Amazon S3 integrieren [vgl.Scott(2015b)].

Von Anfang an wurde Apache Spark optimiert, um im-Memory zu laufen. Es hilft Prozessdaten viel schneller zu verarbeiten als alternative Ans¨atze wie Hadoops MapReduce, das dazu neigt,

(23)

2. Grundlagen

Abbildung 2.5.: Apache Spark Stack, Quelle:Scott(2015a), S. 17

Daten zu und von Computer-Festplatten zwischen jeder Phase der Verarbeitung zu schreiben. [vgl. Penchikala(2015)] Dazu basiert das Kernkonzept von Apache Spark auf skalierbaren Cluster-Computer, sodass ein Bedarf von mehr Rechenleistung durch einfaches einf ¨uhren von weiteren Prozessoren bedient werden kann.

2.3.1. Der Spark-Stack

Apache Spark besteht derzeit aus dem Spark Core und vier Bibliotheken, die optimiert sind, um Anforderungen von vier verschiedenen Anwendungen zu erf ¨ullen. Diese Bibliotheken setzen alle auf dem Spark Core auf und bilden den sogenannten

Spark Stack“ (Abbildung2.5).

Spark Core: Bildet das Herzst¨uck des Spark Frameworks und ist f¨ur die Managementfunk-tionen verantwortlich. Die Funktionalit¨aten sind um das Resilient Distibuted Dataset (RDD) gebaut und davon abh¨angig. [vgl.Scott(2015a), S. 17 f.]

Spark SQL: wird verwendet, um mit strukturierten Daten zu arbeitet. Spark SQL setzt das von RDD erweiterte

Dataframe“ als Hauptdatenstruktur ein, das die M ¨oglichkeit bietet, di-rekt mit SQL-Anfragen arbeiten zu k ¨onnen. Neben JDBC, ODBC unterst ¨utzt Spark SQL das Open-Source-Hive-Projekt und seine SQL-¨ahnliche HiveQL-Abfragesyntax, was Zugriff auf eine noch breitere Palette an Datenquellen erm ¨oglicht. [vgl.Scott(2015a), S. 18]

(24)

Spark Streaming: Dieses Modul unterst¨utzt eine skalierbare und fehlertolerante Verarbeitung von Streaming-Daten und kann mit etablierten Quellen von Datenstr ¨omen wie Kafka, Flume integriert werden. [vgl.Scott(2015a), S. 18]

Spark MLib: Er ist die skalierbare maschinelle Lernbibliothek von Spark, die eine Reihe von h¨aufig verwendeten maschinellen Lern- und statistischen Algorithmen implementiert. [vgl.Scott(2015a), S. 18]

Spark GraphX: GraphX unterst¨utzt die Analyse und Berechnung ¨uber Graphen von Da-ten und unterst ¨utzt eine Version der Graphenverarbeitung Pregel API. GraphX enth¨alt eine Reihe von weit verbreiteten Graphenalgorithmen, einschließlich PageRank. [vgl.Scott(2015a), S. 18]

2.3.2. Resilent Distributed Dataset - RDD

Spark dreht sich um das Konzept eines elastischen verteilten Datensatzes (RDD), der eine fehlertolerante Sammlung von Elementen ist, die parallel verarbeitet werden k ¨onnen. [vgl.

Spark(e)] Von dem Namen kann man die Definition f ¨ur RDD ableiten.

• Resilient: RDD kann Fehlertoleranz gew¨ahrleisten. Mithilfe des RDD-Linage-Graph (Abh¨angigkeit-Graph von RDDs) ist Spark in der Lage, verlorene oder besch¨adigte Partitionen wiederherzustellen. [vgl.Laskowski(a)]

• Distibuted: Daten befinden sich auf mehreren Knoten in einem Cluster. Der RDD-Abh¨angigkeits-Graph erm ¨oglicht RDDs auf mehreren Rechnern, damit Cluster gecached werden um parallel bearbeitet werden zu k ¨onnen. [vgl.Laskowski(a)]

• Dataset: Jede RDD ist eine Sammlung von partitionierten Daten mit primitiven Werten oder Werten von Werten (z.B. Objekte) (Abbildung2.6). [vgl.Laskowski(a)]

2.3.2.1. Operationen auf RDD

Auf den RDDs lassen sich zwei verschiedene Arten von Operationen durchf ¨uhren:

• Transformation: sind Funktionen, die eine RDD als Eingabe nehmen und eine oder mehrere RDDs als Output erzeugen. RDD werden hierbei nicht ge¨andert, sondern es wer-den immer neue RDDs erzeugt, indem sie die Berechnung anwenwer-den, die sie repr¨asentiert. [vgl.Laskowski(b)] Beispiel:map(), filter(), reduceByKey(), join(), . . .

(25)

2. Grundlagen

Abbildung 2.6.: RDD von Strings und RDD von Paare, Quelle:Laskowski(a)

• Action: triggert die gespeicherten Transformationen, um Werte zu erzeugen, und gibt am Ende das Ergebnis zur ¨uck zum Driver-Programm [vgl.Laskowski(c)]. Beispiel:reduce(), count(), collect(), . . .

”Transformations an RDDs werden lazy berechnet, die Auswertung wird erst bei der Aus-fuhrung einer Action gestartet. Bei der Anwendung von Transformations an RDDs wird jedes der RDD-Objekte, das wahrend der Transformations benutzt wird, in einem gerichteten azy-klischen Graphen (in englisch: DAG = directed acyclic Graph) gespeichert.”[Horgas(2015)] Transformations werden ausgef ¨uhrt, wenn das Ergebnis vom Driver-Programm gefordert ist; also nach Aufruf von Actions [vgl.Spark(c)].

RDDs werden in der Regel bei jeder Benutzung erneut berechnet, aber wenn n ¨otig, kann der Zugriff auf RDD beschleunigt werden, indem man die Operation persist() oder cache() ausf ¨uhrt. Diese Operationen speichert die RDDs im Speicher und bei Bedarf auch auf Festplat-ten f ¨ur den ganzen Cluster. [vgl.Spark(c)] Transformationen der RDDs unterteilen sich in zwei Kategorien:Narrow Transformation und Wide Transformation (Siehe Abbildung2.7).

(26)

Abbildung 2.7.: Abh¨angigkeiten von RDDs, Quelle:Zaharia u. a.(2012)

2.3.3. Architektur

Apache Spark basiert auf einer Master-Slave-Architektur mit zwei Hauptd¨amonen: Master D¨amon (Master-Node) und Worker D¨amon (Worker-Node) in einem Verh¨altnis von 1 zun - 1 Master undn beliebige Workers. [vgl.Spark(a)]

• Auf demMaster-Node l¨auft das Driver-Programm, das die main()-Funktion der Appli-kation ausf ¨uhrt. Das Driver-Programm bestimmt die Arbeitsweise von allen Tasks und Stages des Spark-Jobs sowie den Input und den Output. Es zerlegt die auszuf ¨uhrende Applikation in kleinere Ausf ¨uhrungseinheiten-Tasks und ¨ubernimmt dann auch die Scheduling-Funktion der Ausf ¨uhrung dieser Tasks. Tasks werden dann von den Exeku-toren ausgef ¨uhrt. [vgl.Spark(a)]

• Auf einemWorker-Node l¨auft der Exekutor, der f¨ur die Ausf¨uhrung der Tasks zust¨andig ist. Das beinhaltet alle Datenverarbeitungsprozesse, die Speicherung der Berechnungser-gebnisse im Speicher, im Cache oder auf Festplatten sowie weitere Interaktionen mit den Storage-Systemen. [vgl.Spark(a)]

• Cluster Manager ist f¨ur das Koordinieren der Ressourcen auf einem Spark-Cluster verantwortlich. Daf ¨ur gibt es drei verschiedene Arten von Cluster-Managern: Spark Standalone Cluster Manager, Hadoop YARN oder Apache Mesos. Ressourcen Manage-ment bedeutet Zuweisung und Freigabe von physischen Ressourcen wie Arbeitsspeicher

(27)

2. Grundlagen

Abbildung 2.8.: Spark-Cluster, Quelle:Spark(b)

oder CP Us an Spark-Applikationen und startet die Exekutoren auf den Worker-Nodes. [vgl.Spark(a)]

Der Client reicht am Anfang Applikation-Code beim Spark-Cluster ein. Auf dem Cluster kon-vertiert das Driver-Programm die RDDs und zugeh ¨origen Transformationen und Aktionen in einen logisch gerichteten azyklischen Graphen (DAG). Dieser DAG wird dann in einen physikalischen Ausf ¨uhrungsplan von Mengen von Stages ¨uberf ¨uhrt. In jedem Stage werden mehrere Tasks erzeugt, die dann geb ¨undelt werden, bevor sie an den Spark-Cluster gesendet werden. Das Driver-Programm spricht mit dem Cluster-Manager und verhandelt ¨uber Ressour-cen. Wenn alles erledigt ist, startet der Cluster-Manager die Exekutoren bei den Worker-Nodes. An diesem Punkt sendet das Driver-Programm Tasks auf dem Cluster-Manager basierend auf Daten-Platzierung. Die Ausf ¨uhrungen der Exekutoren kann vom Driver-Programm jeder Zeit

¨

uberwacht werden, da die Exekutoren vom Anfang sich bei dem Driver-Programm registrieren m ¨ussen. Wenn diemain()-Methode beendet oder stop()-Methode aufgerufen wird, werden alle Exekutoren terminiert und die Ressourcen werden vom Cluster-Manager wieder freigegeben. [vgl.Spark(a)]

(28)

In diesem Kapitel wird die implementierte L ¨osung f ¨ur das Traveling Salesman Problem vor-gestellt. Die grundlegenden Ideen, welche auf den Theorien des genetischen Algorithmus’ basieren sowie implementierter Codes, werden im Abschnitt 3.1 vorgestellt. Abschnitt 3.2 geht auf den prim¨aren Kern dieser Arbeit ein: genetische Algorithmen in einem verteilten System. Außerdem wird dabei auf die Grundlagen des Multi-Island-Modells eingegangen. Die Umsetzung auf einem Apache Spark erfolgt anschließend anhand von implementierten Code-Abschnitten.

3.1. Der genetische Algorithmus als L¨osung f¨

ur das TSP

Aus verschiedenen Gr ¨unden wurden genetische Algorithmen als geeignet und sinnvoll zum L ¨osen des Traveling Salesman Problems wahrgenommen. Eines davon sind die Eigenschaften des TSPs, die zu solchen Algorithmen passen. Diese Eigenschaften werden mit ihren passenden Aspekten in Tabelle3.1vorgef ¨uhrt.

”The genetic algorithm searches the space of solutions by combining the best features of two good tours into a single one. Since the fitness is related to the length of the edges included in the tour, it is clear that the edges represent the basic information to be transferred to the offspring.”[Potvin

(1996), S. 345]

In dieser Arbeit wird eine verbesserte Variante des genetischen Algorithmus’ implementiert, die Gr ¨unde daf ¨ur und das Umsetzungsvorgehen mit Pseudocode werden im Abschnitt 3.1.1 pr¨asentiert. Die tats¨achliche Implementierung erfolgt im Abschnitt 3.1.2.

3.1.1. Improved Genetic Algorithm - IGA

Klassische genetische Algorithmen erzeugen nur selten optimale L ¨osungen und wenn sie es tun, geschieht dies nicht innerhalb einer angemessenen Zeit [vgl. Beasley u. a. (1993), S. 58 - 69]. Das liegt m ¨oglicherweise viel an den unterschiedlichen Operationen wie bspw.

(29)

3. L¨osungsvorstellung und Umsetzung

Eigenschaft Bei dem TSP

Chromosome Jedes Chromosom repr¨asentiert eine L ¨osung in kodierter Form [vgl.Potvin(1996)] Fitness Jede Tour (L ¨osung) des TSPs hat seine eigene

Ordnung der St¨adte, die wiederum die L¨ange der Tour reflektiert. Die Fitness der L ¨osung ba-siert unmittelbar auf dieser L¨ange [vgl.Potvin

(1996)]

Menge der L ¨osungen (Population) Aus dem Grund, dass das TSP einem kombi-natorischen Optimierungsproblem entspricht, beschreibt jedes Problem eine Menge von Tou-ren, in der eine beste L ¨osung zu finden ist.

Tabelle 3.1.: Eigenschaften des genetischen Algorithmus’ beim TSP

dem Crossover, der Mutationen und/oder dem Auswahlverfahren. Viele Forscher haben auch versucht die genetischen Algorithmen zu verbessern, indem sie verschiedene Methoden und Operationen eingesetzt haben, um eine optimale L ¨osung innerhalb einer angemessenen Zeit zu finden.

Improved Genetic Algorithm“ (IGA) in der Arbeit von Omar M. Sallabi und Younis El-Haddad [Sallabi und El-Haddad(2009)] beinhaltet neue Crossover-Techniken sowie zus¨atzliche Operationen zur schnellen Ann¨aherung an eine L ¨osung. Dieser L ¨osungsansatz von [Sallabi und El-Haddad(2009)] dient im Rahmen dieser Arbeit als Grundlage f ¨ur eine L ¨osungsfindung.

3.1.1.1. Funktionsweise des IGAs

Weil sie die Ideologien der genetischen Algorithmen repr¨asentieren, sind die Crossover-Operationen in den meisten F¨allen die wichtigsten Operationen dieser Algorithmen [vgl.

Sallabi und El-Haddad(2009), S. 19]. Von daher konzentriert sich derIGAmehr darauf, die Crossover-Operationen zu verbessern. Hierbei wird m ¨oglichst der Suchraum f ¨ur die anf¨angliche Bev ¨olkerung klein gehalten, damit Rechenaufwand minimiert und f ¨ur Kernoperationen zur Verf ¨ugung gestellt werden kann. Zum Crossover werden noch weitere Operationen f ¨ur den

IGAvorgeschlagen, auch zum Zweck der Verbesserung der Ergebnisse.

Im Allgemeinen arbeitet derIGAwie folgt: Die anf¨angliche Bev¨olkerung besteht aus zwei Individuen [vgl. Sallabi und El-Haddad(2009), S. 984], was die Mindestanforderungen der Operationen entspricht. Auf diese zwei Individuen werden verschiedene Crossover-Operationen angewendet, um die Population zu erweitern. Jedes Individuum der erweiterten

(30)

Population wird mit mehreren Mutation-Operationen mutiert. Danach wird f ¨ur jedes einzelne Individuum mit der Fitness-Funktion ausgewertet und die besten zwei ausgew¨ahlt, um weitere neue Generation zu generieren. Auf weitere Operationen wird im Laufe dieser Arbeit genauer eingegangen.

Listing 3.1: Pseudocode f ¨urIGA

IGA(population, restIteration, duration)

IF iteration := 0 Or durattion >= MaxDuration THEN DO

return population END IF startTime := now crossedPopulation := swapInvertedCrossover(population) rearrangedPopulation := rearange(crossedPopulation) mutatedPopulation := mutate(rearrangedPopulation) reformulatedPopulation := reformulate(mutatedPopulation) RETURN IGA(reformulatedPopulation,

restIteration - 1, duration + (now - startTime) END IGA

3.1.1.2. Swapped Inverted Crossover - SIC

Swapped-Inverted-Crossover wurde beschrieben als eine Crossover-Operation, das den geneti-schen Algorithmus verbessert [vgl.Sallabi und El-Haddad(2009), S. 984], indem es verschiedene Verfahren kombiniert, um Vielf¨altigkeit der Population zu schaffen (inkl.Single-Point-Crossover undTwo-Points-Crossover). Grunds¨atzlich werden hierbei Swap-Crossover, Inverted-Crossover und Order-Crossover zusammen angewendet, um ein Swapped-Inverted-Crossover hervorzu-bringen.

Two-Points-SIC

Two-Points-SIC basiert auf der Zerlegung von Touren in drei Teile, Kopf-Mitte-Ende:

parent1 1 2 3 4 — 5 6 7 8 — 9 10 11 parent2 1 6 11 9 — 8 4 10 7 — 3 2 5

Der Kopf und das Ende jedes Elternteils werden umgedreht (Inverted-Crossover). Die Teile von zwei Touren werden miteinander getauscht (Swapped-Crossover). Die Elemente von parent2,

(31)

3. L¨osungsvorstellung und Umsetzung

die mit dem Kopf und dem Ende vonparent1 ¨ubereinstimmen, werden aus parent2 entfernt.

Ansatz 1: Kopf gegen Ende:

child1 5 2 3 —4 7 8 10 — 9 11 6 1 child2 11 10 9 — 6 8 7 5 — 4 3 2 1

Ansatz 2: Kopf gegen Kopf, Ende gegen Ende

child3 9 11 6 1 —4 7 8 10 — 5 2 3 child4 4 3 2 1 — 6 8 7 5 — 11 10 9 One-Point-SIC

One-Point-SIC basiert auf der 2-Parts-Zerlegung der Tour: Kopf-Ende

parent1 1 2 3 4 5 6 — 7 8 9 10 11 parent2 1 6 11 9 8 4 — 10 7 3 2 5

Der Kopf und das Ende vonparent1 werden umgedreht. Child5 ist die Kombination von dem invertierten Kopf desparent1 und den nicht in dem Kopf von parent1 nicht erhaltenen Element desparent2:

child5 6 5 4 3 2 1 — 11 9 8 10 7

Statt des Kopfs, es wird beim Generieren vonchild6 das Ende des parent1 verwendet:

child6 11 10 9 8 7 — 1 6 4 3 2 5

Wir verwenden nun den gleichen Prozess f ¨urparent2, um child7 und child8 zu generieren:

child7 4 8 9 11 6 1—2 3 5 7 10 11 child8 5 2 3 7 10—1 4 6 8 9 11

Die Prozesse k ¨onnen sehr gut nochmal verwendet werden, um child9, child10, child11 und child12 zu erstellen, indem man die invertierten Teile am Ende des zweiten Elternteils platziert.

(32)

child9 11 9 8 10 7—6 5 4 3 2 1 child10 1 6 4 3 2 5—11 10 9 8 7 child11 2 3 5 7 10 11 — 4 8 9 11 6 1 child12 1 4 6 8 9 11 — 5 2 3 7 10 Pseudo Code:

Listing 3.2: Pseudocode f ¨ur SwapInvertedCrossover-Operation

SwapInvertedCrossover(population)

(parent1,parent2) := population.getTheBest2() newPop := new Pop()

newPop.addTours(parent1,parent2) random1 := Random.nextInt() random2 := Random.nextInt() random3 := Random.nextInt() // Two-Points-SIC parent1 := split3Part(paren1,random1,random2) parent2 := split3Part(paren2,random1,random2) child1 := combine(invert(parent1.tail), sub(parent2,parent1.head,parent1.tail) invert(parent1.head)) child2 := combine(invert(parent2.tail), sub(parent1,parent2.head,parent2.tail), invert(parent1.head)) child3 := combine(invert(parent1.head), sub(parent2,parent1.head,parent1.tail), invert(parent1.tail)) child4 := combine(invert(parent2.head), sub(parent1,parent2.head,parent2.tail), invert(parent2.tail)) // One-Point-SIC parent1 := split2Part(paren1,random3 parent2 := split2Part(paren2,random3) child5 := combine(invert(parent1.head), sub(parent2,parent1.head)) child6 := combine(invert(parent1.tail), sub(parent2,parent1.tail)) child7 := combine(invert(parent2.head), sub(parent1,parent2.head)) child8 := combine(invert(parent2.tail), sub(parent1,parent2.tail)) child9 := combine(sub(parent2,parent1.head), invert(parent1.head)) child10 := combine(sub(parent2,parent1.tail), invert(parent1.tail)) child11 := combine(sub(parent1,parent2.head),

(33)

3. L¨osungsvorstellung und Umsetzung

invert(parent2.head))

child12 := combine(sub(parent1,parent2.tail), invert(parent2.tail))

newPop.addTours(child1, child2,, child12)

return newPop End

3.1.1.3. Multi-Mutation-Operation

Um eine Vielf¨altigkeit innerhalb der Bev ¨olkerung zu schaffen, sind mehrere Mutation-Operationen einzusetzen. Dabei werden aber nicht alle Mutationen an allen Individuen innerhalb der Bev ¨olkerung angewandt, sondern zuf¨allig. Bei diesem Vorgehen werden ausgew¨ahlte Elterntei-le zehnmal kopiert und unterschiedlich mutiert [vgl.Sallabi und El-Haddad(2009), S. 986]:

parent 2 4 56 3 8 1 11 10 9 3 7

Zur Erh ¨ohung der Erfolgschancen werden zwei unterschiedliche St¨adte ausgew¨ahlt. Angenom-menciundcj seien folgendes:

i = 4 → ci = 6 (3.1)

j = 8 → cj = 11 (3.2)

Auf Basis von verschiedenen Austauschm ¨oglichkeiten werden Mutationen ausgef ¨uhrt, wobei 2<i und j <n-2 zu erf¨ullen sind:

1. ci mitci+1 2. ci mitci−1 3. ci mitci+2 4. ci mitci−2 5. cj mitcj+1 6. cj mitcj−1 7. cj mitcj+2 8. cj mitcj−1

(34)

9. ci mitcj

10. c1 mitcn

In unserem Beispiel erh¨alt man folgende Touren nach einer Multi-Mutation:

1. 6 wird mit 3 ausgetauschtÕ 2 4 5 3 6 8 1 11 10 9 3 7 2. 6 wird mit 5 ausgetauschtÕ 2 4 6 5 3 8 1 11 10 9 3 7 3. 6 wird mit 8 ausgetauschtÕ 2 4 5 8 3 6 1 11 10 9 3 7 4. 6 wird mit 4 ausgetauschtÕ 2 6 5 4 3 8 1 11 10 9 3 7 5. 11 wird mit 10 ausgetauschtÕ 2 4 5 6 3 8 1 10 11 9 3 7 6. 11 wird mit 1 ausgetauschtÕ 2 4 5 6 3 8 11 1 10 9 3 7 7. 11 wird mit 9 ausgetauschtÕ 2 4 5 6 3 8 1 9 10 11 3 7 8. 11 wird mit 8 ausgetauschtÕ 2 4 5 6 3 11 1 8 10 9 3 7 9. 6 wird mit 11 ausgetauschtÕ 2 4 5 11 3 8 1 6 10 9 3 7 10. 2 wird mit 7 ausgetauschtÕ 7 4 5 6 3 8 1 11 10 9 3 2 Pseudo Code

Listing 3.3: Pseudocode f ¨ur Multi-Mutation-Operation

Mutation(population)

parents = randomParent(population) foreach parent in parents

randomi = Random.nextInt(1,n) randomj = Random.nextInt(1,n) population.addTours(

swap(parent, S randomi, S randomi+1), swap(parent, S randomi, S randomi-1), swap(parent, S randomi, S randomi+2), swap(parent, S randomi, S randomi-2), swap(parent, S randomj, S randomj+1), swap(parent, S randomj, S randomj-1), swap(parent, S randomj, S randomj+2), swap(parent, S randomj, S randomj-2), swap(parent, S randomi, S randomj), swap(parent, S 1, S n)

(35)

3. L¨osungsvorstellung und Umsetzung

end foreach

return population End

3.1.1.4. Reformulate-Operation

In der Arbeit von Omar M. Sallabi und Younis El-Haddad [Sallabi und El-Haddad(2009), S. 986] wird eine neue Operation vorgeschlagen.Reformulate-Operation soll die Population auffrischen, damit es nicht in einem lokalen Minimum eingeschlossen ist. Diese Operation ist in einer Lage die Struktur der Tour zu ¨andern, ohne deren Reihenfolge und vor allem deren Fitness zu beeintr¨achtigen [vgl.Sallabi und El-Haddad(2009), S. 986]. Es geht hier um die Reformierung der Kodierung der Tour. z. B. die Tour1 2 3 4 5 6 7 8 9 kann in zwei Teile ( 1 2 3 4 5 ) und ( 6 7 8 9 ) zerlegt werden. Von der Zusammensetzung der invertierten Versionen der beiden Teile, erhalten wir eine neue Repr¨asentation der gleichen Tour:5 4 3 2 1 9 8 7 6. [vgl.Sallabi und El-Haddad(2009), S. 986]

Pseudo Code

Listing 3.4: Pseudocode f ¨ur Reformulate-Operation

Refomulate (population)

foreach tour in population r = random.nextInt() if r < MutationRate then do tour = split2Parts(tour) tour = combine(invert(tour.head),invert(tour.tail)) end if end foreach End 3.1.1.5. Rearangement-Operation

Rearangement-Operation ist auch eine neue Operation, die von Omar M. Sallabi und Younis El-Haddad [Sallabi und El-Haddad(2009), S. 985] vorgestellt wurde. Das Ziel dieser Operation ist es, den gr ¨oßten Wertki,j von allen adjazenten St¨adten auf einer Tour zu finden und dann mit drei anderen St¨adten zu tauschen, eins zu einer Zeit [vgl.Sallabi und El-Haddad(2009), S. 985], indemki,j die Kosten zwischen zwei adjazenten St¨adtenciundcj:i = 1,2,3, . . . ,n-1 und j = i + 1 ist. Die drei zu tauschenden St¨adten sind c1,cn/2 undcn: Wobein die Anzahl aller St¨adte darstellt. Am Ende werden die Auswirkungen der getauschten Situationen bewertet.

(36)

Die Situation mit dem besten Ergebnis wird ausgew¨ahlt.

Pseudo Code

Listing 3.5: Pseudocode f ¨ur Rearrangement-Operation

Rearrangement(S) i=0

S0 = S max = 0

While i less than n-1

If Ci,j+1 greater than max Begin

max = Ci,j+1 x = i

End End While

S1 = Swap Cityx with City1 S2 = Swap Cityx with Cityn/2 S3 = Swap Cityx with Cityn S = min(S0,S1,S2,S3)

return(S) End

3.1.2. Umsetzung des IGAs

F ¨ur den Einsatz des IGAs f ¨ur TSP werden Klassen ben ¨otigt, welche die wesentlichen Entit¨aten dieses Algorithmus’ und des TSP implementieren. Diese Entit¨aten sind die Stadt, die Tour und die Population. Die Implementierung dieser Entit¨aten wird im Abschnitt 3.1.2.1 detailliert vorgestellt. Im Abschnitt 3.1.2.2 wird auf die Implementierung des Kerns des IGAs eingegangen.

3.1.2.1. Entit¨aten von IGA

Zum L ¨osen des Traveling Salesman Problems werden die Entit¨aten City, Tour und Population im Rahmen dieser Arbeit mit Java-Klassen abgebildet. Auf Abbildung3.1ist das dazugeh ¨orige Klassendiagramm mit ihren jeweiligen Beziehungen zueinander abgebildet. Die City-Klasse stellt die Abbildung f ¨ur eine Stadt mit ihrer geografischen Breite und H ¨ohe dar. Jede m ¨ogliche Tour des Problems wird durch die Tour-Klasse implementiert. Alle St¨adte werden bei jeder Tour in einer Liste gespeichert, deren Indizes die Reihenfolge der St¨adte darstellt. Nat ¨urlich ist dies die in Kapitel 2.1.1 genannte Permutationskodierung. Dabei werden nicht direkt die Ziffern angewendet, sondern die Indizes der Liste. Eine Tour kennt ihre Fitness und L¨ange – zwei wesentliche Eigenschaften des genetischen Algorithmus’. Mehrere Touren bilden eine

(37)

3. L¨osungsvorstellung und Umsetzung

Abbildung 3.1.: Entit¨aten vomIGA

Population. Die Population-Klasse bietet diegetFittest()-Methode, welche die Tour mit bester Fitness zur ¨uckgibt.

3.1.2.2. Die IGA-KLasse

Der Kern des vorgestelltenIGAs wurde durch dieIGA-Klasse implementiert. KlasseIGA umge-setzt. Die HauptmethodeevolvePopulation(Population), mit der man den Berechnungsprozess einer Iteration des genetischen Algorithmus’ ausl ¨ost, f ¨uhrt die Schritte zum evolvieren der als Parameter ¨ubergebenen Population aus. Hierbei bedeutet evolvieren eine verbesserte Generati-on zu erzeugen:

Listing 3.6: Java-Kode f ¨ur evolvePopulation()-Methode

public Population evolvePopulation(Population pop) { Population initPop = getInitPop(pop);

Population crossedPop = swapInvertedCrossover(initPop); Population reformulatedPop = reformulate(crossedPop);

Population mutatedPop = mutate(rearrangedPop);

Population rearrangedPop = rearrange(reformulatedPop);

return rearrangedPop; }

(38)

Am Anfang wird mitgetInitPop()-Methode eine neue Population mit den besten zwei Kandida-ten aus der vorherigen Generation generiert. Die ¨ubergebene Population muss mindesten eine Tour haben, um es generieren zu k ¨onnen. Bei Populationen mit mehr als zwei Touren werden die zwei erw¨ahnten Kandidaten durch einen einfachen Vergleich der Fitness ausgew¨ahlt. Falls nur eine Tour vorhanden ist, ist sie automatisch eine der besten Touren. Die andere Tour wird durch Mutieren der ersten Tour erstellt.

Nachdem die erste Annahme desIGAs erf ¨ullt wurde, kommt es zu dem entspannten Teil – dem Crossover. Die neu generierte Population mit zwei Touren wird an die swapInvertedCrossover()-Methode ¨ubergeben. Bei dieser Crossover-Methode nehmen alle Touren in einer Population paarweise am Crossover-Prozess teil. F ¨ur jedes Paar werden drei Crossover-Operationen ange-wendet:twoPointSIC(), onePointSIC Head() und onePointSIC Tail(). Die Unterschiede liegen an den Schneidepunkten und die umzudrehenden Teile. Die Grundlage dieser Methoden findet man als Teile der Umsetzung derswapInvertedCrossover()-Methode in Abschnitt 3.1.1. Diese Prozesse ergeben am Ende f ¨ur jedes Paar insgesamt zw ¨olf Kinder.

Listing 3.7: Java-Kode f ¨ur swapInvertedCrossover()-Methode

private Population swapInvertedCrossover(Population pop) { Population crossedPop = new Population();

crossedPop.addTours(getTheBestTwo(pop).getTours()); Tour parent1 = crossedPop.getTour(0);

Tour parent2 = crossedPop.getTour(1);

crossedPop.addTours(twoPointSIC(parent1, parent2)); crossedPop.addTours(onePointSICHead(parent1, parent2)); crossedPop.addTours(onePointSICTail(parent1, parent2));

return crossedPop; }

Reformulate-Operation erfolgt direkt nach den Crossover-Prozessen mit einer vordefinierten Rate (REFORMULATE RATE), um das Spektrum der Formen von den Touren zu erweitern. Das bedeutet, nicht alle Touren nehmen an diesen Phasen teil. F ¨ur jeden Durchlauf wird eine zuf¨allige Nummer generiert, Reformulation passiert nur dann, wenn diese Nummer kleiner ist als das der REFORMULATE RATE-Nummer.

(39)

3. L¨osungsvorstellung und Umsetzung

Listing 3.8: Java-Kode f ¨ur reformulate()-Methode

private Population reformulate(Population pop) {

List<Tour> reformulatedTours = pop.getTours().stream().map(tour -> {

double rn = Math.random();

TwoParts<City> tourInTwoParts = new TwoParts<>(tour.getTour(), tour.tourSize() / 2);

if (rn < REFORMULATERATE) {

Collections.reverse(tourInTwoParts.getHead()); Collections.reverse(tourInTwoParts.getTail()); }

return new Tour(tourInTwoParts.getList(), tour.getCities()); }).collect(Collectors.toList());

return new Population(reformulatedTours); }

Nachfolgend werden die Mutationen der Multi-Mutation-Operation vorgestellt. Basierend auf zuf¨alligen Werten, werden die Tauschpunkte f ¨ur jeden Durchlauf zuf¨allig ausgew¨ahlt, m ¨ussen aber die Bedingung erf ¨ullen, damit die Prozesse fortgesetzt werden k ¨onnen. Das Tauschen erfolgt nach der im Abschnitt 3.1.1 erl¨auterten Methode. Am Ende der Methode bekommen wir eine neue Population mit mutierten Touren.

Listing 3.9: Java-Kode f ¨ur mutate()-Methode

private Population mutate(Population pop) {

int tourSize = pop.getTour(0).tourSize();

List<Tour> newTours = pop.getTours().stream().flatMap(tour -> {

int i = 0;

int j = 0;

while (i == j —— (i < 2 —— tourSize - 3 < i) —— (j < 2 —— tourSize - 3 < j)) {

i = (int) (Math.random() * tourSize); j = (int) (Math.random() * tourSize); }

(40)

List<Tour> mutated = new ArrayList<>(); mutated.add(tour);

mutated.add(new Tour(swap(tour.getTour(), i, i + 1), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), i, i - 1), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), i, i + 2), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), i, i - 2), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), j, j + 1), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), j, j + 2), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), j, j - 1), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), j, j - 2), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), i, j), tour.getCities())); mutated.add(new Tour(swap(tour.getTour(), 0, tourSize - 1),

tour.getCities()));

return mutated.stream(); }).collect(Collectors.toList());

return new Population(newTours); }

Zum Schluss wird eine Rearangement-Operation ausgef ¨uhrt, um die Qualit¨at der Population zu verbessern. Jede Tour wird einmal untersucht und nur ge¨andert, wenn es eine bessere Tour gefunden wird.

Listing 3.10: Java-Kode f ¨ur rearrange()-Methode

private Population rearrange(Population pop){

Population rearrangedPop = new Population(pop.getTours());

for (int i = 0; i < pop.getSize(); i++) {

rearrangedPop.saveTour(i, arrange(pop.getTour(i))); }

return rearrangedPop; }

(41)

3. L¨osungsvorstellung und Umsetzung

3.2. Genetischer Algorithmus auf dem Cluster mit Apache

Spark

Die Umsetzung des genetischen Algorithmus’ auf einem Multirechnersystem kann durch un-terschiedliche Ans¨atze realisiert werden. In dieser Arbeit konzentrieren wir uns auf denjenigen Ansatz, bei dem die Arbeitspakete mehrfach von mehreren Rechnern bearbeitet werden, um einen Wettbewerb zu erzielen. Das in [Shrestha und Mahmood(2016)] vorgestellte Multi-Island-Modell, mit dem wir uns im Abschnitt 3.2.1 gr ¨undlich besch¨aftigen werden, beschreibt den im Rahmen dieser Arbeit umzusetzenden Ansatz. Anschließend wird in Abschnitt 3.2.2 die in Java implementierte L ¨osung vorgestellt.

3.2.1. Multi-Island-Modell

Das Ziel des genetischen Algorithmus ist es, der optimalen L ¨osung so nah wie m ¨oglich zu kommen. Da der Suchraum der L ¨osung groß ist, besteht die zentrale Herausforderung darin, das absolute Minimum des gesamten Suchraums von lokalen Minima zu unterscheiden und die Suche nicht vorzeitig zu beenden. Der prim¨are Weg, um das sp¨atere Ziel zu adressieren ist, die richtige Menge an Vielfalt in den Eltern einzuf ¨uhren. [vgl.Shrestha und Mahmood(2016), S. 1]

Genetische Algorithmen basieren haupts¨achlich auf dem Zufall und dem Evolvieren der Po-pulation nach jeder Generation. Jeder zuf¨allige Schritt hat einen enormen Einfluss auf das Resultat des ganzen Prozesses. Genetische Algorithmen garantieren in der Regel nicht die besten Ergebnisse nach schon ein oder zwei Durchl¨aufen der Prozesse des Evolvierens. Die Qualit¨at des Endergebnisses steigt mit der Anzahl der Versuche, was wiederum mehr Zeit- und Rechenaufwand bedeutet.

Nach einigen Iterationen neigt der genetische Algorithmus oft dazu, Konvergenz zu erzeugen, indem Eltern mit gleichen genetischen Informationen beim Crossover genutzt werden, um neue Generation zu schaffen, ohne Verbesserung zu bekommen. [vgl.Shrestha und Mahmood

(2016), S. 4] Von daher spielt hierbei die hohe genetische Varianz eine große Rolle.

In [Shrestha und Mahmood(2016)] wurde beschrieben:Island-Modell wurde mit Multicore-Prozessoren im Server implementiert, indem mehrere Threads parallel ausgef ¨uhrt wurden. Jeder Thread f ¨uhrt seine eigene Version von GA aus. Nach jeder n-ten Iteration/Generation auf jedem Thread, auf welchem der GA l¨auft, wurden eine Handvoll der zuf¨allig ausgew¨ahlten Populationsmitglieder zwischen den Threads ausgetauscht. Der Prozess hat nicht nur mehr

(42)

Rechenressourcen hinzugef ¨ugt, sondern verbesserte auch die Laufzeit von GA. Auch die Diver-sit¨at und die anf¨angliche Stichprobenverzerrung.

In Abbildung3.2wurde die Architektur einesMulti-Island-Modells dargestellt. Dort ist ein Master-Server zu sehen, der daf ¨ur zust¨andig ist, die Prozesse zu bewachen und zu kontrollieren. Nach jeder n-ten Iteration sammelt der Master die Ergebnisse von jedem Server und tauscht die Mitglieder aus. Auf jedem Server laufen mehrere Instanzen des gleichen genetischen Algo-rithmus jeweils auf einem eigenen Thread. Die Ergebnisse aus den Threads sowie die beste Fitness werden auch von dem Server selbst ¨uberwacht. Unten in der Abbildung ist die Prozesse des genetischen Algorithmus, die in der Arbeit [Shrestha und Mahmood(2016)] vorgestellt wurde. Das m ¨ussen wir in Rahmen dieser Arbeit nicht sofort anwenden.

3.2.2. Umsetzung des Multi-Island-Modells mit Apache Spark

Die Architektur des vorgestellten Apache Spark Frameworks und das Multi-Island-Modell verf ¨ugen beide ¨uber die Eigenschaften einerMaster-Slave-Architektur. Bei beiden Architekturen kommen die Aufgaben vom Master und werden anschließend in den Slave-Nodes (Worker-Nodes), unter der ¨Uberwachung des Masters, erf¨ullt. Daher kann man sagen, dass mithilfe des Apache Spark Frameworks die M ¨oglichkeit besteht, einen genetischen Algorithmus nach Multi-Island-Modell zu implementieren.

3.2.2.1. Umsetzungsidee

Anhand der Erkenntnis, dass dieMaster-Slave-Architektur der entscheidende Punkt f¨ur die Um-setzung desMulti-Island-Modells mit Apache Spark ist, wird im Folgenden die Umsetzungsidee grob erl¨autert und anschließenden die Implementierung aufgezeigt.

DasDriver-Programm, das auf dem Master-Node l¨auft, bereitet mehrere Instanzen des geneti-schen Algorithmus’, mit der initiierten Population des zu l ¨osenden TSPs, vor. Diese Instanzen werden dann als Pakete verpackt und auf dem Cluster zum Berechnen verteilt. Auf jedem Worker-Node werden GA-Instanzen ausgef¨uhrt. Die Ergebnisse werden am Ende zur¨uck zum Master-Node geschickt und bewertet.

Nach jedem Durchlauf (also alle GA-Instanzen sind durchgearbeitet) werden die Ergebnisse miteinander verglichen und ggf. kombiniert, um neue GA-Instanzen mit verbesserten Popula-tionen zu erstellen.

(43)

3. L¨osungsvorstellung und Umsetzung

(44)

Abbildung 3.3.: Architektur f ¨ur die Umsetzung desIGAs mit Apache Spark

DasDriver-Programm wendet danach denselben Prozess an den neu erzeugten GA-Instanzen an, um die Berechnung fortzusetzen. Wenn die maximale Anzahl der Iterationen erreicht ist, wird das Endergebnis letztendlich berechnet und zur ¨uckgegeben.

3.2.2.2. Umsetzung

Abbildung 3.3 stellt die Architektur der Umsetzung dar. Im Allgemeinen finden die Prozesse haupts¨achlich um dasPacket herum statt. Ein Packet ist ein Wrapper einer Instanz von dem genetischen Algorithmus, welcher unabh¨angig von anderen Packets arbeiten soll. Am An-fang des Berechnungsprozesses wird eine Instanz desIGAs mit der initiierten Population in ein Packet verpackt. Mehrere Kopien des Packets werden erstellt und alsSpark-RDD an den Worker verschickt. Diese erste Phase passiert lediglich im Driver-Programm auf dem Master. Jeder Worker bekommt mehrere Packets zugeschickt und f ¨uhrt sie alle samt in einem separaten Thread aus. Die Workers schicken am Ende der Berechnungen die Ergebnisse zur¨uck zu dem Master. Mit dermerge()-Funktion werden diese Packets zusammengef¨ugt, indem die besten Ergebnisse sich zu einem neuen Packet zusammenf ¨ugen. Mit dem neu generierten Packet wird der Prozess wiederholt und h ¨ort erst dann auf, wenn die maximale Iteration erreicht ist.

(45)

3. L¨osungsvorstellung und Umsetzung

Packet

Die Packet-Klasse implementiert der Wrapper einer Instanz vom genetischen Algorithmen um das TSP zu l ¨osen. Die Klasse Packet erfordert eine Liste der St¨adte als Parameter f ¨ur den Konstruktor. Die Population kann ggf. im Konstruktor initiiert oder als Parameter eingegeben werden. Es verf ¨ugt in dieser Klasse dierun()-Methode, mit welcher der genetische Algorithmus bis zu einer vorher festgelegten Anzahl von Iterationen ausgef ¨uhrt werden soll. Diese Methode gibt als Ergebnis neues Packet zur ¨uck mit der evolvierten Population des orginalen Problems. Die Signatur lautet run(): Packet. Die run()-Methode ist so gebaut, damit sie w¨ahrend des Map-Reduce-Prozesses aufgerufen werden kann. Außerdem bietet die Klasse Packet auch die M ¨oglichkeit an, sich zu klonen oder zu multiplizieren. Somit l¨auft der genetische Algorithmus auf jedem Thread eines Worker.

Listing 3.11: Java-Kode f ¨ur Methoden von der Packet-Klasse vgl.Dommerholt(b)

public Packet(Cities cities) {

this.cities = cities;

this.pop = new Population(2, cities);

this.ga = new IGA(); }

public Packet run() {

pop = ga.evolvePopulation(pop);

for (int i = 0; i < ITERATIONMAX; i++) pop = ga.evolvePopulation(pop);

System.out.println(i + ”. Current distance: ” + pop.getFittest().getDistance()); } System.out.println(”Packet Finished”); System.out.println(”Packet distance: ” + pop.getFittest().getDistance()); System.out.println(”Solution:”); System.out.println(pop.getFittest().toString());

return this.clone(); }

Listing 3.12: Java-Kode f ¨ur Methoden von der PacketFactory-Klasse

public class PacketFactory {

(46)

return new Packet(cities); }

public static Packet getPacket(Cities cities, Population population) {

return new Packet(cities); }

public static Packet merge(Packet packet1, Packet packet2) { Tour tour1 = packet1.getPopulation().getFittest();

Tour tour2 = packet2.getPopulation().getFittest();

Population newPop = new Population(Arrays.asList(tour1, tour2));

return new Packet(packet1.getCities(), newPop); }

public static List¡Packet¿ multiply(Packet packet, int slices) { List<Packet> packets = new ArrayList<>();

IntStream.range(0, slices).forEach(x -> { packets.add(copy(packet));

});

return packets; }

public static Packet copy(Packet packet)–

Cities cities = new Cities(new HashSet<>(packet.getCities().getCities())); Population pop = new Population(packet.getPopulation().getTours());

return new Packet(cities, pop); }

}

Organiser

Der gesamte Prozess wird mit einem Organiser verwaltet. Die Klasse Organiser ist daf ¨ur zust¨andig die Zusammenarbeit der Wokers zu organisieren. Der Organiser bereitet am Anfang des Berechnungsprozesses ein initiiertes Packet mit der unbearbeiteten Population vor. Das Packet wird dann mehrfach kopiert und in eine Collection gepackt, um RDD f ¨ur die Bear-beitung auf den Workers zu dienen. Jeder Worker ist f ¨ur mindestens eine Instanz vom GA zust¨andig. Die Berechnungen auf einem Packet werden mitmap()-Funktion getriggert. Mit reduce()-Funktion werden die Ergebnisse kombiniert und die Endergebnisse werden zur¨uck zum Driver-Programm gesendet. Dieser Funktion nutzt diemerge()-Methode der Klasse Packet-Factory, welche die beste Tour von den zu kombinierenden Packets ausw¨ahlen und in ein neues Packet packen. Das neu erzeugte Packet wird wie das initiierte Packet behandelt, um die Iterationen fortzusetzen.

(47)

3. L¨osungsvorstellung und Umsetzung

Listing 3.13: Scala-Kode f ¨ur die Organiser-Klasse vgl.Dommerholt(a)

class Organiser(val sc: SparkContext) {

def run(cities: Cities, iterations: Int): Packet = {

var packet = new Packet(cities) //

for(a <- 1 to iterations) –

val packets = collection.JavaConversions.asScalaBuffer(

PacketFactory.multiply(packet,sc.defaultParallelism)).toList

val packetsRDD = sc.parallelize(packets) Packet = packetsRDD.map(p => p.run())

.reduce((p1,p2) => PacketFactory.merge(p1,p2)) println(”Iteration ” + a + ” result: ”+ packet.getShortest.getDistance) }

[vgl. Dommerholt] //

println(”Final Distance: ”+ packet.getShortest.getDistance) println(”Solution Distance: ”+ packet.getShortest)

packet /

(48)

In diesem Kapitel wird die Performance unserer Umsetzung des genetischen Algorithmus’ auf dem Apache-Spark-Cluster in Form von Benchmarks getestet und ausgewertet. Im Fol-genden wird zuerst der Aufbau der Benchmarks erkl¨art. Danach werden die tats¨achlichen Benchmarks durchgef ¨uhrt. Die Testdaten werden durch die entwickelte L ¨osung berechnet und ausgewertet. Im Anschluss wird auf die Performance nach Anzahl der Cluster-Sklaven detaillierter eingegangen.

4.1. Aufbau der Benchmarks

F ¨ur den Aufbau der Benchmarks wird zuerst die Hardware-Spezifikation der Cluster vorgestellt, welche danach mit unterschiedlichen Testdaten gef ¨ullt werden. Diese Testdaten variieren in den Gr ¨oßen, die sehr typische Situationen abdecken. Im Anschluss werden die Testf¨alle f ¨ur die Genauigkeit sowie Performance nach Gr ¨oßen bestimmt, danach wird das Ausf ¨uhrungsmodell des Benchmarks erkl¨art.

4.1.1. Hardware und Software

Getestet wird auf einem Spark-Standalone-Cluster mit vier Rechnern auf einem Apache Spark der Version 2.1.0 f ¨ur Apache Hadoop 2.7. Auf allen vier Rechnern laufen macOS Sierra 10.12.5 und Java 1.8. Jeder Rechner besitzt ein 2-Kern 4-Thread Core i5 Prozessor und es stehen jeweils 8 GB Hauptspeicher zur Verf ¨ugung. Darauf laufen ein Master-Node und mehrere Worker-Nodes. Die Anzahl von Worker-Nodes kann von eins bis zw ¨olf eingestellt werden. Das ist m ¨oglich, weil jeder Rechner mehrerer, parallele Worker-Nodes laufen l¨asst. In diesem Test setzen wir die Grenze f ¨ur diese Zahl aufgrund der Performance f ¨ur jeden Rechner auf drei. Die Ergebnisse werden anschließend mittels der Python-Chart-Bibliothek Pyplot dargestellt.

4.1.2. Testdaten

Referenzen

ÄHNLICHE DOKUMENTE

Tags: Duplicate Detection, Deduplication, Record Linkage, Machine Learning, Big Data, Apache Spark, MLlib, Scala, Hadoop, In-Memory..

Mit der Annahme, daß in der Produktionsstelle mehrere Produkte zyklisch gefertigt werden, läßt sich das Problem als Economic Lot Scheduling Problem (ELSP) formulieren.. Wegen

(3) Ein Mediendiensteanbieter gilt auch dann als in Österreich niedergelassen, wenn er seine Hauptverwaltung in Österreich hat, die redaktionellen Entscheidungen über

Alle Produkt- und Dienstleistungs-Bezeichnungen sind Warenzeichen oder eingetragene Warenzeichen der jeweiligen Firmen und beziehen sich auf Eintragungen in den USA

To enable these features, Spark SQL is based on an extensible optimizer called Catalyst that makes it easy to add optimization rules, data sources and data types by embedding into

[r]

Algorithm, Hadoop, Spark, framework, MapReduce, classification, parallel, k-nearest neighbor’s, naïve Bayesian, Clara, cluster, Tartu University... Spark raamistiku

The OH radicals were produced under controlled conditions in order to ex- amine the relationship between fluorescence intensity and radical concentration; from our measurements the