Sunteți pe pagina 1din 12

Dezvoltare de algoritmi coreci din specificaii

Elemente de teorie Notatie: prin [c1, c2] este notata o propozitie Pseudocod nestandard in care executia porneste dintr-o stare in care preconditia c1 este adevarat si se termina intr-o stare in care postconditia c2 este adevarata Daca este un predicat, atunci prin [x|e] se noteaza rezultatul substituirii in predicatul a variabilelor x cu expresiile e Daca variabila v apare si in preconditia si in postconditia unei parti de algoritm, in postconditie ea este notata prin v' pentru a sublinia ca are alta valoare dupa executia acestei parti de algoritm Reguli de rafinare R1:regula atribuirii: [c1, c2] poate fi rafinat prin vexp daca c2 devine adevarata dupa atribuirea vexp, sau formal c1 c2(v | exp) ( a se citi c1 implic c2 devine adevrat dup substituirea lui v prin exp) R2: regula compunerii secventiale: [c1, c2] este rafinat la [c1, mijloc] [mijloc, c2] pentru orice conditie mijloc R3: regula alternantei (DACA) Fie c o conditie (expresie booleana) si b negatia sa. Atunci [c1, c2] poate fi rafinat la DACA c atunci [c c1, c2] altfel [c c1, c2] SFDACA R4: regula iteratiei: [c1, c1 i c] este rafinat la cttimp c execut [c1 i c, c1 i cond.de terminare] sfct {aici c este adevarat} c este o conditie (expresie booleana) Exemplu 1 Inserare Fie A = (a1, a2,...,an) un vector cu n componente ordonate nedescresctor i fie x o valoare arbitrar. Inserai n vectorul A pe o poziie potrivit pe x astfel ca A s rmn ordonat i s conin o nou component egal cu x. Fie ORD urmtorul predicat:

ORD(n,A) ::= ( i,j: 1 i,j n, i j ai aj) care este adevrat cnd componentele vectorului A sunt ordonate nedescresctor. ::= ORD(n,A) (n natural) ::=ORD(n+1,A) i (A conine componentele iniiale plus o component egal cu x) Prin A0: [, ] notm un algoritm abstract care cere inserarea lui x n vectorul ordonat A cu pstrarea ordinei. Deoarece sunt 2 posibilitati, (x<an i n 0) sau ( x an sau (n=0) )avem A1: Subalgoritmul Insert(n,A,x) este: Dac x<an i n 0 atunci [ (x<an) n 0, ] altfel [ ((x an) (n=0)), ] sfdac sf-Insert

A doua propoziie nestandard se rafineaz printr-o atribuire A2: Subalgoritmul Insert(n,A,x) este: Dac x<an i n 0 atunci [ (x<an) n 0, ] altfel (n,an+1) (n+1,x) sfdac sf-Insert

S notm prin urmtorul predicat ORD(n,A) [ (x<a1) (p=1) (ap-1 x<ap) (1<p n)] Care este o postconditie pentru o problem de cutare i s folosim regula secvenei. Ajungem la: A3: Subalgoritmul Insert(n,A,x) este: Dac x<an i n 0 atunci [ (x<an) n 0, ] [ , ] altfel (n,an+1) (n+1,x) sfdac sf-Insert

Vom satisface postcondiia n urma apelului subalgoritmului de cutare, astfel c ajungem la:

A4:

Subalgoritmul Insert(n,A,x) este: Dac x<an i n 0 atunci Cheam SEARCH(x,n,A,p) [ , ] altfel (n,an+1) (n+1,x) sfdac sf-Insert

In urma cutrii tim c x se afl ntre ap-1 i ap astfel c x trebuie inserat pe poziia p, deci a'i+1 ai, pentru i=n,n-1,...,p iar a'p x. n'n+1 Realizm aceasta prin atribuirile in; Cttimp i p execut ai+1ai ii-1 sfct astfel c ajungem la versiunea final: A5: Subalgoritmul Insert(n,A,x) este: Dac x<an i n 0 atunci Cheam SEARCH(x,n,A,p) in Cttimp i p execut {i scade} ai+1ai ii-1 sfct apx nn+1 altfel (n,an+1) (n+1,x) sfdac sf-Insert

Mai putem rafina acest algoritm observnd c atribuirea nn+1 apare pe ambele ramuri ale propoziiei DACA, astfel c o putem scrie o singur dat dup aceast propoziie. Obinem

A5:

Subalgoritmul Insert(n,A,x) este: Dac x<an i n 0 atunci Cheam SEARCH(x,n,A,p) in Cttimp i p execut ai+1ai ii-1 sfct apx altfel an+1x sfdac Fie nn+1 sf-Insert

Exemplu 2 Sortare prin Inserare Fie A = (a1, a2,...,an) un vector cu n componente ntregi . Se cere s ordonm cresctor componentele vectorului A, deci s scriem un algoritm pentru urmtoarea specificatie: ::= n 2, A are elemente numere intregi ::= ORD(n,A) i A are aceleai elemente ca la nceput deci A0: [ , ]

Folosind regula secvenei i observnd c ORD(k,A) (k=n) obinem A1: Subalgoritmul InsertSort(n,A) este: [, ORD(k,A)] [ORD(k,A), ORD(k, A) i (n=k)] sf-InsertSort Prima propoziie nestandard se rafineaz la atribuirea k1, astfel c obinem

A2: Subalgoritmul InsertSort(n,A) este: Fie k1 [ORD(k,A), ORD(k, A) i (n=k)] sf-InsertSort Propoziia nestandard rmas se rafineaz cu regula iteraiei i obinem: A3: Subalgoritmul InsertSort(n,A) este: Fie k1 Cttimp k<n execut [ORD(k,A) si k<n, ORD(k,A) i ] sfct sf-InsertSort Pentru a asigura terminarea ciclului condiia k trebuie sa creasca. O prima posibilitate ar fi kk+1. Pentru a mentine predicatul (k)::=ORD(k,A) invariant trebuie ca prin inlocuirea lui k cu k+1 predicatul (k|k+1) sa fie adevarat. Ajungem la versiunea A4: Subalgoritmul InsertSort(n,A) este: Fie k1 Cttimp k<n execut [k<n i (k), (k|k+1)] sfct sf-InsertSort S observm c propoziia nestandard [ (k<n) ORD(k,A), ORD(k+1,A)] correspunde urmtoarei probleme, care pentru noi devine o subproblem: Dac ORD(k,A) (deci primele k elemente ale vectorului A sunt ordonate) atunci facei ca primele k+1 elemente sfie ordonate. Aceasta se poate face prin apelul unui subalgoritm de inserare a componentei ak+1 astfel ca dup inserare s fie adevat postcondiia ORD(k+1,A). A4: Subalgoritmul InsertSort(n,A) este: Fie k1 Cttimp k<n execut {n-k scade} Cheam INSERT(k,A, ak+1) sfct sf-InsertSort

Exemplu 3 Impartirea ntreag prin scderi repetate Specificare

: (x 0) (y>0) : (x=q*y+r) (0 r<y) A0: Subalgoritmul CATREST(x,y,q,r) este: [, ] sf-CATREST

S considerm urmtorul predicat : (x=q*y+r) (0 r) i s folosim regula secvenei R1: A1: Subalgoritmul CATREST(x,y,q,r) este: [, ] [ , ] sf-CATREST (r<y )

Intruct devine adevrat prin atribuirea (q,r):= (0,x), iar implic , avem: A2: Subalgoritmul CATREST(x,y,q,r) este: Fie (q,r)(0,x) [ , i r<y] sf-CATREST

Observm c este predicat invariant i putem folosi regula iteraiei, pentru a ajunge la A3: Subalgoritmul CATREST(x,y,q,r) este: Fie (q,r) (0,x) Cttimp r y execut [r y i , i r scade] sfct sf-CATREST

Observm c terminarea execuiei ciclului se obine dac r scade, ceea ce se poate obine prin atribuirea rr-y ntruct r y. Pentru ca invariantul s rmn adevrat va trebui s schimbm i pe q. Intruct q*y+r = (q+1)*y + (r-y) o soluie posibil este atribuirea (q,r) (q+1, r-y), astfel c ajungem la versiunea final: A3: Subalgoritmul CATREST(x,y,q,r) este: Fie (q,r) (0,x) Cttimp r y execut {r scade} (q,r) (q+1,r-y) sfct sf-CATREST

Exemplu 4

Cel mai mare divizor comun In cele ce urmeaz vom nota prin cmmdc(m,n) cel mai mare divizor comun al numerelor m i n. Specificarea problemei: : x>0, y > 0 : d=cmmdc(x,y) A0 Subalgoritmul CMMDC(x,y,d) este: [ , ] sf-CMMDC

Predicatul ::= cmmdc(d,s)=cmmdc(x,y) poate deveni adevarat pentru (d,s)=(x,y), si daca d=s atunci implica . Ca urmare, o versiune corecta a algoritmului este: A1 Subalgoritmul CMMDC(x,y,d) este: [ , ] [ , (d=s)] sf-CMMDC A2 Subalgoritmul CMMDC(x,y,d) este: { e adevarat} Fie (d,s) (x,y) { devine adevarat} Cttimp ds execut @Pastreaza adevarat si asigura terminarea sfct {Aici d=s, ca urmare implica } { } sf-CMMDC Pentru ds avem d>s sau d<s. Ca urmare, din matematica stim ca pentru d>s avem cmmdc(d,s)=cmmdc(d-s,s) ca urmare atribuirea d d-s pastreaza invariant. Ca urmare, o varianta corecta (finala) a algoritmului este: A3 Subalgoritmul CMMDC(x,y,d) este: { e adevarat} Fie (d,s) (x,y) { devine adevarat} Cttimp ds execut {s+d scade}

sfct {Aici d=s, ca urmare implica } { } sf-CMMDC Exemplu 5 Rdcina ptrat ntreag.

Dac d>s atunci dd-s {Pastreaza adevarat} altfel ss-d {Pastreaza adevarat} sfdac {d+s descreste, si acest lucru asigura terminarea}

Se cere s se determine partea ntreag din radical din n. Dac notm prin r aceast valoare, trebuie s avem r radical din n < r+1 deci predicatul de ieire este r2 n < (r+1)2 Specificarea: : n>1 : r2 n < (r+1)2 A0

Subalgoritmul RADICALINT(n,r) este: [ , ] sf-RADICALINT

Pentru a-l gsi pe r l vom iniializa cu o anumit valoare cerut de contextul programului i vom modifica aceast valoare pn cnd ea va satisface predicatul de ieire. ntruct n forma n care se afl nu putem ghici valoarea care satisface acest predicat, vom introduce o nou variabil care s ne ajute la determinarea unui predicat invariant i n final a valorii dorite pentru r. Mai exact, predicatul de ieire va fi adevrat dac (r2 <= n < q2 ) (q=r+1) Predicatul de mai sus nu poate fi satisfcut direct ntruct e imposibil s ghicim valori pentru q i r care s satisfac ambii termeni ai conjunciei. E mult mai uor s satisfacem doar prima parantez, motiv pentru care predicatul ::= (r2 n < q2) (qr+1) ne sugereaz un invariant pentru programul dorit. A1 Subalgoritmul RADICALINT(n,r) este: [ , ] [ , (q=r+1)] { }

sf-RADICALINT Observm c urmtoarea variant: A2 Subalgoritmul RADICALINT(n,r) este: { = ...} Fie (q,r) (n+1,0) Cttimp q>r+1 execut @Pastreaza adev si asigura terminarea micsorand diferenta q-r sfct {Aici q=r+1, ca urmare implica } { } sf-RADICALINT Propoziia nestandard din ciclu cere ca invariantul s rmn invariant, iar condiia de terminare fiind q=r+1 sugereaz funcia de terminare t=q-r, care n final q-r trebuie s devin 1. Intruct valoarea p=(q+r)/2 satisface inegalitatea r<p<q, diferena qr se njumtete dac schimbm intervalul [r,q] cu unul din subintervalele [r,p], respectiv [p,q], ceea ce ar asigura terminarea. Pentru a pastra invariant avem nevoie sa stim daca (p2n) sau (p2>n). Daca (p2n) atunci atribuirea r p pastreaza invariant. Daca (p2>n) atunci atribuirea q p pastreaza invariant. Ca urmare algoritmul este: A3 Subalgoritmul RADICALINT(n,r) este: { = ...} Fie (q,r) (n+1,0) Cttimp q>r+1 execut {q-r scade} Fie p (q+r)/2 Dac p2 n atunci rp altfel qp sfdac { ramane adev si q-r descreste} sfct {Aici q=r+1, ca urmare implica } { } sf-RADICALINT Exemplu 6 Ridicarea la putere prin inmultiri repetate (rapide) Calculati z = xy prin inmultiri repetate. Specificare: devine True pentru r=0 i q=n+1, deci obinem

A0:

: (x>0) (y 0) : z = xy

Observam ca predicatul ::= (z*uv = xy ) (v0) implica daca v=0. Folosindu-l ca predicat de mijloc (invariant), putem aplica regula compunerii secventiale si obtinem versiunea: A1: [ , ] [ , ]

Deoarece e adevarat daca (z,u,v) = (1,x,y) prima linie trebuie inlocuita cu o atribuire multipla. Ca urmare, urmatoarea versiune corecta a algoritmului, definit sub forma unui subalgoritm, este: Subalgoritmul Putere(x,y,z) este: {A: is true} (z,u,v) (1,x,y) [ , ] sf-Putere In propozitia nestandard [ , ] predicatul este un invariant, a.i. este rafinat la o structura iterativa Cattimp: A3: Subalgoritmul Putere(x,y,z) este: {A: is true} (z,u,v) (1,x,y) Cttimp v0 execut {B: is true} @Pstreaz invariant i asigur terminarea ciclului sfctimp {C: is true} sf-Putere A2:

Pentru a asigura iesirea din ciclu, adica v sa devina 0, v trebuie sa descreasca. Cel mai simplu mod de a asifura acest lucru este prin atribuirea vv-1. Deoarece z*uv = z * u*uv-1 atribuirea (z,v)(z*u,v-1) pastreaza invariant. Obtinem urmatorea versiune corecta: A4: Subalgoritmul Putere(x,y,z) este: {A: e adevarata} (z,u,v) (1,x,y) Cttimp v0 execut {B: e adevarat} (z,v) (z*u,v-1) sfctimp {C: e adevarat} sf-Putere

Urmatoarea posibilitate de a descreste v ar fi, daca v este par, atribuirea vv div 2. Deoarece z*uv = z* (u*u)v/2 e nevoie de atribuirea (u,v) (u*u,v/2) pentru a pastra invariant, in acest caz. Ca urmare, obtinem a doua varianta:

Subalgoritmul Putere2(x,y,z) este: {A: e adevarat} (z,u,v) (1,x,y) Cttimp v0 execut Cttimp v is even execut {v scade} (u,v) (u*u,v/2) { is true} sfct {Aici v e impar si il putem descreste cu 1} (z,v) (z*u,v-1) { e adevarat} sfctimp {C: e adevarat} sf-Putere2 Exemplu 7 Inmulire prin adunri repetate Specificare: : (x 0) (y 0) : z = x*y A0 Subalgoritmul Produs(x,y,z) este: [ , ] sf-Produs

ntruct postcondiia nu poate fi satisfacut direct printr-o atribuire vom introduce urmtorul predicat: ::= (z+u*v = x*y ) (v0) Acest predicat devine adevrat prin atribuirea (u,v,z) (x,y,0) iar (v=0) ceea ce ne sugereaz urmtoarea versiune de subalgoritm: A1 Subalgoritmul Produs(x,y,z) este: [ , ] [ , (v=0)] { } sf-Produs Folosind regula iteratiei, obtinem A2

Subalgoritmul Produs(x,y,z) este: (z,u,v) (0,x,y) { e adevrat} Cttimp v 0 execut @Pstreaz z+u*v = x*y invariant adevrat i micoreaz pe v sfct {aici v=0 i e adevrat, deci va fi adevrat} { } sf-Produs Exist dou posibiliti de a-l micora pe v. Prima, cu valoarea 1 prin atribuirea v:=v-1. In acest caz, pentru a-l prstra pe adevrat este necesar i atribuirea z:=z+u deoarece z+u*v = z + u + u*(v-1) A doua se poate aplica numai pentru v par cnd v poate fi mprit cu 2. Cum z+u*v = z + (u*2)* v/2 rezult c rmne adevrat la atribuirea (u,v):=(u+u, v/2). Ajungem la varianta final A3 Subalgoritmul Produs(x,y,z) este: (z,u,v) (0,x,y) { e adevrat} Cttimp v>0 execut {v scade} Cttimp v e par execut (u,v) (u+u,v div 2) sfct { z+u*v = x*y e invariant} {aici v e impar} (z,v) ( z+u, v-1) sfct {aici v=0 i e adevrat, deci va fi adevrat} { } sf-Produs

Exemplu 8 Cautarea pozitiei de inserare a unui element x intr-un sir A ordonat crescator. ::= ORD(n,A) n1 ::= [(x<a1) (p=1)] [(ap-1 x<ap) (1<p n)] [(xan) (p=n+1)]

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