Temporallogik und parallele Programme

Werbung
Temporallogik und
parallele Programme
260
Softwaresysteme allgemein (1)
Bisher:
• Sequentielle Programme
• Relationale Semantik: Anfangs- und Endzustand
• Spezifikation: Vor- und Nachbedingung
• „Programm ist Algorithmus der ein Ergebnis berechnet“
Zweck: Spezifikation von Systemoperationen
Grundannahme: Die Operationen sind atomar, i. e. nicht unterbrechbar,
zeitliche Dauer ist vernachlässigbar
(Meist) adäquat bei sequentiellen Programmen und einzelne
Systemoperationen.
261
Softwaresysteme allgemein (2)
Die Sicht als atomare Operation ist nicht adäquat für
• Abläufe von Softwaresystemen, die eine Reihe von Systemoperationen
aufrufen (vgl. Szenarios in Use Cases/ Abläufe von abstr. Datentypen)
• eingebettete Systeme, die eine Umgebung haben (Benutzer, die
Eingaben machen; Sensoren/Aktoren)
• Programme, die nicht terminieren sollen
(Betriebssysteme, Protokolle, Web-Server etc.)
• Einzelne Threads, die parallel zu anderen laufen (gegenseitige
Beeinflussung)
Für all diese Systeme müssen Abläufe von Programmen betrachtet werden,
die in einer Umgebung stattfinden.
Ziel der heutigen Vorlesung: Definition einer dazu passenden Logik.
262
Motivation - Beispielprogram semaphore
≡
while true do
await S > 0; S := S − 1;
semaphore
while true do
await S > 0; S := S − 1;
(: critical section :)
(: critical section :)
L1 : skip;
S := S + 1;
L2 : skip;
S := S + 1;
(: noncritical section :)
(: noncritical section :)
skip;
skip;
Eigenschaften:
• Sicherheit (engl. safety): Zu keinem Zeitpunkt sind beide Prozesse
gleichzeitig im kritischen Bereich
• Lebendigkeit/Fortschritt (engl. liveness/progress): Ein Prozess betritt
irgendwann seinen kritischen Bereich
263
Parallele Programme: Interleaving
Die Wahl der Programmiersprache trifft 2 zentrale Entscheidungen:
Entscheidung 1: Programme werden interleaved parallel ausgeführt
f
• Ausführung von x:= x + 1 x := x ∗ 2; x:= x ∗ 2
mit x = 0 gestartet dauert 3 Schritte und ergibt
⋆ x = 4 (linker Schritt zuerst) oder
⋆ x = 2 (erster Schritt rechts, dann links, dann rechts), oder
⋆ x = 1 (beide Schritte rechts zuerst).
• Adäquat für Threads/Prozesse auf einem Rechner mit globalem
Speicher
• Multi-Core Prozessoren: Hardware sorgt immer dafür, dass ein
Speicherzugriff „gewinnt“ (Stichwort: cache coherence Protocols)
• Allerdings: Wir betrachten nur sog. sequential consistency:
i.e. es gibt eine interleavete Reihenfolge für Speicherzugriffe
• Prozessoren haben wegen Caching schwächere Speicher-Modelle
• Java Memory Model ist noch schwächer
264
(da es Code-Umordnung durch den Compiler erlauben muss)
Alternativen zu Interleaving
Alternative 1 zu Entscheidung 1: Asynchron parallel
• x :=1 ||a y := 2 dauert 2 oder einen Schritt
• Typischer Formalismus: Statecharts
• Echte Gleichzeitigkeit möglich
• Problem: Was tun bei „Clashes“: x := 5 ||a x := 6? (abort, exception,
einer gewinnt zufällig, sequentiell, ausschliessen etc.)
Alternative 2 zu Entscheidung 1: Synchron parallel
• x :=1 ||s y := 2 dauert genau einen Schritt
• „Getaktet“
• Typischer Formalismen: Alle Hardware-Modellierungssprachen
• Clashes meist syntaktisch verboten („meta-stabile“ Zustände)
265
Parallele Programme: Kommunikation
Entscheidung 2: Kommunikation zwischen parallel ausgeführten
Programmen geschieht über gemeinsame Variablen (oder gemeinsamen
Speicher; engl. shared variables).
• Adäquat für gemeinsamen Speicher/gemeinsame Resourcen
Alternative zu Entscheidung 2: Kommunikation durch Synchronisation
• Typische Sprachen: CSP, CCS, IO-Automaten, Sprachen mit send und
receive-Kommandos
• Konzepte: Signale, Kanäle, Events
• Adäquat für Kommunikation zwischen Rechnern
266
Traces (Intervalle)
Ziel:
Kalkül, der die Untersuchung verteilter Systeme ermöglicht
1. Abläufe definieren (Traces)
2. Formeln reden über alle Zwischenzustände eines Programms
(irgendwann, immer, solange . . . bis etc.)
3. Semantik für Programme, die alle Zwischenzustände berücksichtigt
Grundlegende Definition Ein
Zustandsfolge (z0 , . . . , zn )
Trace ist eine
mit n ∈ IN ∪ {∞}
• Die Semantik von Programmen ist eine Menge möglicher Traces
• Formeln sind wahr oder falsch auf einem Trace
• Zustand zi im Trace = Variablenbelegung (wie bisher)
• Wenn endliche Traces erlaubt sind, heißen sie auch Intervalle
267
Temporallogik vs. Relationale Semantik
TL-Semantik von Programmen α: Einer oder mehrere Traces.
Die relationale Semantik ist „gröber“ und daraus herleitbar:
Deterministische Programme:
• Nur ein möglicher Trace (z0 , . . . , zn ) für einen Startzustand z0
• Wenn endlich (z0 , zn ) ∈ [[α]]
• Wenn unendlich, dann kein Paar (z0 , z) in [[α]]
Nichtdeterministische Programme:
• Evtl. mehrere mögliche Traces (z0 , . . . , zn ) für einen Startzustand z0
• Jeder endliche liefert (z0 , zn ) ∈ [[α]]
• Falls mindestens ein unendlicher: z0 6∈ α ↓
268
Intervalle mit Umgebungsschritten
Wir betrachten Programme mit einer Umgebung
• Z. B. die physikalische Umgebung des Programms
• Bei zwei interleaveten Programmen läuft das eine Programm in der
Umgebung des anderen
⇒ „lokale Analyse eines Threads“
⇒ (engl. thread-local reasoning)
• Beachte: Die bisherigen sequentiellen Programme werden jetzt
innerhalb einer Umgebung betrachtet
• In einem Ablauf (z0 , z′0 , z1 , z′1 . . . , zn ) wechseln sich ab
⋆ Systemschritte (z0 , z′0 ), (z1 , z′1 ), . . . des Programms
⋆ Umgebungsschritte (z′0 , z1 ) , (z′1 , z2 ), . . .
• Der erste Schritt eines Traces ist ein Systemschritt
• Falls endlich, ist der letzte Schritt ein Umgebungsschritt
269
Semantik temporallogischer Formeln
• Temporallogische Formeln sind über einem Ablauf wahr oder falsch:
A, (z0 , z′0 , z1 , . . . , zn ) |= ϕ
• A ist die zugrundeliegenden Algebra (Datenstruktur), die Modell der
Spezifikation ist (im folgenden weggelassen).
• Normale prädikatenlogische Aussagen ϕ sind temporallogische
Formeln. Sie beziehen sich nur auf den Anfangszustand:
(z0 , z′0 , z1 , . . . , zn ) |= ϕ ⇔ z0 |= ϕ
(dasselbe gilt auch für Dynamische Logik)
• Über zukünftige Zustände redet man mit temporallogischen Operatoren
oder mit Variablen.
270
Variablen in Temporallogik
• Statische Variablen haben immer denselben Wert im Ablauf.
(Konvention in KIV: Mit Kleinbuchstaben)
• Flexible Variablen ändern ihren Wert:
X, X′ , X′′ bezeichnen die Werte in z0 , z′0 , z1
(Konvention in KIV: Großbuchstaben)
• Konvention: Falls der Ablauf nur aus einem Zustand besteht,
haben X′ und X′′ auch den Wert von X in z0 .
• Definition variables X : nat flexible;
• Die Formeln X = X′ und X′ = X′′ besagen:
Der erste System- bzw. Umgebungsschritt ändert X nicht
• Zuweisung X := T macht einen Systemschritt und impliziert X′ = T
271
Temporallogische Formeln (1)
Informelle Beschreibung:
2 ϕ d.h. ϕ gilt jetzt und in jedem künftigen Zustand (always).
3 ϕ d.h. ϕ gilt jetzt oder in einem künftigen Zustand (eventually ).
Formale Beschreibung (es gilt: 3 ϕ ↔ ¬ 2 ¬ ϕ):
(z0 , z′0 , z1 . . . , zn ) |= 2 ϕ ⇔ Für alle 0 ≤ i ≤ n gilt: (zi , . . . , zn ) |= ϕ
(z0 , z′0 , z1 , . . . , zn ) |= 3 ϕ ⇔ Es gibt ein 0 ≤ i ≤ n mit (zi , . . . , zn ) |= ϕ
Beispiel: 2 X′ = X′′ ≡ „Die Umgebung modifiziert X nie.“
Beispiel: 2 (X = 5 ∧ X′ = 5) ≡ „X ist 5 vor und nach jedem Systemschritt“
Beispiel: 2 (X = 5 → 3 X > 5) ≡ „Wenn X irgendwann den Wert 5 hat, wird
es irgendwann später erhöht“
272
Temporallogische Formeln (2)
Informelle Beschreibung:
ϕ until ψ
d.h. ψ gilt irgendwann, und davor gilt stets ϕ.
ϕ unless ψ d.h. ϕ gilt immer, bis ψ gilt.
Formale Beschreibung:
(z0 , . . . , zn ) |= ϕ until ψ ⇔ Es gibt ein 0 ≤ i ≤ n mit:
(zi , . . . , zn ) |= ψ
∧ ∀ 0 ≤ j < i.(zj , . . . , zn ) |= ϕ
(z0 , . . . , zn ) |= ϕ unless ψ ⇔ (2 ϕ) ∨ (ϕ until ψ)
Beispiel: N = N′′ + 1 until N = 0 ≡ „N wird bis auf 0 heruntergezählt“
Beispiel: Y′′ = Y′ unless X′ 6= X ≡ „Die Umgebung ändert Y solange nicht,
wie das System X nicht modifiziert“
273
Temporallogische Formeln (3)
Informelle Beschreibung:
◦ ϕ d.h. es gibt einen Folgezustand in dem ϕ gilt (strong next).
• ϕ d.h. wenn ein Folgezustand existiert, gilt darin ϕ (weak next).
last d.h. der aktuelle Zustand ist der letzte.
Formale Beschreibung:
(z0 , . . . , zn ) |= ◦ ϕ ⇔ n 6= 0 ∧ (z1 , . . . , zn ) |= ϕ
(z0 , . . . , zn ) |= • ϕ ⇔ n = 0 ∨ (z1 , . . . , zn ) |= ϕ
(z0 , . . . , zn ) |= last ⇔ n = 0
Beispiel: Eine einzelne Zuweisung impliziert ◦ last ≡ „genau ein Schritt“
Beispiel: 3 last ≡ „endlicher Ablauf = Terminierung“
Beispiel: 2 ϕ ↔ ϕ ∧ • 2 ϕ „ϕ gilt immer gdw. ϕ gilt jetzt, und falls nächster
Zustand ex., dann gilt ϕ ab diesem immer“
274
Programme sind Formeln
• Programme α beschreiben eine Menge möglicher Traces
• Definiere (z0 , . . . , zn ) |= α als:
Der Trace (z0 , . . . , zn ) ist ein möglicher Ablauf des Programms α.
• Somit ist ein Programm „wahr“ auf einem Trace, wenn der Trace ein
möglicher Ablauf von α ist.
• Ergebnis: Programme sind auch einfach spezielle Formeln!
• Programme beschreiben nur Systemschritte in einer beliebigen
Umgebung
275
Zuweisung als Formel
• Temporallogische Zuweisungen nur für flexible Variablen
• X := T impliziert X′ = T und ◦ last
• Problem: Was ist mit den anderen Variablen?
⇒ Programmvariablen sollten unverändert bleiben
• Deshalb: Programmvariablen (relevant für alle Zuweisungen im
Programm) werden explizit durch Variablenliste vl angegeben:
[: vl | α]
• Definition: ρvl ≡
V
{X′ = X | X ∈ vl}
• Damit: [: vl | X := T] ↔ X′ = T ∧ ρvl\X ∧ ◦ last
Beispiel:
[: X, Y, Z | X := 1] ↔ X′ = 1 ∧ Y′ = Y ∧ Z′ = Z ∧ ◦ last
276
Typische TL Beweisziele
α, I, E ⊢ P
• α ist ein Programm
• I ist eine Startbedingung (Prädikatenlogik)
• E ist eine Annahme an die Umgebung
• P ist eine zu zeigende Eigenschaft
„Programm α gestartet im Zustand I mit Umgebung E hat Eigenschaft P“
277
Beispiel: Beweisverpflichtung semaphore
(: P arallelesP rogramm :)
[: S, L1 , L2 | semaphore] ,
(: U mgebungsannahme :)
2 (S ′′ = S ′ ∧ L′′1 = L′1 ∧ L′′2 = L′2 )
(: Initialzustand :)
S = 1, ¬ L1 , ¬ L2
⊢ (: Beweisverpf lichtung :)
2 ¬ (L1 ∧ L2 )
„Programm semaphore erlaubt es nie, dass beide Teilprogramme gleichzeitig
im kritischen Abschnitt sind.“
278
Semantik Paralleler Programme
Zuweisung:
vl | X := t
• X′ = t
• Alle anderen Variablen in vl unverändert: ρvl \ X
• Transition nicht blockiert; terminiert nach einem Schritt
No operation:
vl | skip
• Alle Variablen in vl unverändert: ρvl
• Transition nicht blockiert; terminiert nach einem Schritt
279
Semantik Paralleler Programme
Sequentielle Komposition:
vl | α; β
• Erst Transitionen von vl | α
• Wenn α terminiert, dann Transitionen von vl | β
Konditional:
vl | if ε then α else β
• Auswertung von ε benötigt einen Schritt
• Falls ε gilt, dann Transitionen von vl | α, sonst von vl | β
Schleife:
vl | while ε do α
• Auswertung von ε benötigt einen Schritt
• Solange ε gilt, Transitionen von vl | α, sonst Terminierung
280
Semantik Paralleler Programme
Synchronisation:
vl | await ε
• Auswertung von ε dauert keinen Schritt
• Sobald ε gilt, Terminierung
• Bis dahin:
⋆ Alle Variablen in vl unverändert: ρvl
⋆ Transition ist blockiert
Interleaving:
vl | α
f
β
• Entweder nächste (nicht blockierte) Transition von vl | α oder von
vl | β
• Falls beide Programme blockiert, dann Interleaving blockiert (und ρvl )
281
Kalkül: Symbolische Ausführung
• In Dyn. Logik: Berechne aus Vorbedingung Formel, die nach einem
(Programm)schritt gilt.
• In TL: Gehe einen Schritt im Ablauf vorwärts (geht auch für Formeln)
• Spezialfall, wenn es keinen weiteren Schritt gibt (i. e. last gilt)
Dann haben X, X′ , X′′ alle denselben Wert x0 (neue stat. Variable)
TL-Formeln zu PL reduzierbar, z. B.: last → (2 ϕ ↔ ϕ)
• Im Normalfall gibt es einen Schritt.
• Idee: Ersetze X,X′ ,X′′ durch x0 , x1 , X (mit neuen stat. Variablen x0 , x1 )
um einen Schritt vorwärts zu gehen
• Aus ◦ ϕ wird einfach ϕ
• Beispiel: 2 (X = 0 ∧ X′ = 1) ↔ X = 0 ∧ X′ = 1 ∧ • 2 (X = 0 ∧ X′ = 1)
• Ergebnis der Ausführung deshalb x0 = 0 ∧ x1 = 1 ∧ 2 (X = 0 ∧ X′ = 1)
282
Kalkül: Die Step-Regel
Symbolische Ausführung mittels der Step - Regel:
L(Γ) ⊢ L(∆) S(Γ) ⊢ S(∆)
step
Γ⊢∆
• Funktion L(.) liefert eine Formel, falls kein weiterer Schritt folgt.
• Funktion S(.) liefert eine Formel, die einem Schritt ausgeführt hat.
Ausführung von prädikatenlogischen Formeln ϕ (X′ , X′′ sind
erlaubt):
Speziell:
0 ,x0 ,x0
L(ϕ) :≡ ϕxX,X
′ ,X ′′
0 ,x1 ,X
S(ϕ) :≡ ϕxX,X
′ ,X ′′
283
Kalkül: Symbolische Ausführung
Ausführung von TL Formeln:
ϕ
L(ϕ)
S(ϕ)
2ϕ
3ϕ
ϕ until ψ
ϕ unless ψ
•ϕ
◦ϕ
L(ϕ)
L(ϕ)
L(ψ)
L(ϕ) ∨ L(ψ)
true
false
true
S(ϕ) ∧ 2 ϕ
S(ϕ) ∨ 3 ϕ
S(ψ) ∨ S(ϕ) ∧ ϕ until ψ
S(ψ) ∨ S(ϕ) ∧ ϕ unless ψ
ϕ
ϕ
false
last
284
Kalkül: Symbolische Ausführung
Ausführung paralleler Programme:
L(.)
α
L(α)
vl | X := t
vl | skip
vl | α; β
vl | if ε then α else β
vl | while ε do α
vl | await ε
f
vl | α β
false
false
L(vl | α) ∧ L(vl | β)
false
false
L(ε)
L(vl | α) ∧ L(vl | β)
285
Kalkül: Symbolische Ausführung
Ausführung paralleler Programme:
Stepfunktion S baut auf T auf:
T : VLPROG → P(FMA × {F, T} × (VLPROG ∪ {E}))
• T beschreibt die Menge der ersten Transitionen
• FMA: Beziehung zwischen ungestrichenen und gestrichenen Variablen.
• {F, T}: Flag das angibt, ob die Transition blockiert ist (T).
• VLPROG ∪ {E}: Restprogramm, falls vorhanden, sonst: E.
0 ,x1 ,X
• τvl := (ρvl )xX,X
′ ,X ′′ = { x0 = x1 | X ∈ vl}
286
Kalkül: Symbolische Ausführung
α
T (α)
vl | X := t
vl | skip
{(x1 = S(t) ∧ τvl \ X , F, E)}
{(τvl , F, E)}
{(L(vl | α) ∧ ϕ, b, vl | β ′ ) | (ϕ, b, vl | β ′ ) ∈ T (vl | β)
∪ {(ϕ, b, vl | α′ ; β) | (ϕ, b, vl | α′ ) ∈ T (vl | α)}
{(S(ε) ∧ τvl , F, vl | α), (S(¬ ε) ∧ τvl , F, vl | β)}
vl | α; β
vl | if ε then α
else β
vl | while ε do α
{(S(ε) ∧ τvl , F, vl | α; while ε do α),
(S(¬ ε) ∧ τvl , F, E)}
287
Kalkül: Symbolische Ausführung
α
T (α)
vl | await ε
f
vl | α β
{(¬ S(ε) ∧ τvl , T, vl | await ε)}
f
′
{(ϕ, F, vl | α β) | (ϕ, F, vl | α′ ) ∈ T (vl | α)}
f ′
∪ {(ϕ, F, vl | α β ) | (ϕ, F, vl | β ′ ) ∈ T (vl | β)}
f ′
′
∪ {(ϕ ∧ ψ, T, vl | α β ) | (ϕ, T, vl | α′ ) ∈ T (vl | α),
(ψ, T, vl | β ′ ) ∈ T (vl | β)}
Die Stepfunktion S ist dann definiert als:
S([: vl | α]) :≡
W
{ϕ ∧ ¬ blk0 ∧ [: vl | α′ ] | (ϕ, F, vl | α′ ) ∈ T (vl | α)}
W
∨ {ϕ ∧ blk0 ∧ [: vl | α′ ] | (ϕ, T, vl | α′ ) ∈ T (vl | α)}
288
Kalkül: VD Induktion (1)
Wie bisher vorhanden: Noethersche Induktion. Jetzt zusätzlich VD Induction
und apply VD Induction.
• VD = Verification Diagram
• Erlaubt Induktion für Beweisziele: ⊢ 2 ϕ
• Beweisidee durch Widerspruch: Wenn 2 ϕ falsch ist, gibt es einen
ersten Zustand, in dem ϕ nicht gilt.
• ¬ (2 ϕ) ↔ ∃ N. N = N′′ + 1 until ¬ ϕ
• N wird solange heruntergezählt, bis erstmals ¬ ϕ gilt.
• Jetzt geht Induktion über den Wert von N = die Zahl der Schritte
• Regel VD Induction codiert dies in einen Schritt
289
Kalkül: VD Induktion (2)
• VD induction „verzögert“ die Erstellung einer Induktionshypothese:
Es entsteht nur ein anonymes Prädikat Indhyp(N).
• apply VD Induction erlaubt als Induktionshypothese jedes Beweisziel,
das mit weniger als N Schritten erreicht wurde.
• Dazu muss im Beweisbaum auf den Knoten, der als
Induktionshypothese verwendet werden soll, geklickt werden.
• Idee zur Verwendung: Sobald sich in einem Programm ein vorheriger
Zustand wiederholt, Induktionshypothese anwenden
• Der Zustand darf aus einem anderen Beweisast sein, er muss aber
weniger steps ausgeführt haben (sonst ist er nicht noethersch kleiner)
290
Kalkül: Induktion
apply VD induction
291
Kalkül: Sequentialisierung
• Häufig ergibt das Ausführen von interleaveten Programmen trotz
unterschiedlicher Reihenfolge zweimal dasselbe Goal
f
f
• Beispiel: x := 5; α y := 6; β ergibt 2 goals mit α β
• Regel insert proof lemma wendet einen Beweisknoten als Lemma in
einem anderen Beweisast an.
• Anwendung durch Klicken auf das anzuwendende Lemma
• Spart die Definition eines separaten Lemmas
• Nur anwendbar bei Azyklizität!
Regel
insert proof lemma
<proved in a different proof branch>
V
W
Γ0 ⊢ ∆0
Γ, Γ0 → ∆0 ⊢ ∆
Γ⊢∆
292
Kalkül: Sequentialisierung
Insert Proof Lemma
293
Demo
(: Programm :)
[: X | while
true do { X := 1 }
f
{ await X = 1; X := 0; }],
(: Umgebung :)
2 X′′ = X′ ,
(: Initialisierung :)
X=0
(: Eigenschaft :)
⊢ 2 X ≤ 1;
294
Herunterladen