CATEGORII DOCUMENTE |
Metoda programarii dinamice se aplica in cazul problemelor de optim in care solutia poate fi privita ca rezultatul unui sir de decizii d1, d2, ,dn, unde alegerea fiecarei decizii dk depinde de deciziile luate anterior.
Fie s0 este starea initiala a problemei. Fiecare decizie dk trece problema din starea sk-1 in starea sk. Dupa aplicarea sirului de decizii d1, d2, ,dn problema va ajunge in starea finala sn.
Metoda programarii dinamice se aplica in problemele de optim care satisfac principiul optimalitatii, ea furnizand intotdeauna solutia optima. Principiul optimalitatii presupune ca optimul global implica optimul local (partial) si este enuntat astfel: daca d1, d2, ,dn este un sir optim de decizii, atunci orice k am considera, sirurile de decizii d1, d2, ,dk , respectiv dk+1, dk+2, ,dn sunt optimale.
In multe situatii practice se utilizeaza conditii "mai slabe", dar suficiente, de optimalitate, atunci cand numai unul din sirurile de decizii d1, d2, ,dk sau dk, dk+2, ,dn este optimal, sau in situatii si mai particulare, in care principiul optimalitatii se verifica numai pentru o anumita valoare a lui k (de exemplu k=1 sau k=n-1). Astfel se disting alte doua forme ale principiului optimalitatii:
De exemplu, considerandu-se un graf etichetat G=(X,A), reprezentand orasele Romaniei si distantele intre ele, se cere sa se gaseasca cel mai scurt drum intre doua orase s si p. Este evident ca se verifica principiul optimalitatii: daca cel mai scurt drum intre Bucuresti si Sibiu trece prin Brasov, atunci (pentru k = Brasov) drumul intre Bucuresti si Brasov, precum si cel dintre Brasov si Sibiu sunt cele mai scurte. Daca ar fi existat altele mai scurte, atunci traseul ales pentru Bucuresti - Sibiu nu ar mai fi fost optim.
Trebuie observat faptul ca rationamentul de mai sus nu are loc si in sens invers, adica daca consideram cel mai scurt drum intre Bucuresti si Rm-Valcea si cel mai scurt drum intre Rm-Valcea si Sibiu, de aici nu putem trage concluzia ca cel mai scurt drum intre Bucuresti si Sibiu trece prin Rm-Valcea. Exista un drum mai scurt prin Brasov.
Cu ajutorul metodei programarii dinamice, problema gasirii drumului cel mai scurt poate fi rezolvata in mai multe variante:
Drum(i,j)=mini→k
unde am notat prin i→k faptul ca exista arc intre i si k (altfel spus, perechea (i,k)IA), Drum(i,j) este lungimea optima a drumului de la orasul i (nodul i in graf) catre orasul j, iar d[i,j] este distanta intre cele orase (eticheta intre nodurile i si j in graf). Evident Drum(i,i)=0. Aceasta abordare corespunde metodei inapoi.
Drum(i,j)=mink→j
cu notatiile de mai sus. Si aici avem Drum(i,i)=0. In acest caz a fost utilizata metoda inainte.
x=sk=max
cel mai mare nod al secventei considerate, atunci drumurile s=s0,s1, ,sk=x, respectiv x=sk,sk+1, ,sn=p sunt cele mai scurte intre s=s0 si x=sk respectiv x=sk si p=sn si, in plus, trec prin noduri intermediare cu indici mai mici decat x. Atunci, putem considera:
Drumk(i,j)=Drumk-1 (i,x)+Drumk-1(x,j)
unde Drumk(i,j) este drumul cel mai scurt intre i si j ce trece prin noduri cu indici mai mici decat k.
Verificarea principiului optimalitatii, sub oricare dintre formele sale, ne poate conduce la solutia optima generand si retinand, in mod progresiv, optimele partiale, pana cand ajungem la optimul global.
Practic, aplicarea metodei de programare dinamica presupune parcurgerea urmatorilor pasi:
se verifica daca (si sub ce forma) este satisfacut principiul optimalitatii;
plecand de la forma principiului optimalitatii se deduc relatiile recurente intre optimul global si cele partiale;
se implementeaza relatiile recurente obtinute anterior.
Timpul de calcul
Esential pentru metoda programarii dinamice este faptul ca solutiile bazate pe recursivitate conduc, in marea parte a cazurilor, la recursivitate in cascada, prin recalcularea repetata a unor stari ale problemei, ceea ce face ca timpul de calcul sa sporeasca semnificativ. Pentru a evita acest neajuns se va utiliza metoda tabelarii: starile intermediare ale problemei (obtinute in urma aplicarii unui sir optim partial de decizii) vor fi retinute in masive de date si astfel nu se vor calcula decat componentele neinitializate. In acest context, metoda programarii dinamice va duce, in cea mai mare parte a cazurilor, la timpi de calcul de ordin polinomial.
Fie A(m,n) si B(n,p) doua matrice bidimensionale de dimensiuni m*n, respectiv n*p. Inmultirea lor are ca rezultat o a treia matrice de dimensiuni m*p: C(m,p), unde fiecare element cij se poate obtine cu ajutorul formulei:
Utilizand formula de mai sus, inmultirea dintre A si B va necesita un numar de m*n*p inmultiri intre elemente ale celor doua matrice.
Sa presupunem ca dispunem de un sir de matrice A1, A2, ,An, fiecare matrice Ai are dimensiunile (li, li+1), astfel ca numarul de coloane al fiecarei matrice sa fie egal cu numarul de linii ale matricei urmatoare. Astfel, produsul sirului de matrice este definit: C= A1*A2* *An.
Daca am dispune de un operator supraincarcat pentru inmultirea matricelor, acesta va efectua inmultirile de la stanga la dreapta, astfel:
C=((.((A1*A2)*A3)**An)
ceea ce, dupa cum vom observa mai jos, poate sa nu fie optim din punctul de vedere al numarului de operatii efectuate, intrucat ordinea de grupare (asociere) a matricelor poate influenta semnificativ numarul total de inmultiri efectuate. Pentru ca inmultirea matricelor este asociativa, matricea-rezultat va fi aceeasi, indiferent de ordinea de inmultire aleasa. Problema care se pune in scopul inmultirii optime de matrice este stabilirea ordinii de inmultire, fara a incerca toate posibilitatile.
Sa consideram un exemplu extrem de simplu: presupunem ca avem 4 matrice de dimensiuni (100,1), (1,100), (100,1), (1,100). Asadar, n=4 si l=(100,1,100,1,100). Iata trei modalitati de asociere:
(((A1*A2)*A3)*A4), asocierea implicita de la stanga la dreapta. Ea presupune efectuarea urmatoarelor inmultiri:
(A1*A2), care necesita 100*1*100=10000 inmultiri si rezulta o matrice C1 de dimensiuni (100,100)
C1*A3, matricea C1 de dimensiuni (100,100) obtinuta la pasul anterior este inmultita cu A3, rezultand matricea C2 de dimensiuni (100, 1). Au fost efectuate 100*100*1=10000 de inmultiri.
C2*A4, fiind ultima inmultire de matrice necesita 100*1*100=10000 de operatii.
In total, asocierea stanga-dreapta necesita, in exemplul considerat, 30.000 de inmultiri.
Fig. V . Numarul de inmultiri efectuate prin asocierea stanga-dreapta
((A1*A2)*(A3*A4)), necesita, in urma unui rationament similar celui de mai sus, 100*1*100 + 100*1*100 + 100*100*100 = 10000 + 10000 + 1000000 = 1.020.000 de operatii
Fig. V . Numarul de inmultiri efectuate prin asocierea matricelor extreme
((A1*(A2*A3))*A4), necesita 1*100*1 + 100*1*1 + 100*1*100 = 100 + 100 + 10000 = 10.200 de operatii
Fig. V . Numar de inmultiri
Se observa asadar ca dintre cele trei modalitati ultima asociere presupune cel mai mic numar de inmultiri.
Pentru rezolvarea problemei vom utiliza metoda programarii dinamice introducand o matrice de costuri, unde fiecare element cost[i,j] cu 1 i j n reprezinta numarul minim de operatii necesare pentru a efectua produsul Ai*Ai+1* *Aj.
Daca Ai*Ai+1* *Aj este un produs optim, atunci exista un i k<j astfel ca secventele Ai*Ai+1* *Ak si Ak+1*Ak+2* *Aj sa fie optimale. In urma inmultirii secventei Ai*Ai+1* *Ak , respectiv Ak+1*Ak+2* *Aj se obtin doua matrice de dimensiuni (li, lk+1), respectiv (lk+1, lj+1), care inmultite intre ele necesita li* lk+1*lj+1 operatii. Dintre toate valorile posibile ale lui k intre i si j se alege aceea care minimizeaza totalul comparatiilor. Asadar, in mod natural, deducem urmatoarea formula, care ne arata ca se verifica principiul optimalitatii:
cost[i,j]=mini<=k<j, cand j>i.
Conditia initiala este evidenta: cost[i,i]=0, pentru orice i=1..n.
Am obtinut astfel o definitie recursiva a elementelor matricei cost. Este evident ca numarul minim de inmultiri pentru a obtine produsul de matrice A1, A2, ,An este dat de valoarea elementului cost[1,n].
Mai mult, daca la fiecare evaluare a elementului cost[i,j], pentru j>i, retinem valoarea lui k pentru care a fost realizat minimul, atunci vom putea deduce asocierea matricelor. Pentru ca numai jumatate din matricea de costuri este utilizata, vom incarca valoarea k care minimizeaza numarul de operatii necesar inmultirii Ai*Ai+1* *Aj in elementul cost[j,i].
Pentru exemplul considerat anterior, unde n=4 si l=(100,1,100,1,100), matricea de costuri este:
Tabel V . Matricea de costuri
unde elementele cost[i,j], cu i j, au fost calculate in ordinea crescatoare a diferentei j-i:
Un algoritm iterativ de populare a matricei cost este:
procedure COST(integer n, integer cost[1..n,1..n] for i=1 to n cost[i,i]← 0 next i for d=1 to n-1 /*d reprezinta diferenta j-i*/ for i=1 to n-d j←i+d cost[i,j] ← cost[j,i] ←[valoarea k pentru care se obtine minimul] next i next d end |
Procedeul poate fi imaginat astfel - vom construi un arbore binar cu proprietatile:
radacina arborelui este etichetata (1,n);
fiecare nod etichetat (i,j), cu i<j, are doi fii etichetati (i,k) si (k+1,j), unde k este valoarea retinuta in cost[j,i], care a realizat minimul pentru secventa Ai*Ai+1* *Aj;
nodurile etichetate (i,i) sunt noduri terminale ale arborelui.
Fig. V . Reprezentarea unei asocieri optime ca arbore binar
Parcurgerea in postordine (SDR) a nodurilor neterminale va genera modul de grupare a matricelor: un nod etichetat (i,j) va semnifica gruparea minimala a secventei Ai*Ai+1* *Aj.
In exemplul de mai sus, parcurgerea SDR a nodurilor neterminale va genera: [2,3], [2,4],[1,4], cu semnificatia: o pereche de paranteze incepe inainte de A2 si se termina dupa A3, alta pereche incepe inainte de A2 si se termina dupa A4 si ultima pereche de paranteze incepe inainte de A1 si se termina dupa A4, altfel spus:
(A1*((A2*A3)*A4))
Se observa ca valoarea minima elementului cost[1,4] putea fi obtinuta si pentru k=3, aceasta ar fi dus la generarea unei alte grupari optime, corespunzatoare arborelui:
Fig. V . Reprezentarea unei asocieri optime ca arbore binar
si anume: ((A1*(A2*A3))*A4), care necesita acelasi numar minim de inmultiri, 10.200.
Se cere generarea unei modalitati de asociere a unui sir de matrici A1, A2, ,An, fiecare matrice Ai avand dimensiunile (li, li+1), in vederea obtinerii produsului lor cu un numar minim de inmultiri de elemente.
Indicatie: Se va utiliza functia cost definita mai sus. Aceasta poate fi implementata fie iterativ, determinandu-i valorile cost[i,j] in ordinea crescatoare a diferentei j-i, fie recursiv, evitand insa recalcularea valorilor sale. Am ales varianta recursiva datorita simplitatii sale.
Inmultirea optima a unui sir de matrice
#include<iostream.h>
int n,//numar matrice de inmultit
*l,//vector dimensiuni
**cost;//matrice costuri
int COST(int i,int j)
}
return cost[i][j]=cost_min;
void SDR(int i, int j)
int main()
cout<<'Nr. minim de inmultiri: '<<COST(0,n-1)<<endl;
cout<<'Matricea de costuri:';
for(i=0;i<n;i++)
cout<<endl<<'Perechile de paranteze: '; SDR(0,n-1);
delete []l;
for(i=0;i<n;i++)
delete[]cost[i];
delete []cost;
return 0;
Metoda programarii dinamice are multe aplicatii in prelucrarea grafurilor.
Se considera un graf orientat, definit prin matricea de adiacente A, se cere sa se determine matricea existentei drumurilor intre noduri.
Indicatie: Matricea B a existentei drumurilor va avea forma:
Daca exista drum de la i la j, atunci pentru orice nod k al drumului, va exista drum de la i la k si de la k la j. Asadar, principiul optimalitatii este indeplinit in forma generala. Pentru a scrie relatiile de recurenta, trebuie stabilita mai intai o modalitate de alegere a nodului intermediar k: fie acesta nodul cu indicele cel mai mare din drumul ce leaga i de j. Prin urmare, drumurile [i,k], respectiv [k,j] trec numai prin noduri de indici mai mici decat k.
Ideea algoritmului Roy-Warshall este de a construi recurent un sir de matrice ale drumurilor astfel:
Evident, matricea drumurilor ceruta este Bn.
Exemplu:
Fie graful orientat:
Fig. V . Retea drumuri
definit de matricea de adiacente:
Tabel V . Matricea de adiacente
Vom avea succesiv matricele:
Tabel V . Matricele drumurilor
B0= |
|
B1= |
|
B2= |
|
B3= |
|
B4= |
|
B5= |
|
De exemplu, elementul B1[3,3] a fost evaluat astfel:
B1[3,3]= B0[3,3] or (B0[3,1] and B0[1,3])=0 or 1 and 1= 0 or 1 = 1
Observand faptul ca:
,
deducem ca in implementarea recursiva a algoritmului putem utiliza o singura matrice B.
Solutie
Algoritmul Roy-Warshall - determinarea matricei existentei drumurilor
#include<iostream.h>
void AfisMat(int **A, int n)
void RoyWarshall(int **A, int n, int **B)
main()
RoyWarshall(A,n,B);
cout<<'Matricea drumurilor:'<<endl;
AfisMat(B,n);
delete[]A;
delete[]B;
return 0;
Algoritmul are un timp de calcul de ordin O(n3), cauzat de cele 3 instructiuni if imbricate.
Se considera un graf orientat ponderat definit prin matricea costurilor A,. Se cere sa se determine matricea costurilor drumurilor minime intre oricare doua noduri.
Indicatie:
Problema este similara celei anterioare. Daca [i,j] este un drum de lungime minima de la i la j, atunci oricare ar fi k, apartinand acestui drum, drumurile [i,k] si [k,j] sunt de lungime minima (altfel, daca cel putin unul dintre ele nu ar fi, atunci nici drumul [i,j] nu este minim). Cum se verifica principiul optimalitatii, vom utiliza metoda programarii dinamice, alegand acel nod k de indice maxim, ca si la problema precedenta. Asadar drumurile [i,k] si [k,j] sunt de lungime minima si trec prin noduri cel mult egale cu k-1 (este evident ca nodul k nu poate exista de doua ori in drum, acesta avand cost minim, iar costurile, prin definitie, sunt valori strict pozitive). Vom considera ca daca nu exista arc de la i la j, atunci costul corespunzator in matricea costurilor este o valoare mare (infinit). Vom defini recurent sirul de matrice:
Evident, Bn este matricea cautata.
In implementarea recursiva a algoritmului vom utiliza o singura matrice B, deoarece avem ca:
,
Solutie
Algoritmul Roy-Floyd -Determinarea matricei costurilor minime ale drumurilor
#include<iostream.h>
void AfisMat(int **A, int n)
void Cost(int **A, int n, int **B)
main()
Cost(A,n,B);
cout<<'Matricea drumurilor:'<<endl;
AfisMat(B,n);
delete[]A;
delete[]B;
return 0;
Algoritmul are un timp de calcul de ordin O(n3), cauzat de cele 3 instructiuni if imbricate.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 2355
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved