(Version 2, mit korrigierten Tippfehlern - ich hoffe, dass alle ...)
Hallo Habr!
Jetzt saß er und machte einen Prototyp des genetischen Algorithmus für einen Freund. Inspiriert, davon und einige andere Gedanken zu teilen ...
Gegeben (vom Kunden bestellt): In einem bestimmten
Königreich hat das Lager 100 Zellen. Die Ware ist drin. Wie nimmt man die Menge X, um alle beteiligten Zellen bis zum Ende zu leeren? Das heißt, Sie haben einen Zelltyp [34, 10, 32, 32, 33, 41, 44, 4, 28, 23, 22, 28, 29, 14, 28, 15, 38, 49, 30, 24, 18, 9, 15, 8, 17, 9, 2, 7, 30, 29, 29, 2, 28, 23, 19, 4, 15, 30, 38, 3, 14, 21, 43, 50, 29, 14, 17, 12, 25, 15, 23, 28, 47, 38, 29, 7, 36, 45, 25, 6, 25, 11, 10, 1, 19, 37, 24, 27, 50, 12, 1, 1, 44, 22, 48, 13, 46, 49, 11, 33, 29, 4, 19, 33, 12, 3, 47, 27, 26, 45, 40, 37, 21, 2, 8, 41, 5, 1, 9, 5] - wie man beispielsweise 40 wählt
Nun, Sie können pleite gehen, sicher gibt es etwas Kluges, aber Sie können es mit einem genetischen Algorithmus lösen ...
Die erste Frage: Warum trocknen Sie Ihr Gehirn, denn wenn Sie nur die Liste durchgehen, müssen Sie dafür die ersten beiden Zellen entnehmen - die zweite ist jedoch der Rest. Und Sie müssen nicht weit gehen. Aber um zu sehen, der Kunde ist ein Perfektionist, er möchte, dass es wie in einer Apotheke ist. Wahrscheinlich in einem Zelllager, das Gold wert ist. Es passiert.
Die zweite Frage: Wenn Sie es in aufsteigender Reihenfolge sortieren, können Sie sicherlich viel mehr Zellen durchwischen ... In unserem Beispiel gibt es viele Zellen mit weniger als zehn Zellen. Wahrscheinlich will der Kunde auch nicht;) Ich bin auch auf solche Leute gestoßen: Ich bin der Chef hier. Sie sagten dir - mach es, stell keine Fragen.
(Nun, nicht mein Klient, sonst würde ich wieder das Vertrauen in den menschlichen Verstand verlieren ...)
Nun, Gott sei mit ihm, jeder hat seine eigenen Prioritäten ... Dann werden wir über genetische Algorithmen sprechen - wir müssen das irgendwie lösen ... Wir werden in Java schreiben.
Für diejenigen, die noch nie wirklich davon gehört haben: Mutter Natur nachahmen.
- Verhalten codieren
- Wir überprüfen anhand eines geeigneten Benchmarks, wie gut jede Option funktioniert
- Die besten geben ihre Attribute an die nächste Generation weiter
Im letzten Schritt der Natur gibt es zwei Komponenten: Überkreuzen (Austausch von Zeichen zwischen denselben Teilen des Chromosoms) und Mutation (spontane Änderungen des genetischen Codes). Hallo, High School;)
Das ist wahrscheinlich alles. Wir werden codieren, aus welchen Zellen entnommen werden soll und aus welchen nicht. Wir haben 100 Zellen, was bedeutet, dass unser Chromosom aus 100 wahren / falschen Elementen besteht. Dafür habe ich einen String genommen, in den Nullen und Einsen geschrieben werden. Sie werden natürlich 100 sein.
Der Benchmark ist das Wichtigste in diesem Prozess. Die Natur sucht nach einer Nische, und die Computernatur sucht nach einem Loch in Ihrem Benchmark, um es zu täuschen und zu überleben. Wunderbar, ehrlich ...
Nach alledem so etwas:
private static int benchmark(String chromosome, boolean verbose) { int sum = 0; char[] cArr = chromosome.toCharArray(); for (int i = 0; i < cnt_bins; i++) { if (cArr[i] == '1') { sum += stock[i]; if (verbose) System.out.println("storage bin " + i + ":\t+" + stock[i] + "\t= " + sum); } if (sum == target_qty) { return 0; } } return Math.abs(target_qty - sum); }
Die Idee ist, dass je weiter wir von der gewünschten Zahl 40 entfernt sind, desto schlimmer. Wenn wir 40 Punkte erzielt haben, gehen wir auf dem Chromosom nicht weiter, wir haben gewonnen. Wir werden natürlich in aufsteigender Reihenfolge sortieren - je weniger Strafpunkte, desto besser.
Die erste Generation wird zufällig erstellt:
Da sich der genetische Algorithmus zwar dem Ziel nähert, es aber nicht immer erreicht, ist es wichtig, die Anzahl der Generationen zu begrenzen.
for (int generationNo = 0; generationNo < maxGenerationCnt; generationNo++) {
Sortieren, das Beste lassen:
...
Wir züchten und vermehren uns, stellen die Größe der Population wieder her. Das heißt, wir wählen zufällig Eltern aus, kombinieren die gleichen Zeichen (wenn Sie Glück haben - siehe die Austauschflagge), mutieren (Mutationsflagge), warten auf ein Wunder ...
Nun, hier ist ein Wunder für dich:Zielwert: 40
Bestand: [34, 10, 32, 32, 33, 41, 44, 4, 28, 23, 22, 28, 29, 14, 28, 15, 38, 49, 30, 24, 18, 9, 15, 8 17, 9, 2, 7, 30, 29, 29, 2, 28, 23, 19, 4, 15, 30, 38, 3, 14, 21, 43, 50, 29, 14, 17, 12, 25 15, 23, 28, 47, 38, 29, 7, 36, 45, 25, 6, 25, 11, 10, 1, 19, 37, 24, 27, 50, 12, 1, 1, 44, 22 48, 13, 46, 49, 11, 33, 29, 4, 19, 33, 12, 3, 47, 27, 26, 45, 40, 37, 21, 2, 8, 41, 5, 1, 9 , 5]
Generation 0; Bester / letzter Elternteil / schlechtester: 705/991/1580
Generation 1; Bester / letzter Elternteil / schlechtester: 576/846/1175
Generation 2; Bester / letzter Elternteil / schlechtester: 451/722/1108
Generation 3; Bester / letzter Elternteil / schlechtester: 0/613/904
Lösung gefunden
Lagerplatz 7: +4 = 4
Lagerplatz 10: +22 = 26
Lagerplatz 13: +14 = 40
Und hier ist der ganze Code package ypk; import java.io.IOException; import java.io.StringWriter; import java.util.AbstractMap.SimpleEntry; import java.util.stream.Collectors; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; public class YPK { private static int generation_size = 1000; private static int best_size = 200; private static int cnt_bins = 100; private static int max_stock = 50; private static double exchange_rate = .2; private static double mutation_rate = .01; private static Random rnd = new Random(); private static int target_qty = rnd.nextInt(cnt_bins * max_stock / 5);
Und schließlich: Wenn Sie mit den Parametern verwechseln - zu viele Mutationen, zu kleine Populationsgröße usw. - wird stagnieren oder sogar die schlechtesten Ergebnisse liefern.
Dieses Problem wird übrigens oft schon zufällig gelöst und die nächsten Generationen werden nicht benötigt :) Wenn Sie die Lebensdauer des Computers verkomplizieren möchten, entfernen Sie diese Rückgabe aus dem Benchmark:
if (sum == target_qty) { return 0; }
Dies wird die Aufgabe komplizieren und den Computer ein wenig leiden lassen ...
Viel Glück
m_OO_m