Genetikus algoritmusok globális optimalizálás sok lehetséges megoldás közül keressük a legjobbat értékel függvény: rátermettségi függvény (tness function) populáció kiválasztjuk a legrátermettebb egyedeket keresztezési (rekombinációs) és mutációs m veletekkel aktualizáljuk keresztezés 1. szül 1 0 0 0 1 1 1 2. szül 1 1 1 1 0 0 0 1. utód 1 0 0 1 0 0 0 2. utód 1 1 1 0 1 1 1 mutáció eredeti 1 0 0 0 1 1 1 mutált 1 1 0 0 1 1 1 1
A genetikus algoritmus f bb lépései: 1. (Kezdet) Véletlenszer en el állítunk egy N elem populációt (elemei egyedek v. kromoszómák). 2. (Rátermettség vizsgálata) Kiszámítjuk minden egyed rátermettségét. 3. (Új populáció el állítása) a. (Kiválasztás) Kiválasztunk két egyedet (bizonyos kritérium alapján). b. (Keresztezés) Keresztezzük a két kiválasztott egyedet. c. (Mutáció) A két utódegyeden mutációt hajtunk végre. 4. (Helyettesítés) Helyettesítjük a régi populációt az újjal. 5. (Ellen rzés) Ha a leállási feltétel igaz, akkor vége. Különben folytassuk a 2. lépéssel. 2
Kiválasztási kritériumok elitista kiválasztás: a legrátermettebb egyedek kiválasztása arányos kiválasztás: a legrátermettebbek a legvalószín bbek, de nem feltétlenül rulettkerék kiválasztás: a rátermettebbek nagyobb szeletet kapnak a rulettkeréken, amely véletlenszer en áll meg egy adott helyen skálázott kiválasztás: a rátermettségi függvény változik, ahogy az átlagos rátermettség n verseny típusú kiválasztás: az egyedek részcsoportjain belül mindenki mindenkivel versenyzik. Minden csoportból csak egy kerül tovább. rang szerinti kiválasztás: minden egyed kap egy rangot (a rátermettség alapján), és e szerint választódik ki, nem az abszolút különbség alapján generációs kiválasztás: csak új egyedek kerülnek az új generációba, a régiek kimaradnak stationárius állapotú kiválasztás: bizonyos kiválasztott egyedek visszakerülnek egy el z generációba, hogy a gyengébb egyedeket helyettesítsék hierarchikus kiválasztás: szinteken keresztül történik a kiválasztás 3
Hátizsákfeladat hátizsák kapacitása K s 1, s 2,..., s n tömeg tárgyak, az i-edikb l n i darab van (1 n i < ), e 1, e 2,..., e n érték ek, megoldás: x 1, x 2,..., x n feladat: { s1 x 1 + s 2 x 2 +... + s n x n K 0 x i n i, i = 1, 2,..., n max(e 1 x 1 + e 2 x 2 +... + e n x n ) Ha minden n i = 1, akkor 0-1 hátizsákfeladatról beszélünk. 0-1 hátizsákfeladat tömegek: (s 1, e 1 ) (s 2, e 2 ) (s n, e n ) megoldás: x 1 x 2 x n (kromoszóma) x i = 1, ha az i-edik tárgy bekerül a zsákba 4
Az algoritmus f lépései: 1. Inicializáljuk az els generációt (N kromoszóma) 2. repeat 3. minden kromoszómára számítsuk ki az össztömeget és rátermettséget (nyereséget) 4. if a kromoszómáknak kevesebb, mint 90%-a azonos nyereség 5. then válasszunk ki véletlenszer en két kromoszómát 6. keresztezzük ket, 7. majd hajtsunk végre mindkét utódon mutációt 8. until legalább 90% kromoszóma azonos nyereség vagy a lépésszám nagyobb a fels korlátnál A rátermettségi függvény Minden kromoszómára a populációból végezzük el: 1. while igaz 2. do számítsuk ki az össztömeget és nyereséget 3. if össztömeg K 4. then return össztömeg, nyereség 5. else véletlenszer en válasszunk ki egy 1-est 6. állítsuk 0-ra a megfelel értéket 5
Verseny típusú (csoportos) kiválasztás rátermettségi függvény f(i) az i-edik tárgy rátermettségi függvénye i 0 1 2 3 4 5 6 7 8 9 10 11 f(i) 40 20 5 1 9 7 38 27 16 19 11 3 Csökken sorrendben f értéke szerint a tárgyak indexe: 0 1 2 3 4 5 6 7 8 9 10 11 0 6 7 1 9 8 10 4 5 2 11 3 4 csoportra osztjuk a tömböt (indexek alapján): 02 35 68 911 Véletlenszer en választunk: 50%-os valószín séggel választunk az 1. csoportból, 30%-os valószín séggel választunk a 2. csoportból, 15%-os valószín séggel választunk a 3. csoportból, 5%-os valószín séggel választunk a 4. csoportból. 6
Véletlenszer en generálunk egy 0 99 közötti számot, ha 0 49 közötti, akkor az 1. csoportból választunk véletlenszer en egy elemet, ha 50 89 közötti, akkor az 2. csoportból választunk véletlenszer en egy elemet, ha 90 94 közötti, akkor az 3. csoportból választunk véletlenszer en egy elemet, ha 95 99 közötti, akkor az 4. csoportból választunk véletlenszer en egy elemet. 7
Utazó ügynök problémája (Traveling Salesman Problem) n város: 1, 2, 3,..., n, közöttük adott távolsággal feladat: legrövidebb körút meghatározása Kromoszóma: az 1, 2, 3,..., n számok egy permutációja. Egyéb feladatok: függvények maximuma gráfszínezés Három példa (Javaban): http://www.obitko.com/tutorials/genetic-algorithms 8
A genetikus algoritmus el nyei gyors kis er forrásigény egyszer és olcsó implementáció globális optimumot talál A genetikus algoritmus hátrányai matematikailag nem bizonyítható a megoldás helyessége nem mindig konvergál 9
Generikus algoritmusok b vebben: https://infoc.eet.bme.hu/ea13/#1 { általános, közös, angol: generic román: generic 1. példa nem specikus Szeretnénk egy menü segítségével különböz m veleteket elvégezni. Pl: Menü 1. összeadás 2. szorzás 3. hatványozás 0. kilépés printf("menu\n\n"); printf("1. osszeadas\n"); printf("2. szorzas\n"); printf("3. hatvanyozas\n"); printf("0. kilepes\n"); scanf("%u", &valasztas); 1
if (valasztas<4) { switch (valasztas) { case 1: eredm = osszead(a, b); break; case 2: eredm = szoroz(a, b); break; case 3: eredm = hatvanyoz(a, b); break; } printf("e = %d\n", eredm); } Mi van akkor, ha a menüt szeretnénk b víteni, pl. kivonással? És szeretnénk, ha ez a második helyre kerülne. A direkt beszúrások helyett (több helyre is kell), jobb megoldás lenne egy általános program megírása, ahova könnyen be lehetne szúrni az újabb menüpontot (minél kevesebb helyre). 2
typedef int (*MenuFv)(int, int); typedef struct { char const *nev; MenuFv pfv; } MenuPont; A megvalósítás: printf("menu\n"); MenuPont menupontok[] = { { " osszeadas", osszead }, { " szorzas", szoroz }, { " hatvanyozas", hatvanyoz }, { NULL, NULL } /* végjel */ }; for (i = 1; menupontok[i-1].nev!= NULL; ++i) printf("%d. %s\n", i, menupontok[i-1].nev); meret = i; /* a for() végén i = tömb mérete */ scanf("%d", &valasztas); 3
if (0 < valasztas && valasztas < meret) { eredm = menupontok[valasztas-1].pfv(3, 5); /* függvénypointer */ printf("e=: %d\n", eredm); } Ha szeretnénk beszúrni egy új m veletet, pl. kivonást elég csak megírni az a függvényt és itt módosítani: printf("menu\n"); MenuPont menupontok[] = { }; { " osszeadas", osszead }, { " kivon", kivon }, // *** { " szorzas", szoroz }, { " hatvanyozas", hatvanyoz }, { NULL, NULL } /* végjel */ Teljes példa a honlapon. 4
2. példa A következ függvény teszteli adott esetre, hogy hányszor jelenik meg pénzfeldobásnál a fej vagy az írás. double fejvagyiras(void) { int i, hanyszor; hanyszor = 0; for (i = 0; i < 1000; ++i) if (rand()%2 == 0) hanyszor += 1; return hanyszor / 1000.0; Hasonlóképpen, szeretnénk megvizsgálni, hogy véletlenszer en generált koordinátákra pl. -1 és 1 között, hányszor esik a megfelel pont az egységnyi súgarú körbe. A fenti megoldás mintájára ez is megoldható. De jobb lenne egy általános megoldás, amely máskor is alkalmazható. 5
Írjunk egy generikus programot a Monte Carlo módszerre! int (*kiserlet)(void); double montecarlo(int (*kiserlet)(void)) { int i, hanyszor; hanyszor = 0; for (i = 0; i < 100000; ++i) if (kiserlet()) hanyszor += 1; return hanyszor / 100000.0; //ne egész osztás! A megfelel függvények: int fejvagyiras(void) { } return (rand()%2 == 0); 6
int egysegkorbe(void) { double x = rand()/(double) RAND_MAX; double y = rand()/(double) RAND_MAX; return x*x + y*y < 1; } A f programban: printf("fej:%g\n", 100.0*montecarlo(fejvagyiras)); printf("korbe:%g\n", 100.0*montecarlo(egysegkorbe)); printf("pi:%g\n", 4*montecarlo(egysegkorbe)); Eredmények: 1000-szer: fej: 49.3 korbe: 76.6 pi: 3.048 10000-szer: fej: 49.65 korbe: 78.01 pi: 3.1344 100000-szer: fej: 49.855 korbe: 78.418 pi: 3.14772 7