Documente Academic
Documente Profesional
Documente Cultură
5. Dezvoltarea unui algoritm corect pentru sortarea unei liste de chei folosind un inel.
Costul mediu costa(op) al unei operaii op, calculat pentru o secven oarecare
S de operaii ce acoper cazurile cele mai defavorabile, se numete cost amortizat al
operaiei, iar suma costa(op) este o margine superioar a costului secvenei S.
opS
empty(void) = 1
empty(ins(e,X)) = 0
top(ins(e,X)) = e
del(ins(e,X)) = X
move(ins(e,void)) = ins(e,void)
move(ins(e,ins(e',X))) = ins(e',move(ins(e,X)))
Corectitudine i complexitate
Inelul poate fi implementat ca o list circular, iar prelucrarea este banal dac
limbajul de programare folosit lucreaz direct cu pointerii din celulele listei. n acest caz
toate operaiile sunt n (1). S considerm ns c limbajul de programare folosit nu
lucreaz n mod direct cu pointeri ci dispune de tipul T List (list unidirecional cu
elemente de tip T), cu operatorii i specificaia formal de mai jos, unde:
nil este lista vid.
cons(e,L) construiete din lista L o list care are ca prim element e.
head(L) rentoarce elementul de la vrful listei nevide L.
tail(L) rentoarce lista rezultat prin decuparea elementului de la vrful lui L.
null(L) testeaz dac lista L este vid.
T List ::= nil | cons(T, T List)
head: T List\{nil} T
tail: T List\{nil} T List
null: T List bool
(1L)
(2L)
(3L)
(4L)
head(cons(e,L)) = e
tail(cons(e,L)) = L
null(nil) = 1
null(cons(e,L)) = 0
ek
ek+1
L
ek
e1
en
R
ek+1
en
void = Abspnil,nil
ins(e,AbspL,R) = AbspL,cons(e,R)
del(AbspL,R) = Absp(normalizeL,tail(R))
move(AbspL,R) = Absp(normalizecons(head(R),L),tail(R))
top(AbspL,R) = head(R)
empty(AbspL,R) = null(R)
Prin rescrierea celor doi termeni ai axiomei, conform axiomelor tipurilor T Ring,
T List i ecuaiilor de implementare, se ajunge la acelai inel.
move(ins(e,ins(e',X)))
= move(ins(e,ins(e',AbspL,R)))
2i move(ins(e,AbspL,cons(e',R)))
2i move(AbspL,cons(e,cons(e',R)))
4i,1L,2L Absp(normalize cons(e,L),cons(e',R))
norm Abspcons(e,L),cons(e',R)
= X'
ins(e',move(ins(e,X))
= ins(e',move(ins(e,AbspL,R)))
Corectitudine i complexitate
2i ins(e',move(AbspL,cons(e,R)))
4i,1L,2L ins(e',Absp(normalizecons(e,L),R))
norm ins(e',Abspcons(e,L),R)
2i Abspcons(e,L),cons(e',R)
= X'
din R, ca efect al operaiilor del i costul operaiilor top i empty. Costul tuturor acestor
operaii este (m). Rezult cost(S)= (m)+
(2m)= (m), iar costul amortizat al unei
operaii a inelului este (m)/m = (1).
Metoda utilizat mai sus pentru a estima costul mediu al unei operaii a inelului
unidirecional poart numele de analiz de ansamblu (n englez metoda este ntlnit
sub denumirea aggregate method). Se urmrete contorizarea execuiilor tuturor
suboperaiilor ce formeaz operaiile unei structuri de date n raport cu lungimea unei
secvene oarecare de astfel de operaii. Metoda calculeaz un singur cost amortizat
(cost mediu al operaiilor unei secvene oarecare de operaii care acoper cazurile cele
mai defavorabile) pentru toate operaiile unui algoritm, chiar dac operaiile au costuri
amortizate diferite.
opS
S asociem fiecrui element e din inel un credit credit(e) astfel nct creditul
iniial s fie 0. Doar operatorii del i move pot s modifice creditul elementelor unui
Corectitudine i complexitate
Invariantul arat c pentru orice element din inel creditul rmne mereu pozitiv.
n ipoteza n care operaiile ce nu modific inelul nu modific nici creditele elementelor,
iar costurile amortizate asociate operaiilor care modific inelul respect invariantul,
adic
I(void) (
X T Ring I(X) (
op
{ins,del,move} I(op(X))),
putem admite c, pentru orice secven de operaii i pentru orice inel, costul mediu al
unei operaii op este costa(op). Pentru constructorii void, ins, move i del
demonstraia este prin inducie structural.
Propoziia 2.6 Costurile amortizate ale constructorilor inelului AbspL,R menin
invariantul I(AbspL,R).
Caz de baz. X = Abspnil,nil, iar invariantul I(X) este satisfcut banal.
Pas de inducie. S considerm c pentru inelul X = AbspL,R, R
nil, cu n
elemente, invariantul I(X) este satisfcut (ipoteza inductiv). S artm c invariantul
este satisfcut dup orice operaie ins, del sau move aplicat lui X.
Pentru operaia ins(e,X) inelul devine AbspL,cons(e,R). Costul amortizat
costa(ins) este 1 exact ct cost(ins(e,X)) astfel nct credit(e)=0 i, conform
ipotezei inductive, invariantul I(AbspL,cons(e,R)) este satisfcut.
Pentru operaia move(X) = AbspL',R' fie e elementul de la vrful lui X,
anume e = top(X) = head(R).
Caz 1: tail(R)
nil. Operaia move are o singur faz: deplasarea lui e din R n
L, astfel nct L'= cons(e,L), R'= tail(R). Costul real al operaiei move(X) este 1,
iar diferena costa(move)-cost(move(X)) = 2-1 = 1 este adugat creditului
elementului e. Conform ipotezei inductive, naintea operaiei move avem credit(e)=0,
astfel nct credit(e)=1 dup move(X). Invariantul I(AbspL',R') este satisfcut.
Caz 2: tail(R)=nil. Operaia move are dou faze: transferul lui e din R n L i
apoi normalizarea efectiv a inelului, astfel nct L'= nil i R'= reverse(cons(e,L)).
a) Elementul e este mutat din R n L. Ca urmare a ipotezei inductive, creditul lui
e devine credit(e)=1, iar elementele din L au creditul 1. Invariantul
I(Abspcons(e,L),nil este satisfcut dup aceast prim faz.
b) Inelul este normalizat. Toate elementele din cons(e,L) sunt deplasate n
R'. Costul deplasrii unui element e este 1 i este suportat din creditul
credit(e)=1, astfel nct, odat ajuns n R', elementul e are credit(e)=0.
Invariantul I(Abspnil,reverse(cons(e,L))=I(move(X)) este satisfcut.
n cazul (2) exist n-1 elemente n lista L i un singur element n lista R, iar
costul real al operaiei move(X) este 1+n,. Dei costa(move)=2, diferena n-1 este
suportat din creditele elementelor aflate n L.
Pentru del(X) = AbspL',R', notm e = top(X) = head(R). Ca i pentru
move(X) exist dou cazuri.
nil. Operaia del are o singur faz: eliminarea lui e din R.
Caz 1: tail(R)
Rezult L'= L i R'= tail(R). Costul real al operaiei del(X) este 1 exact ct costul
amortizat, deci nu au loc modificri de credite. Conform ipotezei inductive, invariantul
I(AbspL,tail(R)) este satisfcut.
Caz 2: tail(R)=nil. Operaia del are dou faze: eliminarea elementului e din R
i normalizarea efectiv a inelului. Rezult L'=nil i R'= reverse(L).
a) Elementul e este eliminat din R. Operaia cost 1 exact ct costul amortizat
costa(del). Nu au loc modificri de credite i, conform ipotezei inductive,
invariantul I(AbspL,nil) este satisfcut.
b) Inelul este normalizat. Elementele din L sunt deplasate n R'. Costul
deplasrii unui element e este 1 i este suportat din creditul credit(e)=1,
astfel nct, odat ajuns n R', elementul e are credit(e)=0. Invariantul
I(Abspnil,reverse(L))= I(del(X)) este satisfcut.
n cazul (2) costul real al operaiei del(X) este n. Dei costa(del)=1, diferena
n-1 este suportat din creditele celor n-1 elemente aflate n L naintea operaiei. !
Deoarece suma creditelor elementelor din inel este ntotdeauna pozitiv, rezult
c pentru o secven oarecare S de m operaii ce pleac cu un inel vid X avem:
cost(S) =
cost(op)
opS
costa(op)
opS
2m,
(1)
costa(move)
S
Corectitudine i complexitate
i=1
i=1
costa(opi) = (cost(opi) +
Dac m 0 atunci
i i 1) =
i=1
i=1
cost(opi) +
i=1
m 0
costa(opi)=
i=1
consumat n lips.
10
respect restriciile:
(X) = 0 pentru un inel vid X = Abspnil,nil
(X) 0 pentru un inel oarecare X = AbspL,R
Caz #Ri-1 = 1. Dup transferul unicului element e=top(Ri-1) din Ri-1 are loc
normalizarea efectiv a inelului X'= Abspcons(e,Li-1),nil. Rezult, AbspLi,Ri =
Abspnil,reverse(cons(e,Li-1). Normalizarea inelului X' cost #Li-1+1.
cost(move(Xi-1)) = 1 + cost_normalizare(X') = 1 + #Li-1 + 1
i = #Li = #nil = 0
i-1 = #Li-1
costa(move) = cost(move(Xi-1)) + i - i-1 = 2
Corectitudine i complexitate
11
Caz #Ri-1 = 1. Dup eliminarea unicului element din Ri-1 are loc normalizarea
inelului X'= AbspLi-1,nil astfel nct AbspLi,Ri = Abspnil,reverse(Li-1).
Normalizarea inelului X' cost #Li-1.
cost(del(Xi-1)) = 1 + cost_normalizare(X') = 1 + #Li-1
i = #Li = #nil = 0
i-1 = #Li-1
costa(del) = cost(del(Xi-1)) + i - i-1 = 1
cost(move)
(1)
costa(opi)
i=1
= (m)
Metoda potenialului a fost aplicat mai sus pentru cazul particular (D0)=0.
Urmtoarea proprietate arat c analiza conduce la aceleai rezultate i pentru
(D0)>
>0 cu condiia ca (Di) (D0), i=1,m.
>0 i (Di) (D0), i=1,m, atunci exist o
Propoziia 2.7 Dac (D0)>
funcie de potenial ' astfel nct:
12
cost(opi) +
cost(opi) +
cost(opi) +
costa(opi).
'(Di) - '(Di-1)
(Di) - (D0) - (Di-1) + (D0)
(Di) - (Di-1)
Cu excepia op1, costurile amortizate pentru ' sunt aceleai ca i cele obinute
n cazul funciei de potenial . n ceea ce privete operaia op1, costul ei amortizat
este cel al unei secvene de operaii S' = op1', ..., opq', cu opq' = op1, care aduce
structura de date dintr-o stare cu potenialul 0 n starea D1.1
1 Putem considera op ca operaie compus din prelucrri ce pornesc de la o structur
1
Corectitudine i complexitate
13
14
empty(void) = 1
empty(ins(e,X)) = 0
top(ins(e,X)) = e
del(ins(e,X)) = X
move(ins(e,void)) = ins(e,void)
move(ins(e,ins(e',X))) = ins(e',move(ins(e,X)))
element(i,X) = elm(i mod size(X),X)
elm(0,X) = top(X)
elm((i+1),ins(e,X)) = elm(i,X), pentru i < size(X)
size(void) = 0
size(ins(e,X)) = 1+size(X)
sunt
utile
urmtoarele
dou
propoziii,
Corectitudine i complexitate
15
Propoziia 2.8 X
T Ring | empty(X) P1(X), cu P1(X)=def #move(X))= #X
Caz de baz. X = ins(e,void).
#move(ins(e,void)) 5 #ins(e,void)
Propoziia 2.9 i
,X
T Ring | empty(X) P2(i,X), unde
P2(i,X)=def element(i,move(X)) = element(i+1,X)
Caz de baz.
arbitrar.
element(i,move(ins(e,void)))
5 element(i,ins(e,void))
7 elm(i mod #ins(e,void),ins(e,void))
11,10 elm(i mod 1, ins(e,void))
mod elm(0, ins(e,void))
8,3 e
element(i+1,X)
7 elm((i+1) mod #ins(e,void),ins(e,void))
11,10 elm((i+1) mod 1, ins(e,void))
mod elm(0, ins(e,void))
8,3 e
16
element(i+1,ins(e,ins(e',X')))
7,11 elm((i+1) mod (2+#X'), ins(e,ins(e',X')))
[(i+1) mod (2+#X') = 1] elm(1, ins(e,ins(e',X')))
9 elm(0,ins(e'X'))
8,3 e'
element(1+#X', ins(e,X'))
7 elm((1+#X') mod ins(e,X'), ins(e,X'))
11 elm((1+#X') mod (1+#X'), ins(e,X'))
mod elm(0, ins(e,X'))
8,3 e
element(i+1, ins(e,ins(e',X')))
7,11 elm((i+1) mod (2+#X'), ins(e,ins(e',X')))
[(i+1) mod (2+#X') = 0] elm(0, ins(e,ins(e',X')))
8,3 e
Corectitudine i complexitate
17
Specificaie T Ring
Ring t
e:l
[]
(f x)
T Ring
cons(e,l)
nil (lista vid)
f(x)
18
element(i+1,x)
element(i,x)
x
= move_i(i,move(x))
Corectitudine i complexitate
19
20
i satisface axiomele
(p1) put(e,void) = ins(e,void)
(p2) put(e,ins(e',X)) = if e < e' then ins(e,ins(e',X))
else ins(e',put(e,X))
S artm c, pentru X
int Ring deja sortat nedescresctor, put(e,X)
produce un inel sortat nedescresctor. Pentru c avem nevoie de formalizarea noiunii
de inel sortat nedescresctor, definim urmtoarele predicate:
ord: int Ring bool i
min: int (int Ring) bool
astfel nct:
(o1) ord(void) = 1
(o2) ord(ins(e,X)) = min(e,X) ord(X)
(m1) min(e,void) = 1
(m2) min(e,ins(e',X)) = e e' min(e,X)
unde,
P'(e,e',X) =def min(e,put(e',X)) = e e' min(e,X)
P"(e,e',X) =def e e' min(e',X) min(e,X)
Corectitudine i complexitate
21
Propoziia 2.11 X
int Ring P(X). Demonstraia este prin inducie structural.
Caz de baz: X = void. S alegem e
T arbitrar.
P(e,void) = ord(void) ord(put(e,void))
o1 1 ord(put(e,void))
p1 1 ord(ins(e,void))
o2 1 min(e,void) ord(void)
m1,o1 1 1
= 1
fie
adevrat
trebuie
ca
Caz 2. e e'
ord(put(e,ins(e',X')))
p2 ord(ins(e',put(e,X')))
o2 min(e',put(e,X')) ord(put(e,X'))
ip.induct. P(e,X'), c2 min(e',put(e,X'))3
P'(e',e,X') e' e min(e',X')
Caz 2, c1 1
!
termenul
22
Dac dorim ca rezultatul sortrii s fie o list, inventm o funcie care descarc
elementele unui inel (indiferent de tipul elementelor) ntr-o list iniial vid.
ring_to_list: T Ring T List
ring_to_list(void) = nil
ring_to_list(ins(e,X)) = cons(e,ring_to_list(X))
| cons(top(X),ring_to_list(del(X)))
4 Motivul l constituie definirea constructorilor void i ins ca funcii implementate pe
baza constructorului Abs. Haskell nu accept ca parametrii formali ai funciilor s fie specificai
n forma unor aplicaii de funcii, aa cum cer axiomele nemodificate ale lui put i
ring_to_list. Totodat, codificarea din modulul RingSort are un avantaj: funcioneaz
corect cu ambele implementri ale inelului, conforme modulelor T_Ring i RingImpl.
Corectitudine i complexitate
23
5 foldr cere ca put s fie o funcie binar. n Haskell, put(e,x) definete o funcie
cu un singur parametru din mulimea produs int int Ring, n timp ce put e x descrie o
funcie binar cu primul parametru de tip int i al doilea parametru de tip int Ring. Diferena
este mai subtil: o funcie binar poate fi aplicat parial. Aplicarea asupra primului parametru
produce o funcie unar care ateapt cel de al doilea parametru. Din program, se vede c
nsi foldr este o funcie ternar care are proprieti similare.
24
Modulele Haskell de mai sus implementeaz mai mult dect sortarea unei liste
de ntregi. Ele descriu sortarea unei liste cu elemente de orice tip peste care este
definit o relaie de ordine. Generalitatea este vizibil din signatura Haskell a funciei
sort, sintetizat automat, anume:
RingSort> :type sort
sort :: Ord t => [t] -> [t]
Signatura arat c tipul t trebuie s fac parte din clasa Ord, clasa tipurilor
peste care este definit o relaie de ordine. Astfel, se poate scrie:
RingSort> sort [True,False]
[False,True] :: [Bool]
RingSort1> sort [2.1,3.0,3.14,0.1,4.5]
[0.1,2.1,3.0,3.14,4.5] :: [Double]
(i
i=1
1), D(n) =
(i) i
i=1
R(n) = (n)
Comentarii
Coninutul seciunii 2.7.6 depete cadrul strict al analizei algoritmilor, fiind la
intersecia urmtoarelor domenii: metode formale, programare funcional, analiza
algoritmilor. Dar morala este vizibil i important: este mai sigur i, n unele cazuri,
mai uor s se dezvolte teoretic un algoritm corect dect s fie construit un algoritm
"intuitiv" care, ulterior, trebuie verificat. Totodat, dezvoltarea elaborat, pornind de la
specificaii, poate salva timp i efort n procesul implementrii algoritmului i validrii
programului. Concluzia capt greutate mai ales pentru aplicaiile critice, acolo unde o
anomalie a algoritmului poate fi extrem de costisitoare.
Cine dorete s afle mai mult despre Haskell poate consulta [Tho 96] i adresa
http://www.haskell.org, unde se gsesc medii de programare Haskell, inclusiv
documentaie Haskell (manual de referin).