Home - qdidactic.com
Didactica si proiecte didacticeBani si dezvoltarea cariereiStiinta  si proiecte tehniceIstorie si biografiiSanatate si medicinaDezvoltare personala
referate stiintaSa fii al doilea inseamna sa fii primul care pierde - Ayrton Senna




category
Aeronautica Comunicatii Drept Informatica Nutritie Sociologie
Tehnica mecanica


Informatica


Qdidactic » stiinta & tehnica » informatica
Corectitudinea algoritmilor



Corectitudinea algoritmilor



CORECTITUDINEA ALGORITMILOR


A program and its proof should be developed

hand-in-hand, with the proof usually leading the way.

Gries [Gri85]


5.1Notiunea de corectitudine


Un program este corect daca el satisface specificatiile problemei. Nu ne intereseaza cata memorie foloseste acest program, din cate instructiuni este compus, sau cat timp de executie necesita. Cu alte cuvinte, un program este corect daca pentru acele date de intrare care satisfac specificatiile problemei rezultatele obtinute in urma executiei sunt corecte.



Pentru orice program P deosebim trei tipuri de variabile, pe care le vom grupa in trei vectori X, Y si Z. Componentele vectorului X desemneaza variabilele de intrare, deci datele presupuse cunoscute in problema rezolvata prin programul P. Componentele vectorului Z sunt variabilele care reprezinta rezultatele cerute de problema. In sfarsit, componentele vectorului Y sunt variabilele de lucru, care noteaza diferitele rezultate intermediare necesare in program.

O problema nu are sens pentru orice date de intrare. Vom folosi predicatul φ(X) pentru a preciza datele pentru care problema are sens. φ(X) se numeste predicat de intrare sau preconditie. Pentru acele valori ale lui X pentru care predicatul este adevarat problema are sens, pentru celelalte nu are sens sa executam programul P.

Intre rezultatele Z ale problemei si datele initiale X (cunoscute in problema) exista anumite relatii. Vom reda aceste relatii prin predicatul de iesire ψ(X,Z), numit si postconditie. Acesta este corect pentru acele valori a si b ale vectorilor X si Z pentru care rezultatele problemei sunt b in cazul cand datele initiale sunt a si este fals in caz contrar. Deci, daca executand programul cu datele initiale a obtinem rezultatele b' si ψ(a,b') este fals, acest fapt este un indiciu ca rezultatele obtinute in program nu sunt corecte.


Definitia 5.1.1. Spunem ca cele doua predicate, predicatul de intrare φ(X) si predicatul de iesire ψ(X,Y), constituie specificatia problemei. Cele doua predicate se mai numesc preconditie, respectiv postconditie.

Se subintelege ca pentru a cunoaste aceasta specificatie trebuiesc cunoscuti si vectorii X si Z.

Astfel, daca in problema se cere sa se calculeze radicalul de ordinul 2 (notat prin r) dintr-un numar real pozitiv x, specificatia problemei este data prin predicatele:


φ(X): 'x>0' (preconditia)

ψ(X,Z):'r2=x' (postconditia)


Aceasta specificatie este corecta pentru un matematician, dar nu si pentru un programator. Numarul real r este in general transcendent si nu poate fi reprezentat in calculator decat aproximativ. Deci nu exista procedeu finit prin care putem calcula pe r. Putem construi insa un program care sa aproximeze oricat de bine pe r si va trebui sa adaugam acest lucru la enuntul problemei, care devine: se cere sa se calculeze r cu o eroare absoluta maxima ε data. In aceasta situatie vectorul de intrare este X=(x,ε) iar specificatia problemei va fi:


j(X):'x>0 si ε>0' ;

ψ(X,Z): ' r2-x <ε' .

Se observa mai bine si semnificatia “preciziei” ε. Am ales ca el sa majoreze diferenta dintre r2 si x intrucat diferenta dintre r si valoarea exacta a radicalului e necunoscuta.

Nu putine sunt cazurile in care executia programului intra intr-un ciclu infinit, deci nu se mai termina. Este un caz nedorit, care trebuie evitat in programare.

Referitor la corectitudinea programelor dam urmatoarele definitii:


Definitia 5.1.2. Spunem ca programul P se termina in raport cu predicatul de intrare φ(X) daca pentru orice intrare a = (a1,a2,, an) a vectorului X pentru care predicatul φ este adevarat, executia lui P se termina.


Definitia 5.1.3. Spunem ca programul P este partial corect in raport cu specificatiile problemei daca pentru intrarea a pentru care φ(a) este adevarat si executia programului se termina cu rezultatele b=P(a) atunci ψ(a,b) este adevarat.


Definitia 5.1.5. Spunem ca un program P este total corect in raport cu specificatiile problemei daca programul P se termina si daca el este partial corect in raport cu aceste specificatii.


Exista mai multe metode de demonstrare a corectitudinii unui program. In continuare vom prezenta metoda asertiunilor inductive datorata lui Floyd [Floyd67], metoda care considera algoritmii reprezentati prin scheme logice. Subliniem ca e vorba de corectitudinea logica a programelor si nu de corectitudinea lor sintactica. De aceea nu conteaza forma sub care e dat algoritmul: fie scris intr-o schema logica, fie in Pseudocod, fie intr-un limbaj de programare. In acest capitol prin program ne referim la algoritmul corespunzator, indiferent de forma in care e scris.

Metoda cere alegerea unor puncte in schema logica, numite puncte de taietura. Se va alege cel putin un punct de taietura in fiecare bucla, un punct de taietura la inceputul schemei logice (dupa blocul de citire) si un punct de taietura la sfarsitul schemei logice (inaintea blocului de tiparire a rezultatelor) .

In fiecare punct de taietura se alege un predicat invariant. In punctul de taietura de intrare predicatul invariant este φ(X), iar in punctul de taietura de iesire predicatul invariant este ψ(X,Z).

Pentru o pereche (i,j) de puncte de taietura pot exista mai multe drumuri de la i la j. Fie α un astfel de drum cu proprietatea ca el nu contine un alt punct de taietura. Vom nota prin Rα(X,Y) predicatul care ne da conditia ca sa se parcurga acest drum si prin rα(X,Y) functia care da transformarea variabilelor intermediare Y la traversarea drumului α. Schematic, putem reprezenta notatiile facute astfel:


Pi(X,Y) Rα(X,Y)                         Pj(X,Y)

o──────────────────────────────────→o

i α j


Acestui drum i se asociaza conditia de verificare:


X Y (Pi(X,Y) Rα(X,Y) Pj(X,rα(X,Y)))


Subliniem ca intre doua puncte de taietura pot exista mai multe drumuri directe distincte.

Floyd [Floyd67] demonstreaza urmatoarea teorema:


Teorema 5.1.1. Daca toate conditiile de verificat sunt adevarate atunci programul P este partial corect in raport cu specificatiile φ(X) si ψ(X,Z).


Ca exemplu de demonstrare a corectitudinii unui program sa consideram urmatorul algoritm de calcul al celui mai mare divizor comun a doua numere date:


ALGORITMUL CMMDC1(n1,n2,d) ESTE:

DATE n1,n2;                                     

FIE d:=n1;

FIE i:=n2;

CATTIMP (d i) SI (i>0) EXECUTA           

DACA d>i ATUNCI d:=d-i

ALTFEL i:=i-d

SFDACA

SFCAT

REZULTATE d;

SFALGORITM


Variabilele folosite, grupate in cei trei vectori X, Y, Z sunt:


X = (n1, n2), Y = (d, i) siZ = (d).


Drumurile posibile in acest algoritm sunt: α1 = AB, α2 = BB si α3 = BC, iar conditiile de parcurgere a acestor drumuri sunt:


Rα1(X,Y) = (d i) (i>0) ;

Rα2(X,Y) = (d i) (i>0) ;

Rα3(X,Y) = not [(d i) (i>0)] <=> (d=i) (i=0) .


Transformarile pe aceste drumuri sunt date de:


rα1 X,Y n1,n2

rα2 X,Y = Daca d>i atunci (d-i,i) altfel (d,i-d);

rα3(X,Y) = rα2(X,Y).


Corespunzator acestor drumuri avem urmatoarele conditii de verificare:


Cα1 = (n1 n2) ∧ (0 n2) ( (n1,n2)=(n1,n2) ) ;

Cα2 = ((d,i)=(n1,n2)) ∧ (d i) ∧ (i 0)

((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) ).


Se poate verifica usor ca toate aceste conditii sunt adevarate.


Pentru a demonstra terminarea programelor vom folosi notiunea de multime convenabila.


Definitia 5.1.5. O multime este convenabila daca ea este partial ordonata si nu contine nici un sir descrescator infinit.


Exemple de multimi convenabile sunt multimea numerelor naturale N cu relatia '<' si multimea NxN cu ordinea lexicografica:


(m1,n1)<(m2,n2) daca (m1<m2)(m1=m2) ∧ (n1<n2).


Pentru a demonstra terminarea algoritmului va trebui sa demonstram ca anumite conditii de terminare au loc. Aceste conditii spun ca la trecerea prin schema logica (algoritm) de la un punct de taietura la altul valorile unor functii in multimea convenabila aleasa scad. Intrucat nu putem construi un sir (infinit) descrescator rezulta ca nu vom trece de la un punct de taietura la alt punct de taietura de o infinitate de ori, deci executia este finita; cu alte cuvinte algoritmul se termina. Prin urmare, in punctul de taietura i se alege o functie ui : DX x DY M, iar conditia de terminare pentru drumul α este:

X Y (φ(X) Rα(X,Y) (ui(X,Y)>uj(X,rα(X,Y) )


In cazul in care s-a demonstrat partial corectitudinea si Pi(X,Y) a fost predicatul invariant in punctul i, conditia de terminare pentru drumul α care duce de la punctul i la punctul j se poate lua:


X Y (Pi(X,Y) Rα(X,Y) (ui(X,Y) > uj(X,rα(X,Y)) )


Pentru algoritmul CMMDC1 avem trei puncte de taietura, pentru care alegem:

u1(X,Y) = 2*n1 + 2*n2;

u2(X,Y) = d + i;

u3(X,Y) = 0,


iar conditiile de terminare corespunzatoare acestor drumuri sunt:

Tα1 = (n1 n2) (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 .


Se poate verifica ca toate cele trei conditii sunt adevarate pentru n1>0, dar Tα2 este falsa daca n1=0, intrucat d ia valoarea 0 si inegalitatea i>i este falsa. In acest caz drumul α2 este parcurs de o infinitate de ori, deoarece variabilele d si i nu-si modifica valorile la parcurgerea acestui drum. Pentru a obtine un algoritm total corect este necesara modificarea algoritmului CMMDC1 astfel incat sa nu se intre in drumul α2 daca d=0. Obtinem urmatorul algoritm total corect:


ALGORITMUL CMMDC2(n1,n2,d) ESTE:

DATE n1,n2;                             

DACA n1=0 ATUNCI FIE d:=n2; i:=0

ALTFEL FIE d:=n1; i:=n2;

SFDACA

CATTIMP (d i) SI (i>0) EXECUTA                               

DACA d>i ATUNCI d:=d-i

ALTFEL i:=i-d

SFDACA

SFCAT


REZULTATE d;

SFALGORITM


Demonstrarea corectitudinii algoritmilor poate fi facuta dupa elaborarea lor, sau in timp ce sunt conceputi. Am vazut ca ea presupune scrierea unor predicate invariante corespunzatoare punctelor de taietura, deci ea impune proiectantului respectarea unei discipline in programare. Foarte probabil ca aceste predicate invariante sunt sugerate de semnificatiile variabilelor. Deci este necesar ca fiecare variabila sa aiba semnificatia ei si sa nu fie folosita in scopuri diferite.

Gries [Gries89] spunea: Proiectarea programului si demonstrarea corectitudinii lui trebuie facute in paralel. Intr-o astfel de proiectare convingerea programatorului ca a conceput un algoritm corect creste, iar scrierea predicatelor invariante reduce numarul erorilor in programare. De asemenea, daca s-ar incerca demonstrarea corectitudinii algoritmilor descrisi, multe erori ar fi descoperite si eliminate in faza de proiectare.

Pornind de la aceasta afirmatie vom exemplifica in sectiunea urmatoare cum putem obtine algoritmi corecti prin rafinari succesive, pornind din specificatii. Rezulta din exemplele date ca in prim plan este demonstratia corectitudinii, propozitiile care compun algoritmul fiind o consecinta a acestei demonstratii.



5.2. Dezvoltarea algoritmilor din specificatii


In cele ce urmeaza vom prezenta mai multe reguli ce vor fi aplicate pentru a ajunge de la specificatii la algoritmul final corect. Este vorba despre o rafinare in pasi succesivi, in care unele parti din program sunt exprimate cu instructiuni din limbaj, altele, inca nefinisate, sunt doar specificate. La plecare, in versiunea initiala, avem doar specificatia, formata din cele doua predicate, de intrare si de iesire.

Regulile pe care le vom folosi in acest proces de rafinare se refera la propozitiile admise in descrierea algoritmilor si la reguli cunoscute din logica matematica. Propozitiile 'nestandard' folosite in acest proces de rafinare sunt specificatii care trebuie rafinate la un pas urmator. Astfel, prin propozitia nestandard


[φ1, ψ1]


vom nota acea parte de program care, pornind executia dintr-o stare in care preconditia φ1 este adevarata, ajunge intr-o stare in care postconditia ψ1 e adevarata.

Specificarea ne spune ce trebuie facut din punct de vedere al beneficiarului. Codul final, programul propriu-zis compus numai din instructiunile standard ale limbajului ales, spune calculatorului ce are de facut. Programatorul le intelege pe amandoua si actioneaza ca un translator. El transforma specificatiile, programul abstract, intr-un program executabil pe calculator. Procesul de realizare a acestui program final, adeseori dificil, va consta dintr-o succesiune de versiuni intermediare, compuse atat din specificatii (propozitii nestandard) cat si din propozitii standard (instructiunile limbajului).

In acest proces de rafinare o versiune Pnou va fi obtinuta din versiunea Pvechi prin rafinarea unor specificatii cu aplicarea regulilor care vor fi date putin mai jos. Spunem ca Pnou rafineaza pe Pvechi si scriem

Pvechi Pnou


Initial avem specificatia [φ, ψ], numita program abstract, notat cu P0. Procesul de rafinare a specificatiilor va porni de la programul abstract P0, va trece prin versiunile intermediare P1 , P2 , , Pn-1, pentru a ajunge la programul final Pn, aplicand regulile de rafinare permise, descrise in paginile care urmeaza. Redam acest proces sub forma:


P0 P1 Pn-1 Pn.


Regulile de rafinare sunt date in continuare. In cele ce urmeaza prin φ1(z|e) notam rezultatul substituirii in predicatul φ1(z) a variabilelor z prin expresiile e.


Regula atribuirii. Daca          pre T post[w|e]

atunci

[pre, post] w:=e


Urmatoarea regula se refera la compunerea secventiala

prog1 ; prog2

al carei efect consta in executia mai intai a partii de program prog1 urmata de executia lui prog2.


Regula compunerii secventiale. Oricare ar fi formula mijloc avem

[pre,post] [pre,mid] ; [mid,post]


Regula alternantei. Fie b1 orice predicat si fie b2 negatia lui b1. Specificarea [pre,post] se poate rafina la

DACA b1

ATUNCI [b1 pre, post]

ALTFEL [b2 pre, post]

SFDACA


Regula iteratiei. Pentru orice formula inv si e o expresie intreaga specificarea

[inv, inv not b1

se poate rafina la

Cattimp b1 executa

[inv b1, inv (0<=e<e0)]

sfcat


unde e0 este valoarea expresiei e cu valori naturale inainte de executia propozitiei nestandard din interiorul lui Cattimp, deci paranteza din postconditie este conditia de terminare a ciclului.

In regula de mai sus formula inv joaca rolul de predicat invariant. El apare atat in preconditie cat si in postconditie. Pentru a nu-l scrie de doua ori introducem notatia


[pre, inv, post] :: = [pre inv, inv post]


Cu regulile prezentate mai sus putem da exemple de rafinari.


Exemplul 5.2.1. Inmultirea prin adunari repetate. Daca x si y sunt doua numere naturale arbitrare se cere sa se obtina produsul lor, efectuand doar adunari. Avem urmatoarea specificare:

φ : TRUE

ψ : z = x*y


deci programul abstract P0 este

[TRUE; z = x*y ]


Aplicand regula compunerii secventiale cu predicatul

mijloc ::=z + u*v = x*y

ajungem la versiunea


P1:

[ TRUE ; z + u*v = x*y] ;

[z + u*v = x*y ; z = x*y ]


intrucat postconditia din primul rand este adevarata pentru substitutia (z,u,v) | (0,x,y)

aplicand regula atribuirii ajungem la versiunea


P2:

(z,u,v):=(0,x,y);

[z + u*v = x*y ; z = x*y ]


Pentru a continua vom scrie postconditia din randul doi intr-o forma echivalenta, astfel ca obtinem versiunea

P3:

(z,u,v):=(1,x,y);

[z + u*v = x*y ; (z u*v = x*y) (v=0) ]


Observand ca prima paranteza este predicat invariant, vom aplica regula iteratiei, ajungand la versiunea

P4:

(z,u,v):=(0,x,y);

Catimp v > 0 executa

[v>0, (z + u*v = x*y), v<v0]

sfcat


Prima posibilitate de a-l micsora pe v este v:=v-1. Pentru ca predicatul invariant sa ramana adevarat este necesara substituirea lui z cu z+u, intrucat

z + u*v = (z+u) + u*(v-1)

deci ajungem la versiunea


P5:

(z,u,v):=(1,x,y);

Cattimp v > 0 executa

(z,v):=(z+u,v-1)

sfcat


In versiunea P4 , in cazul in care v este par, o alta posibilitate de a-l micsora pe v este a-l injumatati prin atribuirea v:=v div 2, pastrand predicatul invariant adevarat. Intrucat

(v e par) ∨ (v e impar) = TRUE

aplicand regula alternantei ajungem la urmatoarea versiune:


P6: (z,u,v):=(0,x,y);

Cattimp v > 0 executa

Daca v e par

atunci[v e par,z + u*v = x*y ; (v = v0/2)]

altfel[v impar ; (z + u*v = x*y),v=v0-1]

sfdaca

sfcat


Pentru a pastra invariant predicatul z + u*v = x*y dupa atribuirea v := v / 2 este necesara atribuirea u := u+u intrucat

z + u*v =z + (u+u)*(v/2)

In cazul v impar stim din exemplul anterior ca ultima propozitie nestandard se rafineaza la atribuirea (v,z) := (v-1, z+u), astfel ca cele doua propozitii nestandard se rafineaza prin atribuiri si se ajunge la versiunea finala:


P7: (z,u,v):=(0,x,y);

Cattimp v > 0 executa

Daca v e par

atunci (u,v) : = (u*u, v div 2)

altfel(v,z) : = (v-1,z+u)

sfdaca

sfcat


In versiunea P4 , in cazul in care v este par si-l impartim la doi el poate ramane par. Aplicand de mai multe ori aceeasi micsorare (injumatatire) asupra lui v, acesta va deveni impar, caz in care se va micsora cu 1. Aplicand aceste transformari variantei P4 de mai sus ajungem la urmatoarea versiune:


P8: (z,u,v):=(0,x,y);

Cattimp v > 0 executa

Cattimp v e par executa

[v e par,z + u*v = x*y ; (v = v0/2)]

sfcat

[v impar ; (z + u*v = x*y),v=v0-1]

sfcat


Pentru a pastra invariant predicatul z + u*v = x*y dupa atribuirea v := v / 2 este necesara atribuirea u := u+u intrucat

z + u*v = z + (u+u)*(v/2)

Dupa aceasta rafinare se ajunge la varianta

Deja stim cum se rafineaza cele doua propozitii nestandard, astfel ca in doi pasi ajungem la versiunea:

P9:

(z,u,v):=(0,x,y);

Cattimp v > 0 executa

Cattimp v e par executa

(u,v) : = (u*u, v div 2)

sfcat

(v,z) : = (v-1,z+u)

sfcat


Exemplul 5.2.2 Descompunerea unui numar in factori primi

Pentru a simplifica scrierea vom face urmatoarele notatii:

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 si ei>0', pentru i=1,k)

Cu aceste notatii specificarea problemei noastre este:

Preconditia:nIN; n 2;

Postconditia: (n = PRODUS(k,P,E) ) PRIME(k,P,E)


De asemenea, vom nota prin inv urmatorul predicat:


n = m*PRODUCT(k,P,E) PRIME(k,P,E)


care va avea rolul de predicat invariant. Pornind de la programul abstract


P0:                     [n>2; (n = PRODUS(k,P,E) ) PRIME(k,P,E)]


si folosind regula compunerii secventiale obtinem versiunea:


P1:         [n>2; inv] ;

[inv ; ( n = PRODUS(k,P,E) ) PRIME(k,P,E)] ;


intrucat inv devine TRUE pentru k=0 si m=n, prima propozitie nestandard se rafineaza la o atribuire. Ajungem la versiunea:


P2:

(k,m):= (0,n) ;

[inv ; (n = PRODUS(k,P,E) ) PRIME(k,P,E)] ;


Postconditia se obtine din (m=1) inv astfel ca P2 se poate rafina la

P3:

(k,m):= (0,n) ;

[inv; inv (m=1)]


si folosind regula iteratiei ajungem la


P4:

(k,m):= (0,n) ;

Cattimp m 1 executa

[m>1 ; inv; conditie de terminare]

sfcat


Conditia de terminare ar putea fi m<m0 sau e<e0 pentru o anumita expresie e. Pentru a-l micsora pe m pastrand inv adevarat e nevoie sa “mutam” un factor din m in vectorul P. Avem nevoie de o variabila candidat a fi factor prim al lui m pe care o vom nota cu f. Primul candidat este numarul prim 2, astfel ca initial f trebuie sa primeasca valoarea 2, iar propozitia nestandard o vom rafina prin regula alternantei la:


P5:

(k,m):= (0,n) ; f:=2;

Cattimp m 1 executa

Daca m mod f = 0

atunci

[m mod f =0; inv ; f nu este factor al lui m]

altfel f:=f+1

sfdaca

sfcat


In propozitia nestandard inv este predicat invariant iar “f nu mai este factor al lui m” este o conditie de terminare, deci rafinarea se face cu regula iteratiei. Ajungem la versiunea


P6: (k,m):= (0,n) ; f:=2;

Cattimp m 1 executa

Daca m mod f = 0

atunci

(k,Pk+1,ek+1,m) :=(k+1,f,1,m/f);

Cattimp m mod f =0 executa

[m mod f = 0; inv ; (m=m0/f)]

sfcat

altfel f:=f+1

sfdaca

sfcat


Pentru ca inv sa ramana adevarat dupa atribuirea m:=m/f este necesar ca ek sa creasca cu 1, intrucat Pk=f. Ajungem la versiunea


P7:         (k,m):= (0,n) ; f:=2;

Cattimp m 1 executa

Daca m mod f = 0

atunci

(k,Pk+1,ek+1,m) :=(k+1,f,1,m/f);

Cattimp m mod f =0 executa

(m,ek)=(m/f,ek+1)

sfcat

altfel f:=f+1

sfdaca

sfcat


intrucat pe ramura atunci m se modifica astfel incat m nu se mai divide cu f, care este chiar conditia de pe ramura altfel, atribuirea f:=f+1 se poate muta in afara propozitiei Daca astfel ca obtinem varianta finala


P8:         (k,m,f):= (0,n,2) ;

Cattimp m 1 executa

Daca m mod f = 0 atunci

(k,Pk+1,ek+1,m) :=(k+1,f,1,m/f);

Cattimp m mod f =0 executa

(m,ek)=(m/f,ek+1)

sfcat

sfdaca

f:=f+1

sfcat



5.3 Probleme propuse


I. Folosind metoda lui Floyd, demonstrati corectitudinea algoritmilor precizati la fiecare caz.


1. Demonstrati partial-corectitudinea subalgoritmului CAT(m,n,q,r) in raport cu specificatia:

Preconditia: m≥0, n≥0

Postconditia: (m=n*q+r) ∧ (0≤r<n) .


1.

Subalgoritmul CAT(m,n,q,r) este:

Fie (q,r):=(0,m)

Cattimp r x executa

(r,d,q1):=(r-n,n,1);

Cattimp r d+d executa

(r,d,q1) := (r-d-d,d+d,q1+q1+1)

sfcat

q:= q+q1

sfcat


2. Demonstrati terminarea subalgoritmului CAT(m,n,q,r) in raport cu specificatia:

Preconditia: m≥0, n>0

Postconditia: : (m=n*q+r) si (0≤r<n) .


3. Demonstrati partial-corectitudinea subalgoritmului RADICAL(n,r) in raport cu specificatia:

Preconditia: n≥0

Postconditia: r2 <= n < (r+1)2 .

Subalgoritmul RADICAL(n,r) este:

r:=0; q:=s;

Cattimp r+1 q executa

p:= (r+q)/2;

Daca s<p2

atunci q:= p;

altfel r:=p

sfdaca

sfcat


4. Demonstrati terminarea subalgoritmului RADICAL(n,r) in raport cu specificatia:

Preconditia: n≥0

Postconditia: r2 <= n < (r+1)2 .


5. Demonstrati terminarea subalgoritmului CMMDC2(n1,n2,d) in raport cu specificatia:

Preconditia: n1≥0, n2≥0

Postconditia: d=cmmdc(n1,n2) .


Subalgoritmul CMMDC2(n1,n2,d) este:


Daca n1=0 atunci Fie d:=n2; i:=0

altfel Fie d:=n1; i:=n2;

sfdaca

Cattimp (d i) si (i>0) executa 

Daca d>i atunci d:=d-i

altfel i:=i-d

sfdaca

sfcat


SFCMMCD2


6. Demonstrati terminarea subalgoritmului FERMAT(n,x,y) in raport cu specificatia:

Preconditia: nIN

Postconditia: n=x*y

Subalgoritmul FERMAT(n, x,y) este:

(r,u,v):=(0,1,1);

Cattimp r n executa

Daca r<n

atunci (r,u):=(r+u,u+2)

altfel (r,v):=(r-v,v+2)

sfdaca

sfcat

sf-FERMAT


7. Demonstrati partial corectitudinea subalgoritmului FERMAT(n,x,y) in raport cu specificatia:

Preconditia: nIN

Postconditia: n=x*y


8. Demonstrati total corectitudinea urmatorului subalgoritm:


Algoritmul DIVINT(x,y,q,r) este:

(r, q) (x, 0)

Cattimp y r executa

r:= r-y;

q:=q+1;

sfcat


sf-DIVINT

II. Dezvoltati algoritmi corecti pentru urmatoarele probleme


1. Aflarea celui mai mare divizor comun a doua numere:

Preconditia: x,y I N;

Postconditia: d=cmmdc(x,y)


2. Aflati catul si restul unei impartiri intregi:

Preconditia: (x 0) (y>0)

Postconditia: (x=q*y+r) (0 r<y)


3. Radicalul intreg dintr-un numar natural:

Preconditia: sIN

Postconditia: r = partea intreaga din radical din s, adica r2≤s<(r+1)2


4. Ridicare la putere prin inmultiri repetate:

Preconditia: (x>0) (y 0)

Postconditia:: z = xy


5.5. Suma componentelor unui vector:

Preconditia: n≥1

Postconditia:: s = a1 + a2 + + an


6. Cautare secventiala: gasiti pozitia pe care se afla un numar intr-un sir:

Preconditia: (0<j n, ajIR) (xIR);

Postconditia: ( j, 0<j i, x aj) (i=n conditional x=ai+1) (0 i n)


7. Cautare binara

Preconditia: i, 1 i<n, ai ai+1) (a1 x an)

Postconditia: (1 r<N, ar x ar+1)


8. Sortare: Se da vectorul A cu n componente. Sa se ordoneze crescator.

Preconditia: True

Postconditia: ORD(n,A) si (A=Perm(A0))

unde

ORD(n,A) ::= ( i,j: 1 i,j n, i j T ai aj)

iar Perm(A0) este o permutare a vectorului A0, prin A0 notandu-se valoarea initiala a vectorului A


9. Descompunerea unui numar in produs de doi factori specificatia:

Preconditia: nIN

Postconditia: n=x*y




Contact |- ia legatura cu noi -| contact
Adauga document |- pune-ti documente online -| adauga-document
Termeni & conditii de utilizare |- politica de cookies si de confidentialitate -| termeni
Copyright © |- 2024 - Toate drepturile rezervate -| copyright