Semantyka i weryfikacja programów/Ćwiczenia 2: Różnice pomiędzy wersjami
m Zastępowanie tekstu - "\Longrightarrow\" na "\Longrightarrow" |
m Zastępowanie tekstu – „.↵</math>” na „</math>” |
||
(Nie pokazano 2 pośrednich wersji utworzonych przez tego samego użytkownika) | |||
Linia 96: | Linia 96: | ||
l, s \,\Longrightarrow, l | l, s \,\Longrightarrow, l | ||
\quad \quad | \quad \quad | ||
n, s \,\Longrightarrow, n | n, s \,\Longrightarrow, n</math> | ||
</math> | |||
Podobnie jak poprzednio, zakładamy tutaj dla wygody, że <math>\mathbf{Num} \subseteq \mathbf{Exp}</math> oraz <math>\mathbf{Bool} \subseteq \mathbf{BExp}</math>. | Podobnie jak poprzednio, zakładamy tutaj dla wygody, że <math>\mathbf{Num} \subseteq \mathbf{Exp}</math> oraz <math>\mathbf{Bool} \subseteq \mathbf{BExp}</math>. | ||
Linia 125: | Linia 124: | ||
\mathbf{false} \land b_2, s \,\Longrightarrow, \mathbf{false}, s | \mathbf{false} \land b_2, s \,\Longrightarrow, \mathbf{false}, s | ||
\quad \quad | \quad \quad | ||
\mathbf{true} \land b_2, s \,\Longrightarrow, b_2, s | \mathbf{true} \land b_2, s \,\Longrightarrow, b_2, s</math> | ||
</math> | |||
Analogicznie reguły prawostronne to: | Analogicznie reguły prawostronne to: | ||
Linia 136: | Linia 134: | ||
b_1 \land \mathbf{false}, s \,\Longrightarrow, \mathbf{false}, s | b_1 \land \mathbf{false}, s \,\Longrightarrow, \mathbf{false}, s | ||
\quad \quad | \quad \quad | ||
b_1 \land \mathbf{true}, s \,\Longrightarrow, b_1, s | b_1 \land \mathbf{true}, s \,\Longrightarrow, b_1, s</math> | ||
</math> | |||
Reguły ''równoległe'' otrzymujemy jako sumę reguł lewo- i prawostronnych (w sumie 6 reguł). Zauważmy, że obliczanie wyrażeń <math>b_1</math> i <math>b_2</math> odbywa się teraz w tzw. "przeplocie": Pojedynczy krok polega na wykonaniu jednego kroku obliczenia <math>b_1</math> albo jednego kroku obliczenia <math>b_2</math>. | Reguły ''równoległe'' otrzymujemy jako sumę reguł lewo- i prawostronnych (w sumie 6 reguł). Zauważmy, że obliczanie wyrażeń <math>b_1</math> i <math>b_2</math> odbywa się teraz w tzw. "przeplocie": Pojedynczy krok polega na wykonaniu jednego kroku obliczenia <math>b_1</math> albo jednego kroku obliczenia <math>b_2</math>. | ||
Linia 167: | Linia 164: | ||
n_1 \leq n_2, s \,\Longrightarrow, \mathbf{true}, s \quad \mbox{ o ile } n_1 \leq n_2 | n_1 \leq n_2, s \,\Longrightarrow, \mathbf{true}, s \quad \mbox{ o ile } n_1 \leq n_2 | ||
\quad \quad | \quad \quad | ||
n_1 \leq n_2, s \,\Longrightarrow, \mathbf{false}, s \quad \mbox{ o ile } n_1 > n_2 | n_1 \leq n_2, s \,\Longrightarrow, \mathbf{false}, s \quad \mbox{ o ile } n_1 > n_2</math> | ||
</math> | |||
Reguły powyższe zależą od semantyki wyrażen arytmetycznych. | Reguły powyższe zależą od semantyki wyrażen arytmetycznych. | ||
Linia 212: | Linia 208: | ||
ale nie wiemy już, jaki był dozór pętli (widzimy tylko wynik obliczenia tego dozoru w stanie s, czyli <math>\mathbf{true}</math>). | ale nie wiemy już, jaki był dozór pętli (widzimy tylko wynik obliczenia tego dozoru w stanie s, czyli <math>\mathbf{true}</math>). | ||
Możemy odwołać się do tranzytywnego domknięcia relacji <math>\,\Longrightarrow | Możemy odwołać się do tranzytywnego domknięcia relacji <math>\,\Longrightarrow</math>, (czyli w zasadzie do semantyki dużych kroków): | ||
<math> | <math> | ||
Linia 224: | Linia 220: | ||
Istnieją inne możliwe rozwiązania w stylu małych kroków. | Istnieją inne możliwe rozwiązania w stylu małych kroków. | ||
Jedno z nich oparte jest na pomyśle, aby "rozwinąć" pętlę <math>\mathbf{while}\ | Jedno z nich oparte jest na pomyśle, aby "rozwinąć" pętlę <math>\mathbf{while}\ </math>, zanim obliczymy wartość dozoru <math>b</math>. | ||
Jedyną reguła dla pętli <math>\mathbf{while}\ | Jedyną reguła dla pętli <math>\mathbf{while}\ </math>, byłaby wtedy reguła: | ||
<math> | <math> | ||
\mathbf{while}\, b \,\mathbf{do}\, I, s \,\Longrightarrow, \mathbf{if}\, b \,\mathbf{then}\, (I; \mathbf{while}\, b \,\mathbf{do}\, I) \,\mathbf{else}\, \mathbf{skip}, s | \mathbf{while}\, b \,\mathbf{do}\, I, s \,\Longrightarrow, \mathbf{if}\, b \,\mathbf{then}\, (I; \mathbf{while}\, b \,\mathbf{do}\, I) \,\mathbf{else}\, \mathbf{skip}, s</math> | ||
</math> | |||
Dzięki temu obliczany warunek logiczny <math>b</math> jest zawsze ''jednorazowy''. | Dzięki temu obliczany warunek logiczny <math>b</math> jest zawsze ''jednorazowy''. | ||
Linia 261: | Linia 256: | ||
<div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible-content" style="display:none"> | ||
'''Instrukcja <math>\mathbf{repeat}\ | '''Instrukcja <math>\mathbf{repeat}\ </math>,''' | ||
<br> | <br> | ||
Zacznijmy od pętli <math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math>. | Zacznijmy od pętli <math>\mathbf{repeat}\, I \,\mathbf{until}\, b</math>. | ||
Przyjrzyjmy się dwóm podejściom, które zastosowaliśmy dla pętli <math>\mathbf{while}\ | Przyjrzyjmy się dwóm podejściom, które zastosowaliśmy dla pętli <math>\mathbf{while}\ </math>, w poprzednim zadaniu. | ||
Po pierwsze, rozwinięcie: | Po pierwsze, rozwinięcie: | ||
<math> | <math> | ||
\mathbf{repeat}\, I \,\mathbf{until}\, b, s \,\Longrightarrow, I; \mathbf{if}\, b \,\mathbf{then}\, (\mathbf{repeat}\, I \,\mathbf{until}\, b) \,\mathbf{else}\, \mathbf{skip}, s | \mathbf{repeat}\, I \,\mathbf{until}\, b, s \,\Longrightarrow, I; \mathbf{if}\, b \,\mathbf{then}\, (\mathbf{repeat}\, I \,\mathbf{until}\, b) \,\mathbf{else}\, \mathbf{skip}, s</math> | ||
</math> | |||
Po drugie, spróbujmy odwołać się do <math>\,\Longrightarrow,^{*}</math> dla dozoru pętli <math>b</math>: | Po drugie, spróbujmy odwołać się do <math>\,\Longrightarrow,^{*}</math> dla dozoru pętli <math>b</math>: | ||
Linia 287: | Linia 281: | ||
</math> | </math> | ||
Okazuje się, że jest jeszcze gorzej niż w przypadku pętli <math>\mathbf{while}\ | Okazuje się, że jest jeszcze gorzej niż w przypadku pętli <math>\mathbf{while}\ </math>,: nie pamiętamy już, jaka była instrukcja wewnętrzna naszej pętli! | ||
Czyli takie podejście jest teraz nieskuteczne. | Czyli takie podejście jest teraz nieskuteczne. | ||
Linia 305: | Linia 299: | ||
<math> | <math> | ||
\,\mathbf{do}\, n \,\mathbf{times}\, I, s | \,\mathbf{do}\, n \,\mathbf{times}\, I, s</math> | ||
</math> | |||
Teraz jest już łatwo: | Teraz jest już łatwo: | ||
Linia 317: | Linia 310: | ||
<math> | <math> | ||
\,\mathbf{do}\, n \,\mathbf{times}\, I, s \,\Longrightarrow, s | \,\mathbf{do}\, n \,\mathbf{times}\, I, s \,\Longrightarrow, s | ||
\quad \mbox{ o ile } n = 0 | \quad \mbox{ o ile } n = 0</math> | ||
</math> | |||
<br> | <br> | ||
'''Instrukcja <math>\mathbf{for}\ | '''Instrukcja <math>\mathbf{for}\ </math>,''' | ||
<br> | <br> | ||
W przypadku pętli <math>\mathbf{for}\ | W przypadku pętli <math>\mathbf{for}\ </math>, przyjmijmy, że wartości wyrażeń <math>e_1</math> i <math>e_2</math> obliczane są przed pierwszą iteracją pętli. | ||
Dodatkowo ustalmy, że np. <math>e_1</math> będzie obliczone jako pierwsze. | Dodatkowo ustalmy, że np. <math>e_1</math> będzie obliczone jako pierwsze. | ||
Następnie podstawiamy wartość <math>e_1</math> na zmienną <math>x</math>. | Następnie podstawiamy wartość <math>e_1</math> na zmienną <math>x</math>. | ||
Linia 342: | Linia 334: | ||
<math> | <math> | ||
\mathbf{for}\, x = n_1 \,\mathbf{to}\, n_2 \,\mathbf{do}\, I, s | \mathbf{for}\, x = n_1 \,\mathbf{to}\, n_2 \,\mathbf{do}\, I, s</math> | ||
</math> | |||
Dalsze reguły mogą być podobne do reguł dla pętli <math>\,\mathbf{do}\, n \,\mathbf{times}\, I</math>: | Dalsze reguły mogą być podobne do reguł dla pętli <math>\,\mathbf{do}\, n \,\mathbf{times}\, I</math>: | ||
Linia 363: | Linia 354: | ||
<math> | <math> | ||
\mathbf{for}\, x = n_1 \,\mathbf{to}\, n_2 \,\mathbf{do}\, I, s \,\Longrightarrow, I; \mathbf{for}\, x = n_1+1 \,\mathbf{to}\, n_2 \,\mathbf{do}\, I, s[x \mapsto s(x)+1] | \mathbf{for}\, x = n_1 \,\mathbf{to}\, n_2 \,\mathbf{do}\, I, s \,\Longrightarrow, I; \mathbf{for}\, x = n_1+1 \,\mathbf{to}\, n_2 \,\mathbf{do}\, I, s[x \mapsto s(x)+1] | ||
\quad \mbox{ o ile } s(x) \leq n_2 | \quad \mbox{ o ile } s(x) \leq n_2</math> | ||
</math> | |||
Czy semantyka jest taka sama? | Czy semantyka jest taka sama? | ||
(Rozważ sytuację, gdy zmienna <math>x</math> jest zmieniana przez instrukcję <math>I</math>.) | (Rozważ sytuację, gdy zmienna <math>x</math> jest zmieniana przez instrukcję <math>I</math>.) | ||
Linia 376: | Linia 366: | ||
<math> | <math> | ||
\,\mathbf{do}\, I \,\mathbf{while}\, b, s \,\Longrightarrow, \mathbf{repeat}\, I \,\mathbf{until}\, \neg b, s | \,\mathbf{do}\, I \,\mathbf{while}\, b, s \,\Longrightarrow, \mathbf{repeat}\, I \,\mathbf{until}\, \neg b, s</math> | ||
</math> | |||
</div></div> | </div></div> | ||
Linia 456: | Linia 445: | ||
<math> | <math> | ||
\epsilon + \epsilon \,\Longrightarrow, \epsilon | \epsilon + \epsilon \,\Longrightarrow, \epsilon</math> | ||
</math> | |||
Gdy jeden ze składników ma mniej cyfr niż drugi, potrzebujemy reguł: | Gdy jeden ze składników ma mniej cyfr niż drugi, potrzebujemy reguł: | ||
Linia 472: | Linia 460: | ||
e 0 + \epsilon \,\Longrightarrow, e 0 | e 0 + \epsilon \,\Longrightarrow, e 0 | ||
\quad \quad | \quad \quad | ||
e 1 + \epsilon \,\Longrightarrow, e 1 | e 1 + \epsilon \,\Longrightarrow, e 1</math> | ||
</math> | |||
Niestety, nie możemy użyć reguły przemienności: | Niestety, nie możemy użyć reguły przemienności: | ||
Linia 514: | Linia 501: | ||
e 0 \,\,|\,\, | e 0 \,\,|\,\, | ||
e 1 \,\,|\,\, | e 1 \,\,|\,\, | ||
e_1 + e_2 | e_1 + e_2 </math> | ||
</math> | |||
Na przykład <math>p 1 0 1</math> oznacza tę samą liczbę, co <math>\epsilon 1 0 1</math>, ale z dodatkową informacją, że podczas jej obliczania nastąpiło "przepełnienie". | Na przykład <math>p 1 0 1</math> oznacza tę samą liczbę, co <math>\epsilon 1 0 1</math>, ale z dodatkową informacją, że podczas jej obliczania nastąpiło "przepełnienie". | ||
Linia 534: | Linia 520: | ||
\epsilon \,\,|\,\, | \epsilon \,\,|\,\, | ||
b 0 \,\,|\,\, | b 0 \,\,|\,\, | ||
b 1 | b 1</math> | ||
</math> | |||
reprezentujących sumę liczb binarnych. | reprezentujących sumę liczb binarnych. | ||
Linia 561: | Linia 546: | ||
e 0 + p \,\Longrightarrow, e 0 | e 0 + p \,\Longrightarrow, e 0 | ||
\quad \quad | \quad \quad | ||
e 1 + p \,\Longrightarrow, e 1 | e 1 + p \,\Longrightarrow, e 1</math> | ||
</math> | |||
W takiej sytuacji oczywiście informacja o przepełnieniu zostaje wymazana. | W takiej sytuacji oczywiście informacja o przepełnieniu zostaje wymazana. | ||
Linia 574: | Linia 558: | ||
e 0 + \epsilon \,\Longrightarrow, e 0 | e 0 + \epsilon \,\Longrightarrow, e 0 | ||
\quad \quad | \quad \quad | ||
e 1 + \epsilon \,\Longrightarrow, e 1 | e 1 + \epsilon \,\Longrightarrow, e 1</math> | ||
</math> | |||
z poprzedniego zadania są wystarczające. | z poprzedniego zadania są wystarczające. | ||
Linia 583: | Linia 566: | ||
<math> | <math> | ||
p + p \,\Longrightarrow, p | p + p \,\Longrightarrow, p</math> | ||
</math> | |||
Ale co należy zrobić, gdy tylko jeden ze składników odnotował przepełnienie? <math>p + \epsilon \,\Longrightarrow, ?</math> | Ale co należy zrobić, gdy tylko jeden ze składników odnotował przepełnienie? <math>p + \epsilon \,\Longrightarrow, ?</math> | ||
Linia 593: | Linia 575: | ||
p + \epsilon \,\Longrightarrow, \epsilon | p + \epsilon \,\Longrightarrow, \epsilon | ||
\quad \quad | \quad \quad | ||
\epsilon + p \,\Longrightarrow, \epsilon | \epsilon + p \,\Longrightarrow, \epsilon</math> | ||
</math> | |||
Na koniec zostało najważniejsze: kiedy powinniśmy generować sygnał o przepełnieniu? | Na koniec zostało najważniejsze: kiedy powinniśmy generować sygnał o przepełnieniu? | ||
Linia 603: | Linia 584: | ||
<math> | <math> | ||
e_1 1 + e_2 1 \,\Longrightarrow, ((e_1 + e_2) + p 1) 0 | e_1 1 + e_2 1 \,\Longrightarrow, ((e_1 + e_2) + p 1) 0</math> | ||
</math> | |||
Nowy sztuczny składnik <math>p 1</math> zawiera jakby na wszelki wypadek informacje o potencjalnym przepełnieniu. | Nowy sztuczny składnik <math>p 1</math> zawiera jakby na wszelki wypadek informacje o potencjalnym przepełnieniu. |
Aktualna wersja na dzień 21:29, 11 wrz 2023
Zawartość
Ćwiczymy dalej semantykę małych kroków. Uzupełnimy semantykę języka Tiny o semantykę operacyjną wyrażeń boolowskich i arytmetycznych. Następnie rozszerzymy nasz język o róznorodne konstrukcje iteracji. Na koniec zdefiniujemy operacje arytmetyczne liczb binarnych.
Rozszerzenia semantyki języka Tiny
Ćwiczenie 1
Semantyka języka Tiny z wykładu używała funkcji semantycznych dla określenia znaczenia wyrażeń boolowskich i arytmetycznych. Zdefiniuj znaczenie wyrażeń za pomocą semantyki operacyjnej, w stylu małych kroków.
Rozwiązanie
Ćwiczenie 2
Rozszerzmy język Tiny o następujące dobrze znane konstrukcje iteracji:
Napisz semantykę małych kroków dla powyższych konstrukcji.
Rozwiązanie
Kalkulator binarny
Ćwiczenie 3
Rozważmy następujący język wyrażeń (liczby binarne z dodawaniem):
oznacza słowo puste, czyli np. oznacza binarną liczbę 1011. Napisz semantykę operacyjną obliczającą wartość wyrażeń.
Rozwiązanie
Ćwiczenie 4
Rozszerzmy składnię o jeden symbol oznaczający "przepełnienie":
Na przykład oznacza tę samą liczbę, co , ale z dodatkową informacją, że podczas jej obliczania nastąpiło "przepełnienie". Rozumiemy przez to sytuację, gdy wynik ma więcej cyfr niż każdy z argumentów. Cyfry zero z lewej strony (najbardziej znaczące) również uważamy za pełnoprawne cyfry, nie należy ich usuwać ani dodawać nowych.
Napisz semantykę operacyjną obliczającą wartość wyrażenia wraz z informacja o ewentualnym przepełnieniu. Wynik powinien byc poprawny przynajmniej dla wyrażeń w składni ograniczonej:
reprezentujących sumę liczb binarnych.
Rozwiązanie
Zadania domowe
Ćwiczenie 1
Podaj przykład wyrażenia boolowskiego, które nie policzy się ani przy użyciu strategii lewo-, ani prawostronnej, a policzy się przy strategii równoległej.
Ćwiczenie 2
Zmodyfikuj semantykę wyrażeń następująco: dla każdego podwyrażenia niedeterministycznie wybierana jest strategia lewo- albo prawostronna, ale niedozwolony jest "przeplot".
Ćwiczenie 3
Rozważ inną semantykę pętli , w której wyrażenie jest obliczane na nowo przed każdą iteracją pętli.
Ćwiczenie 4
Dodaj do wyrażeń binarnych operację odejmowania.
Ćwiczenie 5
Zaproponuj semantykę przypisania równoległego w języku TINY:
polegającego na obliczeniu najpierw wartości wyrażeń , a następnie na podstawieniu tych wartości na zmienne .