8. LOGIKA TEMPORALNA Składnia zdaniowej logiki temporalnej: 1) symbole formuł atomowych p, q, r, ... są formułami; 2) jeżeli , są formułami, to , są formułami; 3) jeżeli , są formułami, to , , , U są formułami. Operatory temporalne czasu przyszłego: ( lub F ) „ kiedyś ” ( lub G ) „ zawsze ” ( lub X ) „ w następnej chwili ” U „ aż do ” Istnieją analogiczne operatory czasu przeszłego: „kiedyś w przeszłości ”, „zawsze w przeszłości ”, „w poprzedniej chwili ”, „ od ” (nie będą potrzebne w ciągu tego wykładu).
Zdaniowa logika temporalna zakłada zmienność w czasie prawdziwości poszczególnych formuł atomowych. Przyjmujemy, że czas jest dyskretny, półnieskończony (czyli izomorficzny ze zbiorem liczb naturalnych Nat). Przykładowy wykres prawdziwości pewnej formuły p: T F 0 1 2 3 4 5 6 7 8 t Zakładając, że dla każdej formuły atomowej p, q, r ... mamy daną funkcję z Nat {True, False}, prawdziwość formuły złożonej dla pewnej chwili i Nat określamy następująco: 1) dla funktorów klasycznych (, ) - zgodnie z ich tabelkami; 2) jest prawdziwa w i ( j ) jest prawdziwa dla pewnego j i ; 3) jest prawdziwa w i ( j ) jest prawdziwa dla każdego j i ; 4) jest prawdziwa w i prawdziwa jest ( i + 1 ) ; 5) U jest prawdziwa w i ( j ) jest prawdziwa dla pewnego j i ( k ) jest prawdziwa dla wszystkich k takich, że i k j . Formułę nazywamy inicjalnie prawdziwą, jeśli prawdziwe jest (0).
Dowodzenie własności programów reaktywnych przy użyciu logiki temporalnej Modelem programu jest zbiór skończenie stanowych diagramów przejść z załączonym wykazem początkowych wartości zmiennych. W każdym diagramie wyróżniony jest jeden stan początkowy. Wykonaniem programu jest zbiór procesów, przy czym każdy diagram odpowiada jednemu procesowi. Każdy proces zaczyna pracę od stanu początkowego swojego diagramu. Zbiór procesów wykonuje dowolny słabo uczciwy przeplot akcji elementarnych. Stan procesu jest wektorem, którego składowymi są: a) aktualny stan diagramu, w którym proces przebywa (czyli położenie jego wskaźnika instrukcji); b) aktualne wartości wszystkich zmiennych, na których proces operuje (prywatnych i wspólnych). Stanem zbioru procesów jest zbiór aktualnych stanów wszystkich jego procesów. Uwaga. Programy powinny być tak konstruowane, aby ich ogólne własności nie zależały od zastosowanego przeplotu (przy założeniu słabej uczciwości tego przeplotu).
W ogólności zmienne programu mogą przyjmować (teoretycznie) nieskończenie wiele wartości, więc stanów procesów może być nieskończenie wiele. W praktyce okazuje się jednak, że w większości przypadków o ogólnych własnościach programu decyduje niewielka liczba zmiennych umieszczonych w pamięci wspólnej - tak zwanych zmiennych synchronizacyjnych, które przyjmują tylko skończoną liczbę wartości (dla ustalonej liczby procesów) i nie zależą od wartości zmiennych prywatnych. Ponieważ każdy diagram ma skończoną liczbę węzłów (czyli skończoną liczbę możliwych położeń wskaźników instrukcji), w praktyce do dowodzenia istotnych z punktu widzenia synchronizacji własności programów wystarcza analiza skończenie stanowa. Uwaga 1) W dowodach własności programów współbieżnych często posługujemy się dodatkowymi zmiennymi, które nie występują w treści programu, ale których wartości są zależne od wartości zmiennych programu. 2) Projektowanie programu współbieżnego zwykle zaczyna się od zaprojektowania jego szkieletu synchronizacyjnego, czyli ustalenia zbioru zmiennych synchronizacyjnych oraz przyjęcia uproszczonych diagramów przejść, uwzględniających jedynie te przejścia, w których występują zmienne synchronizacyjne.
Ogólna klasyfikacja własności temporalnych programów współbieżnych Załóżmy, że dany jest pewien program współbieżny P, którego uruchomienie powoduje współbieżne wykonanie procesów P1, P2, ... , Pn, oraz pewna formuła logiki temporalnej , której formuły atomowe wypowiadają się na temat wartości zmiennych oraz położeń wskaźników instrukcji tych procesów. W formule tej nie stosujemy kwantyfikowania zmiennych, więc może ona być traktowana jako formuła logiki zdaniowej, a nie pierwszego rzędu. Definicja Program P posiada własność (wyrażoną przez formułę) , jeżeli każdy ciąg stanów zbioru procesów uzyskany przez dowolne słabo uczciwe wykonanie programu P spełnia inicjalnie (czyli zachodzi (0) = True). Własność nazywamy własnością bezpieczeństwa (safety property) wtedy i tylko wtedy, gdy jest ona równoważna pewnej formule o postaci p, gdzie p nie zawiera operatorów temporalnych czasu przyszłego.
Analogicznie definiujemy pozostałe rodzaje własności: własność postać formuły gwarancji (guarantee) p obowiązku (obligation) ( p q ) odpowiedzi (response) p (nieskończenie wiele razy p) uporczywości (persistence) p (od pewnej chwili stale p) reakcji (reactivity) ( p q ) Wszystkie wymienione własności inne, niż własność bezpieczeństwa, nazywane są łącznie własnościami postępu (progress). Diagram inkluzji reakcji klas formuł: odpowiedzi uporczywości a b obowiązku oznacza a b bezpieczeństwa gwarancji Uwaga: powyższy podział nie jest podziałem na rozłączne klasy formuł. k i i i = 1 k i i i = 1
Jako klasę własności temporalnych wyróżnia się też klasę formuł żywotności (liveness). Klasa ta nie ma charakterystyki syntaktycznej. Jest klasą nieporównywalną (w sensie relacji zawierania) z każdą z klas formuł postępu. Definicje semantyczne: 1) jest formułą bezpieczeństwa dla każdego ciągu stanów nie spełniającego istnieje takie k Nat, że żaden ciąg stanów zawierający prefix {0...k} nie spełnia . 2) jest formułą żywotności dowolny skończony ciąg stanów może być przedłużony do pewnego ciągu nieskończonego, który spełnia . Twierdzenie Definicja syntaktyczna klasy własności bezpieczeństwa jest równoważna definicji semantycznej.
Przykłady własności programów i ich dowodów Niezmiennikiem programu nazywamy każdą formułę klasycznej logiki zdaniowej (której formuły atomowe wypowiadają się na temat zmiennych programu i wskaźników instrukcji) prawdziwą w każdym stanie każdego wykonania tego programu. Dowód, że formuła jest niezmiennikiem, jest zatem równoważny dowodowi inicjalnej prawdziwości formuły (gdzie nie zawiera żadnych operatorów temporalnych), czyli szczególnego przypadku własności bezpieczeństwa. W wielu prostych przypadkach dowodzenie własności bezpieczeństwa programu sprowadza się do dowodu, że pewna formuła jest jego niezmiennikiem. Metodą dowodzenia jest indukcja po wszystkich możliwych przejściach w diagramie programu.
P: while true do || Q: while true do Przykład { x = 0, y = 0 } P: while true do || Q: while true do if x y then x := x + 1; if x y then y := y + 1; Diagram: { x = 0, y = 0 } x < y x > y p0 q0 x y x y x := x + 1 y := y + 1 p1 q1 Własność bezpieczeństwa: ( | x - y | 1 )
Dowód (indukcyjny) Pokażemy silniejszą własność: ((at p0 at q0 |x - y| 1) (at p1 at q0 (x = y x+1 = y)) (at p0 at q1 (x = y x = y+1)) (at p1 at q1 x = y)) 1° W chwili początkowej zachodzi x = 0 y = 0, czyli |x - y| = 0 1 2° Rozważamy wszystkie możliwe przejścia z wszystkich możliwych par stanów: a) dowolne przejście z (p0, q0) nie zmienia wartości x ani y ; b) w (p1, q0) z założenia indukcyjnego zachodzi x = y x+1 = y. Możemy wykonać przejście do (p0, q0) i otrzymać x = y x = y+1, albo wykonać przejście z powrotem do (p1, q0) nie zmie- niając wartości zmiennych; c) w (p0, q1) z założenia indukcyjnego zachodzi x = y x = y+1. Możemy wykonać przejście do (p0, q0) i otrzymać x = y x+1 = y, albo wykonać przejście z powrotem do (p0, q1) nie zmie- d) w (p1, q1) z założenia indukcyjnego zachodzi x = y. Możemy wykonać przejście do (p1, q0) i otrzymać x+1 = y, albo wykonać przejście do (p0, q1) i otrzymać x = y+1. Uwaga. Wartości x, y rosną nieograniczenie, ale można wprowadzić zmienną pomocniczą, np. a = x-y.
(p0, q0) (p0, q1) (p0, q0) (p0, q0) (p0, q0) Własność żywotności: (x = c (x > c)) gdzie c - zmienna pomocnicza Tej własności nie da się dowieść nie korzystając z założenia o słabej uczciwości wykonywanego przeplotu. Bez tego założenia byłby możliwy na przykład następujący ciąg przejść: (p0, q0) (p0, q1) (p0, q0) (p0, q0) (p0, q0) Dokładniej, musimy korzystać z następujących założeń o lokalnej uczciwości: ((at p0 at q0 x = y+1) (at q1) ((at p0 at q0 x+1 = y) (at p1) ((at p0 at q1 x = y+1) (at q0) ((at p1 at q0 x+1 = y) (at p0) Q Q Q Q Q x = 0 x y x = 0 y := y + 1 x = 0 x < y x = 0 x < y x = 0 x < y
Z powyższych czterech założeń oraz z rozważenia wszystkich możliwych przejść otrzymujemy: (at p0 (at p1)) (at p1 (at p0)) (at q0 (at q1)) (at q1 (at q0)) Ponieważ (at p0 (at p1)) implikuje ((at p0 x = c) (at p1 x = c)) oraz (at p1 (at p0)) implikuje ((at p1 x = c) (at p0 x = c+1)) stąd otrzymujemy żądaną własność. To był tylko szkic dowodu, a nie pełny dowód. żywotność P żywotność Q
Przykład. Algorytm Petersona. { y1 y2 t } q0 niekrytyczna1 niekrytyczna2 p1 q1 y1 := true y2 := true p2 q2 P : y1 := false t := false || Q : y2 := false t := true p3 q3 y2 t ? y1 t ? p4 q4 krytyczna1 krytyczna2 p5 q5
Chcemy dowieść, że algorytm Petersona ma własność wzajemnego wykluczania. Przyjmijmy uproszczony zapis: at p4,5 oznacza, że P jest w sekcji krytycznej (to jest w stanie p4 lub p5 lub pomiędzy nimi) at q4,5 oznacza, że Q jest w sekcji krytycznej (to jest w stanie q4 lub q5 lub pomiędzy nimi) Chcemy pokazać, że ( (at p4,5 at q4,5)) (własność bezpieczeństwa) Pokazujemy najpierw prawdziwość prostszych własności: 1) (y1 (at p2 at p3 at p4,5)) Dowód indukcyjny: 1° Na początku zachodzi y1 oraz at p0; 2° Wartość y1 może być zmieniana tylko przez P, zaś z diagramu P wynika teza. 2) (y2 (at q2 at q3 at q4,5)) Dowód analogiczny.
3) ((at p4,5 at q3) t) Dowód indukcyjny: 1° w stanie (p0, q0) poprzednik implikacji jest fałszywy, więc implikacja jest prawdziwa; 2° przejścia p0 ... p3 oraz q0 ... q2 nie mają wpływu na prawdziwość implikacji. Przejście p3 ... p4 może być wykonane, jeśli t = true lub y2 = false. t = true oznacza, że przejście q2 ... q3 musiało odbyć się po przejściu p2 ... p3, czyli zachodzi zarówno at q3, jak i t = true. Jeśli nie jest praw- dziwe at q3, to musi pozostać t = false ustawione przez P. W obu przypadkach implikacja jest prawdziwa. 4) ((at q4,5 at p3) t) Dowód analogiczny. 5) ( (at p4,5 at q4,5)) 1° w stanie (p0, q0) oczywiście nie jest prawdziwe at p4,5 at q4,5 ; 2° jedyne możliwości zaistnienia sytuacji, kiedy P i Q byłyby jednocześnie w sekcjach krytycznych to: a) wykonanie przejścia p3 ... p4 w sytuacji, kiedy zachodzi at q4,5 - musiałby wtedy być spełniony warunek y2 t , co jest niemożliwe na podstawie 2) i 4); b) wykonanie przejścia q3 ... q4 w sytuacji, kiedy zachodzi at p4,5 - musiałby wtedy być spełniony warunek y1 t , co jest niemożliwe na podstawie 1) i 3).