PRACOWNIA Z ALGORYTMÓW EWOLUCYJNYCH Tomasz Kupczyk, Tomasz Urbański Programowanie genetyczne - gra SNAKE II UWr Wrocław 2009
Spis treści 1. Wstęp 3 1.1. Ogólny opis..................................... 3 1.2. Informacje dla użytkowników........................... 3 2. Charakterystyka systemu 4 2.1. Charakterystyka osobnika............................. 4 2.2. Schematy ewolucji................................. 4 2.3. Zastosowane operatory genetyczne........................ 5 2.3..1 MaxReproduction............................. 5 2.3..2 AdaptationCrossover............................ 5 2.3..3 MultipleMutation............................. 5 2.3..4 ClassicCrossover.............................. 5 2.3..5 ClassicMutation.............................. 6 2.3..6 ClassicReproduction............................ 6 3. Wyniki 6 3.1. Mała mutacja.................................... 6 3.2. Duża mutacja.................................... 7 4. Podsumowanie 7 2
1. Wstęp 1.1. Ogólny opis Projekt jest próbą wygenerowania w miarę dobrze grającego programu w popularną grę Wąż przy pomocy algorytmów ewolucyjnych. Reguły gry Wąż są bardzo proste. Sterujemy osobnikiem złożonym z wielu segmentów o tej samej wielkości połączonych razem ze sobą. W grze poruszamy się w trzech możliwych kierunkach: lewo, prawo, prosto (w zależności od orientacji głowy węża). W każdym momencie na planszy znajduje się dokładnie jeden kawałek jedzenia. Gdy wąż go zjada jego ogon wydłuża się o jeden segment, a nowy kawałek jedzenia pojawia się w innym losowym miejscu. Wąż ginie kiedy próbuje zjeść siebie bądź chce wyjśc poza palnsze. Celem gry jest zjedzenie jak najwięcej kawałków jedzenia. Do stworzenia osobnika wykorzystujemy programowanie genetyczne. 1.2. Informacje dla użytkowników Program zrealizowany jest jako applet Java. Można w nim ustalić wielkość populacji, liczbę generacji, prawdopodobieństwo reprodukcji, krzyżowania i mutacji czyli dane wejściowe dla algorytmu ewolucyjnego. Interfejs graficzny zawiera cztery podstawowe przyciski: Rozpocznji ewolucje, Zakończ ewolucje, Rozpocznji symulacje, Zakoncz Symulacje. 3
2. Charakterystyka systemu 2.1. Charakterystyka osobnika Wybraliśmy kodowanie drzewiaste osobnika, gdyż jest najłatwiejsze do zaprogramowania, a nie tracimy w żaden sposób na sile wyrazu takiego osobnika. W węzłach wewnętrznych drzewach przechowywane są funkcje dwuargumentowe. Ich wybór był podyktowany ich przydatnością oraz ustalony eksperymantelnie podczas testowania. W liściach drzewa znajdują się kierunki względne. Oto opis kilku tych funkcji: iff oodup - Jeżeli jedzenie jest bliżej górnej krawędzi planszy niż głowy węża wykonaj lewe poddrzewo. W przeciwnym przypadku wykonaj prawe poddrzewo. if M ovingright - Jeżeli wąż porusza się w prawo to wykonaj lewe poddrzewo. W przeciwnym przypadku wykonaj prawe poddrzewo. ifdangerright - Jeżeli w polu na prawo od głowy węża znajduję się ciało węża lub krawędź planszy to wykonaj lewe poddrzewo. W przeciwnym przypadku wykonaj prawe poddrzewo. ifdangert woahead - Jeżeli w jednym lub dwóch ruchach wąż ugryzie się sam lub zderzy się z krawędzią planszy to wykonaj lewe poddrzewo. W przeciwnym przypadku wykonaj prawe poddrzewo. progn - Wykonaj prawe poddrzewo a przy następnym ruchu wykonaj lewe poddrzewo. 2.2. Schematy ewolucji Przez schemat ewolucji rozumiemy sposób tworzenia populacji potomków z populacji rodzicielskiej. Niech P t oznacza populację rodziców w t-tej generacji. SCHEMAT PIERWSZY - pierwszy zaimplementowany schemat nie opiera się na klasycznym schemacie ewolucji w programowaniu genetycznym. Występują w nim trzy operatory, które będą opisane później. Działa on następująco: Wybierz najlepszego osobnika w populacji P t i zastąp nim pewien ustalony ułamek populacji P t (MaxReproduction). Wybierz m-krotnie po dwóch różnych osobników (metodą ruletki) z P t, skrzyżuj ich i zastąp ich wynikłymi z krzyżowania osobnikami (AdaptationCrossover). Wybierz jednego osobnika (metodą ruletki) z P t, usuń jego dowolne poddrzewo i zastąp je losowym poddrzewem. Umieść osobnika spowrotem w P t (MultipleMutation). SCHEMAT DRUGI - opiera się na klasycznym schemacie programowania genetycznego. Występują również trzy operatory, które zostaną opisane później. Z każdym operatorem związane jest prawdopodobieństwo p 1, p 2 oraz p 3. W każdej generacji każdy z operatorów jest stosowany zgodnie z jednym z powyższych prawdopodobieństw. Schemat działa następująco: Stwórz pustą populację potomków C t. Dopóki liczba osobników w C t nie jest równa liczbie osobników w P t wykonuj poniższy krok. Jeżeli udał się (z ppb. p1) ClassicCrossover, to wybierz dwa osobniki z P t metodą ruletki. Skrzyżuj je i wstaw dwóch potomków do C t. 4
Jeżeli udał się (z ppb. p2) ClassicMutation, to wybierz osobnika z P t metodą ruletki. Zamień jest dowolne losowe poddrzewo na losowe drzewo. Wstaw tak zmutowanego osobnika do C t. Jeżeli udał się (z ppb. p3) ClassicReproduction, to wybierz osobnika z P t metodą ruletki. Wstaw tego osobnika do C t. Zastąp P t przez C t. Schemat pierwszy okazał się niezbyt dobrze dobrany, gdyż operator MaxReproduction powodował zbyt duży nacisk selektywny. Opisaliśmy go jednak, aby pokazać drogę, która dążyliśmy do osiągnięcia najlepszego rozwiązania. 2.3. Zastosowane operatory genetyczne 2.3..1 MaxReproduction Operator ten pobiera trzy parametry: populację P, adaptację A oraz p [0, 1). Parametr p oznacza jaki procent populacji P należy zastąpić najlepszym osobnikiem w populacji P. Operator ten z początku znacznie polepszył wyniki, ale później okazało się, że dość szybko prowadzi on do dominacji najlepszego osobnika w populacji, a co za tym idzie do skupienia się algorytmu w obrębie tego osobnika i słabego rozproszenia poszukiwań. 2.3..2 AdaptationCrossover Operator ten pobiera trzy parametry: populację P, adaptację A oraz nieujemną liczbą całkowitą times, która oznacza ile razy mamy powtórzyć działanie operatora. Działaniem tym jest wylosowanie dwóch osobników metodą ruletki i skrzyżowanie ich. Pierwotne osobniki w P są zastępowane przez swoje dzieci. Bardzo trudno jest określić czy operator ten ma pozytywny czy negatywny wpływ na działanie algorytmu. Może się zdarzyć tak, że dwa dobre programy po tej operacji będą miały mierne wyniki, ale również może zajść sytuacja zupełnie odwrotna. Napewno operator ten jest dobry pod względem rozszerzenia obszaru poszukiwań w obrębie tych najlepszych osobników. Operator ten przypomina trochę przeszukiwanie lokalne, gdyż po skrzyżowaniu najprawdopodobniej dostaniemy osobników bliskich swoim rodzicom. 2.3..3 MultipleMutation Operator ten pobiera trzy parametry: populację P, adaptację A oraz p [0, 1]. Parametr p jest szansą na zastosowanie tego operatora. Operator ten losuje osobnika metodą ruletki, następnie losuje jego losowe poddrzewo i zastępuje je losowym drzewem o losowej wielkości. Pierwotny osobnik jest zastępowany przez zmutowanego osobnika. Głównym zadaniem tego operatora jest rozproszenie przeszukiwań. 2.3..4 ClassicCrossover Działa tak samo jak AdaptationCrossover z tą różnicą, że pobiera dodatkowy parametr, którym jest nowa populacja. Skrzyżowane osobniki nie zastępują swoich rodziców w starej populacji, lecz trafiają do nowej. 5
Rysunek 1: Ewolucja z prawdopodobieństwem mutacji 0.1 widok 1. 2.3..5 ClassicMutation Działa tak samo jak MultipleMutation z tą różnicą, że pobiera dodatkowy parametr, którym jest nowa populacja. Zmutowany osobnik nie zastępuje swojego rodzica, lecz trafia do nowej populacji. 2.3..6 ClassicReproduction Metodą ruletki wybiera osobnika z populacji rodzicielskiej. Pobiera dodatkowy parametr, którym jest nowa populacja. Wybrany osobnik trafia do nowej populacji, populacja rodzicielska pozostaje bez zmian. 3. Wyniki 3.1. Mała mutacja Poniżej znajdują się dwa wykresy obrazujące ilość zjedzonych kawałków jedzenia w zależności od prawdopodobieństwa wyboru operatorów reprodukcji oraz krzyżowania. Prawdopodobieństwo mutacji jest ustalone na 0.1. Funkcja celu to średnia z trzech przeprowadzonych rozgrywek przez osobnika. Dodatkowo każdy test został przeprowadzony trzykrotnie, a wynik przedstawiony na wykresie to średnia z tych trzech testów. Uśrednienie testów zostało wprowadzone w celu uniknięcia sytuacji kiedy przy ustalonych parametrach ewolucja populacji przypadkowo trafia w dobry obszar poszukiwań. Obliczenia zostały wykonane na komputrze z dwurdzeniowym procesorem Intel Core 2 Duo 2.2 GHz wyposażonym w 4 GB pamięci RAM. Przy populacji równej 1000 i 80 generacjach obliczenia trwały około 16 godzin. Z powyższygo wykresu możemy odczytać kilka informacji. Po pierwsze wykres jest lekko chaotyczny. Mamy wiele zaburzeń co sugeruje, że dobór prawdopodobieństw operatorów 6
Rysunek 2: Ewolucja z prawdopodobieństwem mutacji 0.1 widok 2. genetycznych nie jest łatwy, a nawet ich losowy wybór nie determinuje złego wyniku. Po drugie kiedy prawdopodobieństwo krzyżowania jest bliskie zeru otrzymujemy niskie wyniki. Oznacza to, że sam operator mutacji jest niewystarczający do rozwoju populacji nawet dla tak dużej populacji i ilości generacji. Po trzecie otrzymujemy najlepsze wyniki dla obszaru znajdującego sie w kwadracie którego boki odpowiadają prawdopodobieństwom z przedziału 0.8 1.0. Tak więc te parametry dają najlepsze wyniki w przeprowadzaonym teście. 3.2. Duża mutacja Powyżej znajduje sie wykres przedstawiający wynik analogicznego testu, ale dla prawdopodobieństwa mutacji równego 0.3. Zauważmy, że wykres jest chaotyczny co nie było trudne do przewidzenia. Zwiększona mutacja spowodowała większe zaburzenia. Nadal widzimy, że sama mutacja nie jest wystarczająca do rozwoju populacji. Dzięki zwiększonej mutacji udało nam sie uzyskać lepsze wyniki - bliskie 80. 4. Podsumowanie Przedstawione zagadnienie jest ciekawe i wyjątkowo efektowne. Zabawa z programem przyspoży wiele przyjemności i być może zachęci użytkowników do poznania algorymów ewolucyjnych. Najelepszy osobnik jaki udało nam się wyewoluować potrafił zjeść około 80 kawałków jedzenia. Bez wątpienia uzyskalibyśmy lepsze wyniki gdyby nasze komputery mogły pracować dłużej niż 2 3 dni. 7
Rysunek 3: Ewolucja z prawdopodobieństwem mutacji 0.3 widok 1. Rysunek 4: Ewolucja z prawdopodobieństwem mutacji 0.3 widok 2. 8