Vous êtes sur la page 1sur 4

SIMULAREA UNUI ALGORITM GENETIC ELEMENTAR FOLOSIND PERL (algoritm bazat pe modelul propus de Prof. dr. Juan J.

Merelo Guervs, Univ. Granada, Spania)


use strict; my my my my my my $generatii = shift || 1000; $dimensiunePopulatie = 100; $solutiaOptima = 'valoareoptima'; $lungimeSir = length( $solutiaOptima ); @alfabet = ('a'..'z'); @populatie;

Comment [BIOFIZ1]: Scopul programului este s identifice cu ajutorul operatorilor genetici un numr de generaii necesare evoluiei unei populaii, iniializate aleatoriu, s ating soluia optim reprezentat chiar prin irul respectiv. Comment [BIOFIZ2]: Utilizarea modulului strict impune eliminarea utilizrii variabilelor globale i folosirea exclusiv a variabilelor cu caracter local sau privat. Variabilele i subrutinele nu pot fi utilizate nainte de a fi declarate. Acest aspect impune urmtoarea regul de existen a variabilelor. Programul principal nu poate opera dect numai cu variabilele private declarate n blocul principal, nici o variabil privat declarat n subrutine nu poate fi accesibil din programul principal. Subrutinele vor putea opera cu variabilele declarate att n blocul principal ct i n cadrul subrutinei. O sub-sub-rutin poate folosi variabilele din blocul principal, variabilele din subrutina n care a fost construit ct i propriile variabile. Deci, vizibilitatea variabilelor se face ntotdeauna de jos n sus. Altfel spus blocul principal nu poate vedea dect propriile lui variabile, o subrutin ns, fiind mai jos, le vede att pe ale ei ct i pe cele ale blocului principal .a.m.d. Comment [BIOFIZ3]: Dac nu se specific un anumit numr de generaii la lansarea programului (parametru care iniializeaz tabloul @ARGV i este ulterior preluat prin shift) atunci se utilizeaz 1000 de generaii. Comment [BIOFIZ4]: Dimensiunea populaiei este fixat prin program la 100 de componente. Se poate extinde aici programul dup preferin cu posibilitatea de a introduce utilizatorul o valoare la cerere. Comment [BIOFIZ5]: Variabila care deine soluia optim spre care algoritmul genetic trebuie s se ndrepte parcurgnd un numr variabil de generaii. i aceasta poate fi la nevoie introdus de ctre utilizator la cerere. Ea este ns restricionat de utilizarea unui alfabet limitat doar la caracterele minuscule de la a la z, vezi variabila @alfabet. Comment [BIOFIZ6]: Conine elementele populaiei la un moment dat. Ea este iniializat n mod aleatoriu cu ajutorul unei subrutine dedicate. Comment [BIOFIZ7]: Subrutina performan evalueaz i selecteaz cele mai bune rezultate care se apropie de $solutiaOptima. Detalii pentru funciile abs, ord, substr, vezi link-uri utile (documentaia Perl). Funcia ord are rolul de a extrage codul numeric corespunztor caracterului din ir, fiecare caracter de la tastatur are un cod numeric asignat printr-un standard. Funcia substr extrage un subir dintr-un ir de caractere existent ntr-o variabil, se comport oarecum similar cu splice asupra coninutului tablourilor.

sub performanta { my $sir = shift; my $distanta = 0; my $i; for ($i = 0; $i < ($lungimeSir -1); $i++) { $distanta += abs( ord( substr( $sir, $i, 1)) - ord( substr( $solutiaOptima, $i, 1))); } return $distanta; } sub afisarePopulatie { foreach (@populatie) { # print "$_\n"; print "$_->{_str} : $_->{_performanta} \n"; } } sub mutatie { my $cromozom = shift; my $mutatiePunctiforma = rand( length( $cromozom->{_str})); my $caracter_rand = $alfabet[( rand( @alfabet))]; substr( $cromozom->{_secventa}, $mutatiePunctiforma, 1, $caracter_rand); } sub initializarePopulatie { for ( 1..$dimensiunePopulatie ) { my $cromozom = { _sir => '', _valoare => 0 }; for ( 1..$lungimeSir ) { $cromozom->{_str} .= $alfabet[( rand( @alfabet))]; } $cromozom->{_performanta} = performanta( $cromozom->{_str} ); push @populatie, $cromozom; } } initializarePopulatie(); afisarePopulatie(); @populatie = sort { $a->{_performanta} <=> $b->{_performanta} } @populatie; for ( 1..$generatii ) { my $cromozom = $populatie[ rand( @populatie)]; my $clone ={}; do { $clone = { _str => $cromozom->{_str}, _performanta => 0 }; mutatie( $clone ); $clone->{_performanta} = performanta( $clone->{_str} );

} until ( $clone->{_performanta} >

$cromozom->{_performanta});

$populatie[$#populatie] = $clone; @populatie = sort { $a->{_performanta} <=> $b->{_performanta} } @populatie; print "Cel mai performant: $populatie[0]->{_str} ==> $populatie[0]>{_performanta} \n"; last if $populatie[0]->{_performanta} == 0; }

FUNCIONALITATEA PROGRAMULUI Blocul principal al programului pornete de la apelarea subrutinei initializarePopulatie. Aceasta conine dou structuri for condiionate de $dimensiunePopulatie (o variabil scalar fix, valoarea ei fiind 100) i de $lungimeSir (variabil scalar a crei dimensiune este obinut n funcie de ct de lung este irul valoareoptima spre care trebuie s evolueze sistemul). Variabila local (privat) my $cromozom este o referin la un hash fr nume (anonim). Referina presupune o legtur la un array, hash, sau la o subrutin prin asocierea unei variabile scalare (cazul de fa $cromozom) cu un obiect (zona de memorie unde este stocat instana) de tipul datei (array sau hash). n cazul de fa este creat un hash cu dou componente care se iniializeaz cu tipul de dat corespunztor. Cu alte cuvinte, se creeaz un hash anonim cu structur determinat (prima component fiind un ir de caractere, acesta nefiind iniializat (pentru nceput este un ir gol ) i al doilea tip de dat, o valoare numeric care momentan e zero, ambele componente fiind identificare cu _ naintea numelui). Vezi fiierul references.pdf pentru detalii. Ex. dac $dimensiunePopulatie ar fi 2 atunci s-ar executa un ciclu for cu dou iteraii. n prima iteraie s-ar iniializa dou locaii de memorie _sir i _valoare de tipurile indicate care aparin unui hash ca structur de date. Accesul la aceste locaii de memorie se face ns, prin intermediul variabilei $cromozom. Urmtorul for are attea iteraii ct de mare este $lungimeSir. Dac reducem irul atribuit variabilei $solutieOptima la actg atunci $lungimeSir se iniializeaz prin aplicarea funciei length cu valoarea 4, deci acest ciclu for se va executa de 4 ori. n timpul execuiei are loc urmtorul algoritm. $cromozom -> ,_str- reprezint accesarea locaiei de memorie (construit anterior prin referin), locaie ce conine irul care va forma un cromozom al populaiei. @populatie fiind o variabil array este format din mai muli cromozomi. La aceast locaie desemnat $cromozom -> ,_str- se va concatena (.=) cte un caracter obinut n mod aleatoriu din expresia din partea dreapt. Funcia rand aplicat pe array-ul alfabet va extrage la ntmplare un index (de ex. 2), situaie n care apelarea prin scalar $alfabet*2+ nseamn a doua liter din alfabetul impus (ex. b). Litera b se concateneaz n locaia de memorie care este referit prin asociaia dintre numele $cromozom i hash-ul cu structura indicat. La fiecare iteraie se mai adaug cte o liter din alfabet. Cnd se termin for-ul se ncheie sinteza cromozomului din componentele impuse de alfabet. Dup acest for imbricat se continu instruciunile din for-ul anterior unde locaia de memorie stabilit pentru valoare $cromozom->,_performanta- este ncrcat cu un rezultat numeric prin evaluarea performanei combinaiei obinute. Acest lucru se realizeaz prin apelarea subrutinei performanta cu parametrul identificat cu ultima valoare existent n locaia memoriei referit de $cromozom->,_str-, adic cu irul obinut prin concatenarea randomizat. Deci, se transfer ctre subrutina respectiv coninutul existent la locaia de memorie referit. Deoarece aceast referin este apelat prin intermediul unui scalar, $cromozom, nseamn c n cadrul subrutinei se iniializeaz array-ul @_ cu un singur component, astfel nct variabila local my $sir preia prin funcia shift valoarea irului din @_. Scopul subrutinei performanta este s stabileasc, printr-o expresie simpl, distana fa de soluia ideal de evoluie, cu alte cuvinte, ct de departe este rezultatul obinut fa de

valoarea ideal. n variabila $distanta se adun diferenele n valoare absolut dintre codurile ASCII (vezi link-uri utile) ale caracterelor ntlnite n irul din cromozom i n irul ideal spre care se tinde. Este evident c dac se atinge valoarea zero, evoluia se ncheie deoarece irul cromozomului comparat este identic cu valoarea optim. Dup execuia performanei se returneaz valoarea obinut prin diferen ca rezultat reprezentativ al acesteia, iar subrutina initializarePopulatie care nc nu s-a ncheiat, adaug n array-ul populaie o component de tip cromozom cu ajutorul funciei push. Mare atenie la acest aspect. ntruct n spatele $cromozom se afl un hash anonim, compus, la rndul lui, din dou componente (irul de caractere care compune un cromozom i valoarea numeric a performanei acestuia) nseamn c array-ul respectiv se va completa cu un numr de cromozomi, fiecare cromozom fiind de fapt o component bidimensional, deci se obine un array bidimensional conform schemei de mai jos.
Index [0] Cromozom_1 ir_1 Perfroman_1 Index [1] Cromozom_2 ir_2 Perfroman_2 Index [2] Cromozom_3 ir_3 Perfroman_3 Index [3] Cromozom_4 ir_4 Perfroman_4 Index [n] Cromozom_n ir_n Perfroman_n

Odat populaia iniializat, aceasta urmeaz a fi afiat pentru a putea vizualiza ce fel de componente are i ce performan are fiecare component. Scopul algoritmului este de a-l selecta pe cel cu valoarea cea mai mic. Afiarea componentelor populaiei se realizeaz prin parcurgerea @populatie cu ajutorul funciei foreach care ia fiecare cromozom din populaie i afieaz prin intermediul print irul din care e compus cromozomul i performana acestuia, accesnd locaiile de memorie stabilite prin referinele create anterior. Variabila intern $_ este exploatat similar ca i array-ul _, numai c n situaia de fa, n care este utilizat ca referin ctre o locaie de memorie, ea va determina print-area coninutului acelei locaii, n primul caz irul, n al doilea caz valoarea performanei corespunztoare ir-ului. Dac eliminai simbolul # care comenteaz instruciunea print "$_\n"; vei observa afiat valoarea adresei de memorie la care se face referire. Dup generarea aleatoare i afiarea rezultatelor, populaia astfel obinut este sortat (vezi funcia sort), deci n urma aplicrii funciei sort pe componentele @populatie, aceasta va conine aceleai componente doar c ordinea lor este ascendent n funcie de valoarea performanei. n final, programul introduce i un operator de mutaie n populaie. Dac nu ar exista aa ceva populaia nu ar mai putea evolua i s-ar opri la soluiile aleatoare produse la iniializare. Mutaia se efectueaz pe numr de generaii, deci este condiionat de un ciclu for a crui numr de iteraii este limitat de valoarea introdus la $generatii. n cadrul acestui mecanism se extrage aleatoriu un cromozom din @populatie i se iniializeaz o variabil local $clone care va prelua coninutul cromozomului transfernd-ul subrutinei mutatie. $clone ca parametru al subrutinei este tot un pointer pentru c prin intermediul lui se transfer ctre variabila local $cromozom prin aplicarea lui shift pe array-ul @_ cele dou componente ale cromozomului din populaie, irul i performana. Variabila $mutatiePunctiforma se iniializeaz cu o valoare aleatoare ntre 0 i lungimea irului de caractere al cromozomului. Aceast valoare numeric aleatorie este folosit ulterior pentru a modifica un singur caracter prin apelarea substr pe irul de caractere de la locaia point-at de $cromozom->,_str-. Acest ir va fi alterat cu un caracter ales aleatoriu din @alfabet folosind expresia $alfabet[( rand( @alfabet))]. Din acest punct de vedere mutaia este aleatorie folosind strict materialul disponibil n @alfabet. ntruct subrutina se bazeaz pe pointeri nu mai este necesar utilizarea instruciunii return. Coninutul locaiilor de memorie odat alterat este disponibil n continuare doar n aceast variant modificat. Din acest punct de vedere utilizarea pointer-ilor simplific modul de exploatare a datelor i a resurselor ntr-un program, elimin nevoia de a utiliza foarte multe variabile pentru transferul datelor ntre subrutine. Mecanismul de mutaie este repetat n cadrul unei iteraii do until, aceasta fiind asemntoare cu while numai c este cu post-condiie. Evaluarea condiiei

Comment [BIOFIZ8]: n programare, aceast tehnic este cunoscut sub denumirea generic de exploatarea memoriei prin intermediul pointer-ilor. Deoarece adresele hexazecimale ale memoriei alocate de program pentru stocarea datelor sunt dificil de utilizat, tehnica pointer este folosit ca o soluie elegant pentru accesul direct la coninutul locaiilor de memorie fr ca programatorul s fie nevoit s in evidena acestora. Printr-o simpl asociere cu o variabil scalar se creeaz un pointer realizndu-se o legtur ntre adresa de memorie i coninutul acesteia.

se face dup ce se trece obligatoriu mcar o dat prin ciclu. Ca i condiie de oprire este luat chiar valoarea performanei, practic mutaia nu face altceva dect s modifice aceast valoare. $populatie*$#populatie+ = $clone; ntruct populaia a fost deja sortat ascendent, ultimul cromozom (cel mai ndeprtat de soluia ideal) este nlocuit cu cel obinut prin mutaie. Se resorteaz populaia ascendent i se afieaz primul cromozom care este i cel mai performant. Programul se ncheie forat (last) atunci cnd performan este zero, adic s-a atins valoarea ideal.

TEM a. S se adapteze programul astfel nct utilizatorul s poat controla prin introducerea unor valori de la tastatur pentru $generatii, $dimensiunePopulatie, $solutiaOptima i @alfabet. b. ntruct algoritmul indicat este departe de un model real n ceea ce privete evoluia populaiei, s se mbunteasc programul prin introducerea unei subrutine care s simuleze recombinarea prin crossing over.

LINK-URI UTILE http://perldoc.perl.org/ http://www.perl.org/ http://www.sdsc.edu/~moreland/courses/IntroPerl/docs/manual/pod/perlop.html http://www.comptechdoc.org/independent/web/cgi/perlmanual/index.html http://ro.wikipedia.org/wiki/ASCII


Comment [BIOFIZ9]: Documentaia oficial pentru Perl. n stnga, n csua Reference sunt reunite principalele capitole care descriu cu exemple detaliate toate funciile (n ordine alfabetic), instruciunile i operatorii limbajului. Comment [BIOFIZ10]: Descriere amnunit a operatorilor folosii n Perl. Comment [BIOFIZ11]: Tutorial Perl cu descrieri concise i exemple simple.

Vous aimerez peut-être aussi