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 11 wersji utworzonych przez 4 użytkowników) | |||
Linia 1: | Linia 1: | ||
== Zawartość == | |||
Poprawność częściowa prostych programów w języku TINY. | |||
== Poprawność częściowa == | |||
{{cwiczenie|1|cw1| | {{cwiczenie|1|cw1| | ||
Przeprowadź dowód poprawności częściowej poniższego programu: | |||
}} | }} | ||
<math>{\color{Red}\{n\ | |||
<math>{\color{Red}\{n \geq 1\}}</math> | |||
x := 1; y := 0; | x := 1; y := 0; | ||
<math>\ | while x <= n do | ||
y := y + x; | |||
x := x + 1 | |||
<math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | |||
<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ę: | |||
<math>{\color{Red}\{n \geq 1\}}</math> | |||
x := 1; | |||
y := 0; | |||
<math>{\color{Red}\{?\}}</math> | |||
while x <= n do | |||
( | |||
y := y + x; | |||
x := x + 1 | |||
) | |||
<math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | |||
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: | |||
<math>{\color{Red}\{n \geq 1\}}</math> | |||
x := 1; | |||
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> | |||
while x <= n do | |||
( | |||
y := y + x; | |||
x := x + 1 | |||
) | |||
<math>{\color{Red}\{y=\frac{n{\cdot}(n+1)}{2}\}}</math> | |||
Zajmijmy się tą ostatnią. | |||
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 \land x > n \, \implies \, y=\frac{n{\cdot}(n+1)}{2}</math> | |||
oraz prawdziwa jest trójka: | |||
<math>{\color{Red}\{N\}}</math> | |||
while x <= n do | |||
( | |||
y := y + x; | y := y + x; | ||
x := x + 1 | x := x + 1 | ||
<math>\{\color{ | ) | ||
<math>{\color{Red}\{N \land x > n\}}</math> | |||
Aby dowieść tej ostatniej, musimy pokazać: | |||
<math>{\color{Red}\{N \land x \leq n\}}</math> | |||
y := y + x; | |||
x := x + 1 | |||
<math>{\color{Red}\{N\}}</math> | |||
Formalnie rzecz biorąc, powinniśmy teraz zgadnąć asercję, która może być wpisana pomiędzy dwie instrukcje przypisania: | |||
<math>{\color{Red}\{N \land x \leq n\}}</math> | |||
y := y + x; | |||
<math>{\color{Red}\{?\}}</math> | |||
x := x + 1 | |||
<math>{\color{Red}\{N\}}</math> | |||
{{ | a następnie niezależnie dowieść poprawność każdej z dwóch nstrukcji. | ||
< | 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ł. | ||
<math>\{n\ | Jeśli zastosujemy ją do drugiego przypisania "x := x + 1", otrzymamy: | ||
x := 1; y := 0; | |||
<math>{\color{Red}\{N \land x \leq n\}}</math> | |||
y := y + x; | |||
<math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | |||
x := x + 1 | |||
<math>{\color{Red}\{N\}}</math> | |||
Teraz musimy tylko pokazać trójkę: | |||
<math>{\color{Red}\{N \land x \leq n\}}</math> | |||
y := y + x; | |||
<math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | |||
Użyjmy więc ponownie reguły dla przypisania, otrzymując: | |||
<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][y \mapsto y{+}x]\}}</math> | |||
y := y + x; | |||
<math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | |||
Skoro dwie asercje spotkały się, wystarczy teraz udowodnić implikację. | |||
I tak dalej. To znaczy, podobnie postępujemy z pozostałymi przypisaniami. A wszędzie, gdzie spotykają się dwie asercje, dowodzimy implikacji. | |||
Podsumowując, poniższe anotacje całego programu powinny stanowić dowód poprawności częściowej: | |||
<math>{\color{Red}\{n \geq 1\}}</math> | |||
x := 1; | |||
<math>{\color{Red}\{n \geq 0 \land x = 1\}}</math> | |||
y := 0; | |||
<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> | |||
while x <= n do | |||
( | |||
<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> | |||
y := y + x; | |||
<math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | |||
x := x + 1 | |||
<math>{\color{Red}\{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> | |||
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 \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> | |||
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ć. | |||
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. | |||
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. 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. | |||
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>. | |||
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> | |||
N \, \equiv \, y = 1{+}2{+}\ldots{+}(x{-}1) \land x \leq n{+}1</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), np. x := -2, y := 3? | |||
<br> | |||
'''Notacja:''' | |||
<br> | |||
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: | |||
<math>{\color{Red}\{n \geq 1\}}</math> | |||
x := 1; | |||
<math>{\color{Red}\{n \geq 0 \land x = 1\}}</math> | |||
y := 0; | |||
<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> | |||
while <math>{\color{Red}\{N\}}</math> x <= n do | |||
( | |||
<math>{\color{Red}\{N \land x \leq n\}}</math> | |||
... | |||
<br> | |||
'''Wariant:''' | |||
<br> | |||
Wróćmy na chwilę do naszej pierwszej decyzji, polegającej na wpisaniu następującej asercji | |||
<math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</math> | |||
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ć: | |||
<math>{\color{Red}\{n \geq 1\}}</math> | |||
x := 1; | |||
y := 0; | |||
<math>{\color{Red}\{N\}}</math> | |||
co można, za pomocą znanego nam już "przepychania w tył", zredukować do udowodnienia implikacji: | |||
<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> | |||
x := 1; | |||
<math>{\color{Red}\{N[y \mapsto 0]\}}</math> | |||
y := 0; | |||
<math>{\color{Red}\{N\}}</math> | |||
Ostatecznie, anotacje programu wyglądałyby tak: | |||
<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> | |||
x := 1; | |||
<math>{\color{Red}\{N[y \mapsto 0]\}}</math> | |||
y := 0; | |||
while <math>{\color{Red}\{N\}}</math> x <= n do | |||
( | |||
<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> | |||
y := y + x; | y := y + x; | ||
<math>{\color{Red}\{N[x \mapsto x{+}1]\}}</math> | |||
x := x + 1 | x := x + 1 | ||
<math>\{y=\frac{x\ | <math>{\color{Red}\{N\}}</math> | ||
<math>\{y=\ | ) | ||
<math>\{y=\ | <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> | |||
a pierwsza z trzech implikacji to: <math>n \geq 1 \, \implies \, N[y \mapsto 0][x \mapsto 1]</math>. | |||
</div></div> | |||
{{cwiczenie|2|cw2| | |||
Uzupełnij poniższe reguły: | |||
}} | |||
<math> | |||
\frac{?} | |||
{{\color{Red}\{\alpha\}} x:= e {\color{Red}\{\beta\}}} | |||
</math> | |||
<math> | |||
\frac{?} | |||
{{\color{Red}\{\alpha\}} \mathbf{while}\, b \,\mathbf{do}\, I {\color{Red}\{\beta\}}} | |||
</math> | |||
<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> | |||
\frac{\alpha \, \implies \, \beta[x \mapsto e]} | |||
{{\color{Red}\{\alpha\}} x:= e {\color{Red}\{\beta\}}} | |||
</math> | |||
<math> | |||
\frac{\alpha \, \implies \, \gamma | |||
\quad | |||
{\color{Red}\{\gamma \land b\}} I {\color{Red}\{\gamma\}} | |||
\quad | |||
\gamma \land \neg b \, \implies \, \beta} | |||
{{\color{Red}\{\alpha\}} \mathbf{while}\, b \,\mathbf{do}\, I {\color{Red}\{\beta\}}} | |||
</math> | |||
</div></div> | |||
{{cwiczenie|3 (potęgowanie binarne)|cw3| | |||
Dowiedź poprawności częściowej poniższego programu: | |||
}} | |||
<math>{\color{Red}\{y \geq 0\}}</math> | |||
z := 1; p := x; q := y; | |||
while q <> 0 do | |||
if odd(q) then | |||
z := z * p; | |||
q := q div 2; | |||
p := p * p | |||
<math>{\color{Red}\{z = x^y\}}</math> | |||
Wyrażenie odd(q) ma wartość <math>\mathbf{true}</math> wtedy i tylko wtedy, gdy q jest nieparzyste. | |||
<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"> | |||
Jako niezmiennik pętli przyjmijmy <math>N \, \equiv \, z {\cdot} p^q = x^y</math>. Oto odpowiednie anotacje naszego programu: | |||
<math>{\color{Red}\{y \geq 0\}}</math> | |||
<math>{\color{Red}\{N[q \mapsto y][p \mapsto x][z \mapsto 1]\}}</math> | |||
z := 1; | |||
p := x; | |||
q := y; | |||
while <math>{\color{Red}\{N\}}</math> q <> 0 do | |||
( | |||
<math>{\color{Red}\{N \land q \neq 0\}}</math> | |||
if odd(q) then | |||
( | |||
<math>{\color{Red}\{N \land q \neq 0 \land \,\mathrm{odd}(q)\}}</math> | |||
<math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2][z \mapsto z {\cdot} p]\}}</math> | |||
z := z * p | |||
<math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2]\}}</math> | |||
) | |||
else | |||
( | |||
<math>{\color{Red}\{N \land q \neq 0 \land \neq \,\mathrm{odd}(q)\}}</math> | |||
<math>{\color{Red}\{N[p \mapsto p {\cdot} p][q \mapsto q \,\mathrm{div}\, 2]\}}</math> | |||
skip | |||
<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][q \mapsto q \,\mathrm{div}\, 2]\}}</math> | |||
q := q div 2; | |||
<math>{\color{Red}\{N[p \mapsto p {\cdot} p]\}}</math> | |||
p := p * p | |||
<math>{\color{Red}\{N\}}</math> | |||
) | |||
<math>{\color{Red}\{N \land q=0\}}</math> | |||
<math>{\color{Red}\{z = x^y\}}</math> | |||
Po podstawieniu niezmiennika: | |||
<math>{\color{Red}\{y \geq 0\}}</math> | |||
<math>{\color{Red}\{1 {\cdot} x^y = x^y\}}</math> | |||
z := 1; | |||
p := x; | |||
q := y; | |||
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> | |||
if odd(q) then | |||
( | |||
<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 \,\mathrm{div}\, 2)} = x^y\}}</math> | |||
z := z * p | |||
<math>{\color{Red}\{z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | |||
) | |||
else | |||
( | |||
<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 \,\mathrm{div}\, 2)} = x^y\}}</math> | |||
skip | |||
<math>{\color{Red}\{z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | |||
) | |||
<math>{\color{Red}\{z {\cdot} (p {\cdot} p)^{(q \,\mathrm{div}\, 2)} = x^y\}}</math> | |||
q := q div 2; | |||
<math>{\color{Red}\{z {\cdot} (p {\cdot} p)^q = x^y\}}</math> | |||
p := p * p | |||
<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 = x^y\}}</math> | |||
Teraz pozostaje tylko pokazać następujące implikacje: | |||
* <math>y \geq 0 \, \implies \, 1 {\cdot} x^y = 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 \,\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> | |||
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. | |||
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>. | |||
{{uwaga||| | |||
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ą: | |||
wynik będzie poprawny, o ile program się zakończy, ale wcale zakończyć się nie musi! | |||
}} | |||
'''Pytanie:''' czy niezmiennik pętli jest napewno prawdziwy, gdy zmienna q ma wartość ujemną? | |||
</div></div> | </div></div> | ||
{{cwiczenie|4|cw4| | |||
Zaproponuj regułę dla instrukcji <math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math>. | |||
}} | |||
<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; \mathbf{while}\, \neg b \,\mathbf{do}\, I</math>. | |||
Stąd łatwo otrzymać regułę: | |||
<math> | |||
\frac{{\color{Red}\{\alpha\}} I {\color{Red}\{\beta\}} | |||
\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> | |||
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>, otrzymując regułę: | |||
<math> | |||
\frac{{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}} | |||
\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> | |||
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ć: | |||
<math> | |||
\frac{{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}}} | |||
{{\color{Red}\{\beta\}} \mathbf{repeat}\, I \,\mathbf{until}\, b {\color{Red}\{\beta \land 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: | |||
<math> | |||
\frac{{\color{Red}\{\alpha\}} I {\color{Red}\{\beta\}} | |||
\quad | |||
\beta \land \neg b \implies \alpha} | |||
{{\color{Red}\{\alpha\}} \mathbf{repeat}\, I \,\mathbf{until}\, b {\color{Red}\{\beta \land b\}}} | |||
</math> | |||
</div></div> | |||
== Zadania domowe == | == Zadania domowe == | ||
Linia 38: | Linia 474: | ||
{{cwiczenie|1|cw1.dom| | {{cwiczenie|1|cw1.dom| | ||
Wyprowadź ostatnią regułę dla pętli <math>\mathbf{repeat}\ </math>, z pierwszej reguły. | |||
}} | |||
{{cwiczenie|2|cw2.dom| | |||
Napisz program obliczający największy wspólny dzielnik dwóch liczb i przeprowadź dowód poprawności częściowej. | |||
}} | |||
{{cwiczenie|3|cw3.dom| | |||
Przeprowadź dowód poprawności częściowej: | |||
}} | |||
<math>{\color{Red}\{x \geq 0\}}</math> | |||
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; | |||
<math>{\color{Red}\{(b-1)^3 \leq x < b^3\}}</math> | |||
{{wskazowka||| | |||
<math> | |||
(m + 1)^3 \, = \, m^3 + 3 {{\cdot}} m^2 + 3 {{\cdot}} m + 1 | |||
</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