Michal Mašek Genetické algoritmy v evoluční robotice

Podobne dokumenty
Aproximace funkcí 1,00 0,841 1,10 0,864 1,20 0,885. Body proložíme lomenou čarou.

Linea rnı (ne)za vislost

1 Soustava lineárních rovnic

Numerické metody 8. května FJFI ČVUT v Praze

Numerické metody minimalizace

Reprezentace dat. BI-PA1 Programování a Algoritmizace I. Ladislav Vagner

(1) Derivace. Kristýna Kuncová. Matematika B2 17/18. Kristýna Kuncová (1) Derivace 1 / 35

MATEMATIKA 3. Katedra matematiky a didaktiky matematiky Technická univerzita v Liberci

Internet a zdroje. (Zdroje na Internetu) Mgr. Petr Jakubec. Katedra fyzikální chemie Univerzita Palackého v Olomouci Tř. 17.

Edita Pelantová, katedra matematiky / 16

Kapitola 4: Soustavy diferenciálních rovnic 1. řádu

Co nám prozradí derivace? 21. listopadu 2018

Kristýna Kuncová. Matematika B2

Kristýna Kuncová. Matematika B3

Úvodní informace. 18. února 2019

Powyższe reguły to tylko jedna z wersji gry. Istnieje wiele innych wariantów, można też ustalać własne zasady. Miłej zabawy!

Necht je funkce f spojitá v intervalu a, b a má derivaci v (a, b). Pak existuje bod ξ (a, b) tak, že f(b) f(a) b a. Geometricky

Matematika 2, vzorová písemka 1

Matematika (KMI/PMATE)

DFT. verze:

Elementární funkce. Edita Pelantová. únor FJFI, ČVUT v Praze. katedra matematiky, FJFI, ČVUT v Praze

GENETICKÉ PROGRAMOVÁNÍ S JAZYKEM BRAINFUCK

Zásuvný modul QGISu. QGIS plugin pro práci s katastrálními daty

Komplexní analýza. Martin Bohata. Katedra matematiky FEL ČVUT v Praze Martin Bohata Komplexní analýza Mocninné řady 1 / 18

Kristýna Kuncová. Matematika B2 18/19

Funkce zadané implicitně. 4. března 2019

Inverzní Z-transformace

Automatové modely. Stefan Ratschan. Fakulta informačních technologíı. Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti

Obsah. Zobrazení na osmistěn. 1 Zobrazení sféry po částech - obecné vlastnosti 2 Zobrazení na pravidelný konvexní mnohostěn

TGH01 - Algoritmizace

Populační algoritmy a jejich uplatnění pro segmentaci obrazu. Pavel Jedlička

Rovnice proudění Slapový model

Paradoxy geometrické pravděpodobnosti

Lineární algebra - iterační metody

NÁVOD K POUŽITÍ KEZELÉSI KÉZIKÖNYV INSTRUKCJA OBSŁUGI NÁVOD NA POUŽÍVANIE. Česky. Magyar. Polski. Slovensky

TGH01 - Algoritmizace

Statistika (KMI/PSTAT)

Geometrická nelinearita: úvod

IEL Přechodové jevy, vedení

Katedra kybernetiky skupina Inteligentní Datové Analýzy (IDA) Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti

Martin Pergel. 26. února Martin Pergel

podle přednášky doc. Eduarda Fuchse 16. prosince 2010

GENETICKÉM PROGRAMOVÁNÍ

Katedra aplikované matematiky FEI VŠB Technická univerzita Ostrava

(2) Funkce. Kristýna Kuncová. Matematika B2. Kristýna Kuncová (2) Funkce 1 / 25

Stavový popis Stabilita spojitých systémů (K611MSAP) Katedra aplikované matematiky Fakulta dopravní ČVUT. čtvrtek 20. dubna 2006

Obsah Atributová tabulka Atributové dotazy. GIS1-2. cvičení. ČVUT v Praze, Fakulta stavební, katedra mapování a kartografie

Matematika III Stechiometrie stručný

Anna Kratochvílová Anna Kratochvílová (FJFI ČVUT) PDR ve zpracování obrazu / 17

Cauchyova úloha pro obyčejnou diferenciální rovnici

Kristýna Kuncová. Matematika B2 18/19. Kristýna Kuncová (1) Vzorové otázky 1 / 36

5. a 12. prosince 2018

Vladimír Ulman Centre for Biomedical Image Analysis. 10th October, 2007 FI MU, Brno

(13) Fourierovy řady

GEM a soustavy lineárních rovnic, část 2

PA152,Implementace databázových systémů 2 / 25

ggplot2 Efektní vizualizace dat v prostředí jazyka R Martin Golasowski 8. prosince 2016

Vlastnosti. Příprava. Czech - 2 -

kontaktní modely (Winklerův, Pasternakův)

Vybrané kapitoly z matematiky

návod k použití instrukcja obsługi

K SAMOSTATNÉ MODULOVÉ SCHODY MONTÁŽI. asta

Návod k použití BUBNOVÁ SUŠIČKA

Rekrutacja List Motywacyjny

Diferenciální rovnice základní pojmy. Rovnice se

Stochastické modelování v ekonomii a financích Konzistence odhadu LWS. konzistence OLS odhadu. Předpoklady pro konzistenci LWS

Robustní architektura vícevrstvých

MATEMATIKA 3 NUMERICKÉ METODY. Katedra matematiky a didaktiky matematiky Technická univerzita v Liberci

návod k použití instrukcja obsługi

Tvarová optimalizace pro 3D kontaktní problém

Obkládačky a dlaždičky Płytki ścienne i podłogowe: SIGHT šedá szary

TVL UMP2 NÁVOD K POUŽITÍ NÁVOD NA POUŽITIE

Návod k obsluze 2 Ďäçăßĺň ńţóçň 10 Instrukcja obsugi 18 Kullanma Kýlavuzu 26

IB047. Pavel Rychlý. 21. února

Teorie plasticity. Varianty teorie plasticity. Pružnoplastická matice tuhosti materiálu

Západočeská univerzita v Plzni Fakulta aplikovaných věd Katedra kybernetiky

Zadání: Vypočítejte hlavní momenty setrvačnosti a vykreslete elipsu setrvačnosti na zadaných

Register and win!

TVL LED NÁVOD K POUŽITÍ NÁVOD NA POUŽITIE

ČVUT v Praze, katedra geomatiky. zimní semestr 2014/2015

Určitý (Riemannův) integrál a aplikace. Nevlastní integrál. 19. prosince 2018

Paralelní implementace a optimalizace metody BDDC

Ústav teorie informace a automatizace. Tato prezentace je k dispozici na:

Design of Experiment (DOE) Petr Misák. Brno 2016

ULS4805FE. Návod k použití Návod na použitie Instrukcja obsługi Instruction Manual Használatı utasítás. Licensed by Hyundai Corporation, Korea

Numerické metody a statistika

HL24285SMART. Návod k použití Návod na použitie Instrukcja obsługi Használatı utasítás. Licensed by Hyundai Corporation, Korea

A71100TSW0 CS MRAZNIČKA NÁVOD K POUŽITÍ 2 PL ZAMRAŻARKA INSTRUKCJA OBSŁUGI 18 SL ZAMRZOVALNIK NAVODILA ZA UPORABO 35

Mechanika. Použité pojmy a zákony mohou být použity na jakékoliv mechanické stroje.

Euklidovský prostor. Funkce dvou proměnných: základní pojmy, limita a spojitost.

EWP W... CS PRAČKA NÁVOD K POUŽITÍ 2 PL PRALKA INSTRUKCJA OBSŁUGI 28

Algebra I Cvičení. Podstatná část příkladů je převzata od kolegů, jmenovitě Prof. Kučery, Doc. Poláka a Doc. Kunce, se

DXDB 215 NÁVOD K POUŽITÍ NÁVOD NA POUŽITIE INSTRUKCJA OBSŁUGI USER MANUAL

Kombinatorika a komplexní aritmetika

Obsah: Rozhodovací stromy. Úvod do umělé inteligence 11/12 2 / 41. akce

FAKULTA INFORMAČNÍCH TECHNOLOGIÍ

vystavit agenta realitě místo přepisování reality do pevných pravidel

BRNO UNIVERSITY OF TECHNOLOGY FACULTY OF INFORMATION TECHNOLOGY DEPARTMENT OF COMPUTER GRAPHICS AND MULTIMEDIA MASTER S THESIS AUTHOR

Průvodce studiem V této kapitole se budeme zabývat diferenciálním počtem pro funkce více

POLIURETANOWE SPRĘŻYNY NACISKOWE. POLYURETHANOVÉ TLAČNÉ PRUŽINY

Transkrypt:

Univerzita Karlova v Praze Matematicko-fyzikální fakulta DIPLOMOVÁ PRÁCE Michal Mašek Genetické algoritmy v evoluční robotice Kabinet software a výuky informatiky Vedoucí diplomové práce: RNDr. František Mráz, CSc. Studijní program: Informatika Studijní obor: Teoretická informatika 2011

Poděkování: Na tomto místě bych rád poděkoval vedoucímu práce, RNDr. Františku Mrázovi, CSc., za jeho podnětné připomínky a za povzbuzení ve chvílích, kdy se mi nic nedařilo. Dále bych rád poděkoval mé rodině a přátelům za neutuchající psychickou podporu.

Prohlašuji, že jsem tuto diplomovou práci vypracoval samostatně a výhradně s použitím citovaných pramenů, literatury a dalších odborných zdrojů. Beru na vědomí, že se na moji práci vztahují práva a povinnosti vyplývající ze zákona č. 121/2000 Sb., autorského zákona v platném znění, zejména skutečnost, že Univerzita Karlova v Praze má právo na uzavření licenční smlouvy o užití této práce jako školního díla podle 60 odst. 1 autorského zákona. V Praze dne Michal Mašek

Název práce: Genetické algoritmy v evoluční robotice Autor: Michal Mašek Ústav: Kabinet software a výuky informatiky Vedoucí diplomové práce: RNDr. František Mráz, CSc. e-mail vedoucího: mraz@ksvi.mff.cuni.cz Abstrakt: Tato práce se věnuje experimentálnímu porovnání evoluce neuronové sítě pro řízení robota za pomoci různých variant genetických algoritmů. Na třech úlohách evoluční robotiky jsou porovnány algoritmy používající reálné a celočíselné kódování jedinců, algoritmy používající základní a pokročilé způsoby mutací a křížení a algoritmy s pevnou a variabilní velikostí populace. Cílem je určit, zda evoluce s použitím pokročilých genetických algoritmů vede k rychlejší konvergenci nebo k nalezení kvalitnějšího řešení než použití základního genetického algoritmu. Experimenty jsou provedeny v snadno rozšiřitelném simulátoru vyvinutém speciálně pro účely této práce. Klíčová slova: genetické algoritmy, evoluční robotika, reálné kódování jedinců, proměnlivá velikost populace Title: Genetic algorithms in evolutionary robotics Author: Michal Mašek Department: Department of software and computer science education Supervisor: RNDr. František Mráz, CSc. Supervisor s e-mail address: mraz@ksvi.mff.cuni.cz Abstract: Through series of experiments this work compares effects of different types of genetic algorithms on evolution of a neural network that is used to control a robot. Genetic algorithms using binary and real coded individuals, algorithms using basic and advanced mutations and crossovers and algorithms using fixed and variable population size are compared on three tasks of evoltionary robotics. The goal is to determine wether usage of advanced genetic algorithms leads to faster convergence or to better solution than usage of basic genetic algorithm. Experiments are performed in an easily extendable simulator developed for purposes of this work. Keywords: genetic algorithms, evolutionary robotics, real coded individuals, variable population size

Obsah 1 Úvod 1 1.1 Struktura práce.............................. 2 2 Základní pojmy 3 2.1 Umělé neuronové sítě........................... 3 2.2 Genetické algoritmy............................ 6 2.3 Evoluční robotika............................. 7 3 Genetické operátory 9 3.1 Kódování jedinců............................. 9 3.2 Mutace................................... 10 3.3 Křížení................................... 12 3.4 Variabilní velikost populace....................... 13 3.4.1 GAVaPS.............................. 13 3.4.2 PRoFIGA............................. 15 4 Simulátory 17 4.1 Evorobot.................................. 17 4.2 Stage.................................... 18 4.3 Enki.................................... 19 4.4 Použité řešení............................... 20 5 Experimenty 22 5.1 Testovací úlohy.............................. 22 5.1.1 Vyhýbání se překážkám..................... 23 5.1.2 Vyhledávání objektu....................... 24 5.1.3 Dobíjení baterie.......................... 26 5.2 Sady experimentů............................. 27 5.2.1 Základní operátory........................ 28 5.2.2 Pokročilé operátory........................ 28 5.2.3 Variabilní velikost populace................... 29 6 Výsledky 31 6.1 Použité grafy............................... 31 6.2 Pevná velikost populace......................... 33 6.2.1 Vyhýbání se překážkám..................... 34

6.2.2 Vyhledávání objektu....................... 36 6.2.3 Dobíjení baterie.......................... 38 6.3 Variabilní velikost populace....................... 39 7 Hodnocení 43 7.1 Možnosti dalšího výzkumu........................ 44 8 Závěr 46 Literatura 47 A Simulátor evoluce 49 A.1 Pluginy.................................. 49 A.2 Ukázková implementace operátorů.................... 50 A.3 Konfigurace experimentu......................... 55 A.4 Provedení experimentu.......................... 57 A.5 Výsledky experimentu.......................... 58 A.6 Zobrazení jízdy robota.......................... 59

Kapitola 1 Úvod Genetické algoritmy nacházejí použití v mnoha oblastech a jednou z nich je i evoluce řízení robotů. Již dlouho se s použitím genetických algoritmů daří vyvíjet řízení pro roboty řešící i netriviální úlohy. Většinou při tom byly použity základní verze genetických algoritmů v kombinaci s neuronovými sítěmi. Je proto zajímavou otázkou, co by se stalo, pokud by byly použity modernější varianty genetických algoritmů. Odpověd se pomocí série experimentů snaží nalézt tato práce. Porovnány budou algoritmy používající celočíselná kódování jedinců s algoritmy používajícími jedince kódované reálnými čísly. Při použití celých čísel je prohledávaný prostor poměrně malý. Reálné kódování jedinců by proto mohlo poskytnout prostor pro nalezení kvalitnějšího řešení, na druhou stranu může být ale prohledávaný prostor natolik široký, že konvergence bude příliš pomalá. Nebo se může ukázat, že při použití celočíselného kódování s malými čísly (např. čtyři bity na jedno číslo) je již prohledávaný prostor dostatečně široký a použití jiného kódování je jen plýtvání výpočetními prostředky. Dále budou porovnány algoritmy používající základní typ mutace a křížení s algoritmy používajícími jejich modernější varianty. Základní typy mutace a křížení neberou v úvahu žádné vnější vlivy jako kvalitu řešení kódovaného daným jednicem, hodnotu mutovaného genu nebo aktuální fázi evoluce. Modernější varianty mutací a křížení přitom pomocí těchto hodnot směřují evoluci určitým směrem, čímž by mohly přispět ke zrychlení evoluce a k nalezení kvalitnějšího řešení. Ačkoliv byly modernější varianty genetických operátorů primárně navrženy pro jedince kódované reálnými čísly, nic nebrání jejich použití i na jedince kódované celými čísly. Kombinace malého prohledávaného prostoru a modernějších genetických operátorů by mohla dospět k zajímavým výsledkům. Nakonec budou srovnávány algoritmy s pevnou velikostí populace s algoritmy s variabilní velikostí populace. Pokud je velikost populace fixní po celou dobu evoluce, tak hrozí, že genetický algoritmus bud předčasně zkonverguje (typicky v případě, že byla populace příliš malá), nebo že bude zbytečně vyhodnocovat velké množství jedinců a plýtvat tak výpočetními zdroji. Tento nedostatek se snaží řešit algoritmy s variabilní velikostí populace, které velikost populace upravují podle toho, v jaké fázi se evoluce právě nachází. Všechny zmíněné posupy budou experimentálně porovnány na třech úlohách 1

evoluční robotiky. Srovnávacími kritérii při tom budou kvalita nalezeného řešení a rychlost konvergence. 1.1 Struktura práce První polovina práce poskytuje teoretický úvod do problematiky. Kapitola 2 seznámí čtenáře se základními pojmy, které budou v dalším textu použity. Čtenáři, kteří jsou již s problematikou neuronových sít í, genetických algoritmů a evoluční robotiky obeznámeni, ji mohou s klidným srdcem přeskočit. V kapitole 3 jsou popsány jak základní, tak pokročilé genetické operátory, které jsem vybral pro použití v této práci. Konkrétně se jedná o několik druhů mutací a křížení a o dva algoritmy s variabilní velikostí populace. Kapitola 4 pojednává o několika existujících robotických a evolučních simulátorech a knihovnách. Jsou zmíněny jejich základní vlastnosti a jejich použitelnost pro účely této práce. V závěru kapitoly je popsáno řešení, které jsem nakonec k provedení experimentů použil. Druhá polovina práce popisuje provedené experimenty a jejich výsledky. V kapitole 5 je podrobně rozebrána použitá metodika. V první části kapitoly jsou popsány tři vybrané úlohy evoluční robotiky, na kterých jsem experimenty provedl. Ve zbytku kapitoly jsou popsány všechny testované kombinace operátorů a jejich parametry. V kapitole 6 jsou pak popsány výsledky experimentů. Nejprve jsou popsány výsledky experimentů s pevnou velikostí populace, a poté výsledky experimentů s variabilní velikostí populace. Kapitola 7 shrnuje výsledky popsané v kapitole 6 a nabízí několik směrů, kterými by se mohl ubírat další výzkum. Na přiloženém CD je elektronická verze tohoto textu a zdrojové kódy simulátoru použitého k provedení experimentů. 2

Kapitola 2 Základní pojmy Tato kapitola je určena zejména těm, kteří nejsou obeznámeni s funkcí umělých neuronových sítí, s genetickými algoritmy nebo s principy evoluční robotiky. Klade si za cíl vymezit pojmy, které budu v dalším textu často používat, a poskytnout základní náhled na postupy a struktury, na kterých je celá práce postavena. Protože všechny tři zmíněné obory jsou velmi rozsáhlé, zaměřím se pouze na ty jejich části, které budou v této práci opravdu používány. 2.1 Umělé neuronové sítě Umělé neuronové sít ě (Artificial neural networks) jsou počítačové struktury inspirované funkcí biologických neuronových sítí. V této práci se budu zabývat výhradně funkcí umělých, nikoliv biologických neuronových sítí, a proto pokud v dalším textu bude použito slovní spojení neuronová sít, je tím vždy myšlena sít umělá. Neuronová sít je tvořena konečným počtem základních jednotek, které se nazývají neurony. Ty jsou vzájemně různě propojeny a mohou si tak předávat signály. Základní verze neuronu sečte vážené vstupní signály, přičte prahovou hodnotu a výsledek zpracuje pomocí takzvané přenosové funkce (transfer function). Neuron (Artificial neuron [17]) Neuron s vahami (w 1,...,w n ) R n, prahem ρ R a přenosovou funkcí f : R n+1 R n R počítá pro libovolný vstup z R n svůj výstup y R jako hodnotu přenosové funkce v z, f[ w,ρ]( z). V této práci budu používat jako přenosovou funkci tzv. sigmoidální přenosovou funkci [17, 18]: 1 f[ w,ρ]( z) = f(ξ) = 1 + e, λξ kde n ξ = z i w i + ρ i=1 a λ je koeficient strmosti. Průběh sigmoidální přenosové funkce je zobrazen na obrázku 2.1. 3

1 10 5 0 5 10. Obrázek 2.1: Sigmoidální přenosová funkce s koeficientem strmosti λ = 1 Neuronová sít (Neural network [17]) Neuronová sít je uspořádaná šestice M = (N, C, I, O, w, ρ), kde N je konečná množina neuronů, C N N je množina orientovaných spojů mezi neurony, I N je množina vstupních neuronů, O N je množina výstupních neuronů, w : C R je váhová funkce, ρ : N R je prahová funkce. Uspořádaná dvojice (N,C) tvoří orientovaný graf. Vstupní neurony přijímají signály z okolního prostředí a propagují je pomocí vážených spojů k ostatním neuronům v síti. Výstupní neurony naopak své výstupy předávají zpět do okolního prostředí. Neuronům, které nejsou vstupní ani výstupní, se říká skryté, protože nemají s okolním prostředím žádný přímý kontakt. V takto obecné neuronové síti mohou být neurony libovolně pospojovány, a to dokonce i samy se sebou. V praxi se však častěji používají o něco omezenější modely, které se ale o to snáze reprezentují. Ve vrstevnaté neuronové síti (Multilayer neural network) jsou například neurony rozděleny do několika vrstev. V první vrstvě leží všechny vstupní neurony, v poslední vrstvě leží všechny výstupní neurony a ostatní neurony jsou rozděleny do takzvaných skrytých vrstev. Ukázka takové sítě je na obrázku 2.2 A. Spoje mezi neurony vedou pouze z nižších vrstev do vyšších. Každý neuron je navíc spojen se všemi neurony z vyšší vrstvy, čímž mezi každými dvěma vrstvami vznikne m n spojů. Díky tomu je možné váhy mezi dvěma vrstvami snadno reprezentovat jako reálnou matici W typu m n, kde prvek w ij W odpovídá váze spoje mezi i-tým neuronem nižší vrstvy a j-tým neuronem vyšší vrstvy. Kromě jednoduché vrstevnaté neuronové sítě budou v této práci použity i dvě varianty takzvaných rekurentních neuronových sítí (Recurrent neural network). To jsou 4

A: B: Obrázek 2.2: A: Vrstevnatá neuronová sít s jednou skrytou vrstvou. B: Rekurentní neuronová sít, jejž výstupy jsou při příštím průchodu sítí použity jako část vstupu. sítě, kde některé hrany vedou i zpět z vyšší vrstvy do nižší vrstvy. Ukázka takové sítě je na obrázku 2.2 B. Konkrétně se jedná o Jordanovu architekturu sítě [9]. Z každého výstupního neuronu vede jedna hrana do jednoho neuronu vstupní vrstvy. Na rozdíl od ostatních hran mají tyto vždy váhu 1 a nepodléhají učení. Hodnoty výstupních neuronů jsou proto v nezměněné podobě použity jako součást vstupu při příštím vyhodnocení sítě. Takováto sít se mimořádně hodí u robotických experimentů, robot tak vlastně má jakousi omezenou pamět. Kromě Jordanovy architektury sítě bude v jednom z experimentů použita ještě Elmanova architektura sítě [5] (viz obrázek 2.3), která se od Jordanovy liší v tom, že zpětné hrany vedou ze skryté vrstvy. Obrázek 2.3: Příklad Elmanovy architektury sítě. Zpětné hrany vedou ze skryté vrstvy. 5

1 procedure SimpleGA : 2 begin 3 t = 0 4 i n i c i a l i z u j P(t) 5 ohodnot P(t) 6 while (not ukončující podmínka ) do 7 begin 8 t = t + 1 9 P(t) = vyber P(t 1) jedinců z P(t 1) 10 rekombinuj P(t) 11 ohodnot P(t) 12 end 13 end Kód 2.1: Jednoduchý genetický algotitmus 2.2 Genetické algoritmy Genetické algoritmy jsou optimalizační algoritmy inspirované darwinovským principem selektivní reprodukce nejlepších jedinců. Čím je jedinec lépe přizpůsoben svému prostředí, tím lépe se reprodukuje a tím více jeho genů je přeneseno do další generace. Genetický algoritmus pracuje s populací virtuálních jedinců. Každý jedinec má jeden chromozom, ve kterém jsou zakódovány jeho vlastnosti. Algoritmus otestuje všechny jedince v populaci, ty úspěšné rozmnoží do nové populace a provede náhodné změny na jejich chromozomech. Tomuto procesu se říká generace a v průběhu algoritmu se několikrát opakuje. Toto schéma se nazývá Jednoduchý genetický algoritmus (Simple Genetic Algorithm) [7] a znázorňuje ho Kód 2.1. Na počátku (v kroku inicializuj P(t); P(t) označuje populaci jedinců v generaci t) je vytvořena populace jedinců s náhodnými chromozomy. Úspěšnost jedince je dána hodnotou ohodnocovací funkce nazývané fitness. Čím je fitness vyšší, tím je jedinec lepší. Jinými slovy, čím je fitness vyšší, tím lepší řešení problému daný jedinec kóduje. Výpočet fitness může být poměrně složitý a závisí na konkrétní úloze, kterou chceme řešit. Typickým příkladem je hledání maxima matematické funkce. V takovém případě jedinec kóduje jeden bod z definičního oboru funkce a fitness jedince odpovídá hodnotě funkce v tomto bodě. Výpočet fitness všech jedinců probíhá v kroku ohodnot P(t). Výběr jedinců, kteří přejdou do další generace, probíhá pomocí selekce (krok vyber P(t 1) jedinců z P(t 1)). Existuje celá řada různých způsobů selekce, společné ale mají to, že jedinci s lepší fitness jsou vybíráni s větší pravděpodobností, než jedinci s horší fitness. V této práci bude ve všech expermentech používána Turnajová selekce (Tournament selection). Ta z populace P(t 1) vybere náhodně dva jedince a porovná hodnoty jejich fitness. Do populace P(t) vybere většinou lepšího z nich, ale občas (s určitou malou pravděpodobností) vybere horšího z nich. Jedinec není, po tom co je selekcí vybrán, z populace P(t 1) odstraněn, takže může být 6

vybrán opakovaně. Lepší jedinci se díky tomu v populaci množí na úkor horších jedinců. Selekce probíhá tak dlouho, dokud není vybráno P(t 1) jedinců. Velikost populace tedy zůstává po celou dobu běhu Jednoduchého genetického algoritmu stejná. To ale rozhodně není nezbytná vlastnost. Dvěma variantám genetických algoritmů, které za běhu mění velikost populace, se budu podrobněji věnovat v podkapitole 3.4. Aby genetický algoritmus vůbec našel nějaké řešení, musí provést nějaké změny na chromozomech vybraných jedinců. To obstarávají operátory křížení a mutace, které jsou zahrnuty v kroku rekombinuj P(t). Křížení je operátor, který ze dvou jedinců vytvoří dva nové jedince, kteří jsou kombinací původních jedinců. Mutace je operátor, který z jednoho jedince vytvoří nového jedince, který se většinou od původního jedince liší jen trochu. Různých druhů mutací i křížení existují celé řady a často záleží na konkrétním kódování chromozomů. Podrobněji se mutacím a křížení budu věnovat v kapitole 3. Ne všichni jedinci vybraní do další generace projdou křížením nebo mutací (to je dáno pravděpodobnostmi jednotlivých operátorů), ale i tak by se mohlo stát, že pokud je v průběhu algoritmu nalezen nejaký dobrý jedinec, tak se kvůli smůle při selekci nedostane do další generace, nebo se jeho fitness mutací či křížením výrazně sníží. To by byla škoda, protože bychom tak mohli přijít třeba i o nejlepší řešení. Proto je v genetických algoritmech často používán takzvaný elitismus. Část nejlepších jedinců (často určité procento populace) je prostě přenesena do další generace bez jakýchkoliv změn. Tito jedinci se ale stále účastní selekce a tedy se do další generace mohou dostat jejich kopie (případně změněné některými operátory). Nutno podotknout, že Jednoduchý genetický algoritmus elitismus nepoužívá a i přes to bylo dokázáno, že konverguje k optimálnímu řešení v konečném čase [7]. Elitismus tuto konvergenci pouze urychluje. Algoritmus běží, dokud není splněna ukončující podmínka. Tou bývá nejčastěji dosažení určitého počtu generací, provedení určitého počtu vyhodnocení fitness, nebo dosažení určité hodnoty fitness. Je vidět, že Jednoduchý genetický algoritmus je opravdu jednoduchý. V podstatě vše je řízeno náhodou. Aby ale algoritmus co nejrychleji našel co nejlepší řešení daného problému, je potřeba zvolit vhodné operátory mutace a křížení a také jejich pravděpodobnosti a rovněž vhodně nastavit další parametry, jako elitismus nebo velikost populace. U složitějších genetických algoritmů různých parametrů přibývá a jejich správné nastavení bývá na celé úloze to nejobtížnější. 2.3 Evoluční robotika Evoluční robotika je obor, zabývající se automatizovaným vývojem robotů pomocí genetických algoritmů. V zásadě se dají rozlišit dva hlavní směry, kterými se evoluční robotika zabývá. Prvním je vývoj morfologie robota přizpůsobené nějakým podmínkám [6, 21] a druhým je vývoj řízení pro konkrétního robota nebo skupinu robotů [10, 19]. V této práci se budu věnovat pouze druhému směru. Každý robot má určitou sadu senzorů a sadu efektorů. Senzory mu umožňují zjišt ovat informace o okolním prostředí a efektory mu dovolují se pohybovat 7

nebo jinak ovlivňovat okolní prostředí. Senzory mohou být například detektory infračerveného záření, kamera nebo mikrofon. Efektory bývají nejčastěji motory pohánějící kola, mechanická ruka, reproduktory nebo LED diody. Robot může být řízen libovolným programem. Při vývoji řízení robota pomocí genetických algoritmů se často používá řídící systém ve formě neuronové sítě [10, 18, 19]. Jako vstup jsou použity hodnoty robotových senzorů a získané výstupní hodnoty se použijí pro nastavení robotových efektorů (nejčastěji jako rychlosti otáčení kol). Je jasné, že aby neuronová sít byla schopná cokoliv řídit, je potřeba nějakým způsoben nastavit (naučit) její váhy. Tradičně se k tomuto účelu používá například algoritmus zpětného šíření [23] (back propagation) nebo hebovské učení [20] (hebbian learning). Tyto algoritmy však vyžadují množinu tzv. trénovacích vzorů, tj. dvojic (x,y), kde x je vektor vstupních hodnot a y je požadovaný vektor výstupních hodnot. Jinými slovy trénovací množina je konečná množina příkladů správných výstupů pro dané vstupní vzory. Proto se v evoluční robotice váhy nejčastěji vyvíjejí pomocí genetických algoritmů a doučování jedince lze použít jako doplňující prostředek v průběhu života jedince. Učící algoritmy totiž bývají citlivé na počáteční nastavení vah a při jejich aplikaci na váhy předvyvinuté genetickým algoritmem probíhá učení výrazně lépe a i výsledné chování robota bývá lepší [18]. Cílem této práce je důkladněji prozkoumat různé varianty evolučních algoritmů, a proto zde popisované experimenty nebudou vliv doučování neuronových sítí za života jedince využívat. Jak již bylo řečeno v podkapitole 2.2, genetické algoritmy pracují s populací jedinců. V Evoluční robotice je jedincem robot, respektive zakódovaná neuronová sít, která robota řídí. Fitness robota je dána tím, jak dobře dokáže robot vyřešit zadaný problém, například vyhýbat se překážkám. Abychom se dozvěděli, jak dobře se překážkám vyhýbá, musíme do robota nahrát neuronovou sít, umístit ho do prostředí, kde ho budeme testovat a nechat ho chvíli jezdit. Při tom potřebujeme zaznamenávat jak rychle jezdil a jak moc narážel do překážek, případně i další údaje. Toto vyhodnotíme a přiřadíme mu určitou fitness. Toto opakujeme v každé generaci se všemi jedinci v populaci. Provádět takovouto evoluci na reálných robotech je sice možné, ale technicky i časově velmi náročné [18]. Robot musí být mechanicky odolný. Zejména v počátečních fázích evoluce může neuronová sít řídit robota špatně a způsobit mu poškození (narazit do zdi, spadnout ze stolu... ). Robota je potřeba neustále zásobovat elektřinou. Jedno testování fitness může trvat poměrně dlouhou dobu a nelze ho provádět paralelně na více robotech, protože i pokud mají roboti úplně stejný hardware, mohou se v odvedeném výkonu výrazně lišit. Častější postup, a také postup použitý v této práci, je evoluce v simulátoru. Není potřeba se zabývat napájením ani poškozením robotů a rychlost evoluce je mnohonásobně vyšší. Ale ani tento postup není zcela bezproblémový. Je potřeba získat nebo naprogramovat dostatečně kvalitní simulátor fyziky prostředí a kvalitní simulaci robotových senzorů. Ani potom ale nemusí být výsledná neuronová sít bezproblémově použitelná i v reálném robotovi. Ukazuje se ale [18], že alespoň pro jednoduché třídy robotů se řízení vyvinuté v simulátoru chová téměř stejně i v reálném robotovi. 8

Kapitola 3 Genetické operátory Jak již bylo řečeno v kapitole 2, neuronové sítě lze snadno reprezentovat jako matice reálných čísel. Proto se v této kapitole nejprve zmíním o způsobech kódování reálných čísel do chromozomu jedince a poté proberu genetické operátory, které lze nad genomy reálných čísel používat. Pravdou je, že takových operátorů existuje nepřeberné množství, a proto se zde zaměřím pouze na několik vybraných, u kterých jejich autoři slibují dobré výsledky. 3.1 Kódování jedinců V počátcích genetických algoritmů byl jedinec reprezentován výhradně posloupností nul a jedniček [14]. To má dobré opodstatnění, protože počítač umí s takovou reprezentací snadno pracovat. Mutace je potom pouze prostá změna některých bitů a křížení záměna částí genomů dvou jedinců. Problém ale nastává ve chvíli, kdy takto binárně kódujeme reálné číslo. V tradiční reprezentaci reálných čísel je posloupnost nul a jedniček rozdělena na mantisu a exponent. Mantisa kóduje celé číslo a exponent určuje polohu desetinné čárky. Pokud dojde k mutaci jednoho bitu v exponentu, tak se hodnota reálného čísla může výrazně změnit a to nemusí být vždy žádoucí. U křížení je pak problém ještě větší, protože záměnou částí binárních zápisů dvou čísel vzniknou čísla, která nemají s hodnotami původních čísel prakticky nic společného. Nelze proto očekávat nějaké zlepšování nebo dokonce přibližování se k optimálnímu řešení jinak, než tak, že se do něj mutace nebo křížení čirou náhodou trefí. Pokud víme, že reálné číslo může nabývat pouze hodnot z intervalu [a; b], můžeme tento interval rozdělit na n částí a potom celými čísly reprezentovat pouze jednotlivé dělící body [11]: (b a) {x 0 = a,...,x i = i,...,x n = b}. n Na celá čísla v binárním zápise lze použít běžné mutace a křížení. Problém tohoto přístupu spočívá ve ztrátě přesnosti, což by u některých úloh mohlo vadit. Ukazuje se ale 1, že řízení pro robota lze s tímto kódováním vyvinout už pro a = 1.0, b = +1.0 1 Viz. Evorobotstar, http://gral.ip.rm.cnr.it/evorobot/simulator.html 9

a n = 255. Výhodou je naopak výrazné zmenšení prohledávaného prostoru a nižší pamět ové nároky. V počátcích genetických algoritmů byly operace s reálnými čísly výrazně pomalejší než operace s celými čísly. V dnešní době už ale rozdíl mezi nimi tak výrazný není. Navíc v případě evoluční robotiky, kde je potřeba simulovat celý virtuální svět (který při fyzikálních výpočtech používá reálná čísla) a v něm virtuálního robota řízeného neuronovou sítí (která také počítá s reálnými čísly), zabírají operace prováděné při mutacích a křížení jen zanedbatelný čas. Při použití celočíselného kódování reálných čísel je problém s náhodností mutace a křížení mnohem menší než při použití mantisy a exponentu, přesto však stále přetrvává. Z tohoto důvodu vzniklo široké odvětví genetických algoritmů zabývající se kódováním jedinců ne posloupností nul a jedniček, ale posloupností reálných čísel. Jeden gen je tedy jedno reálné číslo a mutace a křížení provádějí různé operace přímo s hodnotami jednotlivých genů. To umožňuje provádět cíleně pouze malé změny a tím i lépe doladit výsledné řešení. Nevýhodou je ale obrovský prohledávaný prostor. Mutace a křížení pracující s jedinci kódovanými posloupností reálných čísel proberu v sekcích 3.2 a 3.3. Tyto dva způsoby, jak pracovat s reálnými čísly, mají každý své výhody i nevýhody. Pomocí experimentů popsaných v kapitole 5 se budu snažit zjistit, zda je některý z nich pro evoluční robotiku výhodněší a jaký vliv mají velikost prohledávaného prostoru, přesnost, či sofistikovanější mutace na rychlost nalezení optimálního řešení a na jeho kvalitu. 3.2 Mutace V praxi se lze setkat v zásadě se dvěma druhy mutací: 1. První typ zvolí náhodně jeden gen daného jedince (genem přitom může být bud bit, celé číslo nebo reálné číslo) a hodnotu tohoto genu pak nějakým způsobem změní. 2. Druhý typ mutací projde všechny geny daného jedince a u každého genu se na základě pravděpodobnosti (většinou malé) rozhodne, zda ho změní nebo ne. Principy, na jejichž základě je gen změněn, jsou při tom v obou případech stejné. Pro účely následujících čtyř definic budu proto za mutaci považovat funkci, která dostane jako vstup hodnotu genu a tuto hodnotu nějakým způsobem změní. a) Binární mutace (Binary mutation) Hodnotu genu x {0, 1} změní binární mutace na hodnotu x = 1 pokud x = 0, nebo x = 0 pokud x = 1. Binární mutace je základní a nejjednodušší mutací, která předpokládá, že jedinec je tvořen posloupností bitů. Mutace se chová stále stejně bez ohledu na fázi evoluce a nebere ani v úvahu, co daný bit kóduje. Z toho plynou nevýhody popsané 10

v předchozí sekci, zde je tato mutace uvedena hlavně pro úplnost. V experimentech popsaných v kapitole 5 budu porovnávat efektivitu algoritmů používajících tuto mutaci s algoritmy používajícími některé z následujících mutací. b) Rovnoměrná mutace (Uniform mutation [12]) Rovnoměrná mutace změní hodnotu genu x [a k ;b k ] na hodnotu x rovnoměrně náhodně z intervalu [a k ;b k ]. vybranou Rovnoměrná mutace je určitou obdobou binární mutace v tom, že také nebere v úvahu fázi evoluce a její efekt je zcela náhodný. Má proto velký význam zejména v počátku evoluce, kdy zajišt uje rovnoměrné prohledávání prostoru řešení. Ke konci, kdy je potřeba spíš doladit již nalezená řešení, už ale nemusí být příliš vhodná. Tou dobou už má většina genů optimální nebo téměř optimální hodnotu, a je proto pouze malá šance, že tato mutace povede ke zlepšení fitness jedince. c) Nerovnoměrná mutace (Non-uniform mutation [12]) Nerovnoměrná mutace změní hodnotu genu x [a k ;b k ] na hodnotu x, kde za x je náhodně zvolena jedna z následujících možností: x + (t,b k x), x (t,x a k ). (t, y) je taková funkce vracející číslo z intervalu [0; y], že pravděpodobnost, že (t,y) bude blízko 0, je tím vyšší, čím vyšší je hodnota t. Michalewicz [12] používá funkci (t,y) = y r (1 t T )b, kde T je maximální počet generací, r je náhodné číslo z intervalu [0; 1] a b je parametr určující úroveň nerovnoměrnosti. Z počátku evoluce se nerovnoměrná mutace chová podobně jako rovnoměrné mutace. Její výhodnost se projeví až v pozdějších generacích. Dokáže totiž dobře prozkoumat prostor v těsném okolí nalezeného řešení a tím odhalit případné lepší hodnoty. d) Hraniční mutace (Boundary mutation [12]) Hraniční mutace změní hodnotu genu x [a k ;b k ] na hodnotu x, kde za x je náhodně zvolena z hodnot a k, b k. Obě hodnoty mají stejnou pravděpodobnost vybrání. Hraniční mutace dokáže snadno najít taková řešení, která leží v hraničních bodech intervalu. Sama o sobě není příliš efektivní, ale v kombinaci s některou jinou mutací nebo křížením může napomoci k řešení, které by bez ní bylo velmi obtížné odhalit. Mutace prvního typu v exerimentech v této práci nebudou použity, proto buduli v dalším textu používat název některé z těchto funkcí, budu tím myslet mutace druhého typu, to jest mutace, které mohou změnit více genů najednou. Tyto mutace potřebují kromě svých specifických parametrů vždy také dvě pravděpodobnosti, 11

označím je jako p + m a p m, kde p + m je pravděpodobnost toho, že se mutace vůbec provede. Hodnota p m je použita pouze pokud byl test na p + m úspěšný a mutace se má provést. V tom případě je u každého genu proveden test na pravděpodobnost p m a je-li úspěšný, je gen změněn pomocí příslušné mutační funkce. 3.3 Křížení Za křížení považujeme operátor, který dostane jako vstup dva jedince, I 1 = (x 1 1,...,x 1 n) a I 2 = (x 2 1,...,x 2 n), z nichž vyprodukuje dva jedince J 1 = (y 1 1,...,y 1 n) a J 2 = (y 2 1,...,y 2 n), kde x 1 i, x 2 i,y 1 i a y 2 i jsou celá nebo reálná čísla z intervalu [a i ;b i ] a i = 1,...,n. Existují sice i křížení, jejichž výsledkem je i jiný počet jedinců než dva [8, 12], v této práci je ale používat nebudu. a) Jednoduché jednobodové křížení (Simple crossover [11]) Náhodně zvolíme číslo k {1,...,n 1}. Vzniknou dva potomci J 1 = (x 1 1,...,x 1 k, x 2 k+1,...,x 2 n) a J 2 = (x 2 1,...,x 2 k,x 1 k+1,...,x 1 n). Jednoduché jednobodové křížení je přímo inspirováno křížením chromozomů v živých organismech. Je to také vůbec nejjednodušší možné křížení a jako takové bude v této práci použito v experimentech se základními genetickými operátory. Jedním genem v tomto křížení sice může být i jeden bit, pro lepší srovnání jedinců s celočíselným a reálným kódováním ale budu za jeden gen považovat vždy celé nebo reálné číslo. b) Aritmetické křížení (Arithmetical crossover [11]) Vzniknou dva potomci J k = (y k 1,...,y k i,...,y k n), k = 1, 2, kde y 1 i = λ x 1 i + (1 λ) x 2 i a y 2 i = λ x 2 i + (1 λ) x 1 i a λ [0; 1] je náhodné číslo. c) Geometrické křížení (Geometrical crossover [13]) Vzniknou dva potomci J k = (y k 1,...,y k i,...,y k n), k = 1, 2, kde y 1 i = (x 1 i) ω (x 2 i) ω 1 a y 2 i = (x 2 i) ω (x 1 i) ω 1 a ω [0; 1] je náhodné číslo. Aritmetické a geometrické křížení pracují narozdíl od jednoduchého křížení přímo s hodnotami jednotlivých genů. Díky tomu by měly být tyto způsoby křížení schopné provádět jemnější změny než jednoduché křížení. Jejich nevýhodou je ale to, že oba nově vytvoření jedinci leží vždy v prostoru mezi původními jedinci. Tato dvě křížení tedy nikdy nejsou schopná nalézt řešení, které leží stranou od původních dvou jedinců. d) Prolínavé křížení (Blend crossover [8]) Vzniknou dva potomci J k = (y k 1,...,y k i,...,y k n), k = 1, 2, kde y k i jsou náhodná čísla s rovnoměrným rozdělením z intervalu [max{a i,min α D};min{Max + α D,b i }]. Min = min{x 1 i,x 2 i }, Max = max{x 1 i,x 2 i }, D = Max Min a α je konstanta. 12

Prolínavé křížení má stejné výhody jako Aritmetické a Geometrické křížní, ale narozdíl od nich dokáže vytvořit i jedince ležící mimo interval vymezený původními jedinci. Pomocí konstanty α lze navíc snadno korigovat jak moc se lze z tohoto intervalu odchýlit. Proto jsem pro experimenty s pokročilými operátory zvolil právě prolínavé křížení. 3.4 Variabilní velikost populace Při návrhu genetického algoritmu je třeba zvolit množství parametrů a jedním z nich je velikost populace. Příliš malá populace může vést k nízké variabilitě a předčasné konvergenci genetického algoritmu, zatímco velká populace vede k opakovanému vyhodnocování fitness špatných jedinců a tím k plýtvání výpočetními zdroji. V různých fázích evoluce navíc může být ideální jiná velikost populace. Zpočátku bývá výhodnější větší populace a tím pádem lepší prohledávání prostoru řešení a snazší nalezení slibných jedinců. V pozdější fázi, kdy již většina jedinců konverguje k nějakým řešením a příliš se od sebe navzájem neliší, je naopak lepší menší populace. V evoluční robotice je tento problém zvlášt palčivý, nebot pro vyhodnocení fitness je třeba simulovat chování robota i prostředí, a to bývá výpočetně velmi náročné. V této práci jsem otestoval dva často citované algoritmy pracující s variabilní velikostí populace. 3.4.1 GAVaPS Řešením problému správné volby velikosti populace může být podle Michalewicze [11] nechat genetický algoritmus, aby si velikost populace určoval sám podle toho, v jaké fázi se právě nachází. Hlavní myšlenkou genetického algoritmu s variabilní velikostí populace (Genetic Algorithm with Varying Population Size (GAVaPS)) [3] je zavedení věku a délky života jedinců. Věk určuje, kolik generací je již daný jedince v populaci a délka života určuje, po kolika generacích bude z populace odstraněn. Délka života je každému jedinci přiřazena při jeho vzniku na základě jeho fitness, přičemž jedincům s nadprůměrnou fitness je délka života přiřazována vyšší než jedincům s podprůměrnou fitness. Délkou života je nahrazen tradiční mechanismus selekce, a jedinci pro reprodukci jsou proto vybíráni náhodně bez ohledu na fitness. Všichni jedinci v populaci mají stejnou pravděpodobnost, že budou vybráni, ale jedinci s vyšší délkou života se výběru budou účastnit vícekrát. Průběh algoritmu znázorňuje Kód 3.1. V běžném genetickém algoritmu jsou selekcí vybíráni jedinci pro reprodukci tak dlouho, dokud velikost nové populace není rovna velikosti původní populace. Je-li v GAVaPS v generaci t populace jedinců P(t), jsou jedinci vybíráni dokud nevznikne ρ P(t) nových jedinců, kde parametr ρ je takzvaný reprodukční koeficient. Výběr jedinců a jejich křížení a mutace jsou zahrnuty v kroku rekombinuj P(t). Poté, co jsou vytvořeni všichni noví jedinci, je spočtena jejich fitness a je jim přiřazena délka života (krok ohodnot P(t)). Ta 13

1 procedure GAVaPS: 2 begin 3 t = 0 4 i n i c i a l i z u j P(t) 5 ohodnot P(t) 6 while (not ukončující podmínka ) do 7 begin 8 t = t + 1 9 zvyš věk všech jedinců o 1 10 rekombinuj P(t) 11 ohodnot P(t) 12 odstraň z P(t) všechny jedince, j e j i c h ž 13 věk je vyšší než j e j i c h délka života 14 end 15 end Kód 3.1: Genetický algoritmus s variabilní velikostí populace zůstává konstantní po celou dobu života jedince. Délka života starších jedinců tedy není přepočítávána. Jediné, co se mění, je věk jedince, který je při vzniku jedince nastaven na nulu a po každé generaci se zvyšuje o jedna. Jedinci, jejichž věk překročí jim přidělenou délku života jsou z populace odstraněni. Aby algoritmus fungoval, je třeba pečlivě zvolit metodu výpočtu délky života. Michalewicz navrhuje tři způsoby výpočtu pro maximalizační problémy s nezápornou 2 fitness funkcí: Proporcionální: Lineární: Bi-lineární: min(minv ek + α fitness[i],maxv ek), PrumFit fitness[i] AbsMinFit MinV ek + 2α AbsMaxFit AbsMinFit, MinV ek + α fitness[i] MinFit PrumFit MinFit 1 (MinV ek + MaxV ek) + αfitness[i] PrumFit 2 MaxFit PrumFit pokud PrumFit fitness[i]. pokud PrumFit < fitness[i]. 2 Spíš by asi mělo jít o kladnou fitness funkci, protože pokud by všichni jedinci v populaci měli fitness rovnu nule došlo by k dělení nulou. To by ale prakticky nemělo nastat, protože populace, kde mají všichni jedinci fitness rovnou nule, nemá moc nadějí na zlepšení a většinou značí chybně navrženou fitness funkci. 14

1 procedure PRoFIGA: 2 begin 3 t = 0 4 G = t / poslední změna f i t n e s s / 5 i n i c i a l i z u j P(t) 6 ohodnot P(t) 7 while (not ukončující podmínka ) do 8 begin 9 t = t + 1 10 if nejlepší fitness se v ýrazně změnila then 11 / zvětšení populace / 12 N = min( P(t 1) k 1,N max ) 13 G = t / potenciální začátek stagnace / 14 elif G t >= d then / stagnace po d generací / 15 / resetování populace / 16 N = min( P(t 1) k 2,N max ) 17 G = t 18 else / krátkodobá stagnace / 19 / zmenšení populace / 20 N = max( P(t 1) k 3,N min ) 21 endif 22 P(t) = vyber N jedinců z P(t 1) 23 rekombinuj P(t) 24 ohodnot P(t) 25 end 26 end Kód 3.2: Schéma upravené verze algoritmu PRoFIGA, která je použita v této práci. MinFit, MaxFit a PrumFit odpovídají nejnižší, nejvyšší a průměrné fitness aktuální populace, zatímco AbsM inf it a AbsM axf it odpovídají nejnižší a nejvyšší dosud zaznamenané fitness a α = 1 (MaxV ek MinV ek). MinV ek a MaxV ek jsou 2 parametry určující nejnižší a nejvyšší povolený věk jedince. 3.4.2 PRoFIGA Trochu jiné řešení navrhují Eiben a kol. [4], Population Resizing on Fitness Improvement Genetic Algorithm (PRoFIGA) vychází z toho, že ze začátku genetitckého algoritmu je lepší prozkoumat co nejvíc možných řešení (explorace) a nalézt oblasti, ve kterých by se mohlo vyskytovat globální optimum, zatímco ke konci je lepší pouze doladit nalezená řešení (exploatace). Z počátku tedy bývá výhodnější větší populace a ke konci menší populace. Pseudokód algoritmu PRoFIGA znázorňuje Kód 3.2. Není to ale přesně tentýž algoritmus navržený Eibenem a spol. Aby byl PRoFIGA aplikovatelný na evoluci 15

řízení robota, bylo potřeba ho mírně upravit. Originální PRoFIGA předpokládá, že fitness jedince nemůže díky elitismu nikdy klesnout. To ale u robotických experimentů není pravda. Robot typicky startuje z náhodných pozic a tedy robot s úplně stejným genotypem může při každém vyhodnocení získat jinou (i nižší) fitness. Řádek 10 se v originálním algoritmu provede pouze pokud se fitness zvětšila, v této upravené verzi se ale provede pokud se fitness změnila. Za změnu se při tom považuje zvýšení nebo snížení fitness o alespoň q procent, kde q je konstanta. S nestálou hodnotou maximální fitness souvisí i druhá odchylka od původního algoritmu. Původní PRoFIGA je takzvaný steady state genetický algoritmus, to znamená, že v každém kroku je obnoveno určité procento jedinců a každý jedinec je vyhodnocen pouze jednou a zůstává v populaci, dokud není nahrazen některým z nových jedinců. Tím se sice ušetří vyhodnocování jedinců, kteří se nijak nezměnili, ale pro robotické experimenty to není ideální řešení. Pokud má jedinec štěstí na startovní pozici, může dostat vysokou fitness i když není moc dobrý. V případě steady state genetického algoritmu by to znamenalo, že by už nikdy nebyl vyhodnocen znovu a tento náhodný výsledek by se stal globálně nejlepším řešením. Cílem by ale mělo být nalezení takového řešení, které obstojí ve všech situacích. Proto verze PRoFIGA použitá v této prácí pracuje s tradičním schématem genetického algoritmu, jak byl popsán v kapitole 2. Jedinci do další generace budou v této práci vybíráni pomocí Turnajové selekce s elitismem, ale může být použit i jakýkoliv jiný selekční mechanismus. Jediná odchylka od Jednoduchého genetického algoritmu je tedy v tom, že množství jedinců vybraných do další generace není konstantní, ale kolísá. Existují tři způsoby, jak se může velikost populace změnit. V žádném z nich ale nesmí klesnout pod N min ani nesmí překročit N max, kde N min a N max jsou kosntanty. Pokud se nejlepší fitness od minulé generace změnila (klesla nebo stoupla) o více než q procent, tak bude velikost populace zvětšena koeficientem k 1 > 1. Pokud se fitness nezlepšila po d generací (dlouhodobá stagnace nebo pokles), je možné, že došlo k uváznutí v lokálním extrému, a proto bude velikost populace zvětšena koeficientem k 2 > 1. Koeficient k 2 by měl být o něco menší než k3 1 d. Tím se dosáhne toho, že populace bude navýšena na o něco nižší velikost, než jakou měla před začátkem stagnace a algoritmus tak získá možnost úniku z případného lokálního optima. V ostatních případech (krátkodobá stagnace) bude velikost populace snížena koeficientem k 3 < 1. 16

Kapitola 4 Simulátory Srovnání různých verzí genetických algoritmů je potřeba podložit dostatečným množstvím důkladných experimentů. Z toho plynou nároky, které jsou kladeny na použité nástroje. Ideální by samozřejmě byla evoluce na reálném robotovi, ale ta je časově a technicky natolik náročná, že by nebylo možné provést dostatečné množství experimentů. Proto jsem se rozhodl provést všechny experimenty pouze v simulátoru. Ten se skládá ze dvou dobře oddělitelných částí: ze simulátoru evoluce a z robotického simulátoru. Simulátor evoluce musí obsahovat základní schéma Jednoduchého genetického algoritmu a musí být jednoduché provést evoluci s různými genetickými operátory a s různě kódovanými jedinci. Kromě toho by mělo být možné provést v něm i experimenty s variabilní velikostí populace, které schéma Jednoduchého genetického algoritmu trochu boří. Experimenty se nebudou snažit nalézt strop toho, co se robot může pomocí evolučních algoritmů naučit, naopak budou spíš jednoduché a již dříve ověřené. Jednoduchý proto může být i použitý robotický simulátor. Bude bohatě stačit 2D simulátor a bude stačit, aby uměl simulovat pouze základní senzory a efektory. Ze senzorů budou potřeba zejména infračervené senzory a z efektorů pouze kola. Na internetu lze nalézt celou řadu různých více či méně použitelných simulátorů. V této kapitole nejprve stručně představím několik z nich, přičemž se zaměřím spíš na jejich použitelnost pro účely této práce, než na kompletní výčet jejich vlastností. Na závěr kapitoly pak popíši řešení, které jsem pro tuto práci zvolil. 4.1 Evorobot Z počátku se zdálo, že použitelným nástrojem by mohl být program Evorobot, který je volně stažitelný z internetu 1. Evorobot je program pro provádění robotických evolučních experimentů, což je přesně to co je náplní této práce, a proto by se jeho použití zdálo jako ideální. Spojuje totiž dohromady jak robotický simulátor, tak evoluci, včetně základních genetických operátorů. 1 http://laral.istc.cnr.it/evorobot/simulator.html 17

Evorobot byl navržen k tomu, aby umožňoval jednoduše zopakovat experimenty popsané v [18] s pomocí simulované nebo reálné Kephery [16]. Kephera už má sice řadu nástupců s podobnými nebo lepšími vlastnostmi (např. Kephera II, Kephera III nebo E-Puck), ale pro účely simulovaných experimentů to nehraje příliš velkou roli. Zajímavým způsobem je v Evorobotu vyřešena simulace senzorů. Odezvy jednotlivých senzorů byly změřeny a zaznamenány přímo na reálném robotovi pro různé vzdálenosti od překážky a s různými natočeními robota vzhledem k překážce. Podobným způsobem je vyřešen i pohyb robota. Na reálném robotovi bylo pro různé kombinace rychlostí otáčení pravého a levého kola změřeno, jakou vzdálenost robot ujede a o kolik se při tom pootočí. Díky tomu odezvy senzorů i pohyb robota dobře odpovídají realitě (alespoň v podmínkách, ve kterých bylo měření provedeno) a simulace je velmi rychlá, protože není třeba odezvu senzorů a pozici složitě počítat. Rozložení objektů v simulovaném světě je určeno v konfiguračním souboru stejně jako parametry evoluce jako jsou velikost populace, pravděpodobnost mutace a podobně. Evoluce probíhá podle schématu Jednoduchého genetického algoritmu s elitismem a s binární mutací a bez křížení. Roboti jsou řízeni pomocí neuronové sítě, kde jedna váha je kódována osmi bity. Za zmínku stojí jistě i nástupce Evorobota, program Evorobot* (čti evorobot star) [19], který je také na internetu volně ke stažení 2. V základu je Evorobot* velmi podobný jako Evorobot, ale přináší řadu nových experimentů a jeho grafické rozhraní je trochu uhlazenější. Na rozdíl od svého předchůdce ale pracuje místo s Kepherou s robotem E-Puck [15]. Právě proto, že jsou oba programy tak podobné, trpí oba i stejnými nedostatky. Aby byl některý z nich použitelný pro účely této práce, bylo by potřeba ho rozšířit o podporu pokročilých genetických operátorů a o podporu různých kódování jedince. Ukázalo se ale, že to není tak jednoduché, jak by se mohlo na první pohled zdát. Fakt, že je použito právě osm bitů na jednu váhu se totiž táhne skrz naskrz oběma programy a při snaze to změnit by bylo potřeba je z větší části přepsat. Kromě toho jsou oba programy silně vázány na grafické rozhraní. Spuštění experimentu například nelze udělat jinak než ručně za pomoci myši a klávesnice a v průběhu evoluce jsou neustále průběžně vykreslovány grafy. To je sice vhodné pro ladění a testování, protože je průběžně vidět pokrok v evoluci a je možné si experiment kdykoliv zastavit a zobrazit si průběh jízdy libovolného jedince v populaci, pro spuštění většího množství experimentů je to ale nepraktické. 4.2 Stage Jelikož se mi nepodařilo najít jiný nástroj, který by v sobě spojoval jak evoluci, tak robotický simulátor, rozhodl jsem se, že simulátor evoluce si naprogramuji sám. Pokročilé operátory a algoritmy s variabilní velikostí populace by konec konců bylo stejně potřeba naprogramovat od nuly i při úpravě Evorobota a samotný Jednoduchý 2 http://laral.istc.cnr.it/evorobotstar/ 18

genetický algoritmus není na implementaci nijak složitý. Naproti tomu naprogramovat pořádně alespoň základní robotický simulátor není vůbec jednoduché. Naštěstí se dá na internetu najít řada robotických simulátorů v různých jazycích a různých kvalitách. Jedním z těch kvalitních je robotický simulátor Stage. Stejně jako Evorobot a Evorobot* i Stage je na internetu volně dostupný ke stažení včetně všech zdrojových kódů 3. Jedná se o 2D robotický simulátor, který má implementovanou širokou škálu senzorů a efektorů. Stage byl navržen pro simulace s velkým počtem robotů, a proto poskytuje spíš výpočetně jednoduchý model světa a senzorů než dokonale realistickou simulaci a díky tomu je velmi rychlý. Podle autorů dokáže Stage simulovat pohyb jednoho robota až 1000 krát rychleji, než jak by se pohyboval ve skutečnosti a tisíc robotů dokáže simulovat zhruba stejnou rychlostí, jakou by se pohybovali ve skutečnosti [22]. Stage může běžet jako samostatný program, ve kterém je simulován virtuální svět, do kterého mohou být za běhu přidáváni virtuální roboti, kteří se pak v tomto světě pohybují. Druhá možnost je použít ho jako plugin pro program Player, který vytváří jednotné rozhraní mezi hardwarem reálného robota a jeho ovládacím programem. Stage v tomto případě převezme roli reálného robota a z kombinace Player/Stage se tak vlastně stává virtuální robot, kterého lze ovládat přes protokol TCP/IP. Třetí možnost je využití Stage jako C++ knihovny (tzv. libstage), která umožňuje provádění robotických simulací uvnitř jiného programu. Pro účely této práce se jako nejpoužitelnější jeví třetí způsob, tedy knihovna libstage. S její pomocí by bylo možné přistupovat k výpočtu fitness stejně jako k ostatním operátorům. Pokud by mutace byla funkce, která dostane jedince a nějakým způsobem ho změní, tak fitness funkce by dostala jedince a pomocí libstage by po určitou dobu simulovala jeho pohyb ve virtuálním světě a po vyhodnocení pohybu by vrátila výslednou fitness. Jako hlavní nevýhodu vidím zejména (sice malý ale ne nezanedbatelný) počet závislostí na externích knihovnách. To znesnadňuje samotnou instalaci a komplikuje přenositelnost mezi různými počítači. Druhou nevýhodu pak vidím v rozsahu celé knihovny (cca. 20 tisíč řádků kódu). Podle mých zkušeností nefunguje vždy všechno tak jak má a pokud je třeba najít příčinu problému, tak čím menší je prohledávaný prostor, tím lépe. 4.3 Enki Pokud bych měl v plánu provádět složitější experimenty, ideálně s větším množstvím robotů, tak bych rozhodně zvolil libstage. Pro účely této práce jsem se ale nakonec přiklonil ke knihovně Enki. Stejně jako libstage je i Enki 2D robotický simulátor napsaný v C++ a je na internetu volně ke stažení 4. Oproti Stage nemá tolik závislostí na externích knihovnách a její zdrojový kód je o poznání menší (cca. 7 tisíc řádků kódu). Umí proto simulovat pouze základní senzory. 3 http://playerstage.sourceforge.net/ 4 viz http://home.gna.org/enki/ 19

Příjemné je také to, že Enki má implementovaných několik robotů s diferenciálním řízením, což v knihovně libstage chybí, protože to je funkcionalita poskytovaná typicky až na úrovni Playeru. V knihovně libstage je tedy potřeba spočítat dopřednou rychlost, boční rychlost a rychlost otáčení robota, zatímco knihovna Enki si tyto údaje spočítá sama na základě rychlostí otáčení kol. Kromě toho je knihovna Enki poměrně hezky a jednoduše objektově navržená a díky tomu i snadno pochopitelná a v důsledku toho se s ní i dobře pracuje. Simulace probíhá tak, že je vytvořen nový svět a do něj jsou přidány různé překážky a robot. V každém kroku je potřeba přečíst hodnoty na robotových senzorech a nastavit rychlost otáčení jeho pravého a levého kola a to je vše. 4.4 Použité řešení Pro experimenty popsané v této práci jsem nakonec použil vlastní program, který v sobě má zabudovanou základní kostru genetického algoritmu a jedinci, mutace, křížení, selekce a fitness jsou implementovány jako pluginy. Díky tomu lze snadno měnit kódování jedinců a provádět experimenty s různými kombinacemi jedinců, mutací a křížení. Program je napsaný pro linux v jazyce C++ a pluginy jsou proto realizovány jako dynamické knihovny, které si program načte za běhu. Hlavní výhodu tohoto řešení vidím v tom, že základní program neklade žádná omezení na použité jedince ani genetické operátory a ani na použitý robotický simulátor. Program byl napsán za účelem provedení velkého množství různých experimentů, a proto nemá žádné grafické rozhraní a spouští se přímo z příkazové řádky. Není tedy žádný problém spouštět ho pomocí skriptu nebo přes SSH na vzdáleném počítači. Program sice nevyužívá více vláken, ale je možné ho bez problémů spustit vícekrát na jednom stroji a využít tak všechny jeho procesory. Paramentry každého experimentu jsou specifikovány v konfiguračním souboru. Ten určuje, které pluginy se mají použít a s jakými parametry. Konfigurační soubor je v jednoduchém strukturovaném formátu, kde každý operátor má vlastní skupinu nastavení, takže nehrozí kolize v názvech parametrů. Nastavení daného operátoru jsou navíc zcela závislá na konkrétní implementaci, takže záleží pouze na autorovi operátoru, kolik a jakých parametrů bude možné nastavit. Konfigurační soubory lze navzájem do sebe vkládat (includovat), takže pokud sada experimetů sdílí část společných nastavení, není třeba je neustále kopírovat, což velmi zjednodušuje správu a úpravy větší sady experimentů. Výsledky každého běhu každého experimentu jsou ukládány do několika souborů. Kromě průběhu fitness a délek trvání jednotlivých generací je zaznamenána i kopie konfiguračního souboru včetně čísla použitého k inicializaci náhodného generátoru, takže je možné experiment později přesně zreprodukovat. Zejména pro ladící účely jsou ukádány i záznamy výpočtu fitness u několika nejlepších jedinců společně se záznamem jejich genotypu. Díky tomu je možné odhalit případné abnormality v genotypech a v případě robotických experimentů je možné zobrazit průběh jízdy robota. Tím se dostávám ke klíčové části každé evoluce a tou je fitness. Vyhodnocení fitness je implementováno jako plugin (pro každou testovací úlohu jeden), který používá 20

knihovnu Enki pro simulaci pohybu robota ve virtuálním prostředí. Pohyb robota v tomto prostředí je řízen pomocí neuronové sítě. Normalizované hodnoty získané ze senzorů se použijí jako vstup pro neuronovou sít a výstup neuronové sít e se použije k nastavení rychlostí otáčení kol. Simulátor poté vyhodnotí pohyb robota a jeho interakci s okolním prostředím a aktualizuje odezvy jeho senzorů. Tento cyklus se opakuje, dokud není odsimulován předem daný počet kroků. Poměrně snadno by šlo nahradit knihovnu Enki knihovnou libstage, jediné co by se změnilo jsou pluginy implementující výpočet fitness. Záměnou jednoho řádku v konfiguračním souboru by pak šlo provést tentýž experiment, ale s úplně jiným způsobem výpočtu fitness. Stejně snadno lze nahradit také třeba jeden druh mutace za jiný, nebo změnit způsob křížení. Simulátor navíc není omezen pouze na robotické experimenty. Velmi snadno lze implementovat například jedince, který reprezentuje jeden bod z definičního oboru nějaké reálné funkce, a odpovdající fitness funkci, která spočítá hodnotu této reálné funkce v bodě reprezentovaném daným jedincem. Ostatní parametry jako mutace, křížení a selekce mohou zůstat beze změny a experiment se z evoluce řízení robota změní na hledání maxima reálné funkce. Více o simulátoru, jeho použití a možnostech jeho rozšíření lze nalézt v Příloze A. 21

Kapitola 5 Experimenty Cílem této práce je posoudit, zda se v evoluční robotice vyplatí používat modernější varianty genetických algoritmů, které jsou většinou výpočetně náročnější a často také složitější na implementaci, ale slibují lepší výsledky, nebo zda stačí používat pouze základní genetický algoritmus s celočíselným kódováním. Lepšími výsledky je myšleno nalezení lepšího řešení daného problému, případně nalezení srovnatelného řešení, ale v kratším čase. K tomuto účelu jsem sestavil sadu experimentů, které v této kapitole popíši. 5.1 Testovací úlohy Výhodnost či nevýhodnost pokročilých variant evolučních algoritmů jsem otestoval na třech robotických experimentech popsaných Nolfim a Floreanem [18]. Není mým cílem posuzovat co je a co není schopen se robot naučit za pomoci evoluční robotiky, ale zda je schopen se to naučit lépe či rychleji. Proto jsou všechny experimenty jednoduché a u všech již bylo dříve experimentálně ověřeno, že jsou zvládnutelné za pomoci základních genetických algoritmů s pevnou velikostí populace a binárním kódováním vah neuronové sítě. Všechny experimenty byly provedeny na simulovaném robotu E-puck za pomocí simulátoru, který jsem stručně popsal v předchozí kapitole, a který je podrobněji popsán v Příloze A. E-Puck (viz obrázek 5.1) je populární robot využívaný pro výukové a experimentální účely. Má průměr 75 mm a výšku 55 mm 1. Má osm infračervených senzorů, jednoduchou kameru, tři mikrofony a 3D akcelerometr a pohybuje se pomocí dvou krokových motorů. Může být ale vybaven i dalšími senzory. V této práci budu z jeho senzorů využívat infračervené senzory pro detekci překážek a v jednom z experimentů i detektory světla (což jsou vlastně infračervené senzory přepnuté do stavu, kdy nic nevysílají a pouze měří úroveň osvětlení) a detektor barvy podlahy. 1 E-puck má výšku 55 mm pouze v základní sestavě, může být ale vybaven různými přídavnými moduly, díky kterým může být vyšší. 22

Obrázek 5.1: Robot E-Puck [15] 5.1.1 Vyhýbání se překážkám Vyhýbání se překážkám [18] je základní problém, který musí řešit snad každý člověk zabývající se mobilní robotikou. Robot, který se nedokáže v prostředí pohybovat bez neustálých kolizí, může jen těžko plnit nějaké smysluplné úkoly. Pro účely experimentu ale předpokládejme, že robot nemá žádný jiný úkol, než se pohybovat co nejvyšší rychlostí a udržovat si při tom odstup od překážek. Kromě toho by se měl pohybovat pokud možno rovně (nechceme aby si jen našel místo, kde je dost prostoru a potom jezdil dokolečka). Robot je řízen nejjednodušší možnou vrstevnatou neuronovou sítí s osmi vstupními, dvěma výstupními a žádnými skrytými neurony, se sigmoidální přenosovou funkcí a s vahami v intervalu [ 5; 5]. Na vstupní neurony jsou mapovány výstupy infračervených senzorů s hodnotami normalizovanými do intervalu [0; 1], kde 0 odpovídá situaci, kdy senzor nedává žádnou odezvu, to jest je daleko od překážky a hodnota 1 značí, že senzor se překážky prakticky dotýká. Hodnoty výstupních neuronů jsou namapované na interval [ 0,5; 0,5] a určují rychlosti otáčení pravého a levého kola. Hodnota 0,5 odpovídá maximální rychlosti otáčení kola směrem dozadu a hodnota 0,5 odpovídá maximální rychlosti otáčení kola směrem dopředu. Simulátor v jednom kroku odsimuluje 100 milisekund. Jedna jízda robota se skládá maximálně z 400 kroků, tedy 40 simulovaných sekund. Fitness robota je počítána v každém kroku i {1,...,400} na základě naměřených hodnot infračervených senzorů a rychlostí otáčení kol podle vzorce [18]: Φ i = V i (1 v i )(1 I i ), kde V i [0; 1] je absolutní hodnota součtu hodnot rychlostí otačení kol v kroku i, v i [0; 1] je absolutní hodnota rozdílu rychlostí otáčení kol v kroku i a I i [0; 1] je maximum z normalizovaných hodnot všech infračervených senzorů v kroku i. Hodnota V i je tím vyšší, čím rychleji se robot pohybuje, hodnota (1 v i ) je nejvyšší, pokud se obě kola točí stejně rychle a robot se tedy pohybuje rovně (je 23

jedno zda dopředu nebo dozadu) a hodnota 1 I i je nejvyšší, pokud je robot daleko od všech překážek. Pokud robot narazí do zdi nebo do překážky, tak je jeho jízda okamžitě ukončena a za všechny kroky zbývající do konce simulace dostane přidělenu fitness Φ i = 0. Celková fitness F je dána jako součet všech Φ i vydělený maximálním počtem kroků, tedy: 400 i=1 Φ i F = 400, a protože Φ i [0; 1] i {1,...,400}, tak také celková fitness F [0; 1]. Obrázek 5.2: Aréna pro učení vyhýbání se překážkám. Simulace probíhá v obdelníkové aréně znázorněné na obrázku 5.2. Rozměry arény jsou 75 cm a 50 cm a je ohraničena zdí, takže z ní robot nemůže vyjet. Válce uprostřed arény mají všechny průměr 3 cm a středy dvou sousedních válců jsou od sebe vzdáleny 6 cm. Na začátku každé simulace je robot umístěn na náhodnou volnou pozici uvnitř arény a je natočen náhodným směrem. Pro srovnání velikostí je v pravém dolním rohu arény znázorněn robot, jeho průměr je 7,5 cm. Protože fitness, kterou robot získá, je z velké míry závislá na počátečním postavení robota, tak se stává, že robot řízený tou samou neuronovou sítí získá při některých počátečních pozicích výrazně horší fitness a při některých zase výrazně lepší fitness. To vede k tomu, že dobří jedinci jsou často evolucí vyřazeni prostě proto, že měli smůlu a propadli se tak hluboko, že je neochránil ani elitismus a špatní jedinci se naopak dostávají do čela a množí se do dalších generací. Není to tak častý jev, aby evoluci úplně rozbil, ale rozhodně ji zpomaluje, a je proto nežádoucí. Aby se těmto výkyvům předešlo, je každý jedinec nezávisle otestován desetkrát. To jest celá simulace jak byla popsána v předchozích odstavcích je provedena desetkrát, vždy s novou počáteční pozicí robota. Výsledná fitness jedince je potom dána jako aritmetický průměr hodnot získaných v jednotlivých simulacích. 5.1.2 Vyhledávání objektu Podobně jako u Vyhýbání se překážkám, ani v této úloze robot nesmí do ničeho narazit. Jeho hlavním cílem je ale najít uvnitř arény válec a zůstat u něho. Musí se 24

tedy naučit prozkoumávat arénu a rozlišovat podle odezvy senzorů, zda je u zdi nebo u válce. Robot je řízen rekurentní neuronovou sítí s deseti vstupními a dvěma výstupními neurony a žádnými skrytými neurony. Váhy jsou v intervalu [ 5; 5] a signály mezi neurony jsou přenášeny pomocí sigmoidální funkce. Výstupy infračervených senzorů jsou použity jako vstup prvních osmi vstupních neuronů, zbylé dva vstupní neurony mají jako vstup v prvním kroku hodnotu 0 a v dalších krocích hodnoty výstupních neuronů z minulého kroku. Jedná se tedy o rekurentní neuronovou sít s Jordanovou architekturou. Hodnoty výstupních neuronů určují stejně jako v předchozí úloze rychlosti otáčení kol. Jedna simulace opět trvá maximálně 400 kroků po 100 milisekundách. V každém kroku i {1,...,400} simulace je robotovi přidělana fitness Φ i = 1, pokud se střed robota nachází do 10 cm od středu válce. Pokud robot narazí do zdi nebo do válce, je jeho jízda ukončena a za další kroky získá fitnes Φ i = 0. V ostatních případech je mu přidělena fitness Φ i = 0,05 (jakýsi bonus za to, že do ničeho nenarazil). Zejména v počátečních fázích evoluce vytváří tato malá hodnota evoluční tlak na schopnost vyhýbat se překážkám. Bez ní by robot, který prakticky ihned narazil do zdi, získal stejnou fitness jako robot, který po celou dobu simulace nenarazil, ale měl smůlu a nedostal se ani na okamžik do blízkosti válce. První robot je při tom naprosto nepoužitelný, zatímco druhý robot má již pravděpodobně vyvinutou schopnost vyhnout se zdi a je tedy výrazně lepší. Celková fitness F robota je opět dána součtem fitness Φ i za všechny kroky a vydělená maximálním počtem kroků, tedy: F = 400 i=1 Φ i 400, a protože opět platí, že Φ i [0; 1], i {1,..., 400}, tak také F [0; 1]. Obrázek 5.3: Aréna pro učení vyhledávání objektu. Simulace probíhá v obdelníkové aréně o rozměrech 75 a 50 cm ohraničené, stejně jako v předchzí úloze, zdí. Aréna je znázorněna na obrázku 5.3. Válec poblíž středu arény má průměr 3 cm. Tečkovaná kružnice kolem něj znázorňuje vzdálenost, ve 25

které se musí nacházet střed robota, aby získal maximální fitness. Robot je opět pro srovnání velikostí znázorněn v pravém dolním rohu obrázku. Pozice robota i válce jsou na počátku každé simulace generovány náhodně. Robot začíná na náhodné volné pozici uvnitř arény natočený náhodným směrem. Válec je umístěn na náhodnou pozici v obdelníkové oblasti uprostřed arény o rozměrech 35 10 cm. Na obrázku je tento obdelník vybarven šedě. Zároveň jsou pozice válce i robota vygenerovány tak, aby vzdálenost jejich středů byla alespoň 30 cm. Bez tohoto opatření by se mohlo stát, že by válec a robot byli těsně u sebe a robot by tedy válec snadno našel. Díky tomu by získal vyšší fitness než robot, který sice válec umí najít, ale kterému byla přiřazena příliš vzdálená startovací pozice. Stejně jako v předchozí úloze, i v této je každý jedinec otestován desetkrát s různými startovacími pozicemi. Výsledná fitness je dána jako aritmetický průměr hodnot získaných v jednotlivých simulacích. 5.1.3 Dobíjení baterie Stejně jako v předchozích experimentech, ani v této úloze nesmí robot do ničeho narazit. Jeho cílem je pohybovat se co nejdelší dobu co nejvyšší rychlostí. Má ale omezenou kapacitu baterie, a proto se musí čas od času dobít. K dobíjení slouží takzvané dobíjecí území, které je umístěno v rohu arény, má černou barvu podlahy (zbytek arény má bílou barvu) a aby ho mohl robot snadno nalézt, je v tomtéž rohu umístěn světelný zdroj. Jakmile robot vstoupí na dobíjecí území, tak je jeho baterie okamžitě dobita. Po dobu pobytu v dobíjecím území ale robot nezískává žádnou fitness. Oproti předchozím úlohám má robot několik senzorů navíc. Vepředu a vzadu má po jednom senzoru detekujícím světlo a uprostřed směrem k zemi má senzor detekující barvu podlahy. Kromě toho má ještě senzor udávající stav baterie. Robot je řízen Elmanovou neuronovou sítí se sedmnácti vstupními neurony, dvěma výstupními neurony a pěti skrytými neurony, s váhami z intervalu [ 5; 5] a se sigmoidální přenosovou funkcí. Na vstupní neurony jsou postupně namapovány výstupy osmi infračervených senzorů, dvou světelných senzorů, detektoru barvy podlahy a detektoru stavu baterie. Výstupy všech senzorů jsou normalizované do intervalu [0;1]. Zbývajících pět vstupních neuronů má jako vstup výstupní hodnoty neuronů ze skryté vrstvy z minulého kroku (0 v prvním kroku). Hodnoty výstupních neuronů určují rychlosti otáčení kol stejně jako v předchozích úlohách. Jedna jízda robota se skládá z 1000 kroků po 100 milisekundách. To je o něco víc než v předchozích úlohách, aby byl robot donucen se v průběhu simulace několikrát dobít. Fitness Φ i robota v kroku i {1,...,1000} je spočítána na základě naměřených hodnot infračervených senzorů a rychlostí otáčení kol podle vzorce: Φ i = V i (1 I i ). Tento vzorec je podobný vzorci v úloze Vyhýbání se překážkám. Oproti němu zde chybí jeho prostřední část, hodnoty V i a I i jsou ale definovány stejně. Pokud se v kroku i robot nachází na dobíjecím území, tak získá fitness Φ i = 0. To robota nutí k tomu, aby v dobíjecím území netrávil zbytečně mnoho času. 26

Baterie robota má kapacitu 200 jednotek a v každém kroku, kdy je robot mimo dobíjecí území se stav baterie sníží o jednu jednotku. Pokud klesne stav baterie na 0 nebo pokud robot narazí do zdi, tak je jeho jízda ukončena a robot dostane za všechny nevyužité kroky zbývající do konce jízdy přidělenu fitness Φ i = 0. Celková fitness F je stejně jako v předchozích úlohách tvořena součtem Φ i za všechny kroky a vydělená maximálním počtem kroků, a protože platí, že Φ i [0; 1], i {1,..., 1000}, tak také F [0; 1]. Obrázek 5.4: Aréna pro učení periodického dobíjení baterie. Simulace probíhá v aréně o rozměrech 50 a 45 cm znázorněné na obrázku 5.4. Aréna je opět ohraničena zdí, aby z ní robot nemohl vyjet. Světlo a dobíjecí území jsou umístěny v levém horním rohu. Dobíjecí území má poloměr 16 cm a na obrázku je vyznačeno šedou plochou. Robot je na začátku každé simulace umístěn na náhodnou volnou pozici uvnitř arény a je natočen náhodným směrem. Pro srovnání velikostí je robot znázorněn v pravém dolním rohu obrázku. Tato úloha je o něco delší (1000 kroků) než předchozí dvě úlohy (400 kroků), tak u ní kolísání fitness není tak výrazné. Proto je každý jedinec vyhodnocen pouze pětkrát. Výsledná fitness jedince je opět dána jako aritmetický průměr hodnot fitness získaných v jednotlivých simulacích. 5.2 Sady experimentů Na testovacích úlohách popsaných v předchozí části jsem provedl řadu experimentů s různě kódovanými jedinci a za použití různých genetických operátorů, které byly popsány v kapitole 3. Experimenty se dají zhruba rozdělit do tří částí podle typu použitých operátrů. Ačkoliv se typy operátorů liší, snažil jsem se, aby byly experimenty vzájemně porovnatelné a lišily se v co nejmenším možném počtu parametrů. 27

5.2.1 Základní operátory Výhodou binárního kódování by měla být zejména menší velikost prohledávaného prostoru (viz sekce 3.1). Výhodou rálného kódování by naopak měla být schopnost lépe doladit finální řešení. Cílem těchto experimentů bylo porovnat rychlost konvergence a kvalitu nalezeného řešení pro různá binární kódování a pro reálné kódování při použití jednoduchých operátorů. Evoluce byla ukončena vždy po 200 generacích. Všechny experimenty probíhaly s pevnou velikostí populace 100 jedinců a používaly turnajovou selekci (pravděpodobnost výběru horšího jedince byla 10%) s elitismem 10% jedinců, rovnoměrnou mutaci a jednoduché jednobodové křížení. Pravděpodobnost zkřížení dvou jedinců byla 60%. Pravděpodobnosti provedení mutace byly p + m = 100% a p m = 15% 2. Binární kódování jedinců a základní operátory (BZ3 BZ8) Tyto experimenty by měly v podstatě kopírovat schéma Jednoduchého genetického algoritmu s elitismem. Trochu se od něho ale odlišují, aby je bylo možné snáze porovnat s experimentem s reálným kódováním jedinců. Jedinci byli sice kódováni binárně, ale pro účely mutace na něho bylo nahlíženo jako na posloupnost bloků bitů, kde každý blok odpovídal jedné váze neuronové sítě a k zakódování jedné váhy bylo použito 3 až 8 bitů 3. Křížení proto probíhalo pouze na hranicích mezi bloky a mutace se týkala vždy celého bloku, ne pouze jednoho bitu. Reálné kódování jedinců a základní operátory (RZ) V tomto experimentu byla každá váha neuronové sítě kódována reálným číslem a na jedince bylo nahlíženo jako na posloupnost reálných čísel, ne posloupnost bitů. Křížení proto probíhalo opět pouze na hranici mezi dvěma váhami a mutace měnila vždy celou váhu, ne jen její část. 5.2.2 Pokročilé operátory Experimenty popsané v předchozí části se sice na jedince dívaly jako na posloupnost vah, ale samotné váhy nijak neinterpretovaly. Mutace i křížení byly zcela nezávislé na konkrétních hodnotách vah. Pokud budeme brát v úvahu i hodnoty jednotlivých vah, fitness jedince a číslo aktuální generace, můžeme použít pokročilejší mutace a křížení, které by mohly pomoci k rychlejší konvergenci a také k lepším výsledkům. Ve většině parametrů se tyto experimenty shodují s experimetny pro testování jednoduchých operátorů popsaných v předchozí části. Experimenty trvaly vždy 200 generací a používaly populaci o pevné velikosti 100 jedinců. Místo jednoduchého jednobodového křížení bylo v těchto experimentech použito prolínavé křížení s pravděpodobností 60%. Mutace byly použity tři: rovnoměrná, nerovnoměrná a hraniční. Jejich pravděpodobnosti jsou uvedeny v tabulce 5.1. Hraniční mutace může občas pomoci najít některá řešení, na která by zbylé mutace jen tak 2 Význam hodnot p + m a p m je vysvětlen na konci podkapitoly 3.2 3 Sít s váhami kódovanými pouze 1 nebo 2 bity se nebyla schopná nic naučit, a proto experimenty začínají až od 3 bitů na váhu. 28

Mutace p + m[%] p m[%] Rovnoměrná 100 7 Nerovnoměrná 100 7 Hraniční 100 1 Tabulka 5.1: Pravděpodobnosti provedení jednotlivých mutací. nepřišly a rovnoměrná mutace přináší možnost velkých změn i v závěru evoluce, kdy již nerovnoměrná mutace dovoluje pouze malé změny. Mutace jsou navzájem nezávislé, jedinec tedy může být zmutován vícekrát. Binární kódování jedinců a pokročilé operátory (BP3 BP8) Tyto experimenty dávají dohromady výhody binárního kódování vah a složitějších genetických operátorů. Jedinci byli sice kódováni binárně, ale za jeden gen byla považována celá váha neuronové sítě, ne pouze jeden bit. Mutace i křížení tedy pracovaly s hodnotami 3 až 8 bitových celých čísel. Reálné kódování jedinců a pokročilé operátory (RP) Jako v RJ i zde byla každá váha kódována jedním reálným číslem. 5.2.3 Variabilní velikost populace Vyhodnocení fitness v evoluční robotice bývá výpočetně náročné, a proto se zdá použití variabilní velikosti populace rozumné. V podkapitole 3.4 jsem popsal dva algoritmy, u nichž jejich autoři slibují dobré výsledky. Předběžné testování ale ukázalo, že algoritmus GAVaPS není prakticky schopen velikost populace jakkoliv regulovat a v závislosti na nastavení reprodukčního koeficientu ρ populace bud vymře, nebo naopak exponenciálně roste. Nastavení minimálního a maximálního věku ani použitá metoda výpočtu věku jedince při tom nehraje žádnou větší roli. Protože na podobný problém narazili i Eiben a spol. [4], tak jsem stejně jako oni GAVaPS z hlavního testování vyřadil. Provedl jsem dva experimenty. Každý trval 200 generací a používal binární kódování jedinců, binární mutaci a jednobodové křížení s dělícími body na hranicích vah. Selekce byla jako v předchozích experimentech turnajová s elitismem 10% populace, ale minimálně 10 jedinců (to je důležité pro zachování dobrých řešení i při klesající velikosti populace). Binární kódování jedinců a pevná velikost populace (PVP) V tomto experimentu byla velikost populace nastavena na pevnou velikost 100 jedinců. Binární kódování jedinců a variabilní velikost populace (VVP) V tomto experimentu byl použit algoritmus PRoFIGA s počáteční velikostí populace nastavenou na 100 jedinců, minimální velikostí populace 20 jedinců, maximální velikostí populace 500 jedinců a koeficienty k 1 = 1,1, k 2 = 0,9 a k 3 = 29

0,8. Parametr q byl nastaven na 5% a počet generací d, po které může fitness stagnovat aniž by byla populace restartována, byl nastaven na 10 (význam jednotlivých parametrů je vysvětlen v části 3.4.2). 30

Kapitola 6 Výsledky Každý z experimentů popsaných v předchozí kapitole jsem spustil stokrát, pokaždé s jinak inicializovaným generátorem náhodných čísel. Základními daty získanými z experimentů jsou hodnoty fitness dosažené všemi jedinci ve všech generacích. Zpracováním těchto dat jsem došel k výsledkům popsaným v této kapitole. Hlavním sledovaným výstupem je fitness nejlepšího jedince v poslední generaci. I přes to, že je použit elitismus, tak fitness v poslední generaci bývá zřídka shodná s celkově nejvyšší dosaženou fitness. To je způsobeno tím, že počáteční pozice robota je generována náhodně. Občas se proto stane, že má robot štěstí a získá velmi vysokou fitness i přes to, že jeho strategie je jinak podprůměrná. V dalších generacích bývá takový robot většinou vyřazen. Druhým důležitým výstupem je rychlost nalezení finálního řešení. Nejprve je spočítán průměr nejlepších řešení v každých deseti po sobě jdoucích generacích, aby se omezil vliv náhodných výkyvů fitness, a poté je nalezena první generace, ve které tento průměr dosáhne nebo překročí hodnotu finálního řešení. Za finální řešení je považován průměr nejlepších řešení v posledních deseti generacích. Rychlost, s jakou je v průměru nalezeno finální řešení, je ale vždy potřeba posuzovat zároveň s průměrnou dosaženou hodnotou fitness. Vysoká rychlost totiž nečiní použité operátory lepšími, pokud je to na úkor kvality řešení. 6.1 Použité grafy Výsledky prezentované v této kapitole se budou z velké části opírat o jeden typ grafu, který umožňuje jednoduché porovnání výsledků experimentů se základními operátory s výsledky experimentů s pokročilými operátory a zároveň umožňuje porovnat experimenty podle velikosti prohledávaného prostoru. Tento graf není nijak zvlášt komplikovaný, na druhou stranu ale není ani zcela triviální. Správné porozumění tomuto grafu je důležité pro pochopení většiny zde prezentovaných výsledků, a proto se v této podkapitole pokusím popsat jeho jednotlivé části. Opírat se při tom budu o ukázkový graf z obrázku 6.1. Graf se vždy vztahuje k jedné ze sad experimentů, které byly popsány v kapitole 5. Na ose x jsou jednotlivé experimenty a na ose y je fitness dosažená nejlepším 31

Fitness 0.50 0.55 0.60 0.65 ZB3 PB3 ZB6 PB6 ZR PR Experiment Obrázek 6.1: Ukázkový graf sloužící k ilustraci jeho vlastností. Grafy stejného typu budou použity dále v této kapitole. jedincem v poslední generaci. Ukázkový graf na obrázku 6.1 zobrazuje výsledky šesti experimentů. Experimenty jsou označeny zkratkami popsanými v kapitole 5, první písmeno značí použité operátory (Z základní, P pokročilé), zbytek značí použité kódování jedinců (B3 binární kódování se třemi bity na váhu, R kódování jedinců reálnými čísly). Každému experimentu odpovídá jeden boxplot. Tlustá čára uvnitř každého boxplotu znázorňuje medián. Obdelník je ohraničen dolním (Q 1 ) a horním kvartilem (Q 3 ), tj. obsahuje polovinu všech výsledků daného experimentu. Kroužky značí odlehlá pozorování, tj. hodnoty, které jsou od obou kvartilů Q 1, Q 3 dál než 3 2 Q 3 Q 1. Experimenty jsou řazeny vzestupně zleva doprava podle vzrůstající velikosti prohledávaného prostoru (počtu bitů na váhu) a střídají se podle použitého kódování. Díky tomu jsou experimenty se stejným počtem bitů na váhu, ale s různými operátory, umístěny vedle sebe a lze je tak snáze porovnat. Aby šlo zároveň dobře vzájemně porovnat i experimenty se stejným kódováním, jsou boxploty náležící k experimentům se základními operátory vybarveny oranžově a experimenty náležící k pokročilým operátorům modře. Průměrná hodnota dosažená každým experimentem je v grafu znázorněna křížkem. Oranžové křížky patří k experimentům se základními operátory a modré k experimentům s pokročilými operátory. Aby bylo možné dobře porovnat průměrné hodnoty experimentů se stejně kódovanými jedinci, jsou křížky náležící k experimentům se základními operátory posunuty doprava a křižky náležící k experimentům s pokročilými operátory jsou posunuty doleva. Tím se křížky dostanou mimo boxplot, kde jsou lépe vidět a navíc křížky náležící k experimentům se stejným počtem bitů na váhu leží nad sebou, takže lze ihned vidět, který z experimentů dosáhl lepšího průměrného řešení. Průměrné hodnoty dosažené experimenty se stejnými operátory jsou spojeny čarou. Ta slouží pouze k tomu, aby bylo vidět, zda průměrná hodnota se zvyšující se velikostí prohledávaného prostoru klesá nebo stoupá. Poslední součástí grafu jsou dvě čárkované čáry. Oranžová opět náleží k experimentům se základními operátory a modrá k experimentům s pokročilými operátory. Tyto čáry značí průměrnou hodnotu dosaženou všemi experimenty se stejnými 32

operátory. Díky tomu lze ihned vidět, které experimenty dosáhly nadprůměrných a které podprůměrných hodnot. Kromě dosažené fitness bude ještě graf stejného typu použit pro porovnání rychlostí konvergence jednotlivých experimentů. V tom případě bude na ose y místo dosažené hodnoty fitness číslo generace, ve které byla poprvé dosažena finální hodnota fitness. Pro ilustraci vyvinutých strategií budu používat záznamy jízdy robota podobné tomu na obrázku 6.2. Šedou barvou jsou na něm znázorněny pozice robota v různých okamžicích jeho jízdy, počáteční pozice je zvýrazněna černě. Interval mezi dvěma nádledujícími pozicemi je 200 milisekund. Typická pozice má tvar velkého písmena E. Prostřední čára určuje směr, kde leží čelo robota a krajní čáry určují rychlosti otáčení kol. Pokud krajní čára směřuje stejným směrem jako prostřední čára, tak se kolo otáčí dopředu, pokud směřuje opačným směrem, tak se otáčí dozadu. Čím je čára delší, tím rychleji se kolo otáčí. Obrázek 6.2: Příklad záznamu jízdy robota. Jedná se o záznam jízdy z úlohy Vyhýbání se překážkám. 6.2 Pevná velikost populace Jedinci mohli ve všech experimentech s pevnou velikostí populace získat fitness v intervalu 0 až 1. Získanou fitness ale budu porovnávat vždy pouze v rámci jedné úlohy, protože hladina, kolem které hodnoty fitness kolísají je na typu úlohy (použité fitness funkci) zcela závislá. U všech úloh by šlo průměrnou hodnotu fitness zvýšit například pouhým prodloužením délky jedné jízdy robota. Pokud je tedy v některé úloze průměrná fitness nižší, než v jiné úloze, neznamená to, že by jedinci byli v jedné úloze naučeni lépe a v druhé hůře. Znamená to pouze to, že v jedné úloze je těžší získat vyšší hodnoty fitness než ve druhé úloze. 33

6.2.1 Vyhýbání se překážkám Z hlediska nejvyšší dosažené fitness v poslední generaci dopadly základní i pokročilé operátory v úloze vyhýbání se překážkám prakticky stejně. Průměrná fitness dosažená za použití základních operátorů byla 0,603 a za použití pokročilých operátorů 0,612. Rozložení hodnot fitness získaných v poslední generaci nejlepším je- Počet výskytů 0 50 150 Počet výskytů 0 100 200 0.0 0.2 0.4 0.6 0.8 1.0 Fitness 0.0 0.2 0.4 0.6 0.8 1.0 Fitness Obrázek 6.3: Vyhýbání se překážkám frekvence výskytů jednotlivých hodnot fitness u nejlepších jedinců z poslední generace. Graf nalevo zobrazuje experimenty se základními verzemi operátorů, graf napravo s pokorčilými verzemi operátorů. dincem znázorňuje obrázek 6.3. Z něho je patrné, že pokročilé operátory mají menší rozptyl. Zatímco u experimentů se základními operátory leží 95% hodnot v intervalu 0,471 až 0,657, tak v experimentech s pokročilými operátory leží v intervalu 0,524 až 0,651. Totéž lze vypozorovat i z grafu na obrázku 6.4, pokud porovnáme jednotlivé dvojice experimentů používající stejné kódování jedinců. Základní operátory se od pokročilých v tomto případě kvalitou nalezeného řešení neliší, dosahují však tohoto řešení mnohem stabilněji. Fitness 0.45 0.50 0.55 0.60 0.65 ZB3 PB3 ZB4 PB4 ZB5 PB5 ZB6 PB6 ZB7 PB7 ZB8 PB8 ZR PR Experiment Obrázek 6.4: Vyhýbání se překážkám nejlepší dosažená fitness v poslední generaci. Vysvětlivky ke grafu najdete ve podkapitole 6.1. 34

Z grafu na obrázku 6.4 lze dále vypozorovat, že s rostoucím počtem bitů na váhu v případě experimentů se základními operátory klesá kvalita nalezeného řešení. V případě pokročilých operátorů tento jev patrný není. Z toho lze usuzovat, že genetickému algoritmu se základními operátory v případě většího prohledávaného prostoru 200 generací k nalezení nejlepšího řešení občas nestačí, zatímco genetickému algoritmu s pokročilými operátory 200 generací vetšinou stačí. Generace 0 50 100 150 200 ZB3 PB3 ZB4 PB4 ZB5 PB5 ZB6 PB6 ZB7 PB7 ZB8 PB8 ZR PR Experiment Obrázek 6.5: Vyhýbání se překážkám - generace, ve které byla dosažena finální hodnota fitness. Čím vyšší je číslo generace, kdy byla dosažena finální fitness, tím nižší je rychlost konvergence. Vysvětlivky ke grafu najdete ve podkapitole 6.1. Rychlost, s jakou genetický algoritmus dospěl k finálnímu řešení, je vidět z grafu na obrázku 6.5. Z absolutního hlediska dopadly pokročilé i základní operátory téměř stejně. Při použití základních operátorů byla finální fitness dosažena v průměru v 64. generaci a při použití pokročilých operátorů byla dosažena v průměru v 61. generaci, což je stejně jako v případě fitness zanedbatelný rozdíl. S rostoucí velikostí prohledávaného prostoru rychlost konvergence mírně klesá jak u algoritmů s pokročilými operátory, tak u algoritmů se základními operátory. Pokročilé operátory si ale vedly ve všech případech, kromě experimentů s váhami kódovanými třemi bity, o něco lépe. Experiment ZB3 rozhodně stojí za bližší pozornost. Nejen že dosáhl průměrné fitness 0,625, což je víc než kolik v úloze vyhýbání se překážkám dosáhl jakýkoliv jiný experiment se základními i s pokročilými operátory, ale dosáhl finální hodnoty fitness v průměru ve 46. generaci, což je o 10 generací dříve než druhý nejlepší (co do rychlosti konvergence) experiment PB3. Ukázalo se tedy, že 3 bity na váhu v případě takto jednoduché úlohy bohatě stačí, a že větší množství bitů na váhu je spíš na škodu, než k užitku. Při tak malém množství bitů nepomohlo ani použití pokročilých operátorů. S rostoucím počtem bitů na váhu se sice použití pokročilých operátorů vyplácí čím dál víc, rostoucí velikost prohledávaného prostoru to ale stejně vykompenzovat nedokáže. 35

6.2.2 Vyhledávání objektu Jestli se základní a pokročilé algoritmy v předchozí sadě experimentů lišily z hlediska nejlepší dosažené fitness v poslední generaci málo, tak v sadě experimentů s vyhledáváním objektu se neliší prakticky vůbec. Jedinci vyvinutí pomocí základních operátorů dosáhli v poslední generaci průměrné fitness 0,683, jedinci vyvinutí pomocí pokročilých operátorů dosáhli fitness 0,684. Oproti předchozí sadě experimentů jsou v tomto experimentu výsledné hodnoty fitness rozprostřeny po mnohem větším intervalu (viz graf na obrázku 6.6). U experimentů se základními operátory leží 95% hodnot v intervalu 0,401 až 0,828 a s pokročilými operátory v intervalu 0,359 až 0,820. Počet výskytů 0 20 60 Počet výskytů 0 20 60 0.0 0.2 0.4 0.6 0.8 1.0 Fitness 0.0 0.2 0.4 0.6 0.8 1.0 Fitness Obrázek 6.6: Vyhledávání objektu frekvence výskytů jednotlivých hodnot fitness u nejlepších jedinců z poslední generace. Graf nalevo zobrazuje experimenty se základními verzemi operátorů, graf napravo s pokorčilými verzemi operátorů. Větší rozptyl výsledné fitness svědčí o tom, že výpočet fitness je hodně závislý na náhodně vygenerované počáteční pozici robota. Vyhodnocení fitness každého jedince se v tomto experimentu skládalo z deseti samostatných jízd a výsledná fitness jedince byla určena jako průměr hodnot fitness získaných v jednotlivých jízdách. Na obrázku 6.7 jsou zobrazeny dva záznamy jízdy nejlepšího jedince z poslední generace z jednoho z experimentů. Jedinec získal celkovou fitness 0,751, což z něj Obrázek 6.7: Záznam dvou různých jízd téhož jednice v úloze Vyhledávání objektu. Na obrázku nalevo měl robot smůlu a válec těsně minul, Na obrázku napravo měl naopak štěstí a válec ihned našel. 36

dělá nadprůměrného jedince. Za jízdu nalevo ale získal fitness pouze 0,558, zatímco za jízdu napravo 0,912. Je vidět, že jedinec je už naučen poměrně dobře, takže pokud se k válci dostane dostatečně blízko, tak už u něho zůstane až do konce jízdy. I přes to ale může být rozdíl v získané fitness mezi dvěma jeho jízdami poměrně veliký. I přes poměrně velký rozptyl výsledné fitness dopadly všechny experimenty bez ohledu na použité kódování či velikost prohledávaného prostoru téměř stejně (viz graf na obrázku 6.8). Některé experimenty sice dopadly o něco lépe a některé o něco hůře, ale ani na jednu stranu nejsou výkyvy nijak výrazné. Fitness 0.5 0.6 0.7 0.8 ZB3 PB3 ZB4 PB4 ZB5 PB5 ZB6 PB6 ZB7 PB7 ZB8 PB8 ZR PR Experiment Obrázek 6.8: Vyhledávání objektu nejlepší dosažená fitness v poslední generaci. Průměrná hodnota fitness pro základní i pokročilé operátory v tomto případě téměř splývá. Vysvětlivky ke grafu najdete ve podkapitole 6.1. Mnohem zajímavější je situace z hlediska rychlosti konvergence (viz graf na obrázku 6.9). Experimenty s pokročilými algoritmy zkonvergovaly v průměru ve 121. generaci, zatímco experimenty se základními algoritmy už ve 105. generaci. Velikost prohledávaného prostoru při tom nemá na rychlost konvergence žádný vliv. Jedinou výjimkou je experiment PR, který zkonvergoval v průměru ve 109. generaci, což je o 7 generací dříve než druhý nejrychlejší experiment s pokročilými algoritmy, PB3. To je zvláštní, protože by se dalo čekat, že větší prohledávaný prostor povede spíš k pomalejší konvergenci. Vzhledem k tomu, že u experimentu ZR se nic takového nestalo a jediné v čem se experimenty ZR a PR liší jsou použité operátory, tak za zvýšení rychlosti mohou pravděpodobně pokročilé operátory. Oproti úloze Vyhýbání se překážkám, je tato úloha o něco složitější. To se projevilo tím, že průměrná generace, kdy došlo ke konvergenci, se výrazně zvýšila. Z hlediska dosažené fitness dopadly experimenty se základními i pokročilými operátory stejně dobře, experimenty se základními operátory ale našly řešení mnohem rychleji. 37

Generace 0 50 100 150 200 ZB3 PB3 ZB4 PB4 ZB5 PB5 ZB6 PB6 ZB7 PB7 ZB8 PB8 ZR PR Experiment Obrázek 6.9: Vyhledávání objektu generace, ve které byla dosažena finální hodnota fitness. Čím vyšší je číslo generace, kdy byla dosažena finální fitness, tím nižší je rychlost konvergence. Vysvětlivky ke grafu najdete ve podkapitole 6.1. 6.2.3 Dobíjení baterie Z grafu na obrázku 6.10 je vidět, že rozptyl hodnot fitness dosažených v poslední generaci je menší než u úlohy Vyhledávání objektu, ale větší než u úlohy Vyhýbání se překážkám, 95% všech hodnot leží v případě experimentů se základními operátory v intervalu 0,495 až 0,710 a v případě experimentů s pokročilými operátory v intervalu 0,529 až 0,727. Počet výskytů 0 40 80 120 Počet výskytů 0 40 80 0.0 0.2 0.4 0.6 0.8 1.0 Fitness 0.0 0.2 0.4 0.6 0.8 1.0 Fitness Obrázek 6.10: Dobíjení baterie frekvence výskytů jednotlivých hodnot fitness u nejlepších jedinců z poslední generace. Graf nalevo zobrazuje experimenty se základními verzemi operátorů, graf napravo s pokorčilými verzemi operátorů. V předchozích dvou úlohách dopadly experimenty se základními i pokročilými algoritmy z hlediska dosažené fitness velmi podobně. V této úloze už se od sebe ale výrazně liší. Experimenty se základními operátory dosáhly v průměru fitness 0,628 a experimenty s pokročilými operátory dosáhly v průměru hodnotu fitness 0,649. Kromě toho i nejhorší experiment s pokročilými operátory (PB7 s průměrnou fitness 0,642) dopadl lépe než nejlepší experiment se základními operátory (ZB7 38

s průměrnou fitness 0,622) (viz graf na obrázku 6.4). Velikost prohledávaného prostoru neměla na výslednou fitnes vliv ani u experimentů se základními operátory ani u experimentů s pokročilými operátory. Fitness 0.45 0.50 0.55 0.60 0.65 0.70 0.75 ZB3 PB3 ZB4 PB4 ZB5 PB5 ZB6 PB6 ZB7 PB7 ZB8 PB8 ZR PR Experiment Obrázek 6.11: Dobíjení baterie nejlepší dosažená fitness v poslední generaci. Vysvětlivky ke grafu najdete ve podkapitole 6.1. Experimenty se základními operátory zkonvergovaly k finálnímu řešení v průměru ve 109. generaci a experimenty s pokročilými operátory ve 118. generaci. Stejně jako u předchozího experimentu neměla velikost prohledávaného prostoru na rychlost konvergence téměř žádný vliv. Jedinou výjimkou je opět experiment PR. Ten zkonvergoval v průměru ve 107. generaci, čímž se vyrovnal experimentům se základními operátory a výrazně se odlišil od ostatních experimentů s pokročilými operátory, které všechny konvergovaly přibližně stejně rychle (viz grav 6.12). Tento jev je v podobné míře pozorovatelný i v úloze Vyhledávání objektu a v malé míře je pozorovatelný i u úlohy Vyhýbání se překážkám. Zdá se tedy, že kombinace reálného kódování vah a pokročilých operátorů má na rychlost konvergence pozitivní vliv. 6.3 Variabilní velikost populace V experimentech s variabilní velikostí populace jsem opět sledoval především kvalitu nalezeného řešení. Narozdíl od experimentů s pevnou velikostí populace ale nejde tak snadno porovnat rychlost konvergence, číslo generace totiž nic neříká o času či množství operací, které konvergence zabrala. Spíš než generace, ve které bylo nalezeno finální řešení, mě proto bude zajímat počet vyhodnocení fitness, který k tomu byl potřeba. To je údaj, který o rychlosti konvergence vypovídá mnohem lépe a dá se snadno srovnat i s experimenty s pevnou velikostí populace, kde počet vyhodnocení fitness je v každé generaci stejný a odpovídá velikosti populace. 39

Generace 0 50 100 150 200 ZB3 PB3 ZB4 PB4 ZB5 PB5 ZB6 PB6 ZB7 PB7 ZB8 PB8 ZR PR Experiment Obrázek 6.12: Dobíjení baterie generace, ve které byla dosažena finální hodnota fitness. Čím vyšší je číslo generace, kdy byla dosažena finální fitness, tím nižší je rychlost konvergence. Vysvětlivky ke grafu najdete ve podkapitole 6.1. Pro každou testovací úlohu jsem provedl dva druhy experimentů, jeden s pevnou velikostí populace (PVP) a jeden s variabilní velikostí populace. V ostatních parametrech se experimenty nelišily. Konkrétní parametry jsou uvedeny v sekci 5.2.3. Stejně jako předchozí experimenty byly i tyto spuštěny každý stokrát. Grafy na Obrázku 6.13 zobrazují nejlepší dosaženou fitness v poslední generaci v experimentech s pevnou velikostí populace a v experimentech s variabilní velikostí populace pro všechny tři testovací úlohy. V úloze Vyhýbání se překážkám dosáhly experimenty s pevnou velikostí populace průměrné fitness 0, 596, zatímco experimenty s variabilní velikostí populace dosáhly v průměru fitness 0,560, což je výrazně méně. V úloze Vyhledávání objektu dosáhly naopak experimenty s pevnou velikostí populace pouze fitness 0,690, zatímco experimenty s variabilní velikostí populace dosáhly fitness 0,712. V úloze Dobíjení baterie získaly experimenty s pevnou velikostí populace fitness 0,631 a experimenty s variabilní velikostí populace 0,634, což je zanedbatelný rozdíl. Grafy, porovnávající výsledky rychlosti konvergence, jsou na obrázku 6.14. Jediná úloha, kde variabilní velikost populace ušetřila několik vyhodnocení fitness je úloha Vyhýbání se překážkám. Experimenty s pevnou velikostí populace potřebovaly v této úloze k nalezení finálního řešení v průměru 6959 vyhodnocení fitness, zatímco experimenty s variabilní velikostí populace potřebovaly v průměru pouze 5201 vyhodnocení fitness. Stejně jako u srovnání základních a pokročilých operátorů nelze ani zde brát v úvahu pouze samotnou rychlost konvergence, je potřeba zohlednit i kvalitu nalezeného řešení. V úloze Vyhýbání se překážkám sice použití variabilní velikosti populace ušetřilo v průměru přes 25% vyhodnocení fitness, ale bohužel to bylo na úkor poklesu dosažené fitness o více než 6%. Zbylé dvě úlohy nedopadly pro variabilní velikost populace o nic lépe. V úloze 40

Fitness 0.45 0.50 0.55 0.60 0.65 Fitness 0.5 0.6 0.7 0.8 Fitness 0.45 0.50 0.55 0.60 0.65 0.70 PVP VVP PVP VVP PVP VVP Experiment Experiment Experiment Obrázek 6.13: Srovnání fitness dosažené v experimentech s pevnou velikostí populace (PVP) s fitness dosaženou v experimentech s variabilní velikostí populace (VVP). Nalevo úloha Vyhýbání se překážkám, uprostřed úloha Vyhledávání objektu a napravo úloha Dobíjení baterie. Počet vyhodnocení fitness 0 5000 10000 15000 Počet vyhodnocení fitness 0 20000 40000 60000 Počet vyhodnocení fitness 0 10000 30000 50000 PVP VVP PVP VVP PVP VVP Experiment Experiment Experiment Obrázek 6.14: Srovnání rychlosti konvergence v experimentech s pevnou velikostí populace (PVP) s rychlostí konvergence v experimentech s variabilní velikostí populace (VVP). Nalevo úloha Vyhýbání se překážkám, uprostřed úloha Vyhledávání objektu a napravo úloha Dobíjení baterie. Výsledky jsou, podobně jako u experimentů s pokročilými operátory, závislé na testovací úloze. 41

Vyhledávání objektu potřebovaly experimenty s pevnou velikostí populace v průměru pouze 10381 vyhodnocení fitness zatímco experimenty s variabilní velikostí populace potřebovaly v průměru 25034 vyhodnocení fitness. Množství provedené práce tedy bylo několikanásobně vyšší, kvalita nalezeného řešení ale byla vyšší pouze o 3,3%. V úloze Dobíjení baterie potřebovaly experimenty s pevnou velikostí populace v průměru 10804 vyhodnocení fitness zatímco experimenty s variabilní velikostí populace potřebovaly 23844 vyhodnocení fitness. Kvalita nalezeného řešení ale byla v obou případech prakticky stejná. 42

Kapitola 7 Hodnocení Pokročilé genetické operátory byly navrženy pro použití s reálným kódováním jedinců. Z výsledků prezentovaných v předchozí kapitole je ale patrné, že se stejně dobře dají použít i s jedinci kódovanými celými čísly. V obou případech nacházejí pokročilé operátory zpravidla stejně dobrá nebo lepší řešení než základní operátory. Záleží při tom ale na složitosti řešené úlohy. U jednodušších úloh (Vyhýbání se překážkám a Vyhledávání objektu) bývá většinou pomocí základních i pomocí pokročilých operátorů nalezeno zhruba stejně kvalitní řešení. Výhoda pokročilých operátorů se výrazněji projevila až u složitější úlohy (Dobíjení baterie), kde už pokročilé operátory nacházely výrazně lepší řešení než základní operátory. Nevýhodou pokročilých operátorů je ovšem mírné zpomalení konvergence. Zpomalení ale není nijak velké, v průměru napříč všemi úlohami bylo 10%. Z výsledků prezentovaných v předchozí kapitole se zdá, že zpomalení závisí na rozptylu výsledné fitness. Čím vyšší je rozptyl, tím pomalejší je konvergence. Testovacích úloh ale bylo příliš málo na to, aby z nich vyplynuly nějaké jednoznačné závěry o závislosti zpomalení konvergence na rozptylu fitness. Ačkoliv lze pokročilé operátory s úspěchem aplikovat i na jedince kódované celými čísly, neprokázalo se, že by menší prohledávaný prostor měl nějaký vliv at už na rychlost konvergence nebo na kvalitu nalezeného řešení. Naopak se ukázalo, že experimenty používající pokročilé operátory v kombinaci s reálným kódováním jedinců (a tedy s mnohem větším prohledávaným prostorem) konvergují výrazně rychleji než experimenty s celočíselným kódováním jedinců. Rychlost konvergence je v tomto případě srovnatelná s experimetny používajícími základní genetické operátory. Variabilní velikost populace, narozdíl od pokročilých genetických operátorů, nepřináší žádný užitek. Nejen že algoritmy s variabilní velikostí populace nedokázaly nalézt lepší řešení (což se ani nijak zvlášt neočekávalo), ale nedokázaly ani rychleji zkonvergovat. Právě naopak potřebovaly k nalezení řešení až několikanásobně vyšší počet vyhodnocení fitness. To ale nutně nemusí být chyba algoritmu PRoFIGA. Problém může být v nevhodné kombinaci parametrů. Místo pouhého určení velikosti populace, které je potřeba u agoritmů s pevnou velikostí populace, je potřeba určit hned tři velikosti populace počáteční, minimální a maximální a ještě další čtyři parametry. Vyhodnocení fitness, která lze použitím algoritmu PRoFIGA potenciálně ušetřit, se podle 43

mých zkušeností při hledání ideální kombinace parametrů zcela ztratí. Všechny parametry napříč všemi úlohami i experimenty jsou stejné. To nutně některé úlohy i experimenty znevýhodňuje, protože pravděpodobnosti mutací a křížení i velikostí populace by se měly idálně odvíjet od velikosti prohledávaného prostoru [1, 2]. Mým cílem ale byla co nejlepší vzájemná porovnatelnost výsledků experimentů s různými typy operátorů a s různými druhy kódování jedinců. Snažil jsem se proto, aby se parametry u různých experimentů i u různých úloh lišily co nejméně. I přesto si ale zvolené parametry dobře poradily se všemi úlohami a výsledné strategie jsou srovnatelné se strategiemi získanými pomocí programu Evorobot (viz obrázek 7.1). 7.1 Možnosti dalšího výzkumu Ukázalo se, že při použití pokročilých genetických operátorů v kombinaci s reálným kódováním jedinců dochází k rychlejší konvergenci než při použití celočíselného kódování jedinců. Jedinci s celočíselným kódováním používali v této práci maximálně 8 bitů na jednu váhu, což je proti jedincům kódovaným reálnými čísly (64 bitů na váhu) směšně málo. Mohlo by proto být zajímavé otestovat i jedince s celočíselným kódováním používající více než 8 bitů na jednu váhu a zjistit, od kolika bitů na váhu (a zda vůbec) dochází ke zrychlení konvergence. Pro experimenty v této práci jsem si vybral pouze dva algoritmy s variabilní velikostí populace, protože jejich implementace a ladění parametrů jsou poměrně náročné. Jeden z nich se navíc později ukázal jako nepoužitelný. Bylo by proto vhodné otestovat i jiné algoritmy s variabilní velikostí populace proti algoritmu s pevnou velikostí populace a ideálně na širším spektru úloh. Výsledky naznačují, že výhodnost pokročilých genetických algoritmů se zvyšuje s rostoucí složitostí úlohy. Součástí dalšího výzkumu by proto mohly být některé složitější úlohy, které byly dříve řešeny pomocí základních genetických operátorů. Například kolektivní navigace více robotů nebo vyhledávání a uklízení odpadků [18]. Simulátor vyvinutý pro účely této práce je pro takovéto srovnávací experimenty ideální. Pro každý z navrhovaných experimentů by stačilo pouze implementovat sadu pluginů pro různé způsoby vyhodnocování fitness nebo pro různé mechanismy výběru populace. Čím složitější je výpočet fitness nebo mechanismus výběru populace, tím složitější bude samozřejmě i implementace a odladění potřebných pluginů. Provedení navrhovaných pokusů proto není úplně triviální záležitostí, použitím tohoto simulátoru se nicméně množství potřebné práce značně sníží. 44

Obrázek 7.1: Srovnání strategií získaných za pomoci mého simulátoru (levý sloupec) a za pomoci programu Evorobot (pravý sloupec). Pomocí obou programů dospěl evoluční algoritmus k podobným řešením. Na prvním řádku je řešení úlohy Vyhýbání se překážkám, na druhém řádku Vyhledávání objektu a na třetím řádku Dobíjení baterie. 45

Kapitola 8 Závěr Cílem práce bylo na vybraných úlohách experimentálně porovnat evoluci řízení robota pomocí základních a pokročilejších variant genetických algoritmů. Na dvou jednodušších a jedné složitější úloze z evoluční robotiky jsem porovnal rychlost konvergence a fitness dosaženou pomocí základních a pomocí pokročilých genetických operátorů za použití pevné velikostí populace a různě kódovaných jedinců. Dále jsem na stejných úlohách porovnal rychlost konvergence a fitness dosaženou pomocí běžného algoritmu s pevnou velikostí populace a pomocí algoritmu s variabilní velikostí populace. Cíl práce byl tedy splněn. Ukázalo se, že při použití pokročilých genetických operátorů lze získat vyšší fitness výměnou za pomalejší konvergenci. Dále se ukázalo, že pokročilé operátory lze bez problémů použít i na jedince kódované celými čísly, při jejich použití na jedince kódované reálnými čísly ale algoritmus konverguje rychleji. Experimenty s variabilní velikostí populace ukázaly, že aplikace dvou vybraných algoritmů používajících variabilní velikost populace na evoluční robotiku je přinejmenším problematická. Algoritmus GAVaPS se nepodařilo vůbec přimět k jakékoliv regulaci velikosti populace a algoritmus PRoFIGA nejenže nepřinesl žádný užitek, naopak až několikanásobně zvýšil počet vyhodnocení fitness. Kromě samotného srovnání je výstupem práce i snadno rozšiřitelný program, který umožňuje jednoduše provádět rozsáhlé sady experimentů s různými genetickými operátory, a taktéž program umožňující přehrávat zaznamenané simulace jednoduchého robota a převést je do tištěné podoby. Je proto ideální pro použití v jiných pracích podobného typu. 46

Literatura [1] Alander J. T.: On Optimal Population Size of Genetic Algorithms. V Proceedings of Computer Systems and Software Engineering, 6th annual European computer conference, IEEE Computer Society, str. 65 70, IEEE Computer Society Press, 1992. [2] Bäck T.: Optimal Mutation Rates in Genetic Search. V Proceedings of the Fifth International Conference on Genetic Algorithms, str. 2 8, Morgan Kaufmann, 1993. [3] Arabas J., Michalewicz Z. a Mulawka J.: GAVaPS A Genetic Algorithm with Varying Population Size. V Procedings of the First IEEE Conference on Evolutionary Computation, str. 73 78, Piscataway, NJ, 1994. [4] Eiben A. R., Marchiori E. a Valkó V. A.: Evolutionary algorithms with on-the-fly population size adjustment. Parallel Problem Solving from Nature PPSN VIII, str. 41 50, Springer, 2004. [5] Elman J. L.: Finding structure in time. Cognitive Science, roč. 14, č. 2, str. 179-211, 1990. [6] Endo K., Yamasaki F., Maeno T. a Kitano H.: A Method for Co-Evolving Morphology and Walking Pattern of Biped Humanoid Robot. V Proceedings of the 2002 IEEE International Conference on Robotics & Automation, str. 2775-2780, 2002. [7] Goldberg D. E.: Genetic Algorithms in Search Optimization and Machine Learning. Addison Wesley, 1989. [8] Herrera F., Lozano M. a Sánchez M. (2003): A Taxonomy for the Crossover Operator for Real-Coded Genetic Algorithms: An Experimental Study. International Journal of Inteligent Systems, roč. 18, č. 3., str. 309 338, 2003. [9] Jordan M. I.: Serial order: A parallel distributed processing approach (Tech. Rep. No. 8604). San Diego: University of California, Institute for Cognitive Science, 1986. [10] Miglino O., Nafasi K. a Taylor C.: Selection for wandering behaviour in a small robot. Artificial Life, roč. 2, č. 1, str. 101 116, MIT Press, 1994. 47

[11] Michalewicz Z.: Genetic Algorithms + Data Structures = Evolution Programs Berlin, Springer, 1998. [12] Michalewicz Z., Logan T. D. a Swaminathan S.: Evolutionary operators for continuous convex parameter spaces. Proceedings of the 3rd Conference on Evolutionary Programming, World Scientific Publishing, River Edge, NJ, str. 84 97, 1994. [13] Michalewicz Z., Nazhiyath G. a Michalewicz M.: A note on usefulness of geometrical crossover for numerical optimization problems. Proceedings of the 5th Annual Conference on Evolutionary Programming, Cambridge, MIT Press, str. 305 312, 1996. [14] Mitchell M.: An Introduction to Genetic Algorithms (Complex Adaptive Systems). Cambridge, MIT Press, 1998. [15] Mondada F., Bonani, M. a col.: The e-puck, a Robot Designed for Education in Engineering. Proceedings of the 9th Conference on Autonomous Robot Systems and Competitions, roč. 14, č. 1, str. 59 65, 2009. [16] Mondada F., Franzi E. a Guignard A.: The Development of Khepera. Proceedings of First International Khepera Workshop, Paderborn, 1999. [17] Mrázová I.: Knowledge Extraction with Neural Networks. Significant Patterns and their Representation in Back-Propagation Networks, VDM Verlag Dr. Müller, Saarbrücken, Germany, 2010. [18] Nolfi S. a Floreano D.: Evolutionary Robotics: The Biology, Intelligence, and Technology of Self-Organizing Machines. Cambridge, MIT Press/Bradford Books, 2000. [19] Nolfi S. a Gigliotta O.: Evorobot*: A tool for running experiments on the evolution of communication. v S. Nolfi a M. Mirolli (eds.), Evolution of Communication and Language in Embodied Agents. Berlin, Springer Verlag, 2010. [20] Sanger T. D.: Optimal unsupervised learning in a single-layer linear feedforward neural network. Neural Networks roč. 2, str. 459 473, 1989. [21] Sims K.: Evolving virtual creatures. Computer graphics proceedings, str. 12 22, 1994. [22] Vaughan R.: Massively Multiple Robot Simulations in Stage. Swarm Intelligence 2, str. 189 208, Springer, 2008. [23] Werbos P. J.: Beyond Regression: New Tools for Prediction and Analysis in the Behavioral Sciences. PhD thesis, Harvard University, 1974. 48

Příloha A Simulátor evoluce Pro simulaci evoluce jsem použil vlastní program napsaný v C++. Mým cílem bylo, aby umožňoval jednoduše (nejlépe bez nutnosti kompilace) provést sadu experimentů lišících se například pouze typem použité mutace nebo typem křížení. Z toho důvodu obsahuje hlavní program pouze kostru genetického algoritmu a všechny mutace, křížení a dokonce i jedinci jsou implementováni v samostatných dynamických knihovnách (pluginech). Program je napsaný pro operační systém linux. K jeho kompilaci jsou potřeba programy gcc a make a open source knihovny libconfig 1 a enki 2 (obě lze nalézt také na přiloženém cd v adresářích code/enki a code/libconfig). Kompilace hlavního programu i všech pluginů se provede spuštěním příkazu make v adresáři code/. Cílem tohoto dodatku je poskytnout jednoduchý návod pro implementaci vlastních operátorů i celých experimentů. A.1 Pluginy Všechny části programu, které jsou implementovány v samostatných pluginech, nazývám operátory, i když z hlediska genetických algoritmů se jako o operátorech mluví pouze o mutacích a křížení. Operátory jsou definovány v hlavičkovém souboru Operators.h jako samostatné třídy, které mají jednu či více čistě virtuálních metod. Implementace vlastního operátoru potom spočívá pouze ve vytvoření potomka příslušné třídy, který implementuje dané virtuální metody. Výjimkou je třída Individual, která reprezentuje jednoho jedince, a jejíž potomek by kromě implementace virtuálních metod měl obsahovat také nějaké proměnné, ve kterých bude zakódována hodnota z prohledávaného prostoru, kterou daný jedinec reprezentuje. Navíc může obsahovat funkce, které bude moct využít jiný operátor. Pluginy použité v této práci například pracují s instancemi třídy, která obsahuje vektor čísel. Každé číslo reprezentuje jednu váhu neuronové sítě. Mutace a křížení mohou pracovat přímo s těmito čísly, ale pro výpočet fitness je potřeba z vektoru čísel vytvořit neuronovou sít. Proto tato třída navíc definuje metodu, která vrací 1 http://www.hyperrealm.com/libconfig/ 2 http://home.gna.org/enki/ 49

neuronovou sít reprezentovanou tímto jedincem. Jeden plugin může obsahovat implementace libovolného množštví operátorů. Operátory v rámci pluginu jsou na sobě navzájem naprosto nezávislé, mohou tedy být stejných typů (například pouze mutace). A.2 Ukázková implementace operátorů V této části ukážu příklad jednoduchého pluginu obsahujícího tři základní operátory: jedince, mutaci a fitness. Celý příklad lze nalézt na přiloženém CD v souboru code/plugins/libexample.cpp, zde ho za účelem větší přehlednosti rozdělím na několik částí. 1 #include Operators. h 2 #include ObjectFactory. h 3 #include RNG. h 4 5 using namespace Operators ; Kód A.1: Úvodní deklarace Na začátku je potřeba includovat tři hlavičkové soubory (viz Kód A.1, řádky 1 3). Soubor Operators.h obsahuje definice všech operátorů, a je proto naprosto nezbytný. Soubor RNG.h obsahuje implementace základních pseudonáhodných funkcí použitelných v operátorech, které nějak pracují s náhodou, zde ho budeme potřebovat pro operátor mutace a pro počáteční inicializaci hodnot jedince. Poslední a nejzajímavější je soubor ObjectFactory.h, který obsahuje několik pomocných šablonových (templatovaných) funkcí, které ale vysvětlím až později. Deklarace použití namespace na řádku 5 je pouze pro zjednodušení, ušetří totiž mnohonásobné psaní prefixu Operators::. Kód A.2 ukazuje možnou implementaci velmi jednoduchého jedince, který obsahuje pouze jedno reálné číslo (proměnná x). Třída musí být odvozena od třídy Individual definované v souboru Operators.h a musí implementovat její čistě virtuální funcke init() (řádek 12) a duplicate() (řádek 18). Funkce init() slouží k počáteční inicializaci jedince a je volána pro každou instanci třídy právě jednou. Jako argument dostane referenci na třídu Parameters, která může obsahovat parametry jedince načtené z konfiguračního souboru experimentu. V tomto případě jsou jimi minimální a maximální hodnota proměnné x, které jsou uloženy do proměnných a a b (řádky 13 a 14). O použití konfiguračního souboru se o něco podrobněji zmíním v podkapitole A.3. Protože genetické algoritmy jsou velmi závislé na generování náhodných čísel, obsahuje každá instance jakéhokoliv operátoru ukazatel na generátor náhodných čísel. Tento ukazatel je uložen v proměnné m rng. Při inicializaci jedince využijeme jednu z metod generátoru a nastavíme počáteční hodnotu proměnné x na náhodné číslo z intervalu [a;b] (řádek 15). 50

7 class ExampleIndividual : public Individual { 8 public : 9 double x, a, b ; 10 11 protected : 12 void i n i t (const Parameters & parameters ) { 13 a = parameters [ min ] ; 14 b = parameters [ max ] ; 15 x = m rng >generate (a, b ) ; 16 } 17 18 void duplicate (const Individual & ind ) { 19 try { 20 const ExampleIndividual & i = 21 dynamic cast<const ExampleIndividual &> ( ind ) ; 22 a = i. a ; 23 b = i. b ; 24 x = i. x ; 25 } catch ( std : : exception e ) { 26 throw OperatorException ( m type, 27 Not an ExampleIndividual! ) ; 28 } 29 } 30 }; Kód A.2: Implementace jedince Funkce duplicate() má za úkol vytvořit kopii jedince a myslím, že ji není třeba důkladněji komentovat. Jedině snad použití proměnné m type na řádku 26. Tato proměnná obsahuje typ operátoru a v případě výskytu výjimky je ve výpisu chyb vidět, ve kterém operátoru k chybě došlo. Kód A.3 ukazuje implementaci jednoduché mutace nad právě definovaným jedincem. Třída implementující mutaci musí být odvozena od třídy Mutation a musí implementovat funkce init() (řádek 33) a mutate() (řádek 35). Funkce init() by měla provést inicializaci třídy, ale v tomto případě to není nutné, takže tělo funkce může zůstane prázdné. Metoda mutate() by měla nějakým způsobem změnit jedince ind. Tato implementace pouze vygeneruje nové náhodné číslo z povoleného intervalu (řádek 39). Složitější mutace by mohla využít informace ze struktury Data, kterou funkce dostane jako vstupní parametr. Tato struktura obsahuje informace o aktuálním stavu experimentu jako číslo generace, maximální počet generací, průměrnou fitness a jiné (viz soubor Operators.h). Poměrně důležitým krokem je dynamic cast na řádku 38 a zachycení výjimky v případě, že argument ind není potomkem třídy ExampleIndividual. Při chybné konfiguraci experimentu se může stát, že mutace bude použita v kombinaci s nekompatibilním jedincem a takto je zajištěno, že chyba bude ihned odhalena. Poslední operátor, který v této kapitole ukážu, je operátor fitness (Kód A.4). 51

32 c l a s s ExampleMutation : public Mutation { 33 void i n i t (const Parameters & parameters ) {} 34 35 void mutate ( Individual & ind, const Data & data ) { 36 try { 37 ExampleIndividual & i = 38 dynamic cast<exampleindividual &> ( ind ) ; 39 i. x = m rng >generate ( i. a, i. b ) ; 40 } catch ( std : : exception e ) { 41 throw OperatorException ( m type, 42 Not an ExampleIndividual! ) ; 43 } 44 } 45 }; Kód A.3: Implementace jednoduchého operátoru mutace Třída implementující tento operátor musí být odvozena od třídy Fitness definované, stejně jako všechny operátory, v souboru Operators.h a musí implementovat funkce init() (stejně jako u mutace i zde zůstane prázdná) a compute() (řádek 50). Funkce compute() dostane jako vstupní parametr celou aktuální populaci jedinců a jejím úkolem je spočítat jejich fitness. Důvod, proč je funkci předána celá populace jedinců a ne pouze jeden jedinec je ten, aby bylo možné provádět experimenty, kde je fitness počítána pro více jedinců současně (například lovec a kořist). Druhým vstupním parametrem je aktuální stav experimentu, na základě kterého je možné upravit parametry výpočtu fitness. Stejně jako v případě mutace je i zde potřeba provést přetypování, aby bylo možné pracovat s členskými proměnnými třídy ExampleIndividual. Kontrola úspěšnosti přetypování na řádku 54 a vyvolání výjimky na řádku 55 zaručuje, že v případě špatné konfigurace bude chyba snadno odhalena. Vypočtená fitness každého jedince musí být uložena do jeho členské proměnné fitness() (řádek 58). Tento výpočet slouží pouze pro ilustraci, je samozřejmě možné použít jakkoliv složitý mechanismus. V této práci byl například použit robotický simulátor Enki. Implementaci operátoru fitnes s jeho použitím je možné nalézt v souborech libavoidance.cpp a libdiscrimination.cpp v adresáři code/plugins/. Popisovat ho zde ale nebudu. Když jsou všechny třídy reprezentující operátory implementované, zbývá pouze napsat funkce, které budou tyto třídy konstruovat a destruovat a tyto funkce exportovat ven z knihovny. Aby nebylo potřeba psát pro každý operátor dvě funkce, probíhá konstrukce i destrukce operátoru pomocí jedné funkce. Příklad takové funkce pro operátor mutace je ukázán v kódu A.5. Pokud je této funkci předán nulový pointer, tak vytvoří novou instanci dané třídy, pokud je pointer nenulový, tak ho smaže. To, aby byla instance exportovaného objektu vytvořena i zničena uvnitř knihovny, je důležité proto, že jak hlavní program, tak knihovna sama mohou mít předefinované 52

47 class ExampleFitness : public Fitness { 48 void i n i t (const Parameters & parameters ) {} 49 50 void compute ( Population & pop, const Data & data ) { 51 for ( s i z e t i =0; i < pop. s i z e ( ) ; ++i ) { 52 ExampleIndividual ind = 53 dynamic cast<exampleindividual > (pop. at ( i ) ) ; 54 if ( ind == NULL) { 55 throw OperatorException ( m type, 56 Not an ExampleIndividual! ) ; 57 } 58 ind >f i t n e s s = ind >x ind >x ; 59 } 60 } 61 }; Kód A.4: Implementace jednoduchého operátoru fitness void mutation ( Mutation mut) { if ( mut == NULL) { mut = new ExampleMutation ( ) ; } else { delete ( mut ) ; mut = NULL; } } Kód A.5: Funkce pro konstrukci a destrukci operátoru mutace operátory new a delete. Pokud by byl objekt vytvářen uvnitř knihovny a destruován v hlavním programu, tak by mohlo dojít k zavolání špatného destruktoru a pamět by nebyla dealokována korektně. Tím se dostávám k významu souboru ObjectFactory.h. Ten obsahuje šablonovou (templatovanou) funkci objectfactory, (), která dělá přesně to, co funkce z kódu A.5, takže exportování třídy z knihovny se zkrátí na tři řádky (viz Kód A.6). První parametr určuje základní třídu exportovaného operátoru a druhý parametr určuje exportovanou třídu. Posledním krokem zbývajícím k dokončení knihovny je vytvoření funkce description (viz kód A.7). Tato funkce je nezbytná pro to, aby byla dynamická knihovna rozpoznána jako použitelný plugin. Hlavní program jejím zavoláním získá seznam implementovaných operátorů. Parametr id je vstupní parametr představující pořadové číslo operátoru a desc je výstupní parametr, ve kterém funkce vrátí popis operátoru s pořadovým číslem id. Funkce je při načítání knihovny volána opakovaně se vzrůstající hodnotou id (počínaje od 0) dokud funkce nenechá parametr desc nevyplněný. 53

63 extern C void individual ( Individual ind ) { 64 objectfactory<individual, ExampleIndividual >(ind ) ; 65 } 66 67 extern C void mutation ( Mutation mut) { 68 objectfactory<mutation, ExampleMutation>(mut ) ; 69 } 70 71 extern C void f i t n e s s ( Fitness f i t ) { 72 objectfactory<fitness, ExampleFitness >( f i t ) ; 73 } Kód A.6: Export funckí ven z knihovny 75 extern C void description (unsigned int id, Description & d){ 76 switch ( id ) { 77 case 0: 78 d. type = INDIVIDUAL; 79 d. name = individual ; 80 d. description = Example individual. ; 81 break ; 82 case 1: 83 d. type = MUTATION; 84 d. name = mutation ; 85 d. description = Example mutation. ; 86 break ; 87 case 2: 88 d. type = FITNESS; 89 d. name = fitness ; 90 d. description = Example fitness. ; 91 break ; 92 } 93 } Kód A.7: Funkce popisující operátory implementované touto knihovnou Pro každý operátor je potřeba vyplnit dvě hodnoty: typ operátoru a jméno funkce, která vytváří nové instance tohoto operátoru. Například pro operátor mutace je vyplněn typ MUTATION (řádek 83) a jméno funkce je mutation() (řádek 84). Funkce mutation byla definována v kódu A.6 na řádku 67. Jméno funkce může být samozřejmě libovolné. Volitelným parametrem je popis operátoru (řádek 85), který může vysvětlit uživateli neznalému implementačních detailů knihovny, jak operátor pracuje. Výsledný soubor by měl jít zkompilovat pomocí g++ následujícími dvěma příkazy: g++ -I./libconfig/lib/ -o libexample.o -c libexample.cpp 54

g++ -shared -o libexample.so libexample.o, kde./libconfig/lib je adresář s hlavičkovými soubory knihovny libconfig (pokud je knihovna nainstalována přímo v systému, tak lze tento parametr vynechat). A.3 Konfigurace experimentu Experiment je určen sadou použitých operátorů a několika dalších parametrů. Ty musí být sepsány v konfiguračním souboru, který je předán simulátoru jako vstupní parametr. Simulátor tento soubor přečte a provede experiment podle instrukcí v něm obsažených. Konfigurační soubor je ve formátu používaném knihovnou libconfig, která již byla zmíněna v předchozí části této přílohy. Tento formát umožnuje tvorbu strukturovaných konfiguračních souborů se všemi základními typy hodnot (čísla, řetězce, pole,...). Kromě toho umožňuje vkládání (includování) jiných konfiguračních souborů, takže nastavení společné pro více experimentů není nutné kopírovat. Myslím, že formát souboru je velmi intuitivní a pro pochopení ukázky v této kapitole není třeba jeho hlubší znalost. Pro podrobnější specifikaci bych čtenáře odkázal přímo na dokumentaci knihovny 3. Kód A.8 obsahuje ukázku konfiguračního souboru, který používá plugin z předchozí podkapitoly. Všechny položky na nejvyšší úrovni až na mutation a crossover (křížení v této ukázce není vůbec použito) jsou povinné. Následující přehled podává stručný popis nestrukturovaných nastavení (všechny jsou uvedeny na začátku vzorového souboru). name Hodnotou je čistě informativní text, který stručně vystihuje podstatu experimentu. seed Hodnotou je celé číslo, které bude použito k inicializaci náhodného generátoru. Pokud je zadána nula, bude k inicializaci použit vždy aktuální čas v sekundách. population Hodnotou je celé číslo, které udává velikost populace. V případě variabilní velikosti populace udává její počáteční velikost. generations Hodnotou je celé číslo určující po kolika generacích bude experiment ukončen. maximalize Hodnotou je bud true nebo false. Pokud je hodnota true, pak za nejlepšího jedince je považován ten s nejvyšší fitness a cílem experimentu je tedy fitness maximalizovat. Pokud je hodnota false, tak za nejlepšího jedince je považován ten s nejnižší fitness a cílem experimentu je celkovou fitness minimalizovat. V tom případě je ale třeba dát pozor na použité operátory, protože například ruletová selekce při minimalizaci nefunguje. 3 http://www.hyperrealm.com/libconfig/libconfig manual.html nebo soubor doc/libconfig.pdf na přiloženém CD 55

name = Example experiment ; seed = 0; population = 50; generations = 5000; maximalize = true ; individual = { id = libexample. so : individual ; parameters = { min = 10.0; max = 10.0; }; }; mutation = { id = libexample. so : mutation ; parameters = { probability = 1. 0 ; }; }; fitness = { id = libexample. so : fitness ; parameters = {}; }; selection = { id = l i b s e l e c t i o n. so : tournament ; parameters = { probability = 0. 1 ; e l i t e = 0.05; individuals = 2; }; }; random = { id = librandom. so : rng ; parameters = {}; }; Kód A.8: Ukázka konfiguračního souboru používající plugin z podkapitoly A.2 56

Zbývající nastavení jsou strukturovaná a jsou vázána na konkrétní operátory. Každé takové nastavení musí obsahovat dvě vnořená podnastavení. Prvním je id a druhým parameters. Hodnotou nastavení id je text ve formátu jmenoknihovny:jmenofunkce, kde jméno knihovny je celý název souboru včetně přípony a jméno funkce je text vrácený funkcí description. Hodnotou nastavení parameters je opět vnořené podnastavení, které je závislé na konkrétním operátoru, a které bude předáno jeho funkci init(). Zde je tedy místo, kde musí být umístěna nastavení specifická pro konkrétní implementaci operátoru. To je vidět u nastavení individual, kde je nastavena minimální a maximální hodnota, kterou může jedinec reprezentovat (jakým způsobem dojde k načtení těchto hodnot je ukázáno v kódu A.2 na řádcích 13 a 14). Pro mutaci a křížení musí nastavení parameters obsahovat ještě nastavení probability, jehož hodnotou je reálné číslo v intervalu [0;1], které určuje pravděpodobnost, že k mutaci či křížení dojde. Ještě jednou bych chtěl zdůraznit, že všechna nastavení, až na zmíněné výjimky, jsou povinná. Je sice implementačně snadné používat pro řadu nastavení defaultní hodnoty a tím zjednodušit konfigurační soubory (například prázdné nastavení parameters u operátorů random a fitness), ale je potom těké poznat, že nedošlo v názvu některého z nastavení k překlepu. Takto pokud dojde k překlepu, tak simulace okamžitě skončí a vypíše název chybějícího parametru. A.4 Provedení experimentu Když jsou připraveny všechny pluginy a konfigurační soubor experimentu, tak už skoro nic nebrání jeho provedení. Nejjednodušší způsob, jak experiment spustit, je zadáním příkazu./simulator example.cfg, kde example.cfg je konfigurační soubor experimentu. Tento příkaz provede jeden běh celého experimentu. Místo pouhého jména konfiguračního souboru může být uvedena celá cesta k němu, případně může být specifikováno více konfigračních souborů najednou. Například příkaz./simulator example.cfg experiments/*.cfg, provede jeden běh experimentu určeného souborem example.cfg a jeden běh všech experimentů určených soubory s koncovkou.cfg v adresáři experiments/ Všechny experimenty lze spustit vícekrát za sebou přidáním parametru-r N, kde N je celé číslo určující počet běhů každého experimentu. Příkaz./simulator -r 10 example.cfg experiments/*.cfg, tedy provede každý ze zadaných experimentů desetkrát. Před prvním spuštěním sady experimentů se ještě může hodit parametr -t, který způsobí, že všechny konfigurační soubory budou otestovány a žádná simulace neproběhne. Tento test odhalí jakékoliv překlepy v konfiguračních souborech, neodhalí ale nekompatibilní operátory (například při použití jiné instance jedince než jakou vyžaduje operátor mutace). 57

A.5 Výsledky experimentu Aby bylo možné výsledky experimentu zhodnotit, generuje program v průběhu simulace řadu souborů. V adresáři, kde se nachází konfigurační soubor experimentu, je vytvořen podadresář results/, do kterého jsou ukládány veškeré výsledky experimentu. Konkrétně se jedná o pět souborů, které mají stejné jméno jako konfigurační soubor, ale liší se koncovkami. Navíc mají v názvu seed, kterým byl inicializován generátor náhodných čísel, aby nedošlo k přepsání starších výsledků vícenásobným spuštěním téhož experimentu a aby bylo možné experiment snadno zopakovat. Úspěšným provedením příkazu./simulator example.cfg vzniknou následující soubory (číslo v názvech je závislé na čase spuštění): example-1296405852.cfg Soubor obsahující kopii konfiguračního souboru. Protože konfigurační soubory se poměrně často mění, je snadné ztratit přehled o tom, jaké parametry byly při kterém spuštění použity. Díky tomuto souboru jsou konkrétní hodnoty vždy zpětně dohledatelné. Kromě toho, že je hodnota použitého seed v názvu souboru, je zároveň uložena i v parametru seed přímo v tomto souboru (i pokud byla hodnota v originálním konfiguračním souboru 0), takže spuštěním příkazu./simulator example-1296405852.cfg se provede přesná kopie původní simulace. example-1296405852.fitness Soubor obsahující hodnoty fitness všech jedinců v průběhu celé simulace. Na každém řádku jsou dvě čísla, první je číslo generace a druhé je fitness jedince. Nultá generace (typicky složená z náhodně vygenerovaných jedinců) má číslo 0. Záznamy jsou řazeny od nejnížší generace a v rámci jedné generace od nejvyšší fitness. example-1296405852.times Soubor obsahující délky trvání jednotlivých generací. Každý řádek obsahuje dvě hodnoty, první určuje dobu běhu simulace dané generace a druhá určuje dobu běhu celé simulace až po danou generaci. Všechny hodnoty jsou v milisekundách. Na prvním řádku jsou hodnoty z první generace, na druhém z druhé generace atd. První generace by měla mít o něco kratší trvání, protože v ní neprobíhají mutace ani křížení, pouze se spočte fitness všech jedinců. example-1296405852.stats Pro hodnocení výsledků je toto pravděpodobně nejdůležitější soubor. Na každém řádku obsahuje čtyři hodnoty. Fitness nejlepšího jedince v populaci, průměrnou fitness všech jedinců, fitness nejhoršího jedince v populaci a počet jedinců v populaci. Na prvním řádku jsou hodnoty z nulté generace, na druhém řádku z první generace atd. Pro každou generaci je tedy v souboru jeden řádek. example-1296405852.rides Tento soubor je zajímavý zejména pro robotické experimenty, i když by možná 58

mohl najít využití i při jiných typech experimentů. Na každém řádku obsahuje jeden záznam průběhu vyhodnocování fitness. Tento záznam pak slouží k vizualizaci jízdy robota pomocí jednoduché aplikace Enki Viewer, kterou stručně popíšu v následující části. Tento způsob vizualizace byl zvolen hlavně z důvodu jeho jednoduchosti. Možnost sledovat průběh vyhodnocení fitness (tj. sledovat jízdu robota) v reálném čase by bylo implementačně příliš náročné a pro účely této práce zcela zbytečné. Z každého experimentu je ukládán záznam jízd nejlepšího jedince z poslední generace a absoultně nejlepšího jedince, jaký se v celém experimentu objevil (ani při použití elitismu to v robotických experimentech většinou nebývá nejlepší jedinec z poslední generace). example-1296405852.inds V tomto souboru je uložen nejlepší jedinec z poslední generace a absolutně nejlepší jedinec z celého experimentu. Každý řádek obsahuje jednoho jedince. Řádek začíná vždy číslem generace, ze které daný jedinec pochází, a hodnotou fitness, kterou získal a pokračuje záznamem konkrétního jedince. Formát záznamu jedince závisí na implementaci metody tostring() daného jedince. V podstatě se jedná o kompletní seznam všech jeho atributů a to jak těch podléhajících mutacím, tak těch, které jsou neměnné. Z tohoto záznamu by mělo být možné jedince zcela zreplikovat. A.6 Zobrazení jízdy robota Pro zobrazení jízdy robota jsem naprogramoval jednoduchou aplikaci v jazyce Java. Ta využívá záznam výpočtu fitness uložený v souborech s koncovkou.rides. Tyto soubory umí aplikace přečíst a přehrát, nebo z nich může vyrobit statické obrázky znázorňující celý průběh jízdy (tyto byly použity pro ilustraci v kapitolách 6 a 7). Na obrázcích A.1 a A.2 jsou screenshoty aplikace. Průběh jízdy je zobrazován v bílé obdelníkové ploše, která zabírá většinu okna. Pod ní jsou tlačítka sloužící k ovládání přehrávání záznamu jízdy. Tlačítko s nápisem Save uloží právě zobrazenou scénu do souboru. Formát souboru může být bud bmp nebo eps. V pravém horním rohu okna jsou ukazatele odezvy robotových infračervených senzorů (IR1 IR8), rychlosti otáčení kol a aktuální fitness (fitness získaná v tomto kroku). Robot na obrázku A.2 řeší složitější úlohu a má tedy několik senzorů navíc. V pravé dolní části je strom všech zaznamenaných jízd ve vybraném podadresáři. Aktuální podadresář se dá změnit pomocí tlačítka Select directory. Strom se záznamy není automaticky aktualizován, takže pokud nějaký soubor se záznamy přibyde, je potřeba stisknout tlačítko Rescan, aby se změna projevila. 59

Obrázek A.1: Screenshot aplikace Enki Viewer při přehrávání jízdy robota. Obrázek A.2: Screenshot aplikace Enki Viewer se zobrazeným statickým náhledem celé jízdy robota. 60