Editura Sfântul Ierarh Nicolae ISBN 978-606-577-027-0
Editura Sfântul Ierarh Nicolae ISBN 978-606-577-027-0
Editura Sfântul Ierarh Nicolae ISBN 978-606-577-027-0
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Editura</strong> Sfântul <strong>Ierarh</strong> <strong>Nicolae</strong><br />
<strong>ISBN</strong> <strong>978</strong>-<strong>606</strong>-<strong>577</strong>-<strong>027</strong>-0
Cap.I Consideratii generale<br />
1) Introducere<br />
Algoritmii genetici sunt o parte a calculului evolutiv care, la rândul său, este o parte a<br />
foarte actualului domeniu al inteligenţei artificiale.<br />
Dacă algoritmii clasici cum sunt greedy, backtracking, divide et impera s.a. fac parte<br />
din categoria algoritmilor deterministi (pentru aceleasi date de intrare dau intotdeauna<br />
aceeasi solutie), algoritmii genetici pot fi caracteriziati ca fiind niste algoritmi<br />
nedeterministi (pentru aceleasi date de intrare ofera solutii diferite). Din acest punct de<br />
vedere ei pot fi usor incadrati in larga categorie a algoritmilor euristici.<br />
Asa cum sugerează si numele, acesti algoritmi sunt inspirati din legile geneticii,<br />
avand insa ca punct de plecare teoriile lui Charles Darwin despre evolutie. Spus intr-un<br />
mod foarte simplist, solutia unei probleme rezolvate de catre un algoritm genetic<br />
evolueaza.<br />
Ideea calculului evolutiv a fost introdusa pentru prima oara in anul 1960 de catre<br />
I. Rechenberg in lucrarea sa “Evolution strategies”, ideea lui fiind dezvoltata apoi si de<br />
catre alti cercetatori. Algoritmii genetici au fost inventati de catre John Holland. Acesta<br />
si-a expus ideile in cartea sa ”Adaptation in Natural and Artificial Systems”, publicata in<br />
1975. In 1992 John Koza a folosit algoritmii genetici pentru a dezvolta programe<br />
destinate anumitor scopuri precise. Metoda folosita de el a primit denumirea de<br />
programare genetica.<br />
In practica se intalnesc nenumarate probleme cu un volum foarte mare de date de<br />
intrare cum ar fi: probleme de recunoastere (a vocii, a scrisului etc.), de coordonare a<br />
miscarii robotilor, de previziune statistica in meteorologie etc. De cele mai multe ori<br />
mintea umana abordeaza cu succes astfel de probleme, dar gasirea unor algoritmi<br />
adecvati pentru rezolvarea lor, astfel incat ele sa poata fi abordate eficient (din punctul de<br />
vedere al timpului de executie si al necesarului de memorie) cu ajutorul calculatorului,<br />
este destul de dificil de realizat. Se pune problema, cum pot entitatile naturale (nu<br />
neaparat inteligente) sa rezolve fara un efort prea mare aceste probleme combinatoriale<br />
masive, un exemplu elocvent in acest sens fiind cel al albinei care poate sa urmeze rute<br />
complexe, rute care chiar si pentru un supercalculator reprezinta o piatra de temelie in<br />
incercarea de a le gasi in timp real. De aceea, pentru astfel de probleme, s-a incercat<br />
imitarea “inteligentei” gasita in natura prin incercarea de a “simula soft” lumea reala,<br />
copiind caile de rezolvare pe care le-a gasit natura pentru solutionarea lor, si de a prelucra<br />
datele de o maniera “cat mai naturala”.<br />
2) Notiuni de genetica<br />
Toate organismele vii sunt alcatuite din celule. In nucleul fiecarei celule exista<br />
aceeasi multime de cromozomi. Cromozomii sunt siruri de A.D.N. (acid<br />
dezoxiribonucleic) si servesc ca model pentru intregul organism, A.D.N.-ul codificand<br />
sub forma chimica informatiile genetice pentru toate caracterele ereditare. Un cromozom<br />
este alcatuit din gene, fiecare gena codificand o caracteristica (spre exemplu culoarea<br />
ochilor). Ea are o pozitie fixa in cromozom.<br />
1
In timpul reproducerii apar doua tipuri de transformari: incrucisarea (engl.<br />
crossover) si mutatia. Mult simplificat, procesul de incrucisare ar arata astfel: doi<br />
cromozomi se “lovesc” unul de celalalt, isi schimba intre ei “fragmente” de informatii<br />
genetice (printr-o recombinare a genelor, insa fara a-si schimba numarul de gene) si apoi<br />
se indeparteaza. Mutatia reprezinta modificarea unor elemente dintr-un cromozom (apar<br />
elemente care nu apartin nici unuia dintre cei doi cromozomi parinti), si apare de obicei<br />
din cauza erorii copierii de gene de la parinti.<br />
O specie se caracterizează prin: numărul de gene, ordinea genelor în cromozom şi<br />
semnificaţia fiecărei gene.<br />
Populaţia este o mulţime de n indivizi (in cazul algoritmilor genetici notiunea de<br />
individ se va confunda cu cea de cromozom), din aceeaşi specie, care ocupă un teritoriu<br />
cu resurse limitate şi care se reproduc între ei. Orice populatie evolueaza in timp prin<br />
aplicarea transformarilor mai sus amintite.<br />
Mediul cuprinde, in afara de teritoriu si resurse, totalitatea regulilor prin care se creează<br />
relaţiile de concurenţă între indivizii din populaţie.<br />
Speranta de viata (engl. fitness) este o valoare care se ataseaza fiecarui individ<br />
(cromozom), si care reprezinta in esenta valoarea adaptabilitatii la regulile impuse de<br />
mediu.<br />
3) Algoritmul general (schema logica si pseudocod)<br />
Asa cum am mai spus, solutia pentru o problema rezolvata prin algoritmi genetici<br />
evolueaza. Algoritmul incepe cu o multime de solutii (solutieindividcromozom),<br />
numita populatie. Aceasta populatie (denumita uneori si generatia 0) se genereaza aleator.<br />
Solutiile dintr-o populatie existenta la un anumit moment dat sunt luate si folosite<br />
pentru a forma o noua populatie pe baza unor anumite criterii. Acest lucru este motivat de<br />
faptul ca noua populatie are sanse foarte mari sa fie mai buna decat cea veche. Formarea<br />
noii populatii are loc prin procesele de incrucisare (crossover) si mutatie. Cu cat speranta<br />
de viata (fitness) a unui cromozom este mai mare, cu atat sansa ca acesta sa<br />
supravietuiasca in populatia urmatoare este mai mare. Totodata, la incrucisare, sansa unui<br />
cromozom de a fi ales pentru acest proces este direct proportionala cu fitness-ul lui.<br />
Algoritmul de mai sus este repetat pana cand o conditie este satisfacuta. Conditia este<br />
de obicei repetarea de un numar de ori al ciclului, imbunatatirea solutiei cu un anumit<br />
grad etc.<br />
In figura de mai jos se reprezinta schema logica care ilustreaza, la modul general,<br />
mecanismele descrise mai sus.<br />
2
(populaţia iniţială)<br />
P t<br />
t = t + 1<br />
P 0<br />
P t<br />
P' t<br />
P t+1<br />
inserţie<br />
evaluare<br />
P t<br />
P'' t<br />
reproducere<br />
selecţie<br />
(urmaşi)<br />
(părinţi)<br />
criteriu<br />
de oprire<br />
nu<br />
P t<br />
da<br />
rezultat<br />
In blocul de instructiuni “evaluare” se calculeaza fitness-ul fiecarui cromozom,<br />
aceste valori ajutand mai apoi la selectia (blocul “selectie”) cromozomilor ce se vor<br />
incrucisa, formand astfel noua populatie.<br />
Blocul “reproducere” efectueaza cele 2 procese de crossover si mutatie.<br />
In secventa “insertie” are loc inlocuirea populatiei vechi cu populatia noua obtinuta<br />
prin reproduceri succesive.<br />
Algoritmul se repeta pana cand se indeplineste criteriul de oprire, care reprezinta de<br />
obicei creerea unui anumit numar de populatii (lucru contorizat de variabila t).<br />
Sageata care duce la “insertie” fara a trece prin “selectie” si “reproducere” reprezinta<br />
fenomenul de elitism, fenomen ce va fi explicat in capitolul urmator.<br />
In continuare vom prezenta codificarea in pseudocod a modului de functionare a unui<br />
algoritm genetic.<br />
// incepe cu un timp initial(se porneste de la generatia 0)<br />
t := 0;<br />
// initializeaza o populatie aleatoare de n cromozomi (care<br />
reprezinta solutii posibile pentru problema)<br />
InitializeazaPopulatie();<br />
// calculeaza fitness-ul fiecarui cromozom din populatia<br />
initiala<br />
CalculFitness ();<br />
// testeaza pentru criteriul de oprire;<br />
3
cat timp nu este indeplinit criteriul de oprire creeaza o<br />
populatie noua pe baza celei vechi;<br />
// incrementeaza contorul de timp;<br />
t := t + 1;<br />
// selecteaza doi parinti cromozomi pe baza unor reguli<br />
prestabilite;<br />
SelectieParinti();<br />
// recombina genele cromozomilor selectati<br />
prin crossover;<br />
Crossover();<br />
// modifica noii cromozomi formati prin mutatie;<br />
Mutatie();<br />
// insereaza cromozomii noi formati in populatia noua;<br />
Insert();<br />
// populatia noua o inlocuieste pe cea veche;<br />
// daca se indeplineste conditia de final afiseaza solutia;<br />
//sfarsit algoritm.<br />
4
Cap.II Codificarea informaţiilor<br />
Precum se poate observa, algoritmul de mai sus (ilustrat prin schema logica si<br />
pseudocod) este foarte general. Pentru fiecare problema particulara in parte trebuie sa se<br />
raspunda la urmatoarele intrebari:<br />
1. Cum codificam cromozomii, si cum este reprezentata o solutie in cromozom<br />
2. Cum initializam cromozomii Care este populatia initiala Cat de mare este ea<br />
3. Cine este fitness-ul unui cromozom<br />
4. Cum selectam parintii pentru incrucisare<br />
5. Cum se face incrucisarea<br />
6. Cum se face mutatia<br />
7. Daca noua populatie este formata doar prin crossover, atunci este posibil sa se piarda<br />
cele mai bune solutii din actuala populatie. Cum evitam acest lucru<br />
8. Cat de des apare mutatia Daca apare prea des, ar insemna ca facem o cautare<br />
aleatoare in spatiul solutiilor. Daca nu apare nici o data, atunci s-ar putea sa cadem<br />
intr-un extrem local.<br />
9. Cand se termina algoritmul<br />
La toate aceste intrebari si la multe altele care se leaga de ele vom raspunde in<br />
paragrafele care urmeaza.<br />
1) Codificarea cromozomilor<br />
Exista multe variante de codificare, totul depinzand de problema pe care dorim sa o<br />
rezolvam. Trebuie avuta mare grija in aceasta etapa deoarece o codificare buna poate<br />
duce la o implementare usoara a operatiilor de incrucisare si mutatie. Exemple:<br />
a) Codificarea binara<br />
Fiecare cromozom este reprezentat ca un sir de 1 si 0:<br />
Cromozomul A 1001100101011101011010011<br />
Cromozomul B 1111110011000000110101101<br />
Problema clasica care foloseste acest tip de codare este problema discreta a<br />
rucsacului. Aici fiecare obiect este codificat cu 1 daca este in rucsac si cu 0 daca nu este<br />
in rucsac.<br />
b) Codificarea sub forma de permutare<br />
Fiecare cromozom este reprezentat sub forma unei permutari:<br />
Cromozomul A 1 5 3 2 6 4 7 9 8<br />
Cromozomul B 8 5 6 7 2 3 1 4 9<br />
Aceasta codificare se face in cazul problemei comis voiajorului. O permutare<br />
reprezinta ordinea in care comis-voiajorul viziteaza orasele.<br />
c) Codificarea sub forma de valori<br />
Fiecare cromzom este un sir de valori:<br />
Cromozomul A 1.234 5.3243 0.4456 2.3293 2.4545<br />
Cromozomul B<br />
ABDJEIFJDHDHDGKDFLDPIRW<br />
Cromozomul C<br />
(back),(back),(right),(forward),(left)<br />
5
2) Populatia initiala<br />
Populatia este o multime de cromozomi care trebuie sa fie suficient de mare pentru a<br />
se putea realiza un numar multumitor de combinatii intre cromozomii componenti, dar nu<br />
prea mare, deoarece acest lucru va incetini algoritmul.<br />
Populatia initiala este una aleatoare. Spre exemplu, pentru determinarea unui drum<br />
hamiltonian de cost minim, se poate incepe cu generarea aleatoare a catorva permutari.<br />
O parte din populatia initiala poate fi generata prin metode euristice, spre exemplu in<br />
cazul problemei comis-voiajorului se pot genera cativa cromozomi prin metoda greedy.<br />
In acest fel se poate ajunge la o solutie mai rapid.<br />
3) Fitness-ul unui cromozom<br />
Fitness-ul unui cromozom este speranta lui de viata. Pe noi ne intereseaza sa obtinem<br />
cromozomi cu fitness-ul cat mai mare, sau cat mai mic, in orice caz, cu un fitness la o<br />
extrema.<br />
In cazul problemei comis-voiajorului, fitness-ul este costul drumului codificat de<br />
respectivul cromozom. Aici ne intereseaza sa obtinem un cromozom cu un fitness cat mai<br />
mic.<br />
In cele ce urmeaza presupunem, pentru simplitate, ca dorim sa obtinem un<br />
cromozom cu fitness-ul cat mai mare.<br />
4) Selectarea cromozomilor parinti<br />
Cromozomii sunt selectati din populatie pentru a fi parinti intr-o incrucisare<br />
(crossover). Conform teoriei lui Darwin, cei mai buni parinti supravietuiesc si se<br />
inmultesc creand noi urmasi.<br />
Dintre metodele cele mai des intalnite de selectie amintim:<br />
a) Selectia aleatoare<br />
Doi parinti sunt alesi aleator din populatie. Acest lucru se face generand un numar<br />
aleator intre 1 si dimensiunea populatiei.<br />
b) Selectarea cu ajutorul ruletei ponderate<br />
Parintii sunt selectati in conformitate cu fitness-ul lor. Cu cat sunt mai buni, cu atat<br />
sansa lor de a fi alesi este mai mare. Imaginati-va o ruleta in care sunt dispusi toti<br />
cromozomii din populatie. Fiecarui cromozom ii corespunde un sector al ruletei, direct<br />
proportional, ca marime, cu fitness-ul cromozomului respectiv. In acest fel cromozomii<br />
cu fitness mai mare au atasate sectoare mai mari iar cei cu fitness mic au atasate sectoare<br />
mai mici. La aruncarea bilei pe ruleta exista mai multe sanse de alegere pentru<br />
cromozomii cu fitness mare. Figura de mai jos reprezinta un exemplu de ruleta ponderata<br />
pentru opt cromozomi.<br />
6
5<br />
6<br />
7<br />
8<br />
4<br />
3<br />
1<br />
2<br />
Simularea rotii de ruleta se face in felul urmator:<br />
se calculeaza suma tuturor fitness-urilor cromozomilor. Fie aceasta S;<br />
se genereaza un numar aleator intre 1 si S. fie acesta r;<br />
se parcurge populatia ordonata crescator dupa fitness si se calculeaza suma<br />
fitness-urilor cromozomilor parcursi pana depasim valoarea r. Se alege<br />
cromozomul la care s-a ajuns.<br />
c) Selectia aranjata<br />
Selectia anterioara nu este recomandata in cazul in care fitness-ul cromozomilor<br />
difera foarte mult. De exemplu daca unul din cromozomi are fitness-ul de 100 de ori mai<br />
mare decat suma fitness-urilor celorlalti cromozomi, sansele cromozomilor cu fitness mic<br />
sunt aproape nule. Pentru a evita aceasta situatie, se ordoneaza cromozomii crescator<br />
dupa fitness, apoi se renumeroteaza cu numere intregi din intervalul [1,..,dimensiunea<br />
populatiei]. Cromozomul cu fitness-ul cel mai mic are numarul 1 etc., iar cromozomul cu<br />
fitness-ul cel mai mare are numarul egal cu dimensiunea populatiei. Aceste numere se<br />
considera fitness-uri si pe ele se aplica selectia rotii de ruleta. Observam ca cromozomii<br />
cu fitness-ul cel mai mare au tot cele mai mari sanse de a fi alesi, dar de data aceasta nu<br />
mai sunt asa mari in comparatie cu sansele celorlalti.<br />
d) Selectia cu starea consolidata<br />
Aceasta nu este o metoda particulara. Ideea esentiala este urmatoarea: cromozomii<br />
nou generati vor inlocui, daca sunt mai buni, o parte din cromozomii vechii populatii. In<br />
acest fel nu mai este necesar sa se lucreze cu mai multe populatii deodata, ci doar cu una<br />
singura.<br />
e) Elitism<br />
Cand cream o noua populatie prin incrucisare si mutatii, exista o sansa mare de a<br />
pierde cei mai buni cromozomi. De aceea se recomanda copierea celor mai buni<br />
cromozomi in noua populatie, fara a-i schimba. Acest proces se numeste elitism si el<br />
creste rapid performantele algoritmilor genetici.<br />
5) Incrucisarea (crossover)<br />
Incrucisarea depinde de tipul de codificare a cromozomilor si de problema<br />
particulara pe care o rezolvam. Iata cateva exemple:<br />
7
Codificarea binara<br />
a) Incrucisare intr-un singur punct<br />
Un punct de incrucisare este ales. Din primul parinte este copiata secventa de la<br />
inceput pana la punctul de incrucisare, iar din al doilea parinte este copiata secventa de la<br />
punctul de incrucisare pana la final.<br />
11001011+110111111 110011111<br />
b) Incrucisarea in doua puncte<br />
Sunt alese doua puncte de incrucisare. Secventa dintre cele doua puncte este aleasa<br />
dintr-unul din parinti, iar ce a ramas din celalalt parinte:<br />
11001001+1101111111011101<br />
c) Incrucisarea uniforma<br />
Bitii sunt copiati aleator din primul si al doilea parinte.<br />
11001011+1101110111011111<br />
d) Incrucisarea aritmetica<br />
Operatii aritmetice sunt efectuate pentru a crea noi urmasi.<br />
11001011+1101111111001001 (AND)<br />
Codificarea sub forma de permutare<br />
Metodele folosite aici sunt asemanatoare cu cele de la codificarea binara. Trebuie<br />
avuta grija sa se pastreze consistenta permutarii, adica sa nu apara un numar de doua ori,<br />
iar altele nici o data.<br />
(1 2 3 4 5 6 7 8 9)+(4 5 3 6 8 9 7 2 1)(1 2 3 4 5 6 8 9 7)<br />
Codificarea sub forma de valoare<br />
Metodele de la codificarea binara pot fi folosite si aici.<br />
Observatii<br />
Probabilitatea de incrucisare indica cat de des trebuie sa apara aceasta operatie intr-o<br />
populatie. De obicei are valoare mare, cuprinsa intre 60% si 90%.<br />
Metodele de incrucisare prezentate mai sus sunt destul de generale. De obicei sunt<br />
alese metode specifice problemei care se doreste a fi rezolvata si care genereaza o<br />
populatie mai buna. Spre exemplu in cazul problemei generarii unei componente intern<br />
stabile maximale (submultime de noduri a unui graf neorientat cu un numar maxim de<br />
elemente cu proprietatea ca oricare doua noduri din submultime nu sunt legate printr-o<br />
muchie) se aleg doi cromozomi care codifica doua componente intern stabile. Aceste<br />
componente sunt de fapt multimi, reprezentate ca un sir de biti. In acest caz se poate<br />
folosi, de exemplu incrucisarea intr-un singur punct, sau cu doua puncte, dar s-ar putea ca<br />
8
in acest caz componentele noi formate sa fie mai mici decat parintii lor. De aceea putem<br />
lua unul din parinti si ii vom adauga noduri din al doilea parinte, rezultand in acest fel un<br />
cromozom cu fitness-ul mai mare sau egal decat cel al parintilor. Este repetata aceeasi<br />
operatie si pentru celalalt parinte. Acest tip de incrucisare se numeste incrucisare<br />
inteligenta.<br />
6) Mutatia<br />
Mutatia apare in principal pentru a evita caderea solutiilor intr-un optim local.<br />
Efectuarea de prea multe ori a acestei operatii va transforma algoritmul intr-o cautare<br />
aleatoare in spatiul solutiilor posibile. De aceea probabilitatea de mutatie trebuie sa fie<br />
mica, circa 0,5-1%.<br />
Codificarea binara<br />
a) Inversarea bitilor<br />
Bitii selectati sunt inversati 10.<br />
1100110001<br />
b) Interschimbarea bitilor<br />
Se aleg doi biti si se schimba valorile intre ei.<br />
1100100110001101<br />
Codificarea sub forma de permutare<br />
a) Transpozitie<br />
Este efectuata o transpozitie asupra permutarii respective. Acest lucru este echivalent<br />
cu interschimbarea bitilor de la codificarea binara.<br />
(1 2 3 4 5 6 8 9 7)(1 8 3 4 5 6 2 9 7)<br />
Codificarea sub forma de valori<br />
Un numar mic este adaugat sau scazut din valorile selectate.<br />
(1.29 5.68 2.86 4.11 5.55)(1.29 5.68 2.73 4.22 5.55)<br />
7) Cand se termina algoritmul<br />
Algoritmii genetici se termina, de obicei, dupa ce s-a creat un numar predefinit de<br />
populatii noi. In alte cazuri se poate determina daca solutia s-a imbunatatit de la o<br />
populatie la alta. In caz afirmativ se continua cu creerea de noi populatii, in caz negativ se<br />
afiseaza cel mai bun cromozom din populatia curenta.<br />
9
Cap.III Implementarea algoritmului<br />
Dupa cele doua capitole pregatitoare suntem in masura de a da o forma generala a<br />
programului ce rezolva o problema prin algoritmi genetici.<br />
Vom incepe prin a da forma generala a programului principal, forma care sufera<br />
foarte mici modificari de la o problema la alta.<br />
Comentariile la nivel de cod sursa sunt suficiente pentru a intelege mecanismul<br />
algoritmului.<br />
void main()<br />
{<br />
int i;<br />
Citire();<br />
/*citeste datele de intrare ale problemei*/<br />
randomize();<br />
InitializeazaPopulatie();<br />
/*genereaza populatia initiala*/<br />
OrdoneazaDupaFitness();<br />
/*ordoneaza cromozomii descrescator(crescator) dupa fitness*/<br />
for(i=1;iMaxIteratii este conditia de iesire din program, i fiind<br />
echivalentul lui t din pseudocod*/<br />
{<br />
NrPop=0;<br />
/*variabila globala care contorizeaza numarul de cromozomi adaugati<br />
la noua populatie*/<br />
Elitism(MaxElitism);<br />
/*copie cei mai buni MaxElitism cromozomi din populatia veche in cea<br />
noua*/<br />
for(co=1;co
*afiseaza cea mai buna solutie gasita*/<br />
}<br />
Algoritmii genetici au o structura foarte generala, care permite folosirea lor pentru<br />
majoritatea problemelor. Ceea ce se schimba sunt urmatoarele:<br />
- codificarea cromozomilor;<br />
- initializarea populatiei;<br />
- incrucisarea;<br />
- mutatia.<br />
Vom da in continuare sursa completa ce implementeaza forma generala a<br />
programului. Pentru o mai buna lizibilitate a codului, toate functiile care se folosesc in<br />
acest program au fost mai intai declarate prin antetul lor inaintea programului principal, si<br />
dezvoltate apoi dupa acesta. Inca o data, comentariile la nivelul codului sursa sunt<br />
suficiente pentru a intelege ce se intampla.<br />
#include<br />
#include<br />
#include<br />
/*aici isi au prototipul functiile randomize() si random(int)*/<br />
const MaxPopulatie=100,<br />
/*numarul de cromozomi in populatie*/<br />
MaxIteratii=100,<br />
/*numarul de iteratii ale algoritmului*/<br />
MaxElitism=2,<br />
/*cati cromozomi sunt copiati prin elitism*/<br />
MaxCrossover=37,<br />
/*de cate ori apare incrucisarea intr-o populatie*/<br />
MaxMutatie=1;<br />
/*de cate ori apare mutatia intr-o populatie*/<br />
typedef struct{<br />
int gena[22];<br />
/*depinde de la problema la problema*/<br />
float fitness;<br />
}TCromozom;<br />
/*tipul care codifica un cromozom*/<br />
typedef TCromozom TPopulatie[MaxPopulatie+1];<br />
/*tipul care codifica o populatie*/<br />
TCromozom CelMaiBunCromozom;<br />
/*cea mai buna solutie in orice moment*/<br />
TPopulatie PopulatieVeche, PopulatieNoua;<br />
/*se lucreaza cu doua populatii*/<br />
int i,j,k,contor,co,r1,r2;<br />
int NrPop;<br />
void citire();<br />
void CalculFitness();<br />
void InitializeazaPopulatie();<br />
void Elitism(int NrMutati);<br />
void Crossover(TCromozom g1, TCromozom g2, TCromozom &rez1, TCromozom<br />
&rez2);<br />
void Mutatie(TCromozom &mutant);<br />
void MutaRestul(int NrMutati);<br />
void OrdoneazaDupaFitness();<br />
void SelectieParinti(int &r1, int &r2);<br />
11
void Afiseaza();<br />
void main()<br />
{<br />
/*programul principal dat mai sus*/<br />
}<br />
void citire()<br />
{<br />
/*se citesc datele de intrare*/<br />
}<br />
void InitializeazaPopulatie()<br />
{<br />
int i,j;<br />
for(i=1;i
sw=0;<br />
for(i=1;iPopulatieVeche[i+1].fitness)<br />
{<br />
aux=PopulatieVeche[i];<br />
PopulatieVeche[i]=PopulatieVeche[i+1];<br />
PopulatieVeche[i+1]=aux;<br />
sw=1;<br />
}<br />
}<br />
/*cautarea unei solutii mai bune si retinerea ei*/<br />
if (PopulatieVeche[MaxPopulatie].fitness> CelMaiBunCromozom.fitness)<br />
CelMaiBunCromozom=PopulatieVeche[MaxPopulatie];<br />
}<br />
void SelectieParinti(int &r1, int &r2)<br />
{<br />
/*selecteaza doi parinti din populatie folosind una din metodele<br />
descrise in capitolul II*/<br />
}<br />
void Afiseaza()<br />
{<br />
/*se va afisa CelMaiBunCromozom*/<br />
}<br />
Sa vedem cum implementam selectia. Metodele cele mai importante pe care le-am<br />
prezentat mai sus sunt:<br />
1. Selectia uniforma<br />
void SelectieParintiUniforma(int &r1, int &r2)<br />
{<br />
r1=1+random(MaxPopulatie);<br />
r2=1+random(MaxPopulatie);<br />
}<br />
2. Selectia folosind ruleta ponderata<br />
void SelectieParintiAranjata(int &r1, int &r2)<br />
{<br />
int s=0,r;<br />
for(i=1;i0)<br />
{<br />
r1++;<br />
r-=PopulatieVeche[r1].fitness;<br />
}<br />
/*pentru al doilea parinte*/<br />
r=1+random(s);<br />
r2=0;<br />
while (r>0)<br />
{<br />
r2++;<br />
13
-=PopulatieVeche[r2].fitness;<br />
}<br />
}<br />
3. Selectia aranjata<br />
void SelectieParintiAranjata(int &r1, int &r2)<br />
{<br />
int s,r;<br />
s=MaxPopulatie*(MaxPopulatie+1)/2;<br />
/*pentru primul parinte*/<br />
r=1+random(s);<br />
r1=0;<br />
while (r>0)<br />
{<br />
r1++;<br />
r-=r1;<br />
}<br />
/*pentru al doilea parinte*/<br />
r=1+random(s);<br />
r2=0;<br />
while (r>0)<br />
{<br />
r2++;<br />
r-=r2;<br />
}<br />
}<br />
14
Cap.IV Aplicatii<br />
1. Ecuatie diofanica<br />
Se citeste de la tastatura un numar natural nenul n si coeficientii naturali a1,a2,…,an si<br />
b ai ecuatiei diofanice a1x1+a2x2+…+anxn=b. Se cere sa se gaseasca o solutie naturala a<br />
ecuatiei date.<br />
Analiza problemei<br />
0) Datele de intrare<br />
n – int;<br />
a – vector de tip int;<br />
b – int.<br />
1) Codificarea cromozomilor<br />
Vom folosi codificarea sub forma de valoare. Fiecare cromozom va contine n biti,<br />
un bit oarecare i reprezentand valoarea lui xi.<br />
Codificarea tipului cromozom este urmatoarea:<br />
typedef struct{<br />
int gena[15];<br />
float fitness;<br />
}TCromozom;<br />
2) Populatia initiala<br />
Generarea populatiei initiale are o importanta foarte mare in cadrul acestui algoritm,<br />
de aceea alegerea multimii din care se vor genera aleator cromozomii populatiei initiale<br />
trebuie sa fie facuta cu atentie. In cadrul problemei de fata observam ca exista sanse mari<br />
ca o solutie x1,x2,…,xn sa fie formata din numere ce se afla in apropierea valorii<br />
b/(a1+a2+…+an). Pentru ca populatia initiala sa contina cromozomi formati din numere ce<br />
se afla in jurul acestei valori, solutiile vor fi generate aleator din multimea<br />
{0,1,…,[2*b/(a1+a2+…+an)]}. Secventa care codifica generarea populatiei initiale este:<br />
for(i=1;i
4) Selectarea cromozomilor parinti<br />
Cromozomii formati intr-o populatie se ordoneaza descrescator dupa fitness. Metoda<br />
de selectie folosita este cea prin selectie aranjata.<br />
5) Crossover-ul<br />
Incrucisarea se realizeaza intr-un singur punct, acesta fiind ales aleator.<br />
r=1+random(MaxGena-1);<br />
for(i=1;i
typedef struct{<br />
long int gena[22];<br />
float fitness;<br />
}TCromozom;<br />
typedef TCromozom TPopulatie[MaxPopulatie+1];<br />
TCromozom CelMaiBunCromozom;<br />
TPopulatie PopulatieVeche, PopulatieNoua;<br />
int i,j,k,contor,co,r1,r2;<br />
int NrPop, MaxGena;<br />
int InitVar=0;<br />
int a[50];<br />
long int b;<br />
void citire();<br />
void CalculFitness();<br />
void InitializeazaPopulatie();<br />
void Elitism(int NrMutati);<br />
void Crossover(TCromozom g1, TCromozom g2, TCromozom &rez1, TCromozom<br />
&rez2);<br />
void Mutatie(TCromozom &mutant);<br />
void MutaRestul(int NrMutati);<br />
void OrdoneazaDupaFitness();<br />
void SelectieParintiAranjata(int &r1, int &r2);<br />
void Afiseaza();<br />
void main()<br />
{<br />
int i,sw=1;<br />
citire();<br />
randomize();<br />
InitializeazaPopulatie();<br />
OrdoneazaDupaFitness();<br />
for(i=1;i
for(i=1;i
{<br />
r1=1+random(b/(10*InitVar));<br />
r2=random(2);<br />
if (r2) mutant.gena[i]+=r1;<br />
else mutant.gena[i]-=r1;<br />
}<br />
}<br />
void MutaRestul(int NrMutati)<br />
{<br />
int i;<br />
for(i=1;i
else<br />
cout
2) Populatia initiala<br />
Cromozomii fiind codificati binar, populatia initiala se va genera prin completarea<br />
aleatoare a bitilor cromozomilor initiali cu valorile 0 sau 1. Secventa de instructiuni care<br />
realizeaza acest lucru este urmatoarea:<br />
for(i=1;i
5) Crossover-ul<br />
Incrucisarea se realizeaza intr-un singur punct, acesta fiind ales aleator.<br />
r=1+random(MaxGena-1);<br />
for(i=1;i
void CalculFitness();<br />
void InitializeazaPopulatie();<br />
void Elitism(int NrMutati);<br />
void Crossover(TCromozom g1, TCromozom g2, TCromozom &rez1, TCromozom<br />
&rez2);<br />
void Mutatie(TCromozom &mutant);<br />
void MutaRestul(int NrMutati);<br />
void OrdoneazaDupaFitness();<br />
void SelectieParintiAranjata(int &r1, int &r2);<br />
void Afiseaza();<br />
void main()<br />
{<br />
int i;<br />
citire();<br />
randomize();<br />
InitializeazaPopulatie();<br />
OrdoneazaDupaFitness();<br />
for(i=1;i
for(i=1;i
int i;<br />
for(i=1;i
Exemplu<br />
Pentru urmatoarele date de intrare:<br />
Capacitate=22;<br />
NrObiecte=6;<br />
Obiect 1 2 3 4 4 6<br />
Utilitate 500 770 690 1000 480 630<br />
Greutate 5 7 6 8 4 6<br />
Programul va afisa:<br />
O umplere optima a rucsacului este formata din obiectele:2 3 4.<br />
Ele au greutatea 21 si utilitatea 2460.<br />
De remarcat faptul ca pentru aceleasi date de intrare un algoritm greedy care pune<br />
obiectele in rucsac in ordinea descrescatoare a raportului utilitate/greutate va afisa:<br />
O umplere optima a rucsacului este formata din obiectele:3 4 5.<br />
Ele au greutatea 18 si utilitatea 2170.<br />
3. Problema comis-voiajorului<br />
Un comis-voiajor are de vizitat un numar de n orase. Oricare doua orase sunt legate<br />
intre ele si costul deplasarii de la orasul i la orasul j este citit in elemetul ai,j al matricei<br />
Anxn. Comis-voiajorul pleaca din orasul 1 si trebuie sa treaca prin toate celelalte orase o<br />
singura data, intorcandu-se in final in orasul 1. Gasiti un drum care minimizeaza costul<br />
total al deplasarii.<br />
Analiza problemei<br />
0) Datele de intrare<br />
n – numarul de orase;<br />
a – matricea costurilor.<br />
1) Codificarea cromozomilor<br />
Un cromozom va fi reprezentat printr-o “permutare” de tipul<br />
1 (2) (3) … (n) 1.<br />
Codificarea tipului cromozom este urmatoarea:<br />
typedef struct{<br />
int gena[15];<br />
int fitness;<br />
}TCromozom;<br />
Orice cromozom va avea gena[1]=gena[MaxGena]=1.<br />
26
2) Populatia initiala<br />
Dificultatea in aceasta etapa consta in generarea unor “permutari” in mod aleator.<br />
Pentru aceasta ne vom folosi de o functie care genereaza prin backtracking o permutare.<br />
Functia are prototipul void GenereazaPermutare(int i, int j), unde i va reprezenta<br />
indicele cromozomului care este generat iar j este un parametru care sporeste caracterul<br />
aleatoriu al permutarii.<br />
Secventa care initializeaza populatia este:<br />
for(i=1;i1))<br />
{<br />
if (k==MaxGena)<br />
{<br />
CopieSolutie(i);<br />
j--;k--;<br />
}<br />
else if (st[k]
5) Crossover-ul<br />
O alta dificultate a acestei probleme este gasirea unui mod de incrucisare care<br />
pastreaza consistenta permutarii dupa transformare. Acest lucru poate fi realizat prin<br />
urmatoarea forma de incrucisare: cei doi cromozomi parinti ( si ) se inmultesc intre ei<br />
prin regula de inmultire dintre permutari, mai intai primul cu al doilea si apoi invers. Se<br />
vor obtine doi cromozomi copii x si x. Avand in vedere faptul ca inmultirea<br />
permutarilor este in general necomutativa, cei doi cromozomi rezultati vor fi diferiti.<br />
for(i=1;i
void Citire();<br />
void CalculFitness();<br />
void GenereazaPermutare(int i, int j);<br />
int Valid(int k);<br />
void CopieSolutie(int i);<br />
void InitializeazaPopulatie();<br />
void Elitism(int NrMutati);<br />
void Crossover(TCromozom g1, TCromozom g2, TCromozom &rez1, TCromozom<br />
&rez2);<br />
void Mutatie(TCromozom &mutant);<br />
void MutaRestul(int NrMutati);<br />
void OrdoneazaDupaFitness();<br />
void SelectieParintiAranjata(int &r1, int &r2);<br />
void Afiseaza();<br />
void main()<br />
{<br />
int i;<br />
Citire();<br />
randomize();<br />
InitializeazaPopulatie();<br />
OrdoneazaDupaFitness();<br />
for(i=1;i
}<br />
}<br />
void GenereazaPermutare(int i, int j)<br />
{<br />
int k=2;<br />
st[1]=1;<br />
st[2]=random(MaxGena-1);<br />
while(j&&(k>1))<br />
{<br />
if (k==MaxGena)<br />
{<br />
CopieSolutie(i);<br />
j--;k--;<br />
}<br />
else if (st[k]
int i;<br />
for(i=1;i
1=0;<br />
while (r>0)<br />
{<br />
r1++;<br />
r-=r1;<br />
}<br />
r=1+random(s);<br />
r2=0;<br />
while (r>0)<br />
{<br />
r2++;<br />
r-=r2;<br />
}<br />
}<br />
void Afiseaza()<br />
{<br />
int i;<br />
cout
4. Maximul unei functii n-dimensionale<br />
Considerandu-se o functie in n nedeterminate definita pe un produs cartezian<br />
[a,b]x[a,b]x..x[a,b] de n intervale identice se cere sa se afle maximul ei si un set de valori<br />
din domeniul de definitie pentru care acest maxim este atins.<br />
Analiza problemei<br />
0) Datele de intrare<br />
Dat fiind gradul ridicat de dificultate pe care il necesita citirea expresiei functiei de la<br />
tastatura, aceasta va fi scrisa intr-o functie care va returna valoarea ei intr-un set de<br />
puncte (x1,x2,…,xn).<br />
Singurele date care se citesc de la tastatura sunt capetele intervalului [a,b].<br />
1) Codificarea cromozomilor<br />
Dificultatea acestei probleme consta in faptul ca punctele (x1,x2,…,xn) iau valori<br />
reale, si deci trebuie sa gasim o modalitate eficienta de codificare a cromozomilor. Daca<br />
vom incerca sa codificam o gena a unui cromozom printr-un numar real (un cromozom<br />
va contine n gene), vom observa ca prin transformarile cunoscute (crossover, mutatie) nu<br />
se obtine un numar multumitor de combinatii, spatiul solutiilor fiind foarte slab acoperit.<br />
Codificarea binara ridica iarasi probleme la transformarea unui numar real in baza 2 si<br />
reciproc. Cea mai buna solutie in acest caz o reprezinta o imbinare a celor doua metode.<br />
O gena va consta dintr-un vector de lungime NrBiti format din cifrele 0 si 1. Astfel o<br />
gena va putea codifica (2^NrBiti)-1 numere naturale prin transformarea numarului format<br />
din elementele binare ale vectorului intr-un numar din baza 10. Decodificarea unei gene<br />
va fi realizata in modul urmator: intervalul [a,b] este impartit in (2^NrBiti)-1 diviziuni. O<br />
gena i ce contine un numar y in baza 2 va fi transformata in numarul xi astfel: y <br />
xi=a+(b-a)*[y]10/[(2^NrBiti)-1], unde [y]10 reprezinta numarul y in baza 10.<br />
2) Populatia initiala<br />
Va fi creata prin generarea aleatoare de valori binare pentru fiecare vector al fiecarei<br />
gene al fiecarui cromozom al populatiei initiale.<br />
3) Fitness<br />
Fitness-ul unui cromozom va reprezenta valoarea functiei in punctele (x1,x2,…,xn)<br />
codificate de acesta. Petru a-l calcula vom avea nevoie de o functie float transf(int<br />
i, int j) care realizeaza decodificarea genei j a cromozomului i.<br />
4) Selectarea cromozomilor parinti<br />
Cromozomii formati intr-o populatie se ordoneaza crescator dupa fitness. Metoda de<br />
selectie folosita este cea prin selectie aranjata.<br />
5) Crossover-ul<br />
Incrucisarea se realizeaza intr-un singur punct, acesta fiind ales aleator.<br />
33
6) Mutatia<br />
Mutatia are o probabilitate de 1% si se realizeaza prin inversarea valorilor bitilor<br />
tuturor genelor unui cromozom ales in mod aleator.<br />
7) Cel mai bun cromozom<br />
Se initializeaza in functia InitializeazaPopulatie() si intr-o generatie se calculeaza in<br />
functia OrdoneazaDupaFitness().<br />
In continuare vom da codul sursa complet al problemei care afla maximul unei functii<br />
in 6 nedeterminate, expresia ei aflandu-se in functia float Functia(float<br />
Nedet[MaxGena+1]).<br />
#include<br />
#include<br />
#include<br />
#include<br />
const MaxPopulatie=100,<br />
MaxIteratii=200,<br />
MaxElitism=3,<br />
MaxCrossover=30,<br />
MaxMutatie=1,<br />
MaxGena=6,<br />
NrBiti=15;<br />
typedef struct{<br />
int gena[MaxGena+1][NrBiti+1];<br />
float fitness;<br />
}TCromozom;<br />
typedef TCromozom TPopulatie[MaxPopulatie+1];<br />
TCromozom CelMaiBunCromozom;<br />
TPopulatie PopulatieVeche, PopulatieNoua;<br />
int i,j,k,contor,co,r1,r2;<br />
float LungDiv=0;<br />
int NrPop,a,b;<br />
void Citire();<br />
float Functia(float Nedet[MaxGena+2]);<br />
float Transf(TCromozom g,int j);<br />
void CalculFitness();<br />
void InitializeazaPopulatie();<br />
void Elitism(int NrMutati);<br />
void Crossover(TCromozom g1, TCromozom g2, TCromozom &rez1, TCromozom<br />
&rez2);<br />
void Mutatie(TCromozom &mutant);<br />
void MutaRestul(int NrMutati);<br />
void OrdoneazaDupaFitness();<br />
void SelectieParintiAranjata(int &r1, int &r2);<br />
void Afiseaza();<br />
void main()<br />
{<br />
int i,j;<br />
Citire();<br />
randomize();<br />
InitializeazaPopulatie();<br />
CelMaiBunCromozom.fitness=0;<br />
OrdoneazaDupaFitness();<br />
for(i=1;i
{<br />
NrPop=0;<br />
Elitism(MaxElitism);<br />
for(co=1;co
eturn x;<br />
}<br />
void CalculFitness()<br />
{<br />
int i,j,co;<br />
float Nedet[MaxGena+2];<br />
for(i=1;i
PopulatieNoua[++NrPop]=PopulatieVeche[1+random(MaxPopulatie-<br />
MaxElitism)];<br />
}<br />
void OrdoneazaDupaFitness()<br />
{<br />
int i,sw=1;<br />
TCromozom aux;<br />
while (sw)<br />
{<br />
sw=0;<br />
for(i=1;iPopulatieVeche[i+1].fitness)<br />
{<br />
aux=PopulatieVeche[i];<br />
PopulatieVeche[i]=PopulatieVeche[i+1];<br />
PopulatieVeche[i+1]=aux;<br />
sw=1;<br />
}<br />
}<br />
if (PopulatieVeche[MaxPopulatie].fitness>CelMaiBunCromozom.fitness)<br />
CelMaiBunCromozom=PopulatieVeche[MaxPopulatie];<br />
}<br />
void SelectieParintiAranjata(int &r1, int &r2)<br />
{<br />
int s,r;<br />
s=MaxPopulatie*(MaxPopulatie+1)/2;<br />
r=1+random(s);<br />
r1=0;<br />
while (r>0)<br />
{<br />
r1++;<br />
r-=r1;<br />
}<br />
r=1+random(s);<br />
r2=0;<br />
while (r>0)<br />
{<br />
r2++;<br />
r-=r2;<br />
}<br />
}<br />
void Afiseaza()<br />
{<br />
int i;<br />
cout
Exemplu<br />
Pentru a=1, b=2 programul va afisa la trei apeluri succesive:<br />
Apel X1 X2 X3 X4 X5 X6 f<br />
1) 1.125034 1.233894 1.375286 1.456343 1.562487 1.681814 0.999044<br />
2) 1.125248 1.251106 1.341746 1.477798 1.578448 1.753929 0.993365<br />
3) 1.122288 1.234077 1.376080 1.501999 1.499985 1.624378 0.989659<br />
38
Cap.V Consideratii finale<br />
Urmarind exemplele de aplicatii care s-au dat in capitolul anterior putem da niste<br />
caracteristici generale ale problemelor pe care le poate rezolva un algoritm genetic. Este<br />
recomandat astfel ca problemele date sa aiba un volum mare de date de prelucrat.<br />
Din punctul de vedere al spatiului solutiilor, problemele se impart in 2 categorii:<br />
1. Probleme cu spatiul solutiilor finit.<br />
Aici sunt incluse problema discreta a rucsacului si cea a comis-voiajorului. In general,<br />
orice problema care se poate rezolva prin backtracking are si o rezolvare prin algoritmi<br />
genetici. Cele doua probleme mentionate mai sus, impreuna cu altele de acest gen, fac<br />
parte din categoria problemelor NP-complete, adica a acelor probleme pentru care nu<br />
exista la ora actuala algoritmi polinomiali deterministi de rezolvare a lor. Algoritmii<br />
genetici reprezinta o alternativa viabila celor deterministi exponentiali care rezolva aceste<br />
probleme, pentru ca, spre exemplu, in cazul problemei comis voiajorului, testarea tuturor<br />
drumurilor posibile care leaga n orase ar presupune n! operatii matematice. Un tur ce<br />
cuprinde 30 de orase ar presupune aproximativ 2.65X10 32 operatii. Presupunand ca un<br />
procesor ar realiza un miliard de operatii pe secunda, timpul de rezolvare a problemei ar<br />
fi in jur de 8,000,000,000,000,000 de ani! Adaugarea unui singur oras creste numarul de<br />
operatii de 31 de ori.<br />
2. Probleme cu spatiul solutiilor infinit.<br />
In aceasta categorie se include problema maximului unei functii n-dimensionale. De<br />
remarcat ca in cazul maximului unei functii unidimensionale exista metode clasice de<br />
rezolvare (metoda coardei, cea a tangentei), dar care se pot aplica numai functiilor care<br />
indeplinesc anumite conditii (continuitate, derivabilitate). Aceste metode insa se limiteaza<br />
la functii intr-o singura nedeterminata.<br />
Desi problema rezolvarii unei ecuatii diofanice ar putea fi inclusa foarte bine in prima<br />
categorie, am preferat sa o mentionez aici, deoarece ea reprezina prin caracterul ei o<br />
probema aflata la granita dintre cele doua tipuri de probleme.<br />
Optimizari<br />
Pentru o mai buna intelegere a algoritmilor genetici, s-a incercat in lucrarea de fata o<br />
prezentare cat mai fixa a lor, variatiile de la o aplicatie la alta limitandu-se la strictul<br />
necesar.<br />
In realitate insa, se poate spune fara exagerare ca numarul lor este egal cu cel al<br />
problemelor care implementeaza un algoritm genetic. Cauzele diversitatii lor sunt<br />
urmatoarele:<br />
Proiectarea unui algoritm genetic incepe cu alegerea caracteristicilor individului. Deci<br />
doua probleme de optimizare conduc la doua programe diferite;<br />
Deciziile pe care le ia proiectantul de programe la implementarea unui algoritm<br />
genetic sunt in mare masura echivalente intre ele, situatie în care intervine stilul<br />
programatorului;<br />
Rezultatul rularii unui algoritm genetic depinde de alegerea parametrilor de control ai<br />
algoritmului genetic, deci depinde de optiunile experimentatorului.<br />
39
In continuare vom da cateva optimizari care se pot face algoritmilor prezentati mai<br />
sus.<br />
In primul rand, prin numarul parametrilor de control si prin operatiile aleatoare care se<br />
fac in cadrul programului (generarea populatiei initiale, alegerea punctului de incrucisare,<br />
mutatia, alegerea supravietuitorilor), acesti algoritmi au un caracter “semialeator”. De<br />
aceea pentru o problema data se recomanda schimbarea valorilor parametrilor de control<br />
si observarea diferentelor dintre solutiile afisate. Principalii parametri care pot fi<br />
schimbati (se pot considera chiar date de intrare) sunt urmatorii:<br />
- numarul cromozomilor unei populatii;<br />
- numarul de generatii create;<br />
- numarul de cromozomi copiati prin elitism;<br />
- numarul de incrucisari pe populatie;<br />
- numarul de mutatii pe populatie.<br />
Pentru ca majoritatea lucrarilor din literatura de specialitate recomanda rularea de mai<br />
multe ori a unui algoritm genetic si apoi notarea celei mai bune solutii gasite, sugerez<br />
introducerea unui alt parametru fata de cei prezentati mai sus. Acesta va ajuta la<br />
simularea rularii multiple a programului. In programul dat mai jos parametrul este<br />
denumit MaxReIteratii.<br />
void main()<br />
{<br />
int i,j;<br />
Citire();<br />
/*aici se va initializa CelMaiBunCromozom*/<br />
for(j=1;j
In sfarsit, un al treilea tip de optimizare care se poate face este cel legat de conditia de<br />
oprire a algoritmului. Este posibil ca in cadrul unor probleme solutia sa evolueze rapid in<br />
primele generatii si apoi evolutia ei sa fie nesemnificativa. De aceea, in cadrul acestui tip<br />
de probleme, se recomanda monitorizarea evolutiei solutiei pe parcursul rularii<br />
algoritmului si terminarea lui in momentul in care aceasta devine lenta.<br />
In finalul acestui capitol vom introduce doua notiuni care permit compararea<br />
performantelor a doi algoritmi genetici.<br />
Timpul de stabilizare a populaţiei şi viteza de convergenţă<br />
Pentru a compara performanţele a doi algoritmi genetici care rezolva aceeaşi problema,<br />
sau pentru a evalua influenta parametrilor de control asupra unui algoritm genetic, se folosesc<br />
cativa indicatori de performanta cum sunt: timpul de stabilizare a populatiei, viteza<br />
de convergenta, etc..<br />
Timpul de stabilizare a populatiei este timpul necesar aglomerarii indivizilor în<br />
vecinatatea punctului optim.<br />
Viteza de convergenta a algoritmului genetic este cresterea valorii medii a fitnessului<br />
f fP<br />
(t) fP<br />
(t 1)<br />
la trecerea de la o generatie la alta.<br />
In figura de mai jos s-a reprezentat grafic evolutia in timp a trei functii: (t), valoarea<br />
curenta a maximului fitness-ului, f P<br />
(t), valoarea curenta a mediei fitness-ului si<br />
f (t) viteza de convergenta.<br />
Pe figura se observa ca din generatia a 20-a valoarea medie a fitness-ului, f P<br />
(t), nu<br />
sufera variatii importante. Viteza de convergenta a algoritmului genetic este panta valorii<br />
medii a fitness-ului, f P<br />
(t)<br />
. Se observa ca pana in generatia a 15-a viteza de convergenta<br />
este semnificativa, iar dupa aceea viteza de convergenta scade si ramane oscilanta in jurul<br />
valorii f 0 .<br />
f opt<br />
41
Evolutia in timp a functiilor f opt<br />
(t), f P<br />
(t)<br />
si f (t)<br />
.<br />
In principiu, urmarirea evolutiei in timp a valorii curente a maximului fitness-ului nu<br />
este un indicator de calitate decat daca algoritmul genetic rezolva o problema test<br />
cunoscuta. Timpul de stabilizare a populatiei si viteza de convergenta a algoritmului<br />
genetic sunt doua criterii in functie de care experimentatorul poate aprecia tendintele care<br />
se manifesta in evolutia populatiei.<br />
42
BIBLIOGRAFIE<br />
Oltean, M. – Proiectarea si implementarea algoritmilor, <strong>Editura</strong> Computer Libris<br />
Agora, Cluj, 1999;<br />
Aspru, O. – Tehnici de programare, <strong>Editura</strong> Adias, Rm. Valcea, 1997;<br />
Andonie, R., Garbacea, I. – Algoritmi fundamentali, o perspectiva C++, <strong>Editura</strong><br />
Libris, Cluj, 1995;<br />
Johnson, G. – Computers and Itractability; A Guide to the Theory of NP-<br />
Completeness, W. H. Freeman & co., 1979;<br />
Colectia Gazetei de informatica;<br />
43
CUPRINS<br />
Capitolul I. Consideraţii generale…………………………… 1<br />
1. Introducere………………………….…………………...<br />
2. Notiuni de genetica…….……………………………..…<br />
3. Algoritmul general (schema logica si pseudocod)……...<br />
Capitolul II. Codificarea informatiei………………………… 5<br />
1. Codificarea cromozomilor……………………………...<br />
2. Populatia initiala……………………………………….<br />
3. Fitness-ul unui cromozom………………………………<br />
4. Selectarea cromozomilor parinti………………………...<br />
5. Incrucisarea (crossover)…………………………………<br />
6. Mutatia…………………………………………………..<br />
7. Cand se termina algoritmul…………………………….<br />
Capitolul III. Implementarea algoritmului…………………… 10<br />
Capitolul IV. Aplicatii………………………………………….. 15<br />
1. Ecuatia diofanica……………………………………...<br />
2. Problema discreta a rucsacului………………………..<br />
3. Problema comis-voiajorului..…………………………<br />
4. Maximul unei functii n-dimensionale………………...<br />
Capitolul V. Consideratii finale……………………………….. 39<br />
Bibliografie…………………………………………………………. 43<br />
1<br />
1<br />
2<br />
5<br />
6<br />
6<br />
6<br />
7<br />
9<br />
9<br />
15<br />
20<br />
26<br />
33<br />
44