Semantyka i weryfikacja programów/Ćwiczenia 13: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sl (dyskusja | edycje)
Nie podano opisu zmian
m Zastępowanie tekstu – „<math> ” na „<math>”
 
(Nie pokazano 8 wersji utworzonych przez 4 użytkowników)
Linia 1: Linia 1:


== Zawartość ==
== Zawartość ==


Poprawność częściowa prostych programów w języku Tiny.
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>
 




{{rozwiazanie||roz1|


<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 ,,przeciągnąć" asercję początkową wprzód otrzymując <math>{\color{Red}\{n \geq 0 \land x = 1 \land y = 0\}}</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:
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:




Dla prawdziwości tej reguły powinniśmy, formalnie rzecz biorąc, zgadnąć asercję, która może być wpisana pomiędzy dwie instrukcje przypisania:
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 ,,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ł.
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 ,,x := x + 1", otrzymamy:
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{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 ,,spotkały się", wystarczy teraz udowodnić implikację.
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 ,,spotykają się" dwie asercje, dowodzimy implikacji.  
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{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{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{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 oduwodnienie następujących implikacje:
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 ,,odgadnąć" poprzez staranną obserwację tego, co dzieje się wewnątrz pętli.
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>.
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{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ż ,,przepychania w tył", zredukować do udowodnienia implikacji:
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{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{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{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{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:




{{rozwiazanie||roz2|


<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.


{{rozwiazanie||roz3|


<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">


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][p \mapsto q \div 2][z \mapsto z \cdot p]\}}</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
     z := z * p
     <math>{\color{Red}\{N[p \mapsto p \cdot p][p \mapsto q \div 2]\}}</math>
     <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][p \mapsto q \div 2]\}}</math>
     <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][p \mapsto q \div 2]\}}</math>
     <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][p \mapsto q \div 2]\}}</math>
   <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:''' jak będzie działał nasz program, jeśli zmienną q zainicjujemy na wartość ujemną?
'''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 regułe dla instrukcji <math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math>.
Zaproponuj regułę dla instrukcji <math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math>.
}}
}}




{{rozwiazanie||roz4|


<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; \mathbf{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>.
Linia 443: Linia 438:
</math>
</math>


Dwukrotnie odwołujemy się do poprawności częściowej instrukcji <math>I</math>, względem różnych asercji początkowych.
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>, otrzymyjąc regułę:
Gdybyśmy chcieli tego uniknąć, moglibyśmy rozważyć <math>\alpha = \beta</math>, otrzymując regułę:


<math>
<math>
\frac{{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}}
\frac{{\color{Red}\{\beta\}} I {\color{Red}\{\beta\}}
       \quad
       \quad
       {\color{Red}\{\beta \land \neg b\}}</math> I {\color{Red}\{\beta\}}}
       {\color{Red}\{\beta \land \neg b\}} I {\color{Red}\{\beta\}}}
     {{\color{Red}\{\beta\}} \mathbf{repeat}\, I \,\mathbf{until}\, b {\color{Red}\{\beta \land b\}}}
     {{\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>
Linia 461: Linia 455:
</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:
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}\,</math> z pierwszej reguły.
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 najmniejszy wspólny dzielnik dwóch liczb i przeprowadź dowód poprawności częściowej.
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:


{n1}
x := 1; y := 0;
while x <= n do
  y := y + x;
  x := x + 1
{y=n(n+1)2}



Rozwiązanie


Ćwiczenie 2

Uzupełnij poniższe reguły:

?{α}x:=e{β}

?{α}𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I{β}



Rozwiązanie


Ćwiczenie 3 (potęgowanie binarne)

Dowiedź poprawności częściowej poniższego programu:


{y0}
z := 1; p := x; q := y;
while q <> 0 do
  if odd(q) then
    z := z * p;
  q := q div 2;
  p := p * p
{z=xy}


Wyrażenie odd(q) ma wartość 𝐭𝐫𝐮𝐞 wtedy i tylko wtedy, gdy q jest nieparzyste.


Rozwiązanie


Ćwiczenie 4

Zaproponuj regułę dla instrukcji 𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b.


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:


{x0}
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;
{(b1)3x<b3}


Wskazówka

(m+1)3=m3+3m2+3m+1