Sunteți pe pagina 1din 10

Lucrarea 3: Algoritmi genetici (AG)

AG sunt implementaţi ca programe ce crează un mediu în care indivizii sunt într-o


permanentă competiţie pentru supravieţuire. Indivizii cu şansele cele mai mari de
supravieţuire sunt cei care reuşesc să se adapteze cel mai bine la mediul în care se
regăsesc. În acest scop, AG simulează fenomene din biologie cum ar fi moştenirea
genetică, selecţia naturală, încrucişarea şi mutaţia genetică, evoluând populaţii de soluţii
candidate de la o generaţie la alta, obţinând la fiecare iteraţie indivizi mai performanţi.
AG se pot aplica în probleme de optimizare complexe, ale căror funcţii obiectiv
pot fi discontinue, nediferenţiabile, stohastice sau neliniare.

Terminologie

Funcţie de fitness. Funcţia pe baza căreia se evaluează indivizii pentru a-i


compara. În mod uzual, aceasta este chiar funcţia pe care vrem să o optimizăm (funcţia
obiectiv).
Individ. Punctul în care se calculează funcţia de performanţă; valoarea rezultată se
numeşte scorul individului. De exemplu, pentru funcţia f ( x1 , x 2 )  x1  (2 x 2  1) 2 ,
vectorul [ x1 , x 2 ] reprezintă un individ. Se observă că dimensiunea vectorului este egală
cu numărul de variabile ale funcţiei obiectiv. Fie un individ având genele [5,2]. Scorul
acestuia va fi f (5,2)  5  (2  2  1) 2  30 .
Populaţie. Mulţime de inidivizi aflaţi în acelaşi mediu. De exemplu, pentru funcţia
de fitness precedentă, o populaţie de dimensiune 3 conţine indivizii: [ x11 , x12 ] ,
[ x 21 , x 22 ] şi [ x 31 , x 32 ] .
Generaţie. Valorile indivizilor dintr-o populaţie la un moment dat (în cadrul unei
iteraţii). De exemplu, indivizii cu genele [5,2] (scor 30), [1,1] (scor 10) şi [3,1] (scor 12).

Algoritm

Un AG general parcurge următorii paşi:

1. Generarea populaţiei iniţiale


2. Trecerea la generaţia următoare
a) evaluarea fiecărui individ din generaţia curentă prin calcularea funcţiei de
performanţă (fitness);
b) selecţia indivizilor în vederea încrucişării pe baza scorurilor acestora;
c) dacă se foloseşte elitismul, indivizii cei mai performanţi trec în generaţia
următoare. Altfel d);
d) crearea urmaşilor prin încrucişare şi mutaţie;
e) înlocuirea generaţiei curente cu urmaşii astfel creaţi;
3. Dacă s-a îndeplinit condiţia de oprire, atunci STOP. Altfel, repetă pasul 2.

Exerciţiu:
Se consideră funcţia f ( x, y )  x  2 y  6 , cu x, y  [0,15] . Să se minimizeze f
utilizând un algoritm genetic cu selecţia tip roată de ruletă, încrucişarea într-un punct
după bitul de rang 5 şi fără mutaţie. Se va calcula o iteraţie, plecând de la populaţia
iniţială P0.
P0:
Individ nr. x y
1 0 0
2 1 10
3 4 0
4 8 6
5 3 5

Rezolvare:

Utilizăm codificarea binară. Pentru aceasta, vom trece în baza 2 toate valorile posibile ale
genelor, adică numerele întregi din intervalul [0,15]. Numărul de biţi pe care se poate
face codificarea celor 16 valori este 4 (deoarece 2 4  16 ).

Zecimal Binar Zecimal Binar


0 0000 8 1000
1 0001 9 1001
2 0010 10 1010
3 0011 11 1011
4 0100 12 1100
5 0101 13 1101
6 0110 14 1110
7 0111 15 1111

Algoritmul genetic va utiliza selecţia tip roată de ruletă şi încrucişarea într-un punct.
Dimensiunea populaţiei, după cum rezultă din P0, este egală cu 5. Forma particulară a
algortmului va fi:
1. Iniţializarea populaţiei iniţiale cu P0; nr_iter=0;
Repetă:
2. Selecţia ruletă
a) calcul fitness; f i  f ( x i , y i ) , cu i  1..5
5
| fi |
b) calcul probabilităţi; p i 
S
,S  | fi | , i  1..5
i 1
c) generarea numerelor aleatoare şi alegerea părinţilor
3. Încrucişarea
4. Înlocuirea generaţiei curente cu urmaşii creaţi prin încrucişare;
nr_iter=nr_iter+1;
Până când nr_iter=1.

Trasăm execuţia acestui algoritm, evidenţiind pasul curent.

Pasul 1. Iniţializăm populaţia iniţială cu P0 şi codificăm indivizii acesteia în binar:


Individ nr. x y Individ_codificat
1 0 0 00000000
2 1 10 00011010
3 4 0 01000000
4 8 6 10000110
5 3 5 00110101
După cum se observă, codificarea indivizilor se face prin alăturarea valorilor binare ale
celor două gene. Pentru decodificare, vom împărţi fiecare individ în grupe de 4 biţi şi le
vom trece în zecimal:
x y
0000 0000

Iteraţia 1.
Pasul 2.
a) Calculăm fitness-ul pentru toţi indivizii din generaţia curentă:
f 1  f ( x1 , y1 )  0  2  0  6  6
f 2  25
f 3  2
f 4  10
f 5  13

5
S  | f i | 56
i 1
b) Calculăm probabilităţile de selecţie pentru fiecare individ, în vederea aplicării selecţiei
de tip ruletă:
| f 1 | 25
p1    0.107
S 56
p 2  0.446
p 3  0.036
p 4  0.179
p 5  0.232

5
Observaţie:  pi 1.
i 1
c) Vom alege părinţii după principiul roţii de ruletă. Calculăm sumele parţiale normalizate
pentru fiecare individ şi le reprezentăm grafic:
q1  p1  0.107
q 2  p1  p 2  0.107  0.446  0.554
q3  0.589
q 4  0.768
q5  1
Împărţirea roţii de ruletă în funcţie de probabilităţi este prezentată în figura 3.1.
Fig. 3.2. Roata de ruletă divizată în funcţie de probabilităţile de selecţie

Reprezentarea grafică a sumelor parţiale:


0.107 0.554 0.768 1.000

0.589
Fig. 3.3. Desfăşurarea sumelor parţiale normalizate

Deoarece dimensiunea populaţiei este 5, trebuie să alegem 3 perechi pentru încrucişare.


Unul din urmaşii rezultaţi (din cei 6) se va ignora.
Pentru a selecta prima pereche, generăm aleator 2 valori din intervalul [0,1). Fie acestea
r1  0.34
r2  0.52
Cum q1  r1  q 2 , primul individ selectat va fi individul 2. q1  r2  q 2 , deci al doilea
părinte va fi tot 2. Prima pereche va fi deci formată din (individ_2, individ_2).
Continuăm procesul de selecţie generând două noi numere aleatoare:
r1  0.47
r2  0.91
Cum q1  r1  q 2 şi q 4  r2  q 5 , a doua pereche de părinţi va fi formată din (individ_2,
individ_5).
Ultima pereche de părinţi se selectează prin generarea aleatoare a două noi numere:
r1  0.88
r2  0.76
Cum q 4  r1  q 5 şi q 3  r2  q 4 , a treia pereche de părinţi va fi formată din (individ_5,
individ_4).
Indivizii selectaţi pentru încrucişare prin metoda roţii de ruletă sunt deci:
Pereche nr. Părinte 1 Părinte 2
1 2 2
2 2 5
3 5 4
S-a încheiat pasul de selecţie al algoritmului genetic şi urmează încrucişarea părinţilor.

Pasul 3. Se utilizează încrucişarea într-un punct. Secţionăm indivizii după bitul de rang 5
(conform cerinţei) şi interschimbăm intre cei doi indivizi biţii care urmează după aceasta:

Individ_2 00011|010 00011|010


Perechea 1 + : ->
Individ_2 00011|010 00011|010

Individ_2 00011|010 00011|101


Perechea 2 + : ->
Individ_5 00110|101 00110|010

Individ_5 00110|101 00110|110


Perechea 1 + : ->
Individ_4 10000|110 10000|101

Păstrăm 5 indivizi dintre urmaşii astfel rezultaţi şi înlocuim generaţia curentă cu aceştia.

Pasul 4.
P1:
Individ codificat x_binar y_binar x_zecimal y_zecimal
00011010 0001 1010 1 10
00011010 0001 1010 1 10
00011101 0001 1101 1 13
00110010 0011 0010 3 2
00110110 0011 0110 3 6

Cum nr_iter=1, s-a îndeplinit condiţia de oprire şi algoritmul se opreşte.

Observaţie: Calculând fitness-ul pentru indivizii din noua generaţie, vom obţine
f 1  f ( x1 , y1 )  25
f 2  25
f 3  31
f 4  7
f 5  15

Valoarea minimă a acestuia se obţine pentru individul numărul 3. Se observă că această


valoare este mai mică decât minimul rezultat pentru generaţia anterioară, ceea ce
înseamnă că prin algoritmul genetic utilizat, de la o generaţie la alta, am ajuns la valori
mai bune.
Lucrare de control (max 10 min): calculaţi probabilităţile de selecţie şi sumele
parţiale normalizate şi alegeţi 3 perechi pentru încrucişare (paşii 2 b şi 2 c din
algoritm) pentru generaţia curentă – cu pasul 2 a calculat la observaţie.

Elemente de limbaj Matlab pentru algoritmi genetici

Funcţia care implementează AG în toolbox-ul GADS se numeşte ga şi are


următoarea sintaxă:

[x val_fitness] = ga(@functie_fitness, nr_var, optiuni)

Parametrii de intrare:
@functie_fitness – referinţa către un fişier .m în care se calculează funcţia pentru
problema de rezolvat;
nr_var – numărul de variabile independente ale funcţiei obiectiv.

Parametrii de ieşire:
x – punctul final (individul cel mai performant găsit);
val_fitness – valoarea funcţiei obiectiv în punctul x (scorul individului x).

Funcţia de fitness, calculată într-un fişier .m, trebuie să accepte ca parametru de


intrare un vector de lungime egală cu numărul de variabile independente ale funcţiei
obiectiv şi să returneze un scalar.
Amintim în continuare paşii pentru scrierea unei funcţii Matlab. Presupunem că
vrem să optimizăm funcţia
3
f1 ( x)   xk .
2

k 1
Fişierul .m care calculează această funcţie trebuie să accepte un vector de trei
componente, corespunzătoare celor trei variabile din sumă. Pentru a scrie fişierul, se
parcurg următorii paşi (vezi lucrarea 1):
1. Selectaţi comanda New din meniul File
2. Alegeţi opţiunea M-file. Se va deschide un fişier .m nou în editorul Matlab
3. În fişierul astfel creat, scrieţi
function y= functie1(x)
y=0;
for j=1:1:3
y=y+x(j)^2;
end
4. Salvaţi fişierul. Pentru a evita problemele de compatibilitate, se obişnuieşte
denumirea fişierelor cu numele funcţiei (aici vom crea deci fişierul functie1.m).

Verificaţi rularea corectă a funcţiei, prin apelul acesteia în linia de comandă:


>> functie1([1 2 3])
ans =
14
Exemple
1. Vom utiliza AG pentru minimizarea sumei din fişierul functie1.m creat anterior. Pentru
aceasta, scrieţi în linia de comandă:

>> [x val_fitness]=ga(@functie1,3)

Rezultatul va fi:

Optimization terminated: maximum number of generations exceeded.

x =

0.0033 0.0021 0.0033

val_fitness =

2.5943e-005

Se observă că rezultatul este foarte apropiat de minimul determinat pe cale analitică


(0,0,0).
2. O funcţie foarte des utilizată în studiul metodelor de optimizare este funcţia Rastrigin,
dată prin
n n
f 2 ( x )  10  n   x i 2  10   cos 2    xi .
i 1 i 1
Pentru a vizualiza grafic această funcţie, scrieţi în linia de comandă sau într-un fişier .m
(Fig. 3.4):

g = -5:0.05:5;
[x,y] = meshgrid(g);
z= 20*size(x,2)+x.^2+y.^2-10*(cos(x.*2.*pi)+cos(y.*2.*pi));
surfc(x,y,z)
shading interp
camlight headlight
Fig. 3.4. Graficul funcţiei Rastrigin

După cum se observă, funcţia prezintă foarte multe minime locale, ceea ce face ca
metodele de gradient să eşueze în găsirea minimului global. Pentru n=3, acesta este în
punctul de coordonate(0,0,0).
Pentru a căuta minimul acestei funcţii cu AG, deschideti un fişier .m, scrieţi următoarele
comenzi şi salvaţi-l cu numele rastrigin.m:

function y= rastrigin(x)
y = 10.0 * size(x,2) + sum(x .^2 - 10.0 * cos(2 * pi .* x),2);

Apoi tastaţi în linia de comandă:

>> [x val_fitness] = ga(@rastrigin,3)

În urma execuţiei acestei comenzi Matlabul va afişa:

Optimization terminated: stall generations limit exceeded.

x =

1.0e-003 *

0.7098 0.2958 -0.0193

val_fitness =

1.1739e-006

3. Fie funcţia
 30 2 
1  sin   x k 
2
 k 1 
f 3 ( x)   ,
30
1  0.001   x k
2

k 1
reprezentată grafic în figura 3.5 cu ajutorul comenzilor:

g = -10:0.1:10;
[x,y] = meshgrid(g);
z = (1-power(sin(sqrt(x.^2+y.^2)),2))./(1+0.001.*(x.^2+y.^2));
surfl(x,y,z)
shading interp
colormap copper

Fig. 3.5. Graficul funcţiei f 3

Dorim să găsim maximul acestei funcţii cu ajutorul AG. Pentru aceasta, având în vedere
faptul că funcţia ga din toolbox-ul GADS minimizează funcţia pe care o primeşte ca
parametru, scriem în fişierul funcţie3.m:

function y= functie3(x)
y = (-1)*((1-power(sin(sqrt(sum(x.^2,2))),2))./(1+0.001.*sum(x.^2,2)));

Şi apelăm în linia de comandă funcţia ga:

>> [x val_fitness] = ga(@functie3,30)

Rezulatul va fi:
-0.9952

După cum se observă, rezultatul obţinut este apropiat de maximul global de valoare 1,
însă are semnul schimbat (deoarece în fişierul funcţiei obiectiv am schimbat semnul,
pentru a transforma problema într-una de maximizare).
Observaţie: Sintaxa funcţiei ga aşa cum a fost prezentată iniţial, conţine parametrul de
intrare opţiuni. Prin acesta se pot stabili diferiţi parametri ai AG, cum ar fi rata de
încrucişare, metoda de selecţie, recombinare sau mutaţie, numărul de generaţii,
dimensiunea populaţiei, etc. Atunci când nu se specifică acest parametru, se utilizează
setările implicte. Opţiunile vor fi aprofundate în cadrul lucrării 4.