30.01.2015 Views

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

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!