1 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówWprowadzimy teraz pojęcie niezmiennika pętli, które jest często wykorzystywane do projektowania algorytmów i dowodzenia ich poprawności. Rozważmy pętlę „while”, która ma postać:
2 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
3 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
4 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówOstatnie stwierdzenie dotyczące prawdziwości zdania g po zakończeniu pętli jest tak oczywistym, że często się o nim zapomina. Jednak dostarcza ono ważnych informacji pozwalających uzasadnić semantyczną poprawność algorytmów. Dlatego zostało umieszczone w treści twierdzenia.
5 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówwhile(k>=4) k=k+1;
6 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówPrzykład 1. Algorytm NWD Euklidesa. Zapis w pseudokodzie Jak znaleźć niezmiennik pętli?
7 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówNajpierw należy pokazać, że
8 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
9 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
10 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
11 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
12 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
13 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówĆwiczenie
14 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
15 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmienników
16 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówPrzykład 2. Rozważmy algorytm dzielenia całkowitego liczb naturalnych. void dzielenie (int x,y) { //: 0<=x i 0<=y int q,r; q=0; r=x; while(y<=r) //p: x=q*y+r i 0<=r i 0<=y { q=q+1; r=r-y; }; } //: x=q*y+r i 0<=r
17 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówNależy udowodnić pewną własność obliczeń algorytmu, która łączy zachodzenie warunku początkowego z warunkiem końcowym. Jaki warunek spełniają x, y, q, r w pętli „while” w chwili sprawdzenia warunku „y<=r” sterującego iteracją? Określamy niezmiennik p. Wykażemy, że za każdym razem, gdy obliczenie algorytmu rozpoczyna się stanem spełniającym warunek początkowy oraz dochodzi do warunku iteracji, to spełniony jest warunek p.
18 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówbezpośrednio z początku algorytmu void dzielenie (int x,y) { //: 0<=x i 0<=y int q,r; q=0; r=x; while(y<=r) //p: x=q*y+r i 0<=r i 0<=y { q=q+1; r=r-y; }; } //: x=q*y+r i 0<=r
19 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówJeśli dojdziemy do p z początku algorytmu, to q=0, r=x i p jest spełniony, bo zachodzi . void dzielenie (int x,y) { //: 0<=x i 0<=y int q,r; q=0; r=x; while(y<=r) //p: x=q*y+r i 0<=r i 0<=y { q=q+1; r=r-y; }; } //: x=q*y+r i 0<=r
20 Semantyczna poprawność algorytmów – dowodzenie za pomocą niezmiennikówvoid dzielenie (int x,y) { //: 0<=x i 0<=y int q,r; q=0; r=x; while(y<=r) //p: x=q*y+r i 0<=r i 0<=y { q=q+1; r=r-y; }; } //: x=q*y+r i 0<=r
21 Semantyczna poprawność algorytmów – dowodzenie własności stopu.Kryterium liczników iteracji Kryterium malejących wielkości
22 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium liczników iteracji.Załóżmy, że dany jest algorytm: M:{ l=c; while(p)do { K; l=l+1; } Dobieramy teraz dwie wielkości: takie, że l<= oraz takie, które wyjaśnia zależność między wartościami zmiennych w chwili sprawdzania warunku (niezmiennika) p. zmienna l jest licznikiem iteracji, służy do obliczania liczby wykonań instrukcji iterowanej K Kryterium liczników iteracji Jeżeli: i >=l jest w algorytmie M niezmiennikiem instrukcji iteracyjnej „while” przy warunku początkowym , K ma własność stopu względem i p, to M oraz „while(p)do K” mają własność stopu względem .
23 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium liczników iteracji.Przykład 3. !! void dzielenie1 (int x,y) { //1: 0<=x i 0
24 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium liczników iteracji.void dzielenie1 (int x,y) { //1: 0<=x i 0
25 (r>=0,y>0) q<=x/ySemantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium liczników iteracji. void dzielenie1 (int x,y) { //1: 0<=x i 0
26 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium malejących wielkości.Załóżmy, że dany jest algorytm: M:{ i=w+1; while(p)do { i=w; K; } Dobieramy teraz trzy wielkości: i oraz w będące liczbami całkowitymi i takie, które wyjaśnia zależność między wartościami zmiennych w chwili sprawdzania warunku (niezmiennika) p. Kryterium malejących wielkości Jeżeli: i i>w, i w>=0 jest w algorytmie M niezmiennikiem instrukcji iteracyjnej „while” przy warunku początkowym , K ma własność stopu względem i p, to M oraz „while(p)do K” mają własność stopu względem .
27 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium malejących wielkości.Metodę malejących wielkości stosuje się, gdy w algorytmie zwiększanie wartości następuje w sposób nieregularny, czyli niekoniecznie o 1. Zamiast szacować wzrost rozpatruje się jednak te wielkości, które zmniejszają swoje wartości w trakcie wykonywania algorytmu i dla których istnieją wartości ograniczające je z dołu.
28 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium malejących wielkości.Przykład 4. void dzielenie2 (int x,y) { //2: 0<=x i 0
29 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium malejących wielkości.void dzielenie2 (int x,y) { //2: 0<=x i 0
30 Semantyczna poprawność algorytmów – dowodzenie własności stopu – kryterium malejących wielkości.void dzielenie2 (int x,y) { //2: 0<=x i 0