Kiểm chứng đoạn chương trình không có vòng lặp : 72

Một phần của tài liệu Giáo trình lập trình mạng đại học Đà Lạt (Trang 73 - 76)

(Verification of nonlooping programs)

Cho : P, Q là các tân từ trên các biến của chương trình , S là một lệnh tổ hợp từ các lệnh gán và lệnh điều kiện dùng cấu trúc tuần tự. Chứng minh : {P} S {Q}. Ở đây vì mỗi lệnh chỉ được thi hành một lần nên tính dừng của đoạn lệnh S được suy ra từ tính dừng của lệnh gán .

1) Bài toán 1 : S là dãy tuần tự các lệnh gán .

Ví dụ : Kiểm chứng tính đúng của đoạn lệnh hoán đổi nội dung 2 biến x và y a) {(x=xo) and ( y = yo ) } t := x ; x := y ; y := t ; {(x=yo ) and (y = xo ) } Chứng minh

1. {(x = yo ) and ( t = xo) } y := t {(x = yo ) and ( y = xo ) } (tiên đề gán) 2. {(y = yo ) and ( t = xo ) } x := y {(x = yo ) and ( t = xo ) } (tiên đề gán) 3. {(y = yo ) and ( t = xo ) } x := y ; y := t {(x = yo) and ( y = xo ) }

( 2,1 và tuần tự )

4. {(y = yo ) and ( x = xo ) } t := x {(y = yo ) and ( t = xo ) } (tiên đề gán) 5. ( (x = xo ) and (y = yo ) ) ==> ( ( y = yo ) and ( x = xo ) } (giao hoán) 6. {( x = xo ) and (y = yo ) } t := x {(y = yo ) and ( t = xo ) } (4, 5 và luật hệ quả) 7. {(x = xo ) and ( y = yo ) } t := x ; x := y ; y := t {(x = yo ) and ( y = xo ) } ( đpcm ) (6, 3 và luật tuần tự) b) CM : { (m :: k=2*m) and (y * zk = c)} k := k div 2 ; z := z * z ; { y * zk = c} Chứng minh : 1. {y * (z*z)k = c} z := z * z {y*zk = c} (tiên đề gán) 2. {y * (z*z)k div 2 = c} k := k div 2 {y*(z*z)k = c} (tiên đề gán) 3. {y * (z*z)k div 2 = c} k := k div 2 ; z := z*z {y*z)k = c}

(1., 2. luật tuần tự)

4. (m :: k = 2*m) and ( y * zk = c ) ==> (y*z2m = c) and ( m = k div 2 ) ==> y * (z*z)k div 2 = c

5. Từ 3, 4 và luật hệ qủa ta có đpcm . Nhận xét :

Với dẫy tuần tự các lệnh gán, việc chứng minh {P} S1; ...;Sn {Q} được bắt đầu từ lệnh cuối cùng, dùng tiên đề gán để được đkđ, rồi cứ thế lần ngược về đến S1.

{Pn} Sn {Q} tiên đề gán {Pn-1 } Sn-1 {Pn-1 } tiên đề gán {Pn-1 } Sn-1 ; Sn {Q} luật về dãy lệnh tuần tự ...

...

{P1 } S1 ;...; Sn {Q} (a) sau n-1 lần tương tự như trên. Sau đó chứng minh logic rằng :(dùng các tính chất của dữ kiện) P ==> P1 (b)

Từ a ,b, dựa vào luật hệ qủa ta có : {P} S1 ;...; Sn {Q} (đpcm )

2) Bài toán 2 :

2a) {P} if B then S1 else S2 {Q}

Với S1, S2 là nhóm các lệnh gán , B là biểu thức boolean. Cách chứng minh :

+ Tìm P1, P2 thỏa : {P1} S1 {Q} (a1) {P2} S2 {Q} (b1)

+ Chứng minh ( dùng các tính chất logic và đại số ) P and B ==> P1 (a2)

P and (not B) ==> P2 (b2) + Suy ra từ luật hệ quả

a1, a2 suy ra {P and B} S1 {Q} (a) b1 ,b2 suy ra {P and (not B)} S2 {Q} (b) + Từ a , b và luật về điều kiện suy ra :

{P} if B then S1 else S2 {Q} (đpcm ) 2b) {P} S1 ; if B then S2 else S3 {Q} (*) (với S1, S2, S3 là dẫy các lệnh gán.) Ví dụ : {y > 0} x := y-1 ; if (y > 3) then x := x*x else y := y-1 {x >= y} Để khẳng định được (*) ta cần chỉ ra 1 khẳng định R mà : {P} S1 {R}

và {R} if B then S2 else S3 {Q} rồi dùng luật hệ quả để có (*)

Làm thế nào để tìm được R ? Do S2 và S3 là nhóm lệnh gán tuần tự nên ta có thể tìm được (bằng tiên đề gán và luật về dãy lệnh tuần tự ) U và V để :

{U} S2 {Q} (a) và {V} S3 {Q} (b)

Dĩ nhiên ta muốn U và V là các điều kiện tổng quát nhất (tức là U , V là các tân từ yếu nhất thỏa a , b ). R được xây dựng thế nào từ U và V ? Khả năng tổng quát nhất cho R để sau khi điểm điều kiện B sẽ có được U hoặc V là : R (B ==> U) and (not B ==> V) ≡

( lý luận chặt chẽ sẻ được chỉ ra ở các phần sau )

U,V, R được xây dựng như vậy là yếu nhất (weakest precondition) để đạt được Q tương ứng với các lệnh S2, S3 và if B then S2 else S3, thường được ký hiệu là :

WP(S2,Q), WP(S3,Q) và WP(if B then S2 else S3,Q) tương ứng. (Tính chất của toán tử wp sẽ được nghiên cứu ở một mục sau) .

Ví dụ 1 : Kiểm chứng đặc tả : { y > 0 } x := y - 1 ; if ( y > 3 ) then x := x * x else y := y - 1 ; { x >= y } Trong ví dụ này : P là tân từ : ( y > 0 ) ; Q là tân từ : ( x >= y ) B là biểu thức boolean : ( y > 3 ) S1 là lệnh gán : x := y - 1 ; S2 là lệnh gán : x := x * x ; S3 là lệnh gán : y := y - 1 ; 1. {x2 >= y} x := x*x {x >= y} (tiên đề gán ) vậy : U x≡ 2 >= y

2. {x >= y-1} y := y-1 {x >= y} (tiên đề gán ) vậy : V x >= y-1 ≡

Đặt R ((y > 3) ==> (x≡ 2 >= y)) and ((y <= 3) ==> (x >= y-1)) Ta chứng minh được dễ dàng.

3. R and (y>3) ==> (x2 >= y) 4. R and (not(y>3)) ==> (x >= y-1) nên theo luật hệ quả

5. {R and y>3} S2 {x >= y} ( {R and B} S2 {Q} ) 6. {R and not(y>3)} S3 {x >= y} ( {R and (not B)} S3 {Q} ) Theo luật về lệnh chọn

7. {R} if ( y>3) then x := x*x else y := y-1 {x >=y} theo tiên đề gán.

8. {((y>3) ==> ((y-1) 2 >=y)) and ((y <=3) ==> ((y-1) >= (y-1)))} x := y -1 {R}

Dễ kiểm chứng được

9. (y>3) ==> ((y-1) 2 >= y ) ≡ not(y>3) or ((y-1) 2 >= y ) true ≡

10. (y<=3) ==> (y -1) >= y-1 ) ≡ not(y<=3) or (y >= y ) true ≡

Nên : 11. (y >0) ==> ((y>3) ==>((y-1)2 >=y)) and ((y<=3) ==> ((y-1) >=(y-1))) Theo luật hệ quả ta có :

12. {y > 0} x := y-1;

if (y>3) then x := x*x else y := y-1 { x >= y} (đpcn ) Ví dụ 2 : kiểm chứng đặc tả : { true } if ( i <= j) then if (j<k ) then m := k else m := j else if( i<k) then m := k

else m := i {(m >= i) and (m >= j) and (m >= k)}

Đặt Q(m) ( m >= i) and (m >= j) and (m >= k) ≡

1. {Q(i)} m := i {Q(m)} (tiên đề gán) 2. {Q(k)} m := k {Q(m)} (tiên đề gán)

3. Đặt R1 ((i < k) ==> Q(k)) and ( (i >= k) ==>Q(i)) ≡

dùng luật về lệnh chọn ta sẽ chứng minh được :

{R1} if ( i < k) then m := k else m := i {Q(m)}

4. Tương tự đặt R2 ( ( j<k) ==> Q(k) ) and ((j >= k) ==> Q(j)) ≡

Ta có: {R2} if (j < k ) then m := k else m := j {Q(m)} 5. Dùng biến đổi đại số và logic để chứng minh

5a. ( true and ( i <= j)) ==> R2 5b. ( true and ( i > j )) ==> R1

6. Từ 3,4, và 5, theo luật về lệnh chọn ta có đpcm. Nhận xét :

Để chứng minh {P} S {Q} với S là tổ hợp lệnh gồm chỉ các lệnh gán và điều kiện. Ta thực hiện công việc xác định điều kiện đầu yếu nhất P1 của S ứng với Q. Sau đó bước kiểm chứng cuối cùng chỉ đơn giản là chứng minh : P==> P1. Giải thuật tìm P1 được trình bày dưới dạng một hàm đệ quy như sau :

Function DKDYN (S : nhóm_lệnh ; Q : tân_từ ) : tân_tư ø; var e : câu lệnh ; begin if (S <> rỗng ) then begin e := lệnh_cuối(S); S := S - e ;

if ( e = lệnh_gán(x:=expr)) then DKDYN := DKDYN(S,Q( x ^ expr ))

else {lệnh if}

DKDYN := (điều_kiện(e)==>DKDYN(phần_đúng(e),Q)

and not điều_kiện(e)==>DKDYN(phần_sai(e),Q)) end

else DKDYN := Q end ;

Với Q(x^expr) là tân từ có được bằng thay biến x trong Q bằng expr .

DKDYN(phần_đúng(e) ,Q ) là gía trị hàm tìm DKDYN ứng với đoạn lệnh sau từ khóa THEN của lệnh điều kiện e và Q , DKDYN(phần_sai(e) ,Q ) là gía trị hàm tìm DKDYN ứng với đoạn lệnh sau từ khóa ELSE của lệnh điều kiện e và Q .

Một phần của tài liệu Giáo trình lập trình mạng đại học Đà Lạt (Trang 73 - 76)

Tải bản đầy đủ (PDF)

(110 trang)