Sunteți pe pagina 1din 18

8.

Algoritmi genetici
[11, 27, 33, 54] Pentru a nelege algoritmii genetici, n primul rnd trebuie s nelegem i s cuantificm modelul evoluiei naturale (darwiniste). Modelul evolutiv presupune existena unui habitat (a unui spaiu de evoluie) guvernat de legi locale (condiiile de mediu) n care speciile (populaiile reprezentate de indivizi) se supun urmtorului mecanism: 1. Pe baza seleciei, un numr restrns de indivizi din populaia iniial vor constitui populaia intermediar de prini (algoritmul de selecie trebuie s respecte paradigma conform creia un individ mai bine adaptat s aibe anse mai mari de supravieuire). 2. Dintre indivizii selectai ca i prini, pe baza operatorilor genetici (mutaie, ncruciare, ...), se va reconstitui o nou populaie.

Pentru a creea din modelul evolutiv un algoritm genetic (J. Holland, 1970), vom nlocui n primul rnd spaiul de evoluie (habitatul) cu problema dat, indivizii din populaie cu posibile soluii la problema n cauz i urmrind mecanismul evolutiv, ne vom atepta ca dup un timp s gsim cele mai bune (optime) soluii. Acest capitol va prezenta pe larg teoria din spatele algoritmilor genetici, precum i dou probleme rezolvate cu ajutorul acestora.

CUPRINS
8.1. Descrierea algoritmilor genetici .............................................................. 3 8.2. Problema gsirii unei expresii ............................................................... 10 8.3. Rezolvarea sistemelor de ecuaii .......................................................... 15

1.1. Descrierea algoritmilor genetici


a) Cutarea n spaiul soluiilor
n acest paragraf vom aprofunda modul de construcie a unui algoritm genetic, setrile i variantele acestuia, modulele folosite n rezolvarea de probleme i cteva elemente conexe ncadrate de regul n conceptele de inteligen artificial. Pentru a putea rezolva o problem prin algoritmi genetici este necesar transformarea acesteia ntr-o problem de cutare sau optimizare a soluilor. Ca o analogie cu modelul evoluionist, vom numi n continuare soluiile cromozomi, iar spaiul tuturor soluiilor l vom nota cu Crom. n primul rnd avem nevoie de o funcie sau un criteriu de selecie, care va arta ct de adaptat este un cromozom soluie, sau dac cromozomul curent este chiar o soluie acceptabil, asociind acestora, de regul, o valoare real. Aceast funcie se numete funcie de adecvare (en. fitness function) i o vom nota cu fadec i avem:

n conceptul algoritmilor genetici trebuie acceptat c orice element din spaiul soluiilor este o posibil soluie, doar c funcia de adecvare stabilete dac aceast soluie este acceptabil sau nu. S lum de exemplu ecuaia (cu caracter demonstrativ): . Spaiul soluiilor este R i x = 17 este o soluie, ns, evident, nu este cea mai bun, dar este mai bun dect x = 46, de exemplu. Continund cutarea n spatiul soluiilor vom gsi la un moment dat x = 2, aceast soluie fiind cea mai bun. n general, vom accepta o eroare ( ), iar

va fi una din condiiile de oprire a algoritmului. Graficul din figura 8.1.1. a fost obinut reprezentnd valoarea funciei de adecvare pentru fiecare cromozom n parte pentru o problem oarecare P. Funcia de adecvare este n aa fel construit nct:

Fig. 8.1.1. Cutarea n spaiul soluiilor nseamn c c1 este soluia cea mai bun (optimul global), iar pentru , x1 este soluie mai bun (mai acceptabil) dect x2. n acest caz spunem c minimizm funcia obiectiv. Exist dou concepte fundamentale de cutare n spaiul soluiilor: 1. explorarea spaiului soluiilor: cutarea complet aleatorie n spaiul soluiilor atta timp ct nu se gsete o valoare acceptabil (n cazul nostru, atta timp lum cte o valoare aleatorie pe axa reprezentat de spaiul soluiilor, pn cnd aceasta este n unul din intervalele de soluii acceptabile). 2. exploatarea unor poteniale soluii: reprezentat n general de metodele de coborre (gradient, Newton) care vor minimiza succesiv graficul funciei de adecvare. Exploatarea unor poteniale soluii se refer la condiiile iniiale asociate metodei de coborre. n exemplul nostru, o metod de coborre pornit din punctul A va ajunge la optimul local, dar pentru datele de intrare stabilite n punctul B nu va gsi nicio soluie (Fig. 8.1.2.) Pentru a avea posibilitatea ajungerii la o soluie global, este necesar stabilirea unui punct de pornire a unei metode de coborre n intervalul I.

Fig. 8.1.2. Acest mod se poate realiza cel mai eficient prin procesarea mai multor posibile soluii simultan, cu diferite puncte de plecare aleatoare. Conceptul asociat cu mbinarea celor dou metode de cutare n spaiul soluiilor se numete echilibrul explorare exploatare i tratarea celor dou concepte simultan reprezint principalul avantaj al algoritmilor genetici relativ la celelalte metode de optimizare.

b) Algoritmul genetic fundamental


n primul rnd, pentru a construi un model general al unui algoritm genetic, trebuie s lum n calcul timpul de evoluie (notat n continuare tEvol). Considerm valoarea iniial tEvol = 0, ce corespunde cu pasul de initializare a populaiei. Apoi, la fiecare etap de selecie generare, acest timp de evoluie l incrementm. 1. tEvol = 0 2. Se iniializeaz o populaie iniial de soluii (cromozomi) Se verific dac prin metoda aleatoare de inializare a populaiei nu s-a obinut o soluie acceptabil, caz n care se incheie algoritmul. 3. Pe baza funciei de adecvare se selecteaz cele mai optime soluii (se formeaz populaia de soluii-prini). 4. Pe baza operatorilor genetici se genereaz soluiile copii din populaia intermediar. 5. tEvol++

6. Se verific condiiile de oprire n funcie de tEvol = tEvolMAX sau dac s-a gsit o soluie acceptabil Dac da algoritmul se ncheie. Altfel se revine la pasul 3. Paii 3 i 4 reprezint nucleul algoritmului genetic.

c) Selecia
Exist mai multe tipuri de selecie, toate acestea avnd scopul ca implementarea capacitii de supravieuire a unei soluii s fie proporional cu valoarea funciei de adecvare, aici fiind de fapt implementat paradigma evoluiei darwiniste survival of the fittest. Una dintre cele mai simple metode de selecie este selecia bazat pe ordonare (ierarhie), n care se ordoneaz populaia de soluii astfel nct adaptarea lor s fie descresctoare, dup care se selecteaz primii n indivizi dorii. Metoda cea mai natural de selecie este metoda de selecie Monte Carlo (proporional). Aceast metod presupune construirea unei rulete, fiecare individ din populaie fiind reprezentat sub forma unui sector de cerc proporional cu o pondere. Pentru a avea sens din punct de vedere evolutiv, ponderea trebuie s fie cu att mai mare cu ct adecvarea individului soluie este mai bun. n figura 8.1.3. avem o populaie format din cinci indivizi i adaptarea cea mai bun o are crom5.

Fig. 8.1.3. Ruleta Monte Carlo n mod uzual, un algoritm de selecie Monte Carlo are ca date de intrare o matrice format din simboluri i ponderi asociate. De exemplu s cuantificm aruncarea unui zar: simbolurile sunt feele notate cu 1, 2, ..., 6,

reprezentate de numrul de puncte, iar ponderile (de apariie a unei fee) ar trebui s fie identice (1). Astfel avem matricea de intrare:

Cu aceasta construim modelul grafic al ruletei: alegem un punct de referin i nvrtim ruleta. (Fig. 8.1.4.) Simbolul extras este acela a crui sector de cerc asociat se oprete n dreptul puctului de referin. Se pstreaz astfel modelul natural al unui zar perfect (fiecare simbol are aceeai probabilitate de apariie):

Fig. 8.1.4. Ruleta Monte Carlo pentru un zar perfect Algoritmul de selecie Monte Carlo poate fi exprimat astfel: Fie suma ponderilor. Se genereaz un numr aleator t ntre 0 i S 1. Se parcurg ponderile i atta timp ct t >= 0, se scade din t ponderea curent.
int AMC (int ponderi[], int n) { int s = 0; for ( int i = 0 ; i < n; i++ ) s += ponderi[i]; int t = rand() % s, symbol_poz = 0; do { t -= ponderi[symbol_poz]; symbol_poz++; } while (t >= 0); return symbol_poz - 1; }

Exist mai multe tipuri de selecie, pe lng cele dou amintite anterior. Avantajele, dezavantajele, modul lor de implementare i particularitile acestora le vom trata ntr-un manual dedicat inteligenei artificiale.

d) Operatorii genetici
Pentru a continua construcia unui algoritm genetic funcional, avem nevoie de o modalitate de generare a soluiilor-copii din populaia de soluii-prini. Aceasta se realizeaz prin operatorii genetici. Exist doi operatori genetici fundamentali: mutaia (notat n continuare opM), respectiv ncruciarea (opI). Avem: i Se observ c mutaia este un operator unar i acioneaz prin schimbarea uneia sau a mai multor valori din cromozomul printe: n forma cea mai simpl fie un cromozom cu valorile . Atunci un operator de mutaie ar genera o valoare aleatoare t ntre 0 i n 1, iar valoarea corespunztoare lui t ar fi schimbat cu o alt valoare.

S considerm cromozomul 1110001010011111, n codificarea binar. pentru a obine diversitatea populaiei este necesar s inem cont c vom modifica n 1 bitul ales aleator dac valoarea acestuia este 0, respectiv n 0 dac aceast valoare este 1.

Toate variantele operatorilor de mutaie au ca scop diversificarea populaiei, n efect contrar cu selecia. Operatorul de ncruciare este un operator binar i are ca scop schimbarea valorilor existente ntre cromzomii prini. n forma cea mai simpl (numit ncruciarea cu un punct de tietur) se genereaz un

numr aleator t, acesta reprezentnd punctul n care se rup cei doi cromozomi i se recombin.

sau Forma cea mai ntlnit a operatorului de ncruciare este aceea n care se genereaz un ir de numere aleatoare (ti), care vor reprezenta punctele de tietur:

Un exemplu n codificare binar:

Operatorii genetici de mutaie i ncruciare sunt necesari ntr-un algoritm genetic pentru a asigura procesul evolutiv. Pe lng aceti operatori se pot construi i alii, n funcie de cerinele problemei. Exist i posibilitatea cutrii unor soluii pentru care lungimea cromozomilor s fie variabil, sau informaia reinut de acetia s fie supus anumitor restricii, caz n care trebuie adaptai i operatorii genetici n consecin. Algoritmii genetici sunt foarte eficieni atunci cnd dorim soluii apropiate de un optim global ntr-un timp scurt, dar dac dorim optime globale atunci acetia pot fi mai puin eficieni dect alte abordri. Prezentm n continuare dou probleme care se pot rezolva n mod natural cu ajutorul algoritmilor genetici: o problem n care se cere o expresie a crei rezultat s fie un numr dat i o problem n care se cere rezolvarea unui sistem de ecuaii. Sperm ca rezolvrile prezentate n cadrul acestora s v ajute s nelegei att logica din spatele algoritmilor genetici, ct i modul de implementare al acestora.

1.2. Problema gsirii unei expresii


Se dau N 1 operatori matematici O1, O2, ..., ON 1 din mulimea {+, -, *}, avnd semnificaia lor obinuit i un numr S. Scriei un program care gsete un ir de N numere naturale X1, X2, ..., XN din intervalul [1, N], astfel nct expresia format prin alturarea numerelor gsite cu operatorii dai (adic X1O1X2O2 ... ON-1XN) s dea, modulo 16 381, rezultatul S. Datele de intrare se citesc din fiierul expresie.in, iar soluia se scrie n fiierul expresie.out. Fiierul de intrare conine pe prima linie numerele N i S, separate printr-un spaiu, iar pe a doua linie N-1 operatori matemtici din mulimea specificat n enun. n fiierul de ieire se afieaz, separate printr-un spaiu, pe prima linie, elementele irului X. Exemplu: expresie.in expresie.out 4 18 4412 **+ Explicaie: 4 * 4 * 1 + 2 = 18. 18 mod 16 381 = 18. Pot exista i alte soluii. O prim idee de rezolvare este s folosim metoda backtracking. Trebuie s generm toate posibilitile de a completa N poziii cu numere din intervalul [1, N]. Acest lucru se poate face cu un algoritm similar cu cel al generrii permutrilor unei mulimi, doar c acuma nu ne intereseaz dac folosim un element de dou sau mai multe ori. Complexitatea unui astfel de algoritm este O(NN), deoarece pentru fiecare dintre cele N poziii care trebuie completate, avem N posibiliti de completare (N resurse i N poziii). Complexitatea este foarte mare, iar algoritmul este ineficient i n practic pentru valori mari ale lui N. Exist diverse optimizri care pot fi fcute, dar nici acestea nu vor mri cu mult viteza algoritmului. O alt idee este s generm aleator numere pn cnd gsim o expresie care d rezultatul S. n practic, nici aceast metod nu funcioneaz pentru valori mari ale lui N.

Gndii-v ce se ntmpl dac generm un ir de numere a crui rezultat este foarte aproape de S. Asta nseamn c irul respectiv ar putea fi o soluie valid, cu mici modificri. n cazul algoritmului anterior ns, acest ir se va pierde la pasul urmtor, generndu-se alt ir, care va avea mai multe anse s fie mai ndeprtat de soluie dect mai apropiat ca irul curent Ideea din spatele algoritmilor genetici este s reinem mai multe astfel de iruri (o populaie sau ecosistem) generate aleator, pe care s le sortm dup o funcie de adecvare (funcie de fitness) care ia valori tot mai apropiate de 0 pentru iruri (indivizi sau cromozomi) care tind spre o soluie. Cnd am gsit un ir pentru care funcia de adecvare ia exact valoarea 0, am gsit o soluie. Algoritmul nu se oprete ns la sortarea unor iruri generate aleator. Vom genera un anumit numr de iruri o singur dat, dup care vom aplica anumii operatori genetici asupra lor. Aceti operatori asigur faptul c informaia dintr-o generaie nu se va pierde n generaiile urmtoare. O generaie este o stare a populaiei la un moment dat. Se pune problema alegerii indivizilor asupra crora vom aplica operatorii genetici i alegerii indivizilor a cror informaie dorim s o pstrm i n generaia urmtoare. Evident, dac un individ a fost foarte aproape de soluie ntr-o generaie, acesta va merita pstrat aa cum e i n generaia viitoare. Vom menine o list cu elite pentru fiecare generaie, elite care vor trece nemodificate n generaia urmtoare. Operatorii genetici se vor aplica asupra elitelor, combinnd calitile acestora n sperana obinerii unor soluii din ce n ce mai bune. Operatorii genetici se aplic, fiecare, cu o anumit probabilitate, n funcie de necesitatea aplicrii lor. Operatorii cei mai des ntlnii sunt operatorii de recombinare i de mutaie. Operatorul de recombinare combin informaia reinut de doi cromozomi A i B ce fac parte din elite ntr-un singur cromozom ce va face parte din generaia urmtoare. Modul de desfurare al operaiei este similar cu procedeul biologic: se alege un punct (o gen) oarecare P de pe unul dintre cei doi cromozomi din elite. Cromozomul C rezultat prin recombinare va avea primele P gene identice cu primele P gene ale cromozomului A, iar urmtoarele gene identice cu genele de dup poziia P a cromozomului B Pentru problema de fa, lucrnd pe exemplul dat, recombinarea s-ar putea face astfel:

Cromozom Informaie A 4 * 4 * 2 + 3 B 1 * 4 * 1 + 2 C 4 * 4 * 1 + 2 Fig. 8.2.1. Operatorul de recombinare aplicat problemei prezentate Operatorul de mutaie modific aleator valoarea unei gene alese tot aleator. n cazul problemei de fa, operatorul de mutaie trebuie s fie implementat n aa fel nct s nu modifice valoarea unui operator. Exemplu: nainte de mutaie Dup mutaie 4 * 3 * 1 + 2 4 * 4 * 1 + 2 Fig. 8.2.2. Operatorul de mutaie aplicat problemei prezentate Funcie de adecvare este, n acest caz, foarte simplu de construit. Aceasta va calcula, pentru fiecare cromozom, diferena n modul dintre suma S i valoarea expresiei reinute de cromozomul curent. Astfel, algoritmul de rezolvare este urmtorul: Iniializeaz aleator maxpop cromozomi / indivizi. Execut: o Creeaz o nou populaie aplicnd operatorii de recombinare i de mutaie (fiecare cu probabiliti prestabilite). o Sorteaz indivizii cresctor dup funcia de adecvare. Ct timp valoarea funciei de adecvare pentru primul cromozom este diferit de 0. Afieaz operanzii primului cromozom. Pentru mai multe detalii despre funcia de evaluare a unei expresii, vedei capitolul Algoritmi generali.
#include <fstream> #include <algorithm> #include <cstdlib> using namespace std;

const int maxN = 1001; const int maxpop = 400; const int maxlg = 2*maxN + 1; const int maxeli = 50; const int prob_recomb = (int)((double)0.80 * RAND_MAX); const int prob_mutatie = (int)((double)0.95 * RAND_MAX); const int mod = 16381; struct info { int P[maxlg], fitness; }; void citire_init(int &N, int &S, info A[]) { ifstream in("expresie.in"); in >> N >> S; char x; int ops[maxN]; for ( int i = 1; i < N; ++i ) { in >> x; if ( x == '-' ) ops[i] = -1; else if ( x == '+' ) ops[i] = -2; else ops[i] = -3; } ops[N] = -100; in.close(); for ( int i = 1; i < maxpop; ++i ) { for ( int j=1, k=1; j < 2*N; j += 2, ++k ) { A[i].P[j] = 1 + rand() % N; A[i].P[j+1] = ops[k]; } } }

// <EVALUARE> int paran(int &k, int cr, info A[]) { return A[cr].P[k++]; } int inm(int &k, int cr, info A[]) { int ret = paran(k, cr, A); while ( A[cr].P[k] == -3 ) { ++k; ret *= paran(k, cr, A); ret %= mod; } return ret; } int eval(int &k, int cr, info A[]) { int ret = inm(k, cr, A); while (A[cr].P[k] == -1 || A[cr].P[k] == -2) { if ( A[cr].P[k++] == -1 ) ret -= inm(k, cr, A); else ret += inm(k, cr, A); ret %= mod; while ( ret < 0 ) ret += mod; } return ret; } // </EVALUARE>

void calc_fitness(int N, int S, info A[]) { for ( int cr = 1; cr < maxpop; ++cr ) {

bool operator<(const info &x, const info &y) { return x.fitness < y.fitness;

int k = 1; A[cr].fitness = abs(eval(k, cr, A) - S); } sort(A+1, A+maxpop); } void noua_gen(int N, info A[]) { for ( int i = maxeli + 1; i < maxpop; ++i ) { if ( rand() < prob_recomb ) // recombinare { int i1, i2; do { i1 = 1 + rand() % maxeli; i2 = 1 + rand() % maxeli; } while ( i1 == i2 ); int poz; do { poz = 1 + (rand() % (2*N - 1)); } while ( poz % 2 == 0 ); for ( int j = 1; j < poz; j += 2 ) A[i].P[j] = A[i1].P[j]; for ( int j = poz; j < 2*N; j += 2 ) A[i].P[j] = A[i2].P[j]; } if ( rand() < prob_mutatie ) // mutatie { int poz; do { poz = 1 + (rand() % (2*N - 1)); } while ( poz % 2 == 0 ); A[i].P[poz] = 1 + (rand() % N); } } }

} void start(int N, int S, info A[]) { do { noua_gen(N, A); calc_fitness(N, S, A); } while ( A[1].fitness != 0 ); ofstream out("expresie.out"); for ( int i = 1; i < 2*N; i += 2 ) { out << A[1].P[i] << " "; } out << endl; out.close(); }

int main() { int N, S; info *A = new info[maxpop]; srand((unsigned)time(0)); citire_init(N, S, A); start(N, S, A); delete[] A; return 0; }

Exerciii: a) Comparai performana algoritmului cu performana celorlali doi algoritmi menionai. b) Cum afecteaz constantele de la nceputul programului timpul de execuie i memoria folosit? c) Cum am putea modifica operatorii genetici dac numerele folosite n expresie ar trebui s fie distincte?

1.3. Rezolvarea sistemelor de ecuaii


Se d un sistem cu M ecuaii i N necunoscute. Considerm ca necunoscutele se noteaz cu A1, A2, ..., AN, iar o soluie valid este o permutare a mulimii {1, 2, ..., N} care verific fiecare ecuaie. Datele de intrare se gsesc n fiierul sistem.in, iar soluia se scrie n fiierul sistem.out. Fiierul de intrare are urmtoarea structur: pe prima linie N i M, iar pe urmtoarele M linii cte o ecuaie n care operanzii sunt desprii de operatori prin cte un spaiu, aa cum se poate vedea n exemplu. Se presupune c sistemul are ntotdeauna cel puin o soluie i c, in cazul unei operaii de mprire, se reine doar partea ntreag a rezultatului. n ecuaii nu apar paranteze. Exemplu: sistem.in sistem.out 32 312 A1 + A2 - A3 = 2 A1 * A2 / A3 = 1 Explicaie: 3+12=2 3*1/2 =1 Se poate observa c i permutarea (1, 3, 2) ar fi fost valid. Problema se poate rezolva folosind metoda backtracking. Mai exact, se folosete algoritmul de generare a tuturor permutrilor unei mulimi. Folosind algoritmul respectiv, putem verifica, pentru fiecare permutare P, rezultatul fiecrei expresii date, n care nlocuim fiecare necunoscut Ai cu numrul Pi (1 i N). Dac am gsit o permutare care verific toate ecuaiile date, am gsit o soluie a sistemului i putem opri cutarea. Aceast metod are avantajul de a fi relativ uor de implementat i de a gsi rapid o soluie pentru un sistem oarecare. Alt avantaj este posibilitatea gsirii tuturor soluiilor unui sistem. Dezavantajele acestei metode constau n eficien. Complexitatea asimptotic va fi ntotdeauna O(N!) deoarece trebuie s generm toate

permutrile. Totui, exist optimizri care pot face ca algoritmul s ruleze foarte rapid n practic. Cteva astfel de optimizri sunt: Sortarea ecuaiilor dup numrul de necunoscute care apar n acestea i rezolvarea ecuaiilor cu numr mai mic de variabile mai nti. Verificarea ecuaiilor nainte de generarea unei permutri ntregi, fapt ce ne poate ajuta s respingem o permutare mai devreme. Diverse optimizri legate de modul de generare al permutrilor. Aceste optimizri nu garanteaz ns ntotdeauna o mbuntire i pot fi dificil de implementat. Problema se poate rezolva mai eficient folosind algoritmi genetici. Deoarece se cere o singur permutare care s verifice anumite constrngeri (ecuaiile sistemului), putem ncepe cu un numr prestabilit (populaia) de permutri generate aleator (indivizi), pe care vom aplica apoi anumii operatori genetici i pe care le vom sorta dup o funcie de adecvare. Procedeul se repet pn cnd se ajunge la o soluie. Corectitudinea i eficiena acestei metode st aadar n alegerea operatorilor genetici i a funciei de adecvare (fitness). Propunem urmtoarele dou funcii de adecvare: 1. Prima funcie, F1, calculeaz, pentru fiecare individ, numrul de ecuaii ale sistemului pe care permutarea le verific. Evident, am gsit o soluie atunci cnd exist un individ X pentru care F1(X) = M. 2. A doua funcie, F2, calculeaz, pentru fiecare individ,

unde f(i) este rezultatul evalurii expresiei i dac nlocuim fiecare necunoscut cu permutarea reprezentat de individul curent, iar g(i) este rezultatul pe care trebuie s l aib expresia i, adic numrul din dreapta egalului expresiei i. Am gsit o soluie atunci cnd exist un individ X pentru care F2(X) = 0. Ambele funcii de adecvare se comport similar din punct de vedere al timpului de execuie. Acelai lucru nu poate fi spus ns i despre operatorii genetici. Primul lucru care trebuie observat este c nu putem pstra modelul clasic al algoritmilor genetici, deoarece nu putem folosi nici operatorul de recombinare (n caz contrar am genera permutri invalide, cu elemente care se repet), nici operatorul clasic de mutaie (din acelai motiv).

O prim idee ar fi s folosim un operator de inversare: alegem aleator dou poziii x1 i x2, cu 1 x1 < x2 N i inversm secvena cuprins ntre x1 i x2. Acest lucru ncalc ns ideea principal din spatele algoritmilor genetici: pstrarea unor trsaturi ale elitelor din generaia curent pentru a mbunti generaiile urmtoare. Folosind operatorul de inversare, se pierde informaia din generaia curent. Propunem urmtorul operator genetic, similar cu operatorul de recombinare: se alege un individ oarecare din elitele generaiei precedente, din care se copiaz primele x gene n cromozomul curent. Urmtoarele gene se completeaz aleator, avnd grij s nu avem dou gene (o gen reprezint, practic, un element al permutrii) identice. Astfel, generaiile urmtoare au anse mai mari s fie mai aproape de rezolvarea problemei dect generaia curent, iar mbuntirea timpului de execuie este evident pentru un volum mai mare al datelor de intrare. Putem folosi i operatorul de mutaie, dar i acesta trebuie modificat pentru necesitile problemei. Mutaia nu va mai avea loc asupra unei singure gene, ci asupra a dou gene. Vom alege dou gene pe care le vom interschimba, pstrnd astfel proprietatea de permutare. Structura de baz a algoritmilor genetici rmne la fel. n consecin, prezentm doar acele funcii care sufer modificri.
void calc_fitness() { for ( int cr = 1; cr < maxpop; ++cr ) { A[cr].fitness = 0; for ( int i = 1; i <= M; ++i ) { int k = 1; A[cr].fitness += abs(eval(k, cr, A, i) - egal[i]); } } sort(A + 1, A + maxpop); } void noua_gen() { int v[maxn]; for ( int i = 1; i <= N; ++i ) v[i] = 0; for ( int i = maxeli + 1; i < maxpop; ++i ) {

if ( rand() < prob_recomb ) { int x1 = 1 + rand() % maxeli; int poz = 1 + rand() % N; for ( int j = 1; j <= poz; ++j ) { v[ A[x1].var[j] ] = i; A[i].var[j] = A[x1].var[j]; } for ( int j = 1; j <= N; ++j ) if ( v[j] != i ) { ++poz; A[i].var[poz] = j; } } if ( rand() < prob_mutatie ) { int x1 = 1 + rand() % N; int x2 = 1 + rand() % N; swap(A[i].var[x1], A[i].var[x2]); } } }

Precizm c implementarea aceasta folosete funcia de adecvare descris anterior ca F2. Funcia eval() evalueaz expresia numrul i, nlocuind necunoscutele cu valorile date de cromozomul cr. Aceasta a fost descris n cadrul capitolului Algoritmi generali i n cadrul problemei precedente. Exerciiu: Implementai n ntregime un program care rezolv problema, folosind, pe rnd, ambii operatori genetici menionai, precum i ambele funcii de adecvare descrise. Comparai, pe mai multe date de intrare, performanele acestora.