Semantyka i weryfikacja programów/Ćwiczenia 13: Różnice pomiędzy wersjami
Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Nie podano opisu zmian |
m Zastępowanie tekstu – „<math> ” na „<math>” |
||
(Nie pokazano 9 wersji utworzonych przez 4 użytkowników) | |||
Linia 1: | Linia 1: | ||
== Zawartość == | == Zawartość == | ||
Poprawność częściowa prostych programów w języku | Poprawność częściowa prostych programów w języku TINY. | ||
Linia 19: | Linia 18: | ||
y := y + x; | y := y + x; | ||
x := x + 1 | x := x + 1 | ||
<math>{\color{Red}\{y=\frac{n\cdot(n+1)}{2}\}}</math> | <math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | |||
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span> | |||
<div class="mw-collapsible-content" style="display:none"> | |||
Najpierw musimy odgadnąć asercję, którą można wpisać pomiędzy początkowe przypisania a pętlę: | Najpierw musimy odgadnąć asercję, którą można wpisać pomiędzy początkowe przypisania a pętlę: | ||
Linia 38: | Linia 39: | ||
x := x + 1 | x := x + 1 | ||
) | ) | ||
<math>{\color{Red}\{y=\frac{n\cdot(n+1)}{2}\}}</math> | <math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | ||
Możemy na przykład | Możemy na przykład "przeciągnąć" asercję początkową wprzód, otrzymując <math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math>. | ||
Teraz wystarczy dowieść następujące dwie trójki Hoare'a: | Teraz wystarczy dowieść następujące dwie trójki Hoare'a: | ||
Linia 57: | Linia 58: | ||
x := x + 1 | x := x + 1 | ||
) | ) | ||
<math>{\color{Red}\{y=\frac{n\cdot(n+1)}{2}\}}</math> | <math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | ||
Linia 63: | Linia 64: | ||
Naszym zadaniem jest teraz odkrycie niezmiennika <math>N</math> takiego, że zachodzą poniższe dwie implikacje: | Naszym zadaniem jest teraz odkrycie niezmiennika <math>N</math> takiego, że zachodzą poniższe dwie implikacje: | ||
* <math> n \geq 0 \land x = 1 \land y = 0 \, \implies \, N</math> | * <math>n \geq 0 \land x = 1 \land y = 0 \, \implies \, N</math> | ||
* <math>N \land x > n \, \implies \, y=\frac{n\cdot(n+1)}{2}</math> | * <math>N \land x > n \, \implies \, y=\frac{n{\cdot}(n+1)}{2}</math> | ||
oraz prawdziwa jest trójka: | oraz prawdziwa jest trójka: | ||
Linia 87: | Linia 88: | ||
Formalnie rzecz biorąc, powinniśmy teraz zgadnąć asercję, która może być wpisana pomiędzy dwie instrukcje przypisania: | |||
Linia 98: | Linia 99: | ||
a następnie niezależnie dowieść poprawność każdej z dwóch nstrukcji. | a następnie niezależnie dowieść poprawność każdej z dwóch nstrukcji. | ||
Ale w | Ale w "odgadnięciu" pomoże nam reguła dla przypisania, która, intuicyjnie mówiąc, daje sposób na "przeciągnięcie" asercji w tył. | ||
Jeśli zastosujemy ją do drugiego przypisania | Jeśli zastosujemy ją do drugiego przypisania "x := x + 1", otrzymamy: | ||
Linia 121: | Linia 122: | ||
<math>{\color{Red}\{N \land x \leq n\}}</math> | <math>{\color{Red}\{N \land x \leq n\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// tę implikację należy udowodnić </span> | |||
<math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | <math>{\color{Red}\{N[x \mapsto x{+}1][y \mapsto y{+}x]\}}</math> | ||
y := y + x; | y := y + x; | ||
<math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | <math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | ||
Skoro dwie asercje | Skoro dwie asercje spotkały się, wystarczy teraz udowodnić implikację. | ||
I tak dalej. To znaczy, podobnie postępujemy z pozostałymi przypisaniami. | I tak dalej. To znaczy, podobnie postępujemy z pozostałymi przypisaniami. A wszędzie, gdzie spotykają się dwie asercje, dowodzimy implikacji. | ||
A wszędzie, gdzie | |||
Podsumowując, poniższe anotacje całego programu powinny stanowić dowód poprawności częściowej: | Podsumowując, poniższe anotacje całego programu powinny stanowić dowód poprawności częściowej: | ||
Linia 139: | Linia 139: | ||
y := 0; | y := 0; | ||
<math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math> | <math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 1 </span> | |||
<math>{\color{Red}\{N\}}</math> | <math>{\color{Red}\{N\}}</math> | ||
while x <= n do | while x <= n do | ||
( | ( | ||
<math>{\color{Red}\{N \land x \leq n\}}</math> | <math>{\color{Red}\{N \land x \leq n\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 2 </span> | |||
<math>{\color{Red}\{N[x \mapsto x{+}1][y \mapsto y{+}x]\}}</math> | <math>{\color{Red}\{N[x \mapsto x{+}1][y \mapsto y{+}x]\}}</math> | ||
y := y + x; | y := y + x; | ||
Linia 152: | Linia 152: | ||
) | ) | ||
<math>{\color{Red}\{N \land x > n\}}</math> | <math>{\color{Red}\{N \land x > n\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 3 </span> | |||
<math>{\color{Red}\{y=\frac{n\cdot(n+1)}{2}\}}</math> | <math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | ||
A jedyne co pozostaje do zrobienia to tylko | A jedyne co pozostaje do zrobienia to tylko udowodnienie następujących implikacji: | ||
# <math>n \geq 0 \land x = 1 \land y = 0 \, \implies \, N</math> | # <math>n \geq 0 \land x = 1 \land y = 0 \, \implies \, N</math> | ||
# <math>N \land x \leq n \, \implies \, N[x \mapsto x{+}1][y \mapsto y{+}x]</math> | # <math>N \land x \leq n \, \implies \, N[x \mapsto x{+}1][y \mapsto y{+}x]</math> | ||
# <math>N \land x > n \, \implies \, y=\frac{n\cdot(n+1)}{2}</math> | # <math>N \land x > n \, \implies \, y=\frac{n{\cdot}(n+1)}{2}</math> | ||
Co ciekawe, to wszystko uczyniliśmy nie wiedząc wogóle, jaki jest niezmiennik pętli! | Co ciekawe, to wszystko uczyniliśmy nie wiedząc wogóle, jaki jest niezmiennik pętli! | ||
Ale nadszedł wreszcie moment, w którym powinniśmy taki niezmiennik podać. | Ale nadszedł wreszcie moment, w którym powinniśmy taki niezmiennik podać. | ||
Musimy go | Musimy go odgadnąć poprzez staranną obserwację tego, co dzieje się wewnątrz pętli. | ||
Należy oczywiście uwzględnić również implikacje, które wypisaliśmy powyżej. | Należy oczywiście uwzględnić również implikacje, które wypisaliśmy powyżej. | ||
Spróbujmy <math>N \, \equiv \, y = \frac{x\cdot(x{-}1)}{2} \land x \leq n{+}1</math>. | Spróbujmy <math>N \, \equiv \, y = \frac{x{\cdot}(x{-}1)}{2} \land x \leq n{+}1</math>. | ||
Nierówność <math>x \leq n{+}1</math> jest niezbędna. | Nierówność <math>x \leq n{+}1</math> jest niezbędna. Potrzebujemy jej po to, aby z <math>N \land x > n</math> wywnioskować <math>x = n{+}1</math>. | ||
Implikacje są prawdziwe, więc niezmiennik został wybrany poprawnie. | |||
Implikacje są prawdziwe więc niezmiennik został wybrany poprawnie. | |||
Zauważmy, że niezmiennik nie zawiera wymagania <math>x \geq 1</math>. | Zauważmy, że niezmiennik nie zawiera wymagania <math>x \geq 1</math>. Moglibyśmy je jednak dodać, otrzymując <math>N' \, \equiv \, y = \frac{x{\cdot}(x{-}1)}{2} \land 1 \leq x \leq n{+}1</math>. | ||
Moglibyśmy je jednak dodać otrzymując <math>N' \, \equiv \, y = \frac{x\cdot(x{-}1)}{2} \land 1 \leq x \leq n{+}1</math>. | Wszystkie implikacje pozostają prawdziwe, więc jest to też poprawny wybór. Ponadto wiedząc, że <math>x \geq 1</math> możemy, dla czytelności, zapisywać niezmiennik w meta-notacji: | ||
Wszystkie implikacje pozostają prawdziwe, więc jest to też poprawny wybór. | |||
Ponadto wiedząc, że <math>x \geq 1</math> możemy, dla czytelności, zapisywać niezmiennik w meta-notacji: | |||
<math> | <math> | ||
N \, \equiv \, y = 1{+}\ldots{+}(x{-}1) \land x \leq n{+}1 | N \, \equiv \, y = 1{+}2{+}\ldots{+}(x{-}1) \land x \leq n{+}1</math> | ||
</math> | |||
'''Pytanie:''' dlaczego nie potrzebowaliśmy warunku <math>x \geq 0</math>? Jak będzie działał nasz program, jeśli zmienną x zainicjujemy wartością ujemną (zamiast x := 1)? | '''Pytanie:''' dlaczego nie potrzebowaliśmy warunku <math>x \geq 0</math>? Jak będzie działał nasz program, jeśli zmienną x zainicjujemy wartością ujemną (zamiast x := 1), np. x := -2, y := 3? | ||
<br> | <br> | ||
Linia 188: | Linia 184: | ||
<br> | <br> | ||
Niezmiennik pętli będziemy zwykle wpisywać pomiędzy słowem kluczowym while a dozorem pętli. | Niezmiennik pętli będziemy zwykle wpisywać pomiędzy słowem kluczowym while a dozorem pętli. W naszym przypadku otrzymamy następujące anotacje: | ||
W naszym przypadku otrzymamy następujące anotacje: | |||
Linia 197: | Linia 192: | ||
y := 0; | y := 0; | ||
<math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math> | <math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 1 </span> | |||
<math>{\color{Red}\{N\}}</math> | <math>{\color{Red}\{N\}}</math> | ||
while <math>{\color{Red}\{N\}}</math> x <= n do | while <math>{\color{Red}\{N\}}</math> x <= n do | ||
Linia 214: | Linia 209: | ||
<math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math> | <math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math> | ||
pomiędzy początkowe przypisania a pętlę. | pomiędzy początkowe przypisania a pętlę. Mogliśmy uczynić inaczej i wpisać w to miejsce po prostu niezmiennik <math>N</math>. Wtedy należałoby wykazać: | ||
Mogliśmy uczynić inaczej i wpisać w to miejsce po prostu niezmiennik <math>N</math>. | |||
Wtedy należałoby wykazać: | |||
Linia 225: | Linia 218: | ||
co można, za pomocą znanego nam już | co można, za pomocą znanego nam już "przepychania w tył", zredukować do udowodnienia implikacji: | ||
<math>{\color{Red}\{n \geq 1\}}</math> | <math>{\color{Red}\{n \geq 1\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 1 </span> | |||
<math>{\color{Red}\{N[y \mapsto 0][x \mapsto 1]\}}</math> | <math>{\color{Red}\{N[y \mapsto 0][x \mapsto 1]\}}</math> | ||
x := 1; | x := 1; | ||
Linia 241: | Linia 234: | ||
<math>{\color{Red}\{n \geq 1\}}</math> | <math>{\color{Red}\{n \geq 1\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 1 </span> | |||
<math>{\color{Red}\{N[y \mapsto 0][x \mapsto 1]\}}</math> | <math>{\color{Red}\{N[y \mapsto 0][x \mapsto 1]\}}</math> | ||
x := 1; | x := 1; | ||
Linia 249: | Linia 242: | ||
( | ( | ||
<math>{\color{Red}\{N \land x \leq n\}}</math> | <math>{\color{Red}\{N \land x \leq n\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 2 </span> | |||
<math>{\color{Red}\{N[x \mapsto x{+}1][y \mapsto y{+}x]\}}</math> | <math>{\color{Red}\{N[x \mapsto x{+}1][y \mapsto y{+}x]\}}</math> | ||
y := y + x; | y := y + x; | ||
Linia 257: | Linia 250: | ||
) | ) | ||
<math>{\color{Red}\{N \land x > n\}}</math> | <math>{\color{Red}\{N \land x > n\}}</math> | ||
<math>{\color{Green}\Downarrow}</math> <span style="color:brown">// 3 </span> | |||
<math>{\color{Red}\{y=\frac{n\cdot(n+1)}{2}\}}</math> | <math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | ||
Linia 265: | Linia 258: | ||
</div></div> | </div></div> | ||
Linia 284: | Linia 276: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | |||
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span> | |||
<div class="mw-collapsible-content" style="display:none"> | |||
<math> | <math> | ||
\frac{\alpha \, implies \, \beta[x \mapsto e]} | \frac{\alpha \, \implies \, \beta[x \mapsto e]} | ||
{{\color{Red}\{\alpha\}} x:= e {\color{Red}\{\beta\}}} | {{\color{Red}\{\alpha\}} x:= e {\color{Red}\{\beta\}}} | ||
</math> | </math> | ||
Linia 303: | Linia 297: | ||
</div></div> | </div></div> | ||
Linia 324: | Linia 318: | ||
Wyrażenie odd(q) ma wartość <math>\mathbf{true}</math> wtedy i tylko wtedy, gdy q jest nieparzyste. | Wyrażenie odd(q) ma wartość <math>\mathbf{true}</math> wtedy i tylko wtedy, gdy q jest nieparzyste. | ||
Jako niezmiennik pętli przyjmijmy <math>N \, \equiv \, z \cdot p^q = x^y</math>. | <div class="mw-collapsible mw-made=collapsible mw-collapsed"> | ||
Oto odpowiednie anotacje naszego programu: | <span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span> | ||
<div class="mw-collapsible-content" style="display:none"> | |||
Jako niezmiennik pętli przyjmijmy <math>N \, \equiv \, z {\cdot} p^q = x^y</math>. Oto odpowiednie anotacje naszego programu: | |||
Linia 342: | Linia 337: | ||
if odd(q) then | if odd(q) then | ||
( | ( | ||
<math>{\color{Red}\{N \land q \neq 0 \land \odd(q)\}}</math> | <math>{\color{Red}\{N \land q \neq 0 \land \,\mathrm{odd}(q)\}}</math> | ||
<math>{\color{Red}\{N[p \mapsto p \cdot p][ | <math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2][z \mapsto z {\cdot} p]\}}</math> | ||
z := z * p | z := z * p | ||
<math>{\color{Red}\{N[p \mapsto p \cdot p][ | <math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2]\}}</math> | ||
) | ) | ||
else | else | ||
( | ( | ||
<math>{\color{Red}\{N \land q \neq 0 \land \neq \odd(q)\}}</math> | <math>{\color{Red}\{N \land q \neq 0 \land \neq \,\mathrm{odd}(q)\}}</math> | ||
<math>{\color{Red}\{N[p \mapsto p \cdot p][ | <math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2]\}}</math> | ||
skip | skip | ||
<math>{\color{Red}\{N[p \mapsto p \cdot p][ | <math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2]\}}</math> | ||
) | ) | ||
<math>{\color{Red}\{N[p \mapsto p \cdot p][ | <math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2]\}}</math> | ||
q := q div 2; | q := q div 2; | ||
<math>{\color{Red}\{N[p \mapsto p \cdot p]\}}</math> | <math>{\color{Red}\{N[p \mapsto p {\cdot} p]\}}</math> | ||
p := p * p | p := p * p | ||
<math>{\color{Red}\{N\}}</math> | <math>{\color{Red}\{N\}}</math> | ||
Linia 368: | Linia 363: | ||
<math>{\color{Red}\{y \geq 0\}}</math> | <math>{\color{Red}\{y \geq 0\}}</math> | ||
<math>{\color{Red}\{1 \cdot x^y = x^y\}}</math> | <math>{\color{Red}\{1 {\cdot} x^y = x^y\}}</math> | ||
z := 1; | z := 1; | ||
p := x; | p := x; | ||
q := y; | q := y; | ||
while <math>{\color{Red}\{z \cdot p^q = x^y\}}</math> q <> 0 do | while <math>{\color{Red}\{z {\cdot} p^q = x^y\}}</math> q <> 0 do | ||
( | ( | ||
<math>{\color{Red}\{z \cdot p^q = x^y \land q \neq 0\}}</math> | <math>{\color{Red}\{z {\cdot} p^q = x^y \land q \neq 0\}}</math> | ||
if odd(q) then | if odd(q) then | ||
( | ( | ||
<math>{\color{Red}\{z \cdot p^q = x^y \land q \neq 0 \land \odd(q)\}}</math> | <math>{\color{Red}\{z {\cdot} p^q = x^y \land q \neq 0 \land \,\mathrm{odd}(q)\}}</math> | ||
<math>{\color{Red}\{(z \cdot p) \cdot (p \cdot p)^(q \div 2) = x^y\}}</math> | <math>{\color{Red}\{(z {\cdot} p) {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | ||
z := z * p | z := z * p | ||
<math>{\color{Red}\{z \cdot (p \cdot p)^(q \div 2) = x^y\}}</math> | <math>{\color{Red}\{z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | ||
) | ) | ||
else | else | ||
( | ( | ||
<math>{\color{Red}\{z \cdot p^q = x^y \land q \neq 0 \land \neq \odd(q)\}}</math> | <math>{\color{Red}\{z {\cdot} p^q = x^y \land q \neq 0 \land \neq \,\mathrm{odd}(q)\}}</math> | ||
<math>{\color{Red}\{z \cdot (p \cdot p)^(q \div 2) = x^y\}}</math> | <math>{\color{Red}\{z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | ||
skip | skip | ||
<math>{\color{Red}\{z \cdot (p \cdot p)^(q \div 2) = x^y\}}</math> | <math>{\color{Red}\{z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | ||
) | ) | ||
<math>{\color{Red}\{z \cdot (p \cdot p)^(q \div 2) = x^y\}}</math> | <math>{\color{Red}\{z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | ||
q := q div 2; | q := q div 2; | ||
<math>{\color{Red}\{z \cdot (p \cdot p)^q = x^y\}}</math> | <math>{\color{Red}\{z {\cdot} (p {\cdot} p)^q = x^y\}}</math> | ||
p := p * p | p := p * p | ||
<math>{\color{Red}\{z \cdot p^q = x^y\}}</math> | <math>{\color{Red}\{z {\cdot} p^q = x^y\}}</math> | ||
) | ) | ||
<math>{\color{Red}\{z \cdot p^q = x^y \land q=0\}}</math> | <math>{\color{Red}\{z {\cdot} p^q = x^y \land q=0\}}</math> | ||
<math>{\color{Red}\{z = x^y\}}</math> | <math>{\color{Red}\{z = x^y\}}</math> | ||
Linia 401: | Linia 396: | ||
Teraz pozostaje tylko pokazać następujące implikacje: | Teraz pozostaje tylko pokazać następujące implikacje: | ||
* <math>y \geq 0 \, \implies \, 1 \cdot x^y = x^y</math> | * <math>y \geq 0 \, \implies \, 1 {\cdot} x^y = x^y</math> | ||
* <math>z \cdot p^q = x^y \land q \neq 0 \land \odd(q) \, \implies \, (z \cdot p) \cdot (p \cdot p)^(q \div 2) = x^y</math> | * <math>z {\cdot} p^q = x^y \land q \neq 0 \land \,\mathrm{odd}(q) \, \implies \, (z {\cdot} p) {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y</math> | ||
* <math>z \cdot p^q = x^y \land q \neq 0 \land \neq \odd(q) \, \implies \, z \cdot (p \cdot p)^(q \div 2) = x^y</math> | * <math>z {\cdot} p^q = x^y \land q \neq 0 \land \neq \,\mathrm{odd}(q) \, \implies \, z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y</math> | ||
* <math>z \cdot p^q = x^y \land q=0 \, \implies \, z = x^y</math> | * <math>z {\cdot} p^q = x^y \land q=0 \, \implies \, z = x^y</math> | ||
Zauważmy, że w niezmienniku nie wymagamy aby <math>q \geq 0</math>, ponieważ nie jest to potrzebne do udowodnienia powyższych implikacji. | Zauważmy, że w niezmienniku nie wymagamy, aby <math>q \geq 0</math>, ponieważ nie jest to potrzebne do udowodnienia powyższych implikacji. | ||
Musimy tylko umówić się, na wszelki wypadek, jak działa operacja div, gdy jej argument jest ujemny. | Musimy tylko umówić się, na wszelki wypadek, jak działa operacja div, gdy jej argument jest ujemny. | ||
Przyjmijmy, że <math>q \div 2 = m</math> wtedy i tylko wtedy gdy największą liczbą parzystą nie większą od <math>q</math> jest | Przyjmijmy, że <math>q \,\mathrm{div}\, 2 = m</math> wtedy i tylko wtedy, gdy największą liczbą parzystą, nie większą od <math>q</math>, jest | ||
<math>2 \cdot m</math>. | <math>2 {\cdot} m</math>. | ||
{{uwaga||| | {{uwaga||| | ||
Warunek <math>q \geq 0</math> gwarantuje, że program się kończy. | Warunek <math>q \geq 0</math> gwarantuje, że program się kończy. | ||
Fakt, że go nie potrzebujemy wiąże się z tym, że dowodzimy tylko poprawność częściową: | Fakt, że go nie potrzebujemy, wiąże się z tym, że dowodzimy tylko poprawność częściową: | ||
wynik będzie poprawny, o ile program się zakończy, ale wcale zakończyć się nie musi! | wynik będzie poprawny, o ile program się zakończy, ale wcale zakończyć się nie musi! | ||
}} | }} | ||
'''Pytanie:''' | '''Pytanie:''' czy niezmiennik pętli jest napewno prawdziwy, gdy zmienna q ma wartość ujemną? | ||
</div></div> | </div></div> | ||
{{cwiczenie|4|cw4| | {{cwiczenie|4|cw4| | ||
Zaproponuj | Zaproponuj regułę dla instrukcji <math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math>. | ||
}} | }} | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"> | ||
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span> | |||
<div class="mw-collapsible-content" style="display:none"> | |||
<math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math> zachowuje się tak samo jak <math>I; while \neg b \,\mathbf{do}\, I</math>. | <math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math> zachowuje się tak samo jak <math>I; \mathbf{while}\, \neg b \,\mathbf{do}\, I</math>. | ||
Stąd łatwo otrzymać regułę: | Stąd łatwo otrzymać regułę: | ||
<math> | <math> | ||
\frac{ | \frac{{\color{Red}\{\alpha\}} I {\color{Red}\{\beta\}} | ||
\quad | \quad | ||
{\color{Red}\{\beta \land \neg b\}} I {\color{Red}\{\beta\}}} | |||
{ | {{\color{Red}\{\alpha\}} \mathbf{repeat}\, I \,\mathbf{until}\, b {\color{Red}\{\beta \land b\}}} | ||
</math> | </math> | ||
Dwukrotnie odwołujemy się do poprawności częściowej instrukcji <math>I</math> | Dwukrotnie odwołujemy się do poprawności częściowej instrukcji <math>I</math> względem różnych asercji początkowych. | ||
Gdybyśmy chcieli tego uniknąć, moglibyśmy rozważyć <math>\alpha = \beta</math>, | Gdybyśmy chcieli tego uniknąć, moglibyśmy rozważyć <math>\alpha = \beta</math>, otrzymując regułę: | ||
<math> | <math> | ||
\frac{ | \frac{{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}} | ||
\quad | \quad | ||
{\color{Red}\{\beta \land \neg b\}} I {\color{Red}\{\beta\}}} | |||
{ | {{\color{Red}\{\beta\}} \mathbf{repeat}\, I \,\mathbf{until}\, b {\color{Red}\{\beta \land b\}}} | ||
</math> | </math> | ||
Jeśli <math>{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}}</math> to <math>{\color{Red}\{\beta \land \neg b\}} I {\color{Red}\{\beta\}}</math>. | Jeśli <math>{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}}</math> to <math>{\color{Red}\{\beta \land \neg b\}} I {\color{Red}\{\beta\}}</math>. Zatem powyzszą regułę można uprościć: | ||
Zatem powyzszą regułę można uprościć: | |||
<math> | <math> | ||
\frac{ | \frac{{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}}} | ||
{ | {{\color{Red}\{\beta\}} \mathbf{repeat}\, I \,\mathbf{until}\, b {\color{Red}\{\beta \land b\}}} | ||
</math> | </math> | ||
otrzymując regułę prostszą ale słabszą: we wnętrzu pętli nie możemy korzystać z tego, że począwszy od drugiej iteracji nie zachodzi <math>b</math>! | otrzymując regułę prostszą, ale słabszą: we wnętrzu pętli nie możemy korzystać z tego, że począwszy od drugiej iteracji nie zachodzi <math>b</math>! | ||
Jeszcze inna możliwość to: | Jeszcze inna możliwość to: | ||
<math> | <math> | ||
\frac{ | \frac{{\color{Red}\{\alpha\}} I {\color{Red}\{\beta\}} | ||
\quad | \quad | ||
\beta \land \neg b \implies \alpha} | \beta \land \neg b \implies \alpha} | ||
{ | {{\color{Red}\{\alpha\}} \mathbf{repeat}\, I \,\mathbf{until}\, b {\color{Red}\{\beta \land b\}}} | ||
</math> | </math> | ||
Linia 475: | Linia 469: | ||
</div></div> | </div></div> | ||
== Zadania domowe == | == Zadania domowe == | ||
Linia 483: | Linia 475: | ||
{{cwiczenie|1|cw1.dom| | {{cwiczenie|1|cw1.dom| | ||
Wyprowadź ostatnią regułę dla pętli <math>\mathbf{repeat}\ | Wyprowadź ostatnią regułę dla pętli <math>\mathbf{repeat}\ </math>, z pierwszej reguły. | ||
}} | }} | ||
Linia 489: | Linia 481: | ||
{{cwiczenie|2|cw2.dom| | {{cwiczenie|2|cw2.dom| | ||
Napisz program obliczający | Napisz program obliczający największy wspólny dzielnik dwóch liczb i przeprowadź dowód poprawności częściowej. | ||
}} | }} | ||
Linia 510: | Linia 502: | ||
{{wskazowka||| | {{wskazowka||| | ||
<math> | <math> | ||
(m + 1)^3 \, = \, m^3 + 3 \cdot m^2 + 3 \cdot m + 1 | (m + 1)^3 \, = \, m^3 + 3 {{\cdot}} m^2 + 3 {{\cdot}} m + 1 | ||
</math> | </math> | ||
}} | }} |
Aktualna wersja na dzień 22:18, 11 wrz 2023
Zawartość
Poprawność częściowa prostych programów w języku TINY.
Poprawność częściowa
Ćwiczenie 1
Przeprowadź dowód poprawności częściowej poniższego programu:
x := 1; y := 0; while x <= n do y := y + x; x := x + 1
Rozwiązanie
Ćwiczenie 2
Uzupełnij poniższe reguły:
Rozwiązanie
Ćwiczenie 3 (potęgowanie binarne)
Dowiedź poprawności częściowej poniższego programu:
z := 1; p := x; q := y; while q <> 0 do if odd(q) then z := z * p; q := q div 2; p := p * p
Wyrażenie odd(q) ma wartość wtedy i tylko wtedy, gdy q jest nieparzyste.
Rozwiązanie
Ćwiczenie 4
Zaproponuj regułę dla instrukcji .
Rozwiązanie
Zadania domowe
Ćwiczenie 1
Wyprowadź ostatnią regułę dla pętli , z pierwszej reguły.
Ćwiczenie 2
Napisz program obliczający największy wspólny dzielnik dwóch liczb i przeprowadź dowód poprawności częściowej.
Ćwiczenie 3
Przeprowadź dowód poprawności częściowej:
a = 1; b := 1; y := 1; while y <= x do y := y + 3*a + 3*b + 1; a = a + 2*b + 1; b := b + 1;
Wskazówka