190 likes | 392 Views
C 5 / 28.10.2008. Fundamentele program ă rii. Curs Data 1 30 Septembrie 2008 2 7 Octombrie 2008 3 1 4 Octombrie 2008 4 21 Octombrie 2008 5 28 Octombrie 2008 … …. Corectitudinea Algoritmilor. Noţiunea de corectitudine Dezvoltarea algoritmilor din specificaţii.
E N D
C5 / 28.10.2008 Fundamentele programării Curs Data 1 30 Septembrie 2008 2 7Octombrie 2008 3 14Octombrie 2008 421Octombrie 2008 5 28 Octombrie 2008 … …
Corectitudinea Algoritmilor • Noţiunea de corectitudine • Dezvoltarea algoritmilor din specificaţii
VarDeIntrare X VarDeIesire Z Program P VarDeLucru Y Noţiunea de corectitudine : Program corect : satisface specificaţiile problemei (pentru datele de intrare care satisfac specificaţiile, rezultatele sunt corecte). Nu ne interesează: memorie, nr. de instrucţiuni, timp de execuţie Predicat de intrare sau precondiţie φ(X): pentru a preciza datele pentru care problema are sens (pentru celelalte nu are sens să executăm programul). Predicat de ieşiresau postcondiţie ψ(X,Z): pentru a preciza relaţia dintre rezultatele Z şi datele iniţiale X. Acesta este corect pentru acele valori a şi b ale vectorilor X şi Z pentru care rezultatele sunt b în cazul când datele iniţiale sunt a şi este fals în caz contrar.
Specificaţie : Specificaţia problemei : - predicatul de intrare φ(X)–precondiţie şi - predicatul de ieşire ψ(X,Y)–postcondiţie. Ex.:Să se calculeze radical (r) dintr-un număr real pozitiv x. Specificaţia problemei este: precondiţia φ(X): "x>0" , postcondiţia ψ(X,Z): "r2=x" . Corect:Să se calculeze r. din x cu o eroare absolută maximă ε dată. Vectorul de intrare este X=(x,ε) iar specificaţia este: (X): "x>0 şi ε>0" ; ψ(X,Z): "r2-x<ε" .
Program corect: Programul P se termină în raport cu predicatul de intrare φ(X) dacă pentru orice intrare aX pentru care predicatul φ este adevărat, execuţia lui P se termină. P este parţial corect în raport cu specificaţiile problemei dacă pentru intrarea a pentru care φ(a) este adevărat şi execuţia programului se termină cu rezultatele b=P(a) atunci ψ(a,b) este adevărat. P este total corect în raport cu specificaţiile problemei dacă programul P se termină şi dacă el este parţial corect în raport cu aceste specificaţii. Există diverse metode de demonstrare a corectitudinii unui program. Vom prezenta metoda aserţiunilor inductive propusă lui Floyd (pentru corectitudinea logică a programelor nu sintactică).
Pi(X,Y)Rα(X,Y) Pj(X,Y) o o i α j Metoda aserţiunilor inductive: • Se aleg puncte de tăietură: • cel puţin unul în fiecare buclă, • un punct de tăietură la început (după citire) şi • un punct de tăietură la sfârşit (înaintea blocului de tipărire a rezultatelor). • În fiecare punct de tăietură se alege un predicat invariant: • în punctul de tăietură de intrare predicatul invariant este φ(X), • în punctul de tăietură de ieşire predicatul invariant este ψ(X,Z), • pentru un drum α de la i la j vom nota: • - Rα(X,Y) predicatul de traversare, • - rα(X,Y) funcţia de transformare a var. intermediare Y (la traversare). • Schematic, putem reprezenta notaţiile făcute astfel: Acestui drum i se asociază condiţia de verificare: XY (Pi(X,Y) Rα(X,Y) Pj(X,rα(X,Y)))
Program partial corect: Teorema.Dacă toate condiţiile de verificat sunt adevărate atunci programul P este parţial corect în raport cu specificaţiile φ(X) şi ψ(X,Z). Ex.: { Cmmdc(n1,n2) } Algoritmul Cmmdc(n1,n2) Este: Date n1,n2; { A: φ(X)::= n1N, n2N} Daca n1=0 Atunci d:=n2; i:=0 Altfel d:=n1; i:=n2 SfDaca; CatTimp (di) Si (i>0) Executa{ B: RAB:: = (d,i)=(n1,n2)} Daca d>i Atunci d:=d-i Altfel i:=i-d SfDaca SfCat;{ C: ψ(X,Z)::= d=(n1,n2)} Rezultate d; SfAlg. Variabilele X, Y, Z sunt: X = (n1, n2), Y = (d, i) şi Z = (d).
Drumurile sunt: α1 = AB, α2 = BB şi α3 = BC . Condiţiile de parcurgere sunt: Rα1(X,Y) = (di) (i>0) ; Rα2(X,Y) = (di) (i>0) ; Rα3(X,Y) = not [(di) (i>0)] <=> (d=i) (i=0) . Transformările sunt: rα1(X,Y) = (n1,n2) ; rα2(X,Y) = Dacă d>i atunci (d-i,i) altfel (d,i-d); rα3(X,Y) = rα2(X,Y). Condiţiile de verificare sunt: Cα1 = (n1n2) (0n2) ( (n1,n2)=(n1,n2) ) ; Cα2 = ((d,i)=(n1,n2)) (di) (i0) ((d>i) (d-i,i)=(n1,n2)) ((d<i) (d,i-d)=(n1,n2)) ; Cα3 = ((d,i)=(n1,n2)) ((d=i) (i=0)) ( d=(n1,n2) ).
Terminarea programului : Definiţie .O mulţime este convenabilă dacă ea este parţial ordonată şi nu conţine nici un şir descrescător infinit. Ex. : - mulţimea numerelor naturale N cu relaţia "<" , - şi mulţimea N x N cu ordinea lexicografică: (m1,n1)<(m2,n2) dacă (m1<m2)(m1=m2) (n1<n2). Înpunctul de tăietură i se alege o funcţie ui : DX x DY M, iar condiţia de terminare pentru drumul α este: XY (Pi(X,Y)Rα(X,Y) ui(X,Y) > uj(X,rα(X,Y)) Pentru algoritmul Cmmdc alegem: u1(X,Y) = 2*n1 + 2*n2; u2(X,Y) = d + i; u3(X,Y) = 0, iar condiţiile de terminare corespunzătoare acestor drumuri sunt: Tα1 = (n1n2)(n2>0) (2*n1+2*n2 >n1+n2) ; Tα2 = (PB(d>i)(i>0) d+i>d) sau (PB(d<i)(i>0) d+i>i) ; Tα3 = True .
Tema: Demonstraţi parţial-corectitudinea subalgoritmului CAT(m,n,q,r) în raport cu specificaţia: Precondiţia: m≥0, n≥0 Postcondiţia: (m=n*q+r) (0≤r<n) . Subalgoritmul CAT(m,n,q,r) este: Fie (q,r):=(0,m) Câttimp rx execută {P1: : (m=q*n+r) (0r) invariant} (r,d,q1):=(r-n,n,1); Câttimp rd+d execută { P2: : (m=q*n+r+q1*n) (0r)} (r,d,q1) := (r-d-d,d+d,q1+q1+1) sfcât q:= q+q1 sfcât Demonstraţi terminarea subalgoritmului CAT(m,n,q,r)în raport cu specificaţia: Precondiţia: m≥0, n>0 Postcondiţia: : (m=n*q+r) (0≤r<n)
Tema: Demonstraţi corectitudinea (parţial&terminarea=total) subalgoritmului RADICAL(n,r)în raport cu specificaţia: Precondiţia: n≥0 Postcondiţia: r2 <= n < (r+1)2 . Subalgoritmul RADICAL(n,r)este: r:=0; q:=s; Câttimp r+1q execută {I: r2 <= n < q2 invariant} p:= (r+q)/2; Dacă s<p2 atunci q:= p; altfel r:=p sfdacă sfcât Sfrad.
Dezvoltarea algoritmilor din specificaţii: Reguli: specificaţii algoritmul final corect. Rafinare în paşi succesivi: versiunea iniţială (doar specificaţia). Propoziţia nestandard [φ1, ψ1] repr.: pornind execuţia dintr-o stare în care precondiţia φ1este adevarată se ajunge într-o stare în care postcondiţia ψ1e adevărată. In procesul de rafinare o versiune Pnou va fi obţinută din versiunea Pvechi prin rafinarea unor specificaţii cu aplicarea unor reguli. PnourafineazăPvechi : Pvechi Pnou Iniţial avem [φ, ψ] - program abstract, notat cu P0. Procesul de rafinare a specificaţiilor va porni de la P0, va trece prin versiunile intermediare P1, P2, , Pn-1, pentru a ajunge la programul final Pn, aplicând regulile de rafinare permise, descrise în continuare: P0 P1 ... Pn-1 Pn .
Reguli de rafinare : Notam rezultatul substituirii în predicatul φ1(z) a var. z prin expr. e cu φ1(z|e) . Regula atribuirii: Dacă pre post[w|e] atunci [pre, post] w:=e Regula compunerii secvenţiale (prog1 ; prog2): Oricare ar fi formula mijloc avem [pre,post] [pre,mid] ; [mid,post] Regula alternanţei: Fie b1 un predicat şi b2 negaţia lui. Specificarea [pre,post] (se rafineaza la): Daca b1 Atunci[b1 pre, post] Altfel [b2 pre, post] SfDaca
… Reguli de rafinare : Regula iteraţiei: Pentru o formulă inv şi o expresie întreagă e, specificarea [inv, inv not b1 ] (se poate rafina la) : CâtTimp b1 execută [inv b1, inv (e<e0)] SfCât unde e0 este valoarea expresiei e cu valori naturale înainte de execuţia propoziţiei nestandard din interiorul lui CâtTimp, deci paranteza din postcondiţie este condiţia de terminare a ciclului. - inv este un predicat invariant. Simpificam notatia prin: [pre, inv, post] :: = [pre inv, inv post]
Exemplu:Înmulţirea prin adunări repetate (x*y) : Specificare: φ : TRUE ψ : z = x*y P0 : [TRUE; z = x*y ] P1: [ TRUE ; z + u*v = x*y] ; [z + u*v = x*y ; z = x*y ] R.Comp.Secv. P2: (z,u,v):=(0,x,y); [z + u*v = x*y ; z = x*y ] P3: (z,u,v):=(0,x,y); [z + u*v = x*y ; (z + *u*v = x*y) (v=0) ] R.Atr. Rescr. F. echiv. z + u*v = (z+u) + u*(v-1) P4: (z,u,v):=(0,x,y); Câtimp v > 0 execută [v>0, (z + u*v = x*y), v<=0] SfCâtTimp P5: (z,u,v):=(0,x,y); Câtimp v > 0 execută (z,v):=(z+u,v-1) SfCâtTimp R.Iter. R.Atr.
… Exemplu: Înmulţirea prin adunări repetate (x*y) : (v e par) (v e impar) = TRUE P6: (z,u,v):=(0,x,y); Câttimp v > 0 execută Dacă v e par atunci [v par, z + u*v = x*y ; (v = v/2)] altfel [v impar ; (z + u*v = x*y), v=v-1] sfdacă sfcât R. Alternantei. z + u*v = z + (u+u)*(v/2) P7: (z,u,v):=(0,x,y); Câttimp v > 0 execută Dacă v e par atunci (u,v) : = (u*u, v div 2) altfel (v,z) : = (v-1,z+u) sfdacă sfcât P8: (z,u,v):=(0,x,y); Câtimp v > 0 execută Câttimp v e par execută [v e par, z + u*v = x*y ; (v = v/2)] SfCâtTimp; [v impar ; (z + u*v = x*y), v=v-1] SfCâtTimp P9: (z,u,v):=(0,x,y); Câtimp v > 0 execută Câttimp v e par execută (u,v) : = (u*u, v div 2) SfCâtTimp; (v,z) : = (v-1,z+u) SfCâtTimp
Tema: Descompunerea unui număr în factori primi Notaţii: P=(p1,p2,..., pn); E=(e1,e2,..., en) PUTERE(p,e) = pe; PRODUS(k,P,E) ::= PUTERE(p1,e1)*PUTERE(p2,e2)*...*PUTERE(pk,ek) PRIME(k,P,E) ::= ("pi este prim şi ei>0", pentru i=1,k) Specificarea problemei: Precondiţia: nN; n2; Postcondiţia: (n = PRODUS(k,P,E) ) PRIME(k,P,E) Predicatul invariant (inv) :n = m*PRODUCT(k,P,E) PRIME(k,P,E) Programul abstract:P0: [n>2; (n = PRODUS(k,P,E) ) PRIME(k,P,E)] Varianta finală:P8: (k,m,f):= (0,n,2) ; Câttimp m1 execută Dacă m mod f = 0 atunci {aici f este prim} (k,Pk+1,ek+1,m) :=(k+1,f,1,m/f); { f este pus în P si inv rămâne adevărat} Câttimp m mod f =0 execută {aici Pk=f} (m,ek)=(m/f,ek+1) sfcât {aici m mod f 0} sfdacă f:=f+1 {deci diferenţa dintre n şi f scade} sfcât
Alt/e Teme: 1. Aflarea celui mai mare divizor comun a două numere: Precondiţia: x,y N; Postcondiţia: d=cmmdc(x,y) 2. Aflaţi câtul şi restul unei împărţiri întregi: Precondiţia: (x0) (y>0) Postcondiţia: (x=q*y+r) (0r<y) 3. Radicalul întreg dintr-un număr natural: Precondiţia: sN Postcondiţia: r = partea întreagă din radical din s, adică r2≤s<(r+1)2 4. Ridicare la putere prin înmulţiri repetate: Precondiţia: (x>0) (y0) Postcondiţia:: z = xy 5. Suma componentelor unui vector: Precondiţia: n≥1 Postcondiţia:: s = a1 + a2 + ... + an
6. Căutare secvenţială: găsiţi poziţia pe care se află un număr într-un şir: Precondiţia: (0<jn, ajR) (xR); Postcondiţia: (j, 0<ji, xaj) (i=n conditional x=ai+1) (0in) 7. Căutare binară Precondiţia: (i, 1i<n, ai ai+1) (a1 x an) Postcondiţia: (1r<N, arxar+1) 8. Sortare: Se dă vectorul A cu n componente. Să se ordoneze crescător. Preconditia: True, Postconditia: ORD(n,A) şi (A=Perm(A0)) unde ORD(n,A) ::= ( i,j: 1i,jn, ij aiaj), iar Perm(A0) este o permutare a vectorului A0, prin A0 notându-se valoarea iniţială a vectorului A 9. Descompunerea unui număr în produs de doi factori specificaţia: Precondiţia: nN Postcondiţia: n=x*y . . . C5 / 28.10.2008