Sunteți pe pagina 1din 6

Curs Nr.

Complexitatea algoritmilor
Teoria complexitătii are ca obiect de studiu clasificarea problemelor, bazată pe timpul de
executie si spatiul de lucru utilizat de algoritmi pentru solutionarea lor. Cînd se analizează algoritmi
paraleli, se poate lua în considerare si numărul de procesoare.
Desi teoria complexitătii a fost dezvoltată pentru probleme de decizie, aceasta nu este o restrictie
severă deoarece multe alte probleme pot fi formulate în termeni de probleme de decizie. De exemplu
o problemă de optimizare poate fi rezolvată prin punerea întrebării existentei unei solutii cu cel mult
sau cel putin o valoare specificată.
Din punctul de vedere al calculului secvential, 3 clase sînt relevante: P, NP, Pspace
Clasa P contine problemele solvabile în timp polinomial ceea ce înseamnă că pentru aceste
probleme există algoritmi secventiali cu timpul de executie mărginit de un polinom de variabilă "
dimensiunea problemei ". Problemele din P sînt numite, în mod curent, bine solutionabile sau
usoare.
NP este clasa problemelor pentru care nu este cunoscut un algoritm secvential cu timp de
executie polinomial.
Pspace contine problemele care sînt solvabile utilizînd un spatiu polinomial, adică spatiul de
lucru este marginit de un polinom de variabilă " dimensiunea problemei ".
Evident, P Í NP Í Pspace . Se presupune că ambele incluziuni sînt proprii (stricte).
O altă clasă inclusă în Pspace, neinteresantă din punct de vedere al calculului secvential, dar
importantă pentru calculul paralel este Polylogspace. Aici sînt incluse problemele rezolvabile în
spatiu polilogaritmic (spatiul de lucru este mărginit de un polinom de variabilă "log(dimensiunea
problemei)"). Multe probleme din P apartin lui Polylogspace, dar în general, se crede că P
ËPolylogspace. Se stie totusi că Polylogspace# Pspace .
Remarcabile în Pspace si NP sînt problemele complete.Problemele Pspace-complete sînt
generalizări ale tuturor celorlalte probleme din Pspace în termeni de transformări care necesită timp
polinomial. Mai precis: o problemă este Pspace-completă sub transformări de timp polinomial dacă
apartine lui Pspace si oricare altă problemă din Pspace este reductibilă la ea prin transformări care
necesită timp polinomial. Urmează că dacă o problemă Pspace-completă ar apartine lui P atunci
Pspace = P. Deoarece se crede că aceasta egalitate nu este adevărată, este improbabil să existe un
algoritm de timp polinomial pentru o problemă Pspace-completă. Problemele NP se definesc în mod
asemănător, rezultînd aceleasi concluzii.
Clasa P are si ea problemele ei complete. Problemele P-complete sînt generalizări ale tuturor
celorlalte probleme din clasa P, în termenii transformărilor care necesită spatiu de lucru logaritmic.
Formal, o problemă este P-completă sub transformări spatiale logaritmice dacă apartine clasei P si
orice altă problemă din P este reductibilă la ea prin transformări ce utilizează spatiu logaritmic.
Dacă o problemă P-completa ar apartine clasei Polylogspace, atunci ar fi adevărată incluziunea P Í
Polylogspace. Cum această incluziune se presupune a fi falsă, nu este de asteptat să existe un
algoritm pentru o problemă P-completă care să utilizeze spatiu de lucru polilogaritmic.
Complexitatea timpului de executie a unui algoritm paralel care rezolvă o instantă de dimensiune
n a unei probleme, pe o masină paralelă cu p procesoare (p=dimensiunea masinii) se notează a cu
T(p,n)=Tp(n).
O problemă se numeste dependentă de dimensiunea masinii (PDD) dacă n este o functie de
variabilă p. Altfel, problema se numeste independentă de dimensiunea masinii (PID). Un algoritm
dependent de dimensiunea masinii este un algoritm ce rezolvă o problemă PDD. altfel, algoritmul se
numeste independent de dimensiunea masinii.
Factorul de încărcare (L) a unei probleme este raportul n/p. Viteza Sp(n)) unui algoritm paralel
este raportul T1(n)/Tp(n). Eficienta (Ep(n)) unui algoritm paralel se defineste ca fiind raportul dintre
viteză si numărul procesoarelor:
E p(n)=Sp(n)/p=T1(n)/[p·Tp(n)].
Pentru a aprecia comportarea asimtotică a functiei Tp(n) se utilizează următoarele notiuni:
Fiind date două functii f si g pozitive de variabile p si n se notează :

o(g)={f/(")e>0,$[{p0,n0(p)}Ì N] a.i.( ")[(p>p0)Ù(n>n0(p))]: f(p,n)<e·g(p,n)}

1
Rezultă că f este în o(g) dacă limn®¥(f/g)=0.

O(g)={f/$[{p0,n0(p)}Ì NÙ(cÎR+] a.i.( ")[(p>p0)Ù(n>n0(p))]: f(p,n)<c ·g(p,n)}

Deci f este în O(g) dacă functia f/g este mărginită.

Q(g)={f/$[{p0,n0(p)}Ì NÙ(c1,c2) ÌR+] a.i.( ")[(p>p0)Ù(n>n0(p))]: 0<c1·g(p,n)<f(p,n)<c 2·g(p,n)}

Aceasta înseamnă că fÎQ(g) dacă f/g este o functie strict pozitivă si mărginită.

W(g)={f/$[{p0,n0(p)}Ì NÙcÎR+] a.i.( ")[(p>p0)Ù(n>n0(p))]: 0<c·g(p,n)<f(p,n)}

Rezultă că fÎW(g) dacă f/g este mărginita inferior de o valoare strict pozitivă.

Relatia între calculul secvential si paralel este dată de teza calculului paralel (Chandra, Kozen &
Stockmeyer, 1981; Goldshlager, 1982): pentru orice functie T(n), (n= dimensiunea problemei), clasa
problemelor solvabile de o masină cu paralelism nemărginit în timp T(n) O(1) (polinomial în T(n) ) este
egală cu clasa problemelor solvabile de masini secventiale cu spatiu (T(n)) O(1) .
Această teză este o teoremă pentru multe dintre modelele relativ rezonabile. Astfel, clasa
problemelor solvabile în T(n)O(1) timp de o masină PRAM este egală cu clasa problemelor solvabile
cu T(n)O(1) spatiu de lucru de o masină Turing, dacă T(n)³log n (Fortune & Wyllie, 1978). In
consecintă, clasa problemelor solvabile de o masină PRAM în timp paralel polinimial este egală cu
clasa Pspace. De asemenea, Polylogspace este clasa problemelor solvabile de o masină PRAM în
timp paralel polilogaritmic.
Problemele din PÇPolylogspace sînt solvabile în timp paralel polilogaritmic. Ele pot fi
considerate cele mai usoare probleme din P, în sensul că influenta dimensiunii problemei asupra
timpului de rezolvare a fost redusă la minimum. O reducere ulterioară a a timpului de solutionare la
dimensiuni sublogaritmice este, în general, imposibilă. Una din ratiunile acestei afirmatii este aceea
că o masină PRAM necesită O(log n) timp pentru activarea a n procesoare.
Pe de altă parte, este improbabil ca problemele P-complete să admită solutii în timp
polilogaritmic. Dacă o astfel de problemă ar fi rezolvabila în timp paralel polilogaritmic ar urma că
apartine clasei Polylogspace si astfel ar fi adevărată incluziunea PÌPolylogspace. Din acest motiv,
nu este de asteptat o solutie în timp paralel polilogaritmic. Orice metodă de rezolvare pentru
problemele grele din P necesită probabil timp superlogaritmic si aceasta deoarece natura lor este
probabil inerent secventiala. Aceasta nu înseamnă însă că paralelismul nu poate aduce cresteri
substantiale de viteză, algoritmilor de rezolvare.
In concluzie, clasa P poate fi partitionată în probleme foarte usoare (very easy) care sînt
rezolvabile în timp paralel polilogaritmic si probleme mai putin usoare (not so easy), pentru care
este improbabilă cresterea vitezei prin paralelism.
Tabloul modelului PRAM : Modelul este foarte util teoretic dar paralelismul nemăginit este
nerealist. Dacă o margine de timp polinomială este considerată rezonabilă, o margine polinomială a
numărului de procesoare este absolut necesară. In aceste conditii clasa problemelor rezolvabile este
P iar problemele NP-complete si cele Pspace-complete rămîn la fel de grele cum au fost si fără
paralelism. Cele două limitări ale resurselor conduc însă la noi clase de complexitate: NC si SC.
Clasa NC (Nick Pippenger Class) contine toate problemele solvabile în timp paralel polilogaritmic
cu un număr polinomial de procesoare. Clasa SC (Steve Class) este formată din problemele
rezolvabile în timp secvential polinomial cu spatiu de lucru polilogaritmic.
Se presupune că NC = SC Aceasta este o problemă majoră a teoriei complexitătii nerezolvată
incă.

Complexitatea algoritmilor secventiali

La evaluarea (estimarea) algoritmilor secventiali se pune în evidenta necesarul de timp si de


spatiu de memorare al lui.

2
Studierea complexitatii presupune analiza completa în cadrul algoritmului a urmatoarelor 3
puncte de vedere:
1. configuratia de date cea mai defavorabila (cazurile degenerate);
2. configuratia de date cea mai favorabila;
3. comportarea medie.

Punctul 3 presupune probabilitatea de aparitie a diferitelor configuratii de date la intrare.


Punctul 1 este cel mai studiat si este folosit, de obicei, pentru compararea algoritmului. Si în
ceea ce priveste timpul, se studiaza configuratia cea mai defavorabila a algoritmului.

Complexitatea unui algoritm secevntial se exprima de regula in limbajul clasei O.

Definitie
Fie f : N ® N si g : N ® N doua functii.
Spunem ca f Î O(g) si notam f = O(g) daca si numai daca $ o constanta c Î R si un numar
n0 Î N astfel încât pentru " n > n0 f(n) < c×g(n)

Observatie:
f : N ® N este o functie f(n) cu n ¾ dimensiunea datelor de intrare.
f(n) reprezinta timpul de lucru al algoritmului exprimat în "pasi".

Lema 1
Daca f este o functie polinomiala de grad k, de forma:
f(n) = ak × nk + ak-1×nk-1 + ... + a1 × n + a0, atunci f = O(nk).

Facându-se majorari în membrul drept, obtinem rezultatul de mai sus:


f(n) = ½ak½ × nk + ½ak-1½× nk-1 + ... +½a1½ × n +½a0½ < nk·× (½ak½ + ½ak-1½ + ½a0½) < nk ×
c pentru " n > 1 Þ f(n) < c × nk, cu n0 = 1.

Concluzie: f = O(nk), si ordinul O exprima viteza de variatie a functiei, functie de argument.

Exemplu: Calcularea maximului unui sir

maxsir(A,n)
{
max = A[1]
for i= 2 to n do
if A[i] > max then
max = A[i]
return (max)
}

Exprimam:
T(n) ¾ timpul de executie în pasi al acestui algoritm;
T(n)= 1 + 2(n-1) = numarul de atribuiri si comparatii
Cazul cel mai defavorabil: situatia în care vectorul este ordonat crescator (pentru ca de
fiecare data se face si comparatie si atribuire).
Putem spune ca T(n) = O(n), este o functie polinomiala de gradul I. Conteaza doar Ordinul
polinomului, nu coeficientul termenului de grad maxim. Iar la numararea pasilor ne concentram
asupra numarului buclelor, nu asupra pasilor din interiorul buclei.

Exemplu: Insertion Sort (algoritmul de sortare prin inserare)


Algoritmul INSERTION SORT considera ca în pasul k, elementele A[1÷k-1] sunt sortate,
iar elementul k va fi inserat, astfel încât, dupa aceasta inserare, primele elemente A[ ÷k] sa fie
sortate.
Pentru a realiza inserarea elementului k în secventa A[1÷k-1], aceasta presupune:
· memorarea elementului intr-o varibila temporara;

3
· deplasarea tuturor elementelor din vectorul A[1÷k-1] care sunt mai mari decât
A[k], cu o poziie la dreapta (aceasta presupune o parcurgere de la dreapta la stânga);
· plasarea lui A[k] în locul ultimului element deplasat.

Complexitate: O(n)

insertion_sort(A,n)
{
for k= 2 to n do
|Żtemp = A[k]
| i=k-1;
| while (i>=1) and (A[i] > temp) do |Ż A[i+1] = A[i]
| |_ i=i-1
|_ A[i+1] = temp
}
Cazul cel mai dafavorabil: situatia în care deplasarea (la dreapta cu o pozitie în vederea
înserarii) se face pâna la începutul vectorului, adica sirul este ordonat descrescator.
Exprimarea timpului de lucru:
T(n) = 3·(n - 1) + (1 + 2 + 3+ ... + n - 1) = 3(n-1) + 3n (n - 1)/2
Rezulta complexitatea: T(n) = O(n2) ¾ functie polinomiala de gradul II.

Observatie: Când avem mai multe bucle imbricate, termenii buclei celei mai interioare dau
gradul polinomului egal cu gradul algoritmului.

Bucla cea mai interioara ne da complexitatea algoritmului.


n
 i  O ( n2 )
i 1

Exemplu: Înmultirea a doua matrici

prod_mat(A,B,C,n)
{
for i = 1 to n do
for j = 1 to n do
|Ż C[i,j] = 0
|for k = 1 to n do
|_ C[i,j] = C[i,j] + A[i,k] * B[k,j]
}
Rezulta complexitatea O(n3).

Exemplu: Cautarea binara(Binary Search)

Fie A, de ordin n, un vector ordonat crescator. Se cere sa se determine daca o valoare b se


afla printre elementele vectorului. Limita inferioara se numeste low, limita superioara se numeste
high, iar mijlocul virtual al vectorului, mid (de la middle).

low middle high

Binary_search(A,n,b)
{
low = 1;
high = n;
while low =< high do

4
|Ż mid = [(low + high)/2] //partea întreaga
| if A[mid]=b then return (mid)
| else if A[mid]>b then high=mid-1 //restrâng
| //cautarea la partea
| //stânga
|_ else low = mid+1 //restrâng cautarea
//la dreapta
return(0)
}

Calculul complexitatii algoritmului consta în determinarea numarului de ori pentru care se


executa bucla while.
Se observa ca, la fiecare trecere, dimensiunea zonei cautate se înjumatateste. Cazul cel mai
defavorabil este ca elementul cautat sa nu se gaseasca în vector. Pentru simplitate se considera n = 2k
unde k este numarul de înjumatatiri.
Rezulta k = log2 n si facând o majorare, T(n) £log2 n + 1 ® $ n, a.î. 2k £ n < 2k+1.
Rezulta complexitatea acestui algoritm: este O(log2n). Dar, baza logaritmului se poate
ignora, deoarece: logax = logab · logbx si logab este o constanta, deci ramâne O(log n), adica o
functie logaritmica.

Proprietati:

1) Fie f, g : N ® N.
Daca f = O(g) Þ | k ´ f = O(g)
| f = O(k ´ g) , " k Î R constant.

2) Fie f, g, h : N ® N.
si: f = O(g) |
g = O(h) | Þ f = O(h)

3) Fie f1, f2, g1, g2 : N ® N.


si: f1 = O(g1) | Þ | f1 + f2 = O(g1 + g2)
f2 = O(g2) | Þ | f1´ f2 = O(g1´g2)

Aceasta proprietate permite ca, atunci când avem doua bucle imbricate (de complexitati
diferite), complexitatea totala sa se obtina înmultindu-se cele doua complexitati. Cele doua
complexitati se aduna, daca buclele sunt succesive.

Teorema:
Oricare ar fi doua constante c > 0, a > 1, si " f : N ® N, o functie monoton strict crescatoare,
atunci:
(f(n))c= O(af(n))
Demonstratia se bazeaza pe limita:
xp
lim ( a , p )
x  a x

Între clasa functiilor polinomiale si cea a functiilor exponentiale exista relatia: O(nc) Ì O(an).

Au loc urmatoarele incluziuni:


O(1) Ì O(log n) Ì O(n) Ì O(n×log n) Ì O(n2) Ì … Ì O(nk×log n) Ì O(nk+1) Ì O(2n)
Pentru calculul complexitatii se va încerca încadrarea în clasa cea mai mica de complexitate din
acest sir:
O(1) ¾ clasa algoritmilor constanti;
O(log n) ¾ clasa algoritmilor logaritmici;
O(n) ¾ clasa algoritmilor liniari;

5
O(n×log n) ¾ clasa algoritmilor polilogaritmici;
O(n2) ¾ clasa algoritmilor patratici;
O(nk×log n) ¾ clasa algoritmilor polilogaritmici;
O(nk+1) ¾ clasa algoritmilor polinomiali;
O(2n) ¾ clasa algoritmilor exponentiali.

Tehnici de calcul a complexitatii


Se folosesc urmatoarele sume:
n
n ( n  1)
i  2
 O(n2 )
i 1
n
n ( n  1)  ( 2 n  1)
 i2  6
 O(n3 )
i 1
n
n2 ( n  1)2
 i3 
4
 O(n4 )
i 1
n
 21  2n1 - 1
i 0
n
Sa calculam, de exemplu, suma:  i  21
i 1
n
Se noteaza: G ( n)   i  21
i 1
n n n n
G (n)  2  G (n)  G (n)   2i  2 1   i  2 1   i  2 11   i  2 1 
i 1 i 1 i 1 i 1
n n
 n  2 n 1  2   (i  1  i )  2 1  n  2 n 1  2   2 1  (n  1)  2 n 1  2
i 2 i 2

n
Prin aceeasi tehnica se calculeaza suma:  (n  1)  21
i 1

S-ar putea să vă placă și