Formale Methoden im Software Engineering

Werbung
Formale Methoden im
Software Engineering
Eine praktische Einführung
Gerhard Schellhorn,Gidon Ernst, Dominik Haneberg
Bogdan Tofan, Jörg Pfähler
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
1 / 318
Organisatorisches
Vorlesung:
Dienstag: 14:00 Uhr - 15:30 Uhr (1057 N)
Versuche: (Raum 3017 N)
(Freitag: 08:15 - 09:45 Uhr)
(Freitag: 10:00 - 11:30 Uhr)
Freitag: 12:15 - 13:45 Uhr
Freitag: 14:00 - 15:30 Uhr
(Freitag: 15:45 - 17:15 Uhr)
anderer Termin wählbar, wenn für alle ok
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
2 / 318
Leistungspunkte und Sprechstunden
Leistungspunkte
2 V + 4 Ü = 8 Creditpoints.
Alte PO: Für den Bereich ”Softwaretechnik” oder für den Bereich
”Theoretische Informatik”
Neue PO: Nur für den Bereich ”Softwaretechnik”
Sprechstunden
Gerhard Schellhorn: Raum 3016 N, Tel. 2124
Bogdan Tofan: Raum 3043 N, Tel. 2181
Gidon Ernst: Raum 3014 N, Tel. 2183
Jörg Pfähler: Raum 3014 N, Tel. 2229
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
3 / 318
Anmeldung
• In Zweiergruppen in die Liste eintragen: Ergibt Gruppennummer
• Vorausgesetzt: Kenntnisse aus Logik-Vorlesung
• Spätestens am Montag auf Webseite:
Welche Gruppen an welchen Terminen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
4 / 318
Prüfung
Anwesenheitspflicht in den Übungen!
• Vorbereitung der Aufgaben anhand der Doku!
•
• Abgabe der gelösten Aufgaben im SVN.
• 2 Mündliche Abnahmen im Semester in Zweiergruppen:
• 1. Abnahme nach ca. 6 Wochen
(zu: Prädikatenlogik und Algebraische Spezifikationen)
• 2. Abnahme am Ende
(Programmbeweisen und TL)
• Mit: Testaufgaben (KIV) & Fragen zur Vorlesung
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
5 / 318
Formale Methoden: Ziel 1
Ziel 1: Grundlagen für das Verständnis von Software
• Vermeidung von Mißverständnissen und Unklarheiten
• Was bedeutet eine UML-Spezifikation?
• Welche Compileroptimierungen sind möglich?
• Ermöglichung von präzisen Vorhersagen und Tests
• Verständnisverbesserung
• Was sind gute“, gut strukturierte“, gut dokumentierte“
”
”
”
Programme?
• Was sind saubere“ Schnittstellen?
” gute“ Spezifikationssprache?
• Was ist eine
”
A computer is a mathematical machine.
A program is a mathematical expression.
A programming language is a mathematical theory.
Programming is a mathematical activity.
— C. Anthony R. Hoare, 1989
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
6 / 318
Formale Methoden: Ziel 2 und Vorgehen
Ziel 2: Beweisbar korrekte Software
Vorgehen
1
Formale Spezifikation der Anforderungen
2
Validierung/Nachweis von Sicherheitseigenschaften
3
Programmierung
4
Beweis, dass Programm die Spezifikation erfüllt
Notwendig für beide Ziele
Definition formaler Modelle und Aussagen ⇒ Logik
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
7 / 318
Warum Beweise über Programme?
Fehler in Software sind eine nicht enden wollende Geschichte: Oft nur
ärgerlich, manchmal sehr teuer oder sogar lebensgefährlich!
• Softwarefehler in deutschen EC-Karten Anfang 2010
• Verlust aller Kontaktdaten der Sidekick-
Nutzer von T-Mobile USA (Okt. 2009)
• Gepäckverteilung Flughafen Denver (1994)
und Terminal 5 London Heathrow (2008)
• Strahlentherapiesystem Therac-25
• Ariane 5 Explosion beim ersten Start
• Flash-Filesystem des Mars Rover Spirit
(und vor ein paar Wochen Opportunity)
• ...
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
8 / 318
Warum formale Beweise mit KIV?
These: Eine detaillierte Analyse des Programms von Hand genügt,
um seine Korrektheit nachzuweisen!
Problem
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
9 / 318
Warum formale Beweise mit KIV?
These: Eine detaillierte Analyse des Programms von Hand genügt,
um seine Korrektheit nachzuweisen!
Problem
Beweise über Software sind häufig sehr langwierig (viele Details) und
daher noch fehleranfälliger als die Programme selbst.
⇒ Systemunterstützung mit KIV
(andere Systeme: ACL2, Isabelle, PVS, . . . )
Durch die Systemunterstützung wird die Korrektheit der Beweise (durch
korrekte Anwendung der Kalkülregeln) sichergestellt
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
9 / 318
Lernziele
• Erlernen des Umgangs mit KIV
• Strukturierte Spezifikation mit KIV
• Formales Beweisen mit KIV
• Umsetzen von Beweisen in einem Kalkül
• Automatisierung durch Simplifikation und Heuristiken
• Beweise für Datenstrukturen und Programme
• Verschiedene Verfeinerungskonzepte um von abstrakten
Spezifikationen zu konkreten Programmen zu kommen
• Verifikationstechnik für nebenläufige Systeme
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
10 / 318
Praktische Anwendung
• Einsatz von KIV durch KIV-Experten in sicherheitskritischen
Anwendungen
• Einsatz von automatischen (spezialisierten) Tools:
•
•
•
•
Model Checking (HW-Design, eingebettete Systeme)
Bounded Model Checking, SAT checking (z. B. Security-Protokolle)
Datenflussanalyse (z. B. MS Kernel Treiber im SLAM-Projekt)
Predicative Abstraction und Typechecking (z. B.
Nullpointer-Exceptions, SPEC#)
• Entscheidungsprozeduren für Arithmetik
(z .B. für Zeitconstraints bei Echtzeitsystemen)
• ...
• Systematisches Testen mit aus Spezifikationen generierten Testfällen
• Konstruktion von endlichen Gegenbeispielen (z. B. Alloy, MACE)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
11 / 318
Überblick
1.
2.
3.
4.
5.
6.
7.
Aussagen- und Prädikatenlogik
Beweise über Datenstrukturen (Listen, Heaps)
Algebraische Spezifikationen
Programmbeweise (Hoare, while-Schleifen)
Data Refinement
Temporallogik & Parallele Programme
Programmieren von KIV in Scala
8. Juli 2013
(2 Wochen)
(2 Wochen)
(1 Woche)
(1.5 Wochen)
(1.5 Wochen)
(2 Wochen)
(2 Wochen)
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
12 / 318
Prädikatenlogik mit Sorten
und der Sequenzenkalkül
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
13 / 318
Prädikatenlogik mit Sorten
• In Logik für Inf.: n-stellige Funktionssymbole f ∈ F n
Semantik: n-stellige Funktion über Grundbereich D
• Hier: Gegeben ist eine endliche Menge S von Sorten.
Semantik: Jede Sorte bezeichnet einen Grundbereich
• Funktionen jetzt: f ∈ Fs→s 0 oder einfacher: f : s → s 0
wobei s = s1 , . . . , sn mit n ≥ 0 (n = 0: Konstante c : s 0 )
• Vorteile:
• Theorie:
• Praxis:
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
14 / 318
Prädikatenlogik mit Sorten
• In Logik für Inf.: n-stellige Funktionssymbole f ∈ F n
Semantik: n-stellige Funktion über Grundbereich D
• Hier: Gegeben ist eine endliche Menge S von Sorten.
Semantik: Jede Sorte bezeichnet einen Grundbereich
• Funktionen jetzt: f ∈ Fs→s 0 oder einfacher: f : s → s 0
wobei s = s1 , . . . , sn mit n ≥ 0 (n = 0: Konstante c : s 0 )
• Vorteile:
• Pro Datentyp eine Sorte, damit Typcheck wie in Prog.-sprachen
• Theorie: Sorten können in Prädikate codiert werden ⇒ redundant
• Praxis: Ohne Sorten zusätzliche Axiome und Deduktion notwendig!
(Z. B. nat(x) ∧ nat(y ) → nat(x + y )) ⇒ schlecht
• Es gibt immer eine vordefinierte Sorte bool.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
14 / 318
Die Sorte bool: Formeln sind auch Terme!
• Mit einer vordefinierten Sorte bool wird es möglich,
Formeln mit den Terme der Sorte bool zu identifizieren
• Logische Operatoren sind jetzt vordefinierte boolesche Funktionen:
. ∧ ., . ∨ ., . → ., . ↔ . : bool × bool → bool
¬ . : bool → bool
true, false : bool
• Formeln ϕ, ψ und Terme t heissen jetzt Ausdrücke e
• Prädikate sind einfach Funktionen mit Zielsorte bool
• Funktionen und Prädikate heissen jetzt Operationen OP
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
15 / 318
Signaturen und Variablen
Eine Signatur Σ = (S, OP) ist ein Paar mit:
• Endlicher Menge S von Sorten, mit bool ∈ S
• Endlicher Familie
S
OP =
•
•
•
•
s∈S ∗ ,s 0 ∈S
OP s→s 0
von Operationssymbolen mit Argumentsorten s und
Ergebnissorte s 0 (leere Liste von Argumentsorten: Konstante c)
OP enthält immer die üblichen booleschen Operationen
Wie üblich: Konstanten sind null-stellige Operationen
Boolesche Konstanten = atomare Aussagen
Aussagenlogik = atomare Aussagen + boolesche Ops., keine
Variablen/ Quantoren
Eine Variablenmenge X besteht aus einer abzählbar unendlichen Menge
von Variablen Xs für jede Sorte s ∈ S
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
16 / 318
Syntax von Ausdrücken
Ausdrücke e ∈ EXPR s (Σ, X ) der Sorte s ∈ S über der Signatur Σ und
über den Variablen X sind rekursiv definiert durch
• x aus Xs ist ein Ausdruck der Sorte s
• Sind e1 , . . . , en Ausdrücke der Sorten s1 , . . . , sn und
op : s1 , . . . , sn → s 0 , dann ist op(e1 , . . . , en ) ein Ausdruck der Sorte s 0
• Bem.: Schreibe c statt c() für Konstanten (n = 0)
• Sind e1 , e2 Ausdrücke der Sorte s, so ist
e1 = e2 eine Formel (i. e. ein Ausdruck der Sorte bool)
• Ist ϕ eine Formel und x eine Variable, so sind
∀ x.ϕ und ∃ x.ϕ Formeln
EXPR(Σ, X ) :=
S
s∈S
EXPR s (Σ, X ), For (Σ, X ) := EXPR bool (Σ, X )
Terme t ∈ T (Σ, X ) sind Ausdrücke ohne Quantoren und Gleichheit.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
17 / 318
KIV-Syntax für Signaturen
sorts nat;
list;
constants 0 : nat;
ϕ: bool; (: 0-stelliges Prädikat als boolesche Konstante :)
functions f : nat × nat → nat;
g : nat, nat -> nat; (: es geht auch ASCII :)
predicates isprime : nat;
. < . : nat × nat;
variables x,y : nat;
u : list;
• Sorten, Funktionen, Prädikate, Variablen immer in dieser Reihenfolge
• Aufzählungen mit derselben Sorte nur bei Variablen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
18 / 318
KIV: verfügbare Symbole
• Sonderzeichen eintippen mit Funktionstaste F12, dann:
not
¬
and
∧
or
∨
implies
→
equiv
↔
all
∀
ex
∃
follows
`
neq
6=
times
×
• F12 TAB zeigt alle Möglichkeiten (z.B. auch oplus für ⊕)
• Eindeutiges Präfix reicht, z.B. imp oder fol für →, `.
• KIV gibt sehr viel Freiheit für die Characters in Bezeichnern:
Z.B. ist ⊕∀ ∧ x → y − < (keine Spaces) ein legaler Bezeichner!
• Deshalb müssen Bezeicher, insbes. auch logische Operatoren von
Trennzeichen umgeben sein
• Trennzeichen sind Space, Klammern, Komma oder Strichpunkt
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
19 / 318
KIV: Infix-Schreibweise und Bindungsstärken
• Signatur: . ⊕ . : s1 × s2 → s,
s1 , s2 , s ∈ S
• Term (t1 ⊕ t2 )
• Infix-Funktionssymbole in KIV können priorisiert werden
(∗ bindet stärker als +, ∧ bindet stärker als ∨)
• Es gibt auch Postfix (z.B. für Fakultät “. !”)
und Präfix (z.B. “# .” für Anzahl der Elemente: # ∅ = 0)
Bindungsstärken
{postfix} > {präfix} > {infix} > {¬} > {∧} > {∨} > {→} > {↔} > {∀, ∃}
Außenklammern werden weggelassen
Beispiel: ϕ → ψ ↔ χ ≡ ((ϕ → ψ) ↔ χ)
Quantoren binden größtmögliche Formel: ∀ x.ϕ ↔ ψ ≡ ∀ x.(ϕ ↔ ψ)
Aufzählungen mit ∧, ∨ ungeklammert: ϕ ∧ ψ ∧ χ ≡ ϕ ∧ (ψ ∧ χ).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
20 / 318
Sequenzenkalkül
• Erfunden von Gerhard Gentzen (1934)
• Nur einer von vielen möglichen Kalkülen:
Hilbertkalkül, natürliches Schliessen, Tableaukalkül,
Modellelimination
• Charakteristik: Versucht, Beweisziel auf Axiome zu reduzieren
(schrittweise Vereinfachung des Problems); am menschlichen
Beweisen orientiert
ϕ1 , . . . , ϕn ` ψ1 , . . . , ψm
ϕ1 , . . . , ϕn
ψ1 , . . . , ψm
Sequenz
Antezedent (n ≥ 0)
Sukzedent (m ≥ 0)
Beachte: “`” ist Sequenzenpfeil, “`PL ” ist Ableitbarkeit
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
21 / 318
Beispiel
Ein erster Beweis.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
22 / 318
Sequenzenkalkül
Notation
Γ, Γ1 , ∆, . . . Listen von Formeln,
Γ = ϕ1 , . . . , ϕn , ∆ = ψ1 , . . . , ψm
Γ ` ∆ := ϕ1 , . . . , ϕn ` ψ1 , . . . , ψm
Γ, ϕ ` ψ := ϕ1 , . . . , ϕn , ϕ ` ψ
Γ, ϕ ∧ ψ, ∆ `
^
[ϕ1 , . . . , ϕn ]
^
[]
_
[ψ1 , . . . , ψm ]
_
[]
:= ϕ1 , . . . , ϕn , ϕ ∧ ψ, ψ1 , . . . , ψm `
:= ϕ1 ∧ . . . ∧ ϕn
:= true
:= ψ1 ∨ . . . ∨ ψm
:= false
Bedeutung einer Sequenz: Γ ` ∆ =
8. Juli 2013
V
Γ→
W
∆
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
23 / 318
Sequenzenkalkül: Inferenzregeln
Regel: (n ≥ 0)
Γ1 ` ∆1
Γ2 ` ∆2
Γ`∆
...
Γn ` ∆n
• Regeln werden von unten nach oben gelesen:
Um Γ ` ∆ (die Konklusion) zu beweisen, beweise stattdessen
einfachere Prämissen Γ1 ` ∆1 , . . . , Γn ` ∆n
• Bei n = 0 ist die Konklusion direkt bewiesen
• n = 1: Vereinfachung
• n = 2: Fallunterscheidung
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
24 / 318
Sequenzenkalkül: Ableitbarkeit
Γ ` ∆ ist aus einer Menge von Formeln (Axiomen) Ax ableitbar
(kurz: Ax `PL Γ ` ∆)
:⇔ Es gibt eine Ableitung (Baum) mit
• Wurzel: Γ ` ∆ (Konklusion)
• Blätter: ` ϕ mit ϕ ∈ Ax (Prämissen)
• Innere Knoten durch Regelanwendungen gebildet
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
25 / 318
Kalkül für Aussagenlogik
(axiom)
(false left)
(true right)
ϕ, Γ ` ϕ, ∆
false, Γ ` ∆
Γ ` true, ∆
Γ ` ϕ, ∆
ϕ, Γ ` ∆
Γ0 ` ∆0
(weakening, Γ0 ⊆ Γ, ∆0 ⊆ ∆)
(cut formula)
Γ`∆
Γ`∆
Γ ` ϕ, ∆
ψ, Γ ` ∆
(negation left)
(negation right)
¬ ϕ, Γ ` ∆
Γ ` ¬ ψ, ∆
ϕ, ψ, Γ ` ∆
Γ ` ϕ, ∆
Γ ` ψ, ∆
(conjunction left/right)
ϕ ∧ ψ, Γ ` ∆
Γ ` ϕ ∧ ψ, ∆
ϕ, Γ ` ∆
ψ, Γ ` ∆
Γ ` ϕ, ψ, ∆
(disjunction left/right)
ϕ ∨ ψ, Γ ` ∆
Γ ` ϕ ∨ ψ, ∆
Γ ` ϕ, ∆
ψ, Γ ` ∆
ϕ, Γ ` ψ, ∆
(implication left/right)
ϕ → ψ, Γ ` ∆
Γ ` ϕ → ψ, ∆
Γ ` ϕ, ψ, ∆ ϕ, ψ, Γ ` ∆
ϕ, Γ ` ψ, ∆ ψ, Γ ` ϕ, ∆
(equivalence left/right)
ϕ ↔ ψ, Γ ` ∆
Γ ` ϕ ↔ ψ, ∆
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
26 / 318
Bis zum Freitag
Vorbereiten der ersten Hälfte von
Übung 1 anhand der Doku
(bitte von der Webpage laden)!
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
27 / 318
KIV: Anmeldung und Starten
• Anmelden im Praktikumsraum unter Windows mit DCE-Account
• Starten der VMWare für Linux und KIV
• Anmelden als user
• Starten von KIV durch Click auf’s Logo
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
28 / 318
KIV: Organisation in Projekte
Grundlegende Organisation:
• In KIV arbeitet man in (SW-Entwicklungs-) Projekten
• Im Praktikum: Projekte Exercise1“ . . . Exercise6“
für die 6 Versuche
”
”
• Jedes Projekt definiert Spezifikationen (Σ + Ax + Weiteres)
• Spezifikationen können aufeinander aufbauen
⇒ Entwicklungsgraph
• Über jeder Spezifikation kann man Theoreme formulieren und
beweisen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
29 / 318
KIV: Projektauswahl- und Projektebene
4 Ebenen:
1 Projektauswahlebene
• Projekte anlegen, löschen, auf einem Projekt arbeiten
2
Projektebene
• Zeigt den Entwicklungsgraph der Spezifikationen
• Spezifikationen anlegen, ändern, löschen
• Auf einer Spezifikation arbeiten
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
30 / 318
KIV: Spezifikations- und Beweisebene
3
Spezifikationsebene
• Theoreme anlegen, ändern, löschen
• Ein Theorem zum Beweisen wählen
4
Beweisebene
• Beweise führen durch interaktive Anwendung von Regeln
• Zwei Regelsätze: Basisregeln zum Lernen
+ für echte Beweisen optimierte Regeln
• Backtracking, Pruning
• Simplifikation + Heuristiken zur automatischen Anwendung von
Regeln
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
31 / 318
KIV: Verzeichnisstruktur
Verzeichnisstruktur:
• Im projects“-Verzeichnis von KIV
”
pro Projekt ein Verzeichnis <projektname>
• <projektname> enthält alle relevanten Daten zum Projekt
• Darin:
• Ein Unterverzeichnis specs
• [Eine Datei devgraph für den Entwicklungsgraph]
• In specs: ein Unterverzeichnis <specname> für jede Spezifikation
• Darin:
• Eine Datei specification für Signatur, Axiome etc.
• Eine Datei sequents für Theoreme
• [Ein Verzeichnis proofs das geladene Theoreme, geführte Beweise etc.
speichert]
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
32 / 318
Variablen und freie Variablen eines Ausdrucks
Die Variablen eines Ausdrucks (Var (e))
Var (x)
Var (op(e1 , . . . , en ))
Var (e = e 0 )
Var (Qx.ϕ)
=
=
=
=
{x}
Sn
x ∈X
Var
(e
)
i
i=1
Var (e) ∪ Var (e 0 )
{x} ∪ Var (ϕ)
Q ∈ {∀, ∃}
Die freien Variablen einer Formel (free(ϕ)) sind genauso definiert ausser:
free(Qx.ϕ) = free(ϕ) \ {x} Q ∈ {∀, ∃}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
33 / 318
Substitution
Die Substitution einer Variablen x durch einen Ausdruck t in e (ext )
xxt
= t
yxt
= y
op(e1 , . . . , en )tx
= op((e1 )tx , . . . , (en )tx )
(e1 = e2 )tx
t
t
= ((e
 1 )x = (e2 )x )


Qy .ϕ
falls y = x ∨ x 6∈ free(ϕ)



 Qy .ϕt
falls y 6= x, y 6∈ free(t), x ∈ free(ϕ)
x
=
z t


 Qz.(ϕy )x falls y 6= x, y ∈ free(t), x ∈ free(ϕ)



(z neu, d. h. z 6∈ Var (ϕ) ∪ Var (t))
(Qy .ϕ)tx
falls x 6= y
(Q ∈ {∀, ∃})
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
34 / 318
Regeln für Gleichungen
Γ ` τ = τ, ∆
(reflexivity right)
x = τ, Γτx ` ∆τx
(insert equation)
x = τ, Γ ` ∆
• Statt x = τ ist auch τ = x erlaubt (Symmetrie)
• KIV erlaubt auch:
• Einsetzen von Gleichungen τ = τ 0 (beides keine Variable).
Ersetzt τ nur dort, wo alle Variablen frei sind.
• Einsetzen der Gleichung nur an spezifischen
Positionen in Γ ` ∆ (selten gebraucht)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
35 / 318
Beispiel
Ein Beweis mit Quantoren.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
36 / 318
Regeln für Quantoren
•
ϕτx , ∀ x.ϕ, Γ ` ∆
(all left)
∀ x.ϕ, Γ ` ∆
•
ϕyx , Γ ` ∆
(exists left)
∃ x.ϕ, Γ ` ∆
Γ ` ϕτx , ∃ x.ϕ, ∆
(exists right)
Γ ` ∃ x.ϕ, ∆
Γ ` ϕyx , ∆
(all right)
Γ ` ∀ x.ϕ, ∆
ϕτx die Substitution von x durch einen beliebigen Term τ in ϕ.
y ist eine neue Variable, i. e. eine, die nicht frei in Q x.ϕ, Γ, ∆
(Q ∈ {∀, ∃}) vorkommt.
Genauer: y 6∈ (free(ϕ)\{x}) ∪ free(Γ) ∪ free(∆)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
37 / 318
Intuition für Quantorenregeln (1)
all left:
• Allquantor im Antezedent: ∀ x.ϕ wird als wahr angenommen
• Aus der Annahme folgt, dass auch die Annahme ϕtx für einen
beliebigen Term t wahr ist
• Jede Formel ϕtx darf hinzugenommen werden
• Einziges Problem: Welches t ist nützlich (kreativ!)?
all right:
• Allquantor im Sukzedent: ∀ x.ϕ soll bewiesen werden
• Dazu muss ϕ für jedes beliebige, feste“ Element bewiesen werden
”
• Eine Variable y bezeichnet so ein beliebiges Element, aber nur, wenn
sie neu ist
• Wenn die Variable nicht neu wäre, wäre ihr Wert nicht beliebig,
sondern durch die Formeln eingeschränkt.
• Statt ∀ x.ϕ zeige man also ϕyx mit neuem y .
• Keine Kreativität erforderlich
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
38 / 318
Intuition für Quantorenregeln (2)
ex right:
• ∃ x.ϕ im Sukzedent soll bewiesen werden
• Wenn ϕtx für einen Term t bewiesen werden kann, so ist ∃ x.ϕ wahr
für den Wert den t bezeichnet.
• Also darf man sich ein t (hoffentlich das richtige“) aussuchen, um
”
einen Beweis für ϕtx zu führen.
ex left:
• ∃ x.ϕ im Antezedent darf angenommen werden.
• Es gibt also eine Belegung von x mit einem Element, für die ϕ wahr
ist
• Über das Element weiss man nur, dass ϕ wahr wird.
• Eine neue Variable y können wir mit dem Element belegen, da die
Gültigkeit der Sequenz von der Belegung bisher nicht abhängt.
• Die neue Variable gibt einen Namen“ für das existierende Element.
”
• Statt ∃ x.ϕ wird also ϕyx mit neuem y als Annahme verwendet.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
39 / 318
Zusätzliche Regel: Insert Axiom
`ϕ
all right
` Cl∀ (ϕ)
weakening
Γ, Cl∀ (ϕ) ` ∆ Γ ` Cl∀ (ϕ), ∆
cut
Γ`∆
Cl∀ (ϕ) := ∀ x1 , . . . , xn .ϕ, wobei {x1 , . . . , xn } = free(ϕ)
Neue Regel im Basiskalkül, um obige Schritte abzukürzen:
` Ax
Cl∀ (Ax), Γ ` ∆
(insert axiom)
Γ`∆
• KIV bietet die erste Prämisse nicht mehr an
• Später: Der KIV-Kalkül hat noch komfortablere Regeln:
insert lemma & insert rewrite-lemma
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
40 / 318
Vorgriff: Induktion für natürliche Zahlen
• Theoretisches zu Induktion später
• In KIV gibt es pro Datentyp meist eine strukturelle Induktionsregel
• Nat. Zahlen: Wenn für eine Formel ϕ(n)
• ϕ(0) gilt
• Für jedes n: Aus Ind.hyp. ϕ(n) folgt: ϕ(n +1)
dann gilt für ∀ n. ϕ(n)
• Im Sequenzenkalkül: ϕ ist jetzt die Sequenz Γ ` ∆ (für
Induktionsformel in Formel umwandeln!)
` ϕ(0)
ϕ(n) ` ϕ(n +1)
Γ`∆
V
W
ϕ = ∀ y. Γ →
∆,
y = free(Γ → ∆) \ {n}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
41 / 318
Semantik von
Formeln und Sequenzen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
42 / 318
Grundidee der Verwendung von
Logik im Softwareentwurf
Menge von Formeln
= Axiome Ax
Syntax:
beschreiben
Semantik:
Software-Systeme:
Menge von Algebren
{A, B, . . .}
`K
,,ist beweisbar”
O
Vollständigkeit
Formel ϕ
Korrektkeit
beschreibt
|=
,,ist gültig in”
Eigenschaft ϕA
Ziel: Nachweis, dass ein reales Softwaresystem eine Eigenschaft hat.
Technik: Formaler Beweis ( Rechnen mit Formeln“) in KIV.
”
Korrektheit + Vollständigkeit garantieren, dass man das richtige tut
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
43 / 318
Grundidee der Verwendung von
Logik im Softwareentwurf (1)
Semantik (i. e. der Inhalt, dessen was wir tun):
• 1. Schritt: Wir wollen Softwaresysteme und funktionale
Anforderungen an solche beschreiben
• SW-Systeme sind Datenstrukturen, Programme etc.
Bei eingebetteten Systemen evtl. inclusive Umgebung
• 2. Schritt: Gegeben eine beliebige Implementierung, die die
Anforderungen erfüllt, wollen wir Eigenschaften wie z. B. Korrektheit
und Sicherheit nachweisen
Mathematik:
Das allgemeinste Modell für ein SW-System ist eine Algebra A.
Wir wollen also Algebren beschreiben, und Eigenschaften von Algebren
nachweisen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
44 / 318
Grundidee der Verwendung von
Logik im Softwareentwurf (2)
Mathematik: Sprachen zum Beschreiben von Algebren und ihren
Eigenschaften heissen Logiken
Bem.: Auch Prog.sprachen sind spezielle Beschreibungen von Algebren!
Syntax
• Algebren kann man durch Formelmengen Ax beschreiben
• Eigenschaften werden durch Formeln ϕ beschreiben
• Statt informell zu überlegen ob eine Eigenschaft gilt, verwenden wir
einen Kalkül K , und zeigen formal: Ax `K ϕ
Gewinn: Garantie, dass SW-System Eingenschaft hat
Keine absolute Garantie: Nur so gut, wie die Genauigkeit der Beschreibung
des SW-Systems (insbes. die Umgebung bei eingebetteten Systemen!)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
45 / 318
Semantik: Σ-Algebren
Eine Σ-Algebra A = ((As )s∈S , (op A )op∈OP )
zu einer Signatur Σ = (S, OP) ist ein Paar mit:
• Nichtleeren Mengen As für jede Sorte s ∈ S (Trägermengen)
• Die Trägermenge Abool ist immer gleich {tt,ff}
• Funktionen op A : As1 × . . . × Asn → As 0 für alle op : s1 , . . . , sn → s 0
• Die vordefinierten booleschen Symbole haben in jedem A die
“normale” Bedeutung (Wahrheitstafeln):
trueA = tt, ∧A (tt,ff) = ff, ∨A (tt,ff) = tt etc.
Die Menge aller Σ-Algebren über Σ wird mit Alg(Σ) bezeichnet.
Merke: Sorten bedeuten Datenmengen,
Operationssymbole bezeichen Funktionen
Algebra = Datenstruktur, Σ entspricht Interface
Bsp: Datenmenge = Menge aller Listen, Operation: Aneinanderhängen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
46 / 318
Semantik: Belegungen von Variablen
Eine Belegung (engl. v aluation; auch: ein Zustand)
S
v : s∈S vs : Xs → As
ist eine Abbildung, die jedem Variablensymbol in Xs einen Wert in As
zuordnet
Die Abänderung vxa der Belegung v für x ∈ Xs und a ∈ As ist definiert
durch:
v (y ) falls x 6= y
a
vx (y ) :=
a
falls x = y
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
47 / 318
Semantik von Ausdrücken
Gegeben eine Algebra A und eine Belegung v . Dann ist die Semantik
[[e]]A,v eines Ausdrucks e der Sorte s das folgende Element aus As :
• [[x]]A,v := v (x) für x ∈ Xs
• [[op(e1 , . . . , en )]]A,v := op A ([[e1 ]]A,v , . . . , [[en ]]A,v ) für op ∈ OP und
ei ∈ EXPR(Σ, X )
• [[e1 = e2 ]]A,v := tt, falls [[e1 ]]A,v = [[e2 ]]A,v (sonst := ff)
• [[∀ x.ϕ]]A,v := tt, falls für alle a ∈ As 0 gilt: [[ϕ]]A,v a = tt (sonst := ff)
(x ∈ Xs 0 )
x
• [[∃ x.ϕ]]A,v := tt, falls es ein a ∈ As 0 gibt mit [[ϕ]]A,v a = tt (sonst :=
x
ff) (x ∈ Xs 0 )
Hinweis: Falls ϕ eine Formel ist, so ist [[ϕ]]A,v immer tt oder ff.
(“Die Formel ist wahr oder falsch in A mit v ”)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
48 / 318
Gültigkeit
Für ϕ ∈ For (Σ, X ) und Ax ⊆ For (Σ, X ) definiert man:
• A, v |= ϕ :⇔ [[ϕ]]A,v = tt
Gesprochen: ϕ gilt in A unter Belegung v“
”
• A |= ϕ :⇔ für jedes v gilt: A, v |= ϕ
Gesprochen: ϕ gilt in A“, A Modell von ϕ “
”
”
• A |= Ax :⇔ A |= ϕ für alle ϕ ∈ Ax
• Ax |= ϕ :⇔ für alle A ∈ Alg(Σ) gilt: A |= Ax ⇒ A |= ϕ
Gesprochen: ϕ folgt aus Ax“
”
• ϕ Tautologie, |= ϕ :⇔ für alle A ∈ Alg(Σ) gilt A |= ϕ
Beachte: A |= p(x) genau dann, wenn pA konstant für alle Elemente
wahr ist, also auch genau dann, wenn A |= ∀ x.p(x)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
49 / 318
Erfüllbarkeit
Für ϕ ∈ For (Σ, X ) und Ax ⊆ For (Σ, X ) definiert man:
• ϕ erfüllbar in der Algebra A
:⇔ es gibt Belegung v mit A, v |= ϕ
• Ax erfüllbar in der Algebra A
:⇔ es gibt Belegung v mit A, v |= ϕ für alle ϕ ∈ Ax
• ϕ erfüllbar, falls ϕ erfüllbar in einer Algebra
• Ax erfüllbar, falls Ax erfüllbar in einer Algebra
Beachte: p(x) ist erfüllbar in A, wenn pA für ein Element wahr liefert,
also auch genau dann, wenn A |= ∃ x.p(x)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
50 / 318
Eigenschaften der Prädikatenlogik (1)
1
A, v |= ϕ ⇔ Nicht A, v |= ¬ ϕ (kurz: A, v 6|= ¬ ϕ)
2
A, v |= ϕ oder A, v |= ¬ ϕ
3
v (x) = v 0 (x) für alle x ∈ free(ϕ) ⇒ (A, v |= ϕ ⇔ A, v 0 |= ϕ)
4
Nur, wenn free(ϕ) = ∅: A |= ϕ oder A |= ¬ ϕ
5
Nur, wenn free(ϕ) = ∅: A |= ϕ ⇔ A 6|= ¬ ϕ
6
A |= ϕ ⇔ A |= Cl ∀ (ϕ)
7
{Ax1 , . . . , Axn } |= ϕ ⇔ {Cl ∀ (Ax1 ), . . . , Cl ∀ (Axn )} |= ϕ
Bedeutung: Cl ∀ (ϕ)-Allquantifizierung aller freien Variablen in ϕ
Beachte Nummer 7: Axiome sind immer allquantifiziert
(Unterschied zur Vorlesung Logik f. Informatiker!)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
51 / 318
Eigenschaften der Prädikatenlogik (2)
Substitutionstheorem
[[t ]]
A, vx A,v |= ϕ ⇔ A, v |= ϕtx
Korollar (Instanzierung und Umbenennung)
Es gilt:
|= (∀ x. ϕ) → ϕtx
Wenn z 6∈ free(ϕ) \ {y }, so gilt außerdem:
• A, v |= ∀ y . ϕ ⇔ A, v |= ∀ z. ϕzy
• |= (∀ y . ϕ) ↔ (∀ z. ϕzy )
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
52 / 318
Semantik von Sequenzen
Definition (Semantik von V
Sequenzen)
W
A, v |= Γ ` ∆ ⇔ A, v |=
Γ→
∆
Folgerungen
Für ϕ ∈ For (Σ, X ) und Ax ⊆ For (Σ, X ) gilt
8. Juli 2013
A |= ϕ
⇔
A |= ` ϕ
A |= ¬ ϕ
⇔
A |= ϕ `
Ax |= ϕ
⇔
Ax |= ` ϕ
Ax |= ¬ ϕ
⇔
Ax |= ϕ `
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
53 / 318
Korrektheit der Basisregeln
Satz (Regelkorrektheit der Basisregeln)
Für alle Basisregeln gilt:
A |= {Γ1 ` ∆1 , . . . , Γn ` ∆n } ⇒ A |= (Γ ` ∆)
Alles andere wäre nicht sehr sinnvoll!
Satz (Invertierbarkeit der Basisregeln)
Für alle Basisregeln außer Abschwächung gilt:
A |= (Γ ` ∆) ⇒ A |= {Γ1 ` ∆1 , . . . , Γn ` ∆n }
Wichtige Konsequenz:
Durch Regelanwendung wird aus einer beweisbaren Sequenz nie eine
unbeweisbare!
(Man kann nichts falsch machen, nur Unnötiges und Umständliches)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
54 / 318
Korrektheit und Vollständigkeit von PL
Kann man mit den Basisregeln einen Beweisbaum mit Konklusion ` ϕ
und Prämissen in Ax konstruieren, dann schreibt man
Ax `PL ϕ.
Satz (Korrektheit)
Für jede Formel ϕ und jede Formelmenge Ax gilt
Ax `PL ϕ
⇒
Ax |= ϕ
Satz (Vollständigkeit)
Für jede Formel ϕ und jede Formelmenge Ax gilt
Ax |= ϕ
8. Juli 2013
⇒
Ax `PL ϕ
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
55 / 318
Unentscheidbarkeit von PL
Satz (Unentscheidbarkeit von PL)
Es gibt kein Entscheidungsverfahren für die Allgemeingültigkeit von
prädikatenlogischen Formeln. Zählt man alle Beweise des
Sequenzenkalküls auf, so wird darin jede allgemeingültige Formel
irgendwann vorkommen, aber das Verfahren kann nicht so verschärft
werden, daß es auch für alle nicht allgemeingültigen Formeln immer
abbricht.
Beachte: Für reine Aussagenlogik ist der Sequenzenkalkül ein
Entscheidungsverfahren: Man kann blind einfach Regeln anwenden,
das terminiert immer. Genau wenn der Beweis geschlossen wird ist die
Formel allgemeingültig!
Das Problem bei PL liegt wo?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
56 / 318
Unentscheidbarkeit von PL
Satz (Unentscheidbarkeit von PL)
Es gibt kein Entscheidungsverfahren für die Allgemeingültigkeit von
prädikatenlogischen Formeln. Zählt man alle Beweise des
Sequenzenkalküls auf, so wird darin jede allgemeingültige Formel
irgendwann vorkommen, aber das Verfahren kann nicht so verschärft
werden, daß es auch für alle nicht allgemeingültigen Formeln immer
abbricht.
Beachte: Für reine Aussagenlogik ist der Sequenzenkalkül ein
Entscheidungsverfahren: Man kann blind einfach Regeln anwenden,
das terminiert immer. Genau wenn der Beweis geschlossen wird ist die
Formel allgemeingültig!
Das Problem bei PL liegt bei der Frage, welche Terme τ man bei den
Regeln all left/exists right wählen soll.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
56 / 318
Beweise über Datenstrukturen
mit dem KIV-Kalkül:
Simplifier und Heuristiken
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
57 / 318
KIV-Kalkül: Überblick
• Versuch 1: Basisregeln, ab Versuch 2: KIV-Kalkül
• Wechseln durch Use Basic Rules“ unter Menü Control-Options
”
• Sequenzenkalkül kennt keine Beweisstrukturierung:
⇒ Lemmas + Regeln zum Anwenden von Lemmas
• Beobachtung: Sequenzenkalkül ist sehr elementar:
⇒ Viele Regeln automatisch anwendbar
• Deshalb: Definition eines Simplifiers, der alle unkritischen Regeln
immer automatisch anwendet.
• Regeln mit 2 Prämissen (disjunction left, conjunction right etc.) sind
der Idee nach alle Fallunterscheidungen
⇒ Zusammenfassen zu einer Regel case distinction
• Automatisches Anwenden von Regeln durch Heuristiken, die man
jederzeit dazu- oder wegschalten kann
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
58 / 318
Spezifikation von Listen (1)
list-basic =
enrich nat with
sorts elem; list; constants [] : list;
functions
.+.
: elem × list → list;
.+.
: list × list
→ list;
. .first : list
→ elem;
. .rest : list
→ list ;
#
: list
→ nat ;
predicates
. < . : elem × elem;
. ∈ . : elem × list;
variables c, b, a: elem; z2 , y2 , x2 , z1 , y1 , x1 , z0 , y0 , x0 , z, y, x: list;
induction list generated by [], + :: (elem × list → list);
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
59 / 318
Spezifikation von Listen (2)
axioms
irreflexivity :
transitivity :
totality :
constructors :
first :
rest :
append-base :
append-rec :
size-base :
size-rec :
In :
end enrich
8. Juli 2013
` ¬ a < a;
` a < b ∧ b < c → a < c;
` a < b ∨ a = b ∨ b < a;
`[] 6= a + x;
` (a + x).first = a;
` (a + x).rest = x;
`[] + x = x;
` (a + x) + y = a + x + y ;
` #([]) = 0;
` #(a + x) = #(x) + 1;
` a ∈ x ↔ (∃ y , z. x = y + a + z);
used for : s,ls;
used for : f,lf;
used
used
used
used
used
used
used
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
for
for
for
for
for
for
for
:
:
:
:
:
:
:
s,ls;
s,ls;
s,ls;
s,ls;
s,ls;
s,ls;
s,ls;
60 / 318
Weitere KIV-Regeln: Induktion
• Theoretisches zu Induktion später
• In KIV gibt es pro Datentyp meist eine strukturelle Induktionsregel
• Nat. Zahlen: Wenn für eine Formel ϕ(n)
• ϕ(0) gilt
• für jedes n: aus Ind.hyp. ϕ(n) folgt: ϕ(n +1)
dann gilt für ∀ n. ϕ(n)
• Im Sequenzenkalkül: ϕ ist jetzt die Sequenz Γ ` ∆
für Induktionsformel in Formel umwandeln!
` ϕ(0)
ϕ = ∀ y.
8. Juli 2013
ϕ(n) ` ϕ(n +1)
Γ`∆
V
Γ→
W
∆,
y = free(Γ → ∆) \ {n}
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
61 / 318
Induktion für Listen
• Jede Liste ist entweder die leere Liste ([])
oder durch Addition von a vorne an x (a + x) gebildet
• Achtung: append von zwei Listen wird auch x + y geschrieben
• Es gilt ebenfalls strukturelle Induktion:
Wenn für eine Formel ϕ(x)
• ϕ([]) gilt
• Für jede Liste x: aus Ind.hyp. ϕ(x) folgt für jedes a: ϕ(a + x)
dann gilt für ∀ x. ϕ(x)
` ϕ([])
ϕ(x) ` ϕ(a + x)
Γ
`∆
V
W
ϕ = ∀ y. Γ →
∆,
y = free(Γ → ∆) \ {x}
Hinweis: Ind.hyp. weglassen entspricht Fallunterscheidung, ob Liste = []
oder = a + x (≡ Regel constructor cut)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
62 / 318
Pragmatik zur Listeninduktion
• Viele Definitionen sind rekursiv
•
•
•
•
append: [] + y = y , (a + x) + y = a + (x + y )
size: #([]) = 0, #(a + x) = 1 + # x
isprefix: isprefix([],y ), ¬ isprefix(a + x,[]),
isprefix(a + x, b + y ) ↔ a = b ∧ isprefix(x, y )
sorted: sorted([]), sorted(a + []),
sorted((a + (b + x)) ↔ a < b ∧ sorted(b + x)
Induktion, wann immer möglich, über Variable am rekursiven
Argument.
Also: Erstes Argument bei append und isprefix
Wenn dort keine Variable, oft Generalisierung des Arguments zu
Variable notwendig
Anschliessend rekursive Definition anwenden (oft mit Simplifier!),
dann Induktionshypothese
Bei sorted geht Rekursion über 2 Stufen: Induktion für FU!
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
63 / 318
Beispiel (1)
Zu zeigen: ` # (x + y ) = # x + # y
Erstes Vorkommen von x: An rekursiver Position von +
Erstes Vorkommen von y: Nicht an rekursiver Position von +
Zweites Vorkommen von x: An rekursiver Position von #
Zweites Vorkommen von y: An rekursiver Position von #
Daraus folgt: Sinnvoll für Induktion ist nur die Variable x!
Beweis durch strukturelle Induktion über x:
Induktions Anfang x = []
# ( [] + y ) = # y = 0 + # y = # x + # y
Induktionsschritt x ⇒ a + x
# ( (a + x) + y ) = # (a + x + y ) = # (x + y ) + 1
= # x + # y + 1 = # x + 1 + # y = # (a + x)+ # y
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
64 / 318
KIV-Kalkül: Lemmaanwendung
Beim Anwenden von Axiomen will man nicht umständlich cut, all left
(und evtl. insert equation) machen
Γ0 ` ∆0
V
Γ ` Θ( Γ0 ), ∆
Γ`∆
Θ(
W
∆0 ), Γ ` ∆
(insert lemma)
• Γ0 ` ∆0 ist das Lemma (Axiom oder anderes Theorem)
• Θ ist eine Substitution für die freien Variablen des Lemmas
• Die Prämisse mit dem Lemma wird vom System als geschlossen
betrachtet
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
65 / 318
KIV-Kalkül: Ersetzungslemmas
Γ0 ` ϕ → σ = τ
V
Γ ` Θ( Γ0 ∧ ϕ), ∆
Γ`∆
Γ00 ` ∆00
(insert rewrite lemma)
• Γ0 ` ϕ → σ = τ ist das Lemma (Γ und Vorbedingung ϕ dürfen
fehlen)
• Θ ist eine Substitution für die freien Variablen des Lemmas
• Γ00 ` ∆00 entsteht aus Γ ` ∆ durch Ersetzen von Θ(σ) durch Θ(τ )
• Lemmas der Form Γ0 ` ϕ → (ψ ↔ χ) mit ψ Literal erlaubt:
Dann wird Θ(ψ) durch Θ(χ) ersetzt
• Wird kontextsensitiv unterstützt: Klicken auf das führende
Funktionssymbol von σ in der Sequenz bietet passende
Rewrite-Regeln an
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
66 / 318
KIV-Kalkül: Der Simplifier
Beobachtung: Viele Vereinfachungen macht man beim mathematischen
Beweisen ohne darüber nachzudenken. Alle unkritischen Regeln wendet
der Simplifier in einem Schritt immer an.
Es gibt 2 Arten von Vereinfachung:
Logische Vereinfachung
• Beipiel: Ersetzen von A ∧ A durch A (für jede Formel A)
• Sind von Axiomen unabhängig, werden immer angewandt
Simplifierregeln
• Beispiel (nat. Zahlen): n + 0 = n zum Ersetzen von τ + 0 durch τ
• Benötigen eine als Simplifierregel markiertes Axiom oder Lemma
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
67 / 318
Simplifier: Logische Vereinfachung
• Aussagenlogische Regeln mit einer Prämisse
(wie implication right, con. left, dis. right etc.)
• All right, Exists left, axiom, reflexivity
• Aussagenlogik mit true und false
• ∃ x. x = τ ∧ A kann zu Aτx vereinfacht werden, falls x 6∈ Vars(τ ).
• Vereinfachung mit Hilfe des Kontexts
Beispiele:
A, Γtrue
` ∆true
A
A
A, Γ ` ∆
Γfalse
` A, ∆false
A
A
Γ ` A, ∆
Afalse
→ B, Γ ` ∆
B
A → B, Γ ` , ∆
A ∨ BAfalse , Γ ` ∆
A ∨ B, Γ ` ∆
A → BAtrue , Γ ` ∆
A → B, Γ ` , ∆
Γ ` A ∧ BAtrue , ∆
Γ ` A ∧ B, ∆
Bsp.: A ∧ A ⇒ A ∧ Atrue
= A ∧ true ⇒ A
A
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
68 / 318
Simplifier: Datenstrukturabhängige Regeln
• Simplifierregeln sind Axiome oder Theoreme (Sequenzen),
die einen entsprechenden Verwendungseintrag haben
• Die syntaktische Form bestimmt den Effekt
• Es gibt mehrere Klassen:
• Simplifierregeln
• Forward-Regeln
• Alle Regeln können lokal oder global sein
Zentral für das Verständnis von KIV:
Welche Simplifierregel hat welchen Effekt?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
69 / 318
Simplifier: Lokale und globale Regeln
2 Klassen von Simplifierregeln
• Lokale Simplifierregeln: Werden in Beweisen über der Spezifikation,
in der sie definiert sind, benutzt.
• Globale Simplifierregeln: Werden in Beweisen in Spezifikationen, die
über der, in der sie definiert sind, benutzt.
Pragmatik
• Lokal werden Axiome als Simplifierregeln verwendet
• Global werden Theoreme verwendet, die “gute” Simplifierregeln sind
Analog für Forward-Regeln
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
70 / 318
Simplifier: Eingabe von Simplifierregeln
Theoreme werden als Simplifierregeln eingetragen, wahlweise durch:
• Am Ende der Sequenz in der specification/sequents-Datei:
used for: s, ls;
used for: f, lf;
• Auf Spezifikationsebene im Menü:
Add (Local) Simplifierrules
Add (Local) Forwardrules
• Auf Spezifikationsebene: Durch Rechtsklick auf das Theorem
und Anklicken der Checkbox
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
71 / 318
Simplifier: Typen von Simplifierregeln
Simplifierregeln (mit Eintrag s und/oder ls) gehören zu einer der Klassen
• Termersetzungsregel = Rewriteregel:
Generelle Form: Γ ` ϕ → (σ = τ )
Effekt: (Instanzen von) σ durch τ ersetzen
• Formelersetzungsregel = Äquivalenzregel
Generelle Form: Γ ` ϕ → (ψ ↔ χ)
Effekt: (Instanzen von) ψ durch χ ersetzen
• Assoziativität und Kommutativität:
Generelle Form: (a + b) + c = a + (b + c) und a + b = b + a
Effekt: Alle anderen Regeln modulo Ass. und Komm. anwenden
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
72 / 318
Simplifier: Pragmatik von Bedingungen
Rewrite- und Äquivalenzregeln haben die generelle Form
Γ ` ϕ → σ = τ und Γ ` ϕ → (ψ ↔ χ)
• Vorbedingungen Γ und ϕ:
Als Formel dieselbe Bedeutung, aber unterschiedlich behandelt.
• ϕ = ϕ1 ∧ . . . ∧ ϕn muss Konjunktion von Literalen sein
• Literal = evtl. negierte atomare Formel
• Atomare Formel = Anwendung von Gleicheit oder
nicht vordefiniertem Prädikat (ungleich ∧, ∨, . . . ) auf Terme
• (Instanzen von) ϕ1 , . . . , ϕn werden in Sequenz gesucht:
Nichtnegierte Formeln im Antezedent, negierte im Sukzedent
• Γ wird versucht durch rekursiven Simplifieraufruf zu beweisen
• Γ darf beliebige Formeln enthalten
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
73 / 318
Simplifier: Pragmatik von Bedingungen
Wann sollte man Vorbedingungen in Γ stecken, wann in ϕ1 , . . . ,ϕn ?
• Vorbedingungen vor dem Sequenzenhaken in Γ sollten nur dann
definiert werden, wenn sie in sinnvollen Sequenzen immer erfüllt sind.
• Typische sinnvolle Vorbedingungen sind Definiertheitsbedingungen:
•
•
•
•
m −1 (Vorgänger von m) ist nur für m 6= 0 definiert
m − n ist nur für n ≤ m definiert
.rest und .last sind nur für nichtleere Listen definiert
Arrays: i < #ar sollte für Zugriff a[i] immer wahr sein
• Wenn man die Pragmatik nicht befolgt:
Viele nutzlose Simplifieraufrufe (wird schnell sehr langsam)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
74 / 318
Simplifier: Beispiele zu Vorbedingungen
• n 6= 0 ` (m < n −1 ↔ m +1 < n)
Vorbedingung ok im Antezedent, da 0 −1 nicht sinnvoll ist
• ` m < n → (n < m + 2 ↔ m + 1 = n)
Nicht im Antezedent, sonst, sobald Instanzen von n < m + 2
vorkommen: Viele unnötige Beweisversuche für m < n
• m ≤ n ` (n − m) + m = m
Beweist z. B. die Sequenz f(x) > 5 ` (f(x) − 3) + 3 = f(x)
(da der Simplifier f(x) > 5 ` 3 ≤ f(x) beweisen kann)
` m ≤ n → (n − m) + m = m beweist die Sequenz nicht,
da 3 ≤ f(x) nicht in der Sequenz vorkommt
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
75 / 318
Simplifier: Rewrite-Regeln
Γ`ϕ→σ=τ
ersetzt (Instanzen von) σ durch τ , wenn Vorbedingungen ok
Einschränkungen:
• free(ϕ) ∪ free(σ) muß alle freien Variablen abdecken
• σ und τ müssen Terme sein, σ darf keine Variable sein
Beispiele:
• (m + n) − n = m
• i > 0 → sqrt(i ˆ 2) = i (i integer; warum nicht im Antezedent?)
• (s1 ∪ s2) \ s2 = s1 \ s2 (Mengen)
• x 6= [] → (x + y ).first = x.first (Listen, + = append, warum nicht
Ant.?)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
76 / 318
Simplifier: Äquivalenzregeln
Γ ` ϕ → (ψ ↔ χ)
ersetzt (Instanzen von) ψ durch χ, wenn Vorbedingungen ok
Einschränkungen:
• free(ϕ) ∪ free(ψ) muß alle freien Variablen abdecken
• ψ muss Literal sein, χ ist beliebige Formel
• Vereinfachung: Falls ψ keine Gleichung, statt (ψ ↔ true) nur ψ
• Vereinfachung: Statt (ψ ↔ false) nur ¬ ψ
Beispiele:
• sorted(a + []),
# x = 0 ↔ x = [] (Listen)
• m + n < m + n0 ↔ n < n0
• n 6= 0 ` (m < n −1 ↔ m +1 < n)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
77 / 318
Simplifier: Kommutativität und Assoziativität
• Kommutativität: m + n = n + m
• Assoziativität: (m + n) + k = n + (m + k)
• Kurz: C(+), A(+), AC(+) für komm., ass., komm. und ass.
• Werden nicht direkt verwendet (Warum?)
• Ob eine Simplifierregel passt, wird “modulo” dieser Regeln geprüft
• ` a + b ∗ c = c ∗ b + a wird mit C(+,*) sofort (per Reflexivität)
bewiesen
• ` b ∗ c ≤ (c ∗ a) ∗ b wird für AC(∗) mit der Regel m ≤ m ∗ n
bewiesen
• Viele Operatoren sind AC: +, ∗, min, ggt, ∪
• Nur assoziativ ist z. B. append auf Listen, ∗ auf Matrizen
• Nur kommutativ ist sehr selten
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
78 / 318
Simplifier: Forwardregeln
• Manchmal will man neue Information zu einer Sequenz dazunehmen
• Fast nur für Transitivität von Ordnungs- und Äquivalenzrelationen:
• m < n ∧ n < n0 → m < n0
• isperm(x, y ) ∧ isperm(y , z) → isperm(x, z)
• Dazu gibt es Forward-Regeln der Form:
Γ ` ϕ1 ∧ . . . ∧ ϕn → ϕ
• Vorbedingungen werden wie bei Simplifierregeln behandelt
• ϕ wird genau einmal zur Sequenz addiert
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
79 / 318
Simplifier: Hinweise zu Forwardregeln
• Transitivität ist unkritisch (sollte man machen)
• Häufig etliche Varianten notwendig:
• m < n ∧ n ≤ n0 → m < n0
• m < n ∧ ¬ n0 < n → m < n0
• m ≤ n + 1 ∧ n < n0 → m ≤ n0
• Ein Lemma sollte nie Forward- und Simplifierregel sein. Warum?
• Forward-Regeln geben sehr leicht Endlosschleifen im Simplifier! ⇒
Sehr vorsichtig, nur mit gutem Grund verwenden
• Einfaches Bsp. für Endlosschleife: ` m < n → m < n + 1
• Bsp.: 0 < n ` (∗ n) ≤ m → m 6= 0
• Warum nur (∗ n) und nicht einfach n? Warum 0 < n im Antezedent?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
80 / 318
KIV-Kalkül: Elimination für Selektoren
• Listen haben (Postfix-)Selektoren
• .first (erstes Element)
• .rest (Rest der Liste)
• Trick: Selektoren loswerden mit Hilfe von insert elim lemma
• Benötigt wird Lemma
` x 6= [] → (a = x.first ∧ y = x.rest ↔ x = a + y )
• Eliminationsregel sucht einen Term t.first oder t.rest
• Wenn t 6= [] gilt, wird t = a + y ersetzt (neue Variablen a, y )
• Damit wird aus t.first bzw. t.rest jetzt a bzw. y
t = a + y , Γ(a, y , a + y ) ` ∆(a, y , a + y )
t 6= [], Γ(t.first, t.rest, t) ` ∆(t.first, t.rest, t)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
81 / 318
KIV-Kalkül: Elimination für andere Funktionen
• Manchmal geht Elimination auch für andere “unbeliebte” Funktionen
• Beliebte Beispiele: Minus und Division
• Lemma für Minus: n ≤ m ` n0 = m − n ↔ m = n0 + n
• Vorteil: Man kann auf Simplifierregeln für − verzichten!
• Nachteil: Neue Variable n0 wird eingeführt (manchmal unintuitiv)
Γ(n0 + n, n, n0) ` ∆(n0 + n, n, n0)
n ≤ m, Γ(m, n, m − n) ` ∆(m, n, m − n)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
82 / 318
Automatisierung in KIV: Heuristiken
• Flexible Automatisierung ist zentral, um bei grossen Fallstudien nicht
immer wieder die gleichen Beweisschritte wiederholen zu müssen
• Deshalb in KIV: Automatisierung durch zuschaltbare Heuristiken
• Speziell: Der Simplifier ist eine Heuristik
⇒ Sollte man (fast) immer benutzen
• Für jedes Beweisziel werden alle Heuristiken der Reihen nach
ausprobiert
• Gewählte Heuristiken jederzeit änderbar
Sehr wichtig für das Verständnis von KIV:
Welche Heuristik hat welchen Effekt?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
83 / 318
Wichtige Heuristiken für PL in KIV (1)
• Simplifier
• Wendet die Simplifier-Regel an
• pl case distinction
• Wendet Regel case distinction an
• Für einfache bis mittelschwere Beweise
• Gefahr, unnötige Fallunterscheidungen zu machen
• if-then-else-split
• if-then-else-Operator:
(ϕ ⊃ σ; τ ) bezeichnet σ, falls ϕ wahr ist, sonst τ
• Wendet cut Regel mit ϕ an
• Häufig einsetzbar, um sinnvolle Fallunterscheidungen zu erzwingen
• Beispiel: Fallunterscheidung nach Anwendung von Rewrite-Regel
abs(i) = (i ≥ 0 ⊃ i; − i)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
84 / 318
Wichtige Heuristiken für PL in KIV (2)
• Quantifier closing
• Sucht Instanzen, mit denen eine Prämisse direkt geschlossen werden
kann
• Immer verwenden
• Einziges Problem: Bei sehr vielen Quantoren braucht die Heuristik viel
unnötige Zeit
• Deshalb Spezifikationsmethodik:
Prädikat (+ Simplifierregeln) definieren statt grosse Quantorenformeln
zu verwenden
• Quantifier:
• Sucht sinnvolle“ Instanzen für Quantoren
”
• Kann Endlosschleifen verursachen!
• Nur bei einfachen Quantorenbeweisen einsetzbar
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
85 / 318
Wichtige Heuristiken für PL in KIV (3)
• structural induction:
• Macht strukturelle Induktion über “sinnvolle” Terme
• Idee für “sinnvoll”: Variablen an rekursiven Positionen:
n ist sinnvoll in m + n, da + rekursiv über das zweite Argument
definiert: m + 0 = m, m + (n +1) = (m + n) +1
• Klappt meistens, aber nicht immer
• Heuristik wendet ausserdem einmal die Induktionshypothese an
• module specific:
• Eigentlich eine Meta-Heuristik: Erlaubt heuristische Anwendung von
Regeln durch Patterns
• Pattern: Gibt Formeln (oder Schemas für Formeln) an, die in der
Sequenz vorkommen müssen bzw. nicht vorkommen dürfen + Regel
die angewandt werden soll
• Alle Patterns stehen in der Datei module-specific
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
86 / 318
Wichtige Heuristiken für PL in KIV (4)
elimination:
• Heuristik gesteuert durch Eliminationsregeln
(analog zu: Simplifier durch Simplifierregeln)
• KIV-Eingabe analog: used for: e; etc.
• Beispiel: n ≤ m ` n0 = m − n ↔ m = n0 + n
• Vorbedingung im Antezedent: n ≤ m muss beweisbar sein
(analog zu Simplifierregeln)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
87 / 318
KIV-Kalkül: Heuristiksätze
• In KIV: 3 vordefinierte Heuristiksätze:
• PL Heuristics: Minimale Menge sinnvoller Heuristiken
• PL Heuristics + Case Splitting: Keine Induktion, FU automatisch
• PL Heuristics + Struct. Ind.:
Versucht, Ziel induktiv zu beweisen und Fallunterscheidungen (FU)
automatisch zu machen
• Für grössere Projekte definiert man häufig seinen eigenen
Standardsatz
⇒ Datei default-heuristics
• Weitere Heuristiken für Programme (DL). Dort noch wichtiger, da
Programme mehr Struktur haben (später)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
88 / 318
Formale Spezifikation und Induktion
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
89 / 318
Was ist ein SW-System mathematisch?
1. Sicht: Operational
Ein SW-System ist ein Automat
• mit Zustand,
• Zustandsübergängen und
• mit Abläufen.
2. Sicht: Algebraisch
Ein SW-System ist eine Algebra = Datenstruktur, d. h. ein System von
Daten und Operationen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
90 / 318
Was ist spezieller?
Einen Automaten kann man als spezielle Algebra auffassen:
• Zustand = Element einer Datenstruktur ⇒ Algebra!
• Sorten = State, Input, Output mit Operationen
• Anfangszustände:
isinitial: State → Bool
• Zustandsübergangsfunktion (oder auch Relation):
exec: Input × State → (State × Output → Bool)
• Z. B. Zustand eines Programms:
Programm + Programmzähler + Speicherbelegung
• Theoretisch: Algebraische Sicht genügt
• Praktisch: Automatensicht hat viele Spezialeigenschaften
(u. a. ist eine Idee von Zeit“ damit verbunden).
”
Deshalb Codierung oft nicht die beste Idee.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
91 / 318
SW-Beschreibungsformalismen
SW-System ist Datentyp:
• Modellorientierte Spezifikation (Z, VDM):
Alle Datentypen sind mit Mengenlehre gebildet (Tupel und Mengen
z. B. für UML-Klassendiagramme)
• Algebraische Spezifikation
SW-System ist Menge von Abläufen:
• Algorithmische Spezifikation, z. B. Programmiersprachen
• Programme über algebraischen/modellorientierten Datentypen
• Automaten, Harel/UML Statecharts, Abstract State Machines
(ASMs)
Eignung hängt von den Zielen ab (Was will ich beschreiben? Was
beweisen?)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
92 / 318
Spezifikation
Ziel: Ein bestimmter Datentyp (Algebra) soll spezifiziert werden.
Fragen:
1
Was für Operationen brauche ich?
2
Welche Axiome brauche ich?
3
Welche Datentypen kann ich überhaupt spezifizieren?
4
Kann ich alle wahren Aussagen über dem Datentyp auch beweisen?
Zunächst: Fragen 3 + 4 speziell für die natürlichen Zahlen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
93 / 318
Natürliche Zahlen: Die Peano-Axiome
• Es gibt eine ausgezeichnete Zahl 0 ∈ IN.
• Jede Zahl n ∈ IN hat einen Nachfolger succ(n) ∈ IN.
• Zu zwei Zahlen gibt es Summe m + n und Produkt m ∗ n
• Axiom 1: 0 ist kein Nachfolger.
• Axiom 2: Die Nachfolgerfunktion ist injektiv.
• Axiom 3: m + 0 = m, m + succ(n) = succ(m + n)
• Axiom 4: m ∗ 0 = 0, m ∗ succ(n) = m ∗ n + m
• Axiom 5: IN ist die kleinste Menge M mit:
0 ∈ M und wenn n ∈ M, dann succ(n) ∈ M
Aus dem letzten Axiom folgt das Induktionsprinzip:
Wenn ϕ(0) gilt, und sich ϕ von n auf n +1 vererbt, dann ist ϕ für alle n
wahr
Begründung: M := {n : ϕ(n)} ist mindestens so groß wie IN.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
94 / 318
Natürliche Zahlen: Mit PL nicht spezifizierbar!
Satz (Charakterisierung der natürlichen Zahlen)
Die Peano-Axiome charakterisieren ein Modell (eben die natürlichen
Zahlen) bis auf Isomorphie (= Umbenennung).
Beachte dabei: Peano-Axiom 5 ist kein prädikatenlogisches Axiom!
Aber:
Satz von Skolem
Es gibt keine Menge Ax-Nat von prädikatenlogischen Formeln, die als
einziges Modell (modulo Umbenennung) nur die natürlichen Zahlen hat.
Beweisbar mit Vollständigkeitssatz
Intuition: Prädikatenlogische Axiome können nicht ausdrücken, dass es
neben den echten“ natürlichen Zahlen keine weiteren Zahlen gibt.
”
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
95 / 318
Natürliche Zahlen: Ein schwächeres Ziel
Wir wissen schon: Jede Axiomenmenge hat auch andere
Modelle als IN mit zusätzlichen Elementen.
Wir versuchen es schwächer: Suche Axiomenmenge, mit der alle über IN
wahren Aussagen bewiesen werden können (dass sie auch über anderen
Modellen gelten, könnte uns ja egal sein).
Die Axiomenmenge sollte entscheidbar sein, d. h. es gibt Programm,
das immer terminiert und sagt: “ja, ist Axiom” oder “nein, ist kein
Axiom”.
Sonst Triviallösung: Nehme als Axiome sämtliche wahren Aussagen.
Zum Beispiel: Nehme Induktionsschema zu den Axiomen dazu:
ϕ0n ∧ (∀ n. ϕ → ϕnn +1 ) → ∀ n. ϕ; (: für jedes ϕ ∈ For(Σ,X) :)
Die Formel ϕ(n) mit freier Variable n beschreibt die Menge
{n : IN |= ϕ(n)}.
Das Induktionsschema für ϕ entspricht Peano-Axiom 5 für diese Menge
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
96 / 318
Natürliche Zahlen: Unvollständigkeit
Problem: Alle Formeln (abzählbar viele) beschreiben nicht alle Mengen
(überabzählbar viele)!
Es gilt leider:
Gödelscher Unvollständigkeitssatz
Es gibt keine entscheidbare Menge von Formeln über (0, succ, +, ∗), die
die ersten 4 Peano-Axiome und n 6= 0 → ∃ n. n = succ(m) enthält oder
impliziert, mit der sich alle in IN wahren Aussagen ableiten lassen
(insbesondere ist das Induktionsschema auch unvollständig).
Der Trick zum Beweis ist das Lügnerparadoxon ( ich lüge jetzt“)
”
in Form einer Formel, die sagt: Ich bin nicht beweisbar“.
”
Indem man die Formeln durchnumeriert (z.B. ASCII-Codierung),
wird das Ich“ durch Meine Nummer“ ausdrückbar.
”
”
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
97 / 318
Natürliche Zahlen: Unvollständigkeit
Intuition:
• Leider findet man auch keine gute“ Axiomenmenge, mit der die
”
wahren Aussagen herleitbar sind
• Alle wahren Aussagen könnte man als Axiome trivialerweise nehmen.
• Die Menge der wahren Aussagen ist also nicht entscheidbar.
• Wahre Aussagen für die natürlichen Zahlen zu beweisen, ist kreativ.
• Verursachte ziemlich viel Wirbel in den 30er Jahren:
Die Idee, Mathematik auf ganz einfachen Grundlagen aufzubauen
(Hilbert’sches Programm), war gescheitert
• Heute: Komplizierte Mengenlehre (Zermelo-Fränkel, Gödel-Bernays)
als Grundlage für Mathematik.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
98 / 318
Problem: Prädikatenlogik reicht nicht
Problem: Prädikatenlogik kann nicht ausdrücken, dass es ausser den
Zahlen 0, 1, 2 (= die aus 0 und +1 gebildeten Terme 0, 0 +1, 0 +1 +1, . . .)
keine weiteren Elemente gibt.
Dasselbe Problem gibt es auch für andere Datentypen:
• Alle ganzen Zahlen sind mit 0, +1, −1 gebildet
• Alle Listen sind die aus [] und + gebildeten Terme:
[], a + [], a + b + [], . . .
• Bei Listen: Terme dürfen Elementvariablen enthalten
• Alle (endlichen) Graphen bekommt man aus dem leeren ∅, durch
Addieren von Knoten (addnode) und Kanten (addedge)
• Alle Arrays bekommt man durch:
• mkarray(n) (erzeugt Array der Grösse n)
• put(a, i, d) (schreibt an Position i das Datum d)
Gemeinsame Idee: Alle Datenelemente durch endlich-malige Anwendung
von Konstruktoren bildbar
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
99 / 318
Generiertheitsklauseln: Syntax
Deshalb Idee: Wir definieren ein “Spezialaxiom”, genannt
Generiertheitsklausel, das aussagt: Die Daten eines Datentyps sind genau
die mit bestimmten Konstruktoren gebildeten Terme.
Syntax
s generated by C ist Termerzeugtheitsklausel (∈ Gen(Σ)) ⇔
• s ∈ S, C = {f1 , . . . , fn } ⊆ OP,
• die Konstruktoren fi haben die Ergebnissorte s
(Konstanten sind als Konstruktoren erlaubt)
• für wenigstens ein fi sind alle Argumentsorten ungleich s
(sonst gibt es keine Konstruktorterme!)
Ein Konstruktorterm t hat die Sorte s, ist mit Konstruktoren aus C
gebildet und enthält nur Variablen anderer Sorten, ist also aus
Ts ((S, C), X \ Xs ).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
100 / 318
Generiertheitsklauseln: Semantik
Idee: Jedes Element der generierten Sorte ist der Wert eines
Konstruktorterms, wenn man die (Parameter)-Variablen geeignet belegt.
Semantik
A |= s generated by C :⇔
für jedes a ∈ As gibt es ein v und t ∈ Ts ((S, C ), X \ Xs ) mit a = [[t]]A,v .
Beispiel: Zur Liste [2,5] gibt es den Konstruktorterm a + b + [].
Mit einer Belegung v der Variablen a, b als v (a) = 2 und v (b) = 5 gilt:
[[a + b + []]]A,v = [2,5].
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
101 / 318
Basisspezifikation
Basisspezifikation
Eine Spezifikation SP = (Σ, Ax, Gen) ist ein Tripel mit:
• Σ = (S, OP)
• Ax ⊆ For(Σ, X ) endlich
• Gen ⊆ Gen(Σ) endlich
Modell
A ist Modell von SP (A |= SP, A ∈ Mod(SP))
A |= SP :⇔ A ∈ Alg(Σ), A |= Gen und A |= Ax.
Gültigkeit
SP |= ϕ :⇔ für alle A in Mod(SP): A |= ϕ
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
102 / 318
Konsistenz und Monomorphie
Definition
Eine Spezifikation ist konsistent
:⇔ Axiome nicht widersprüchlich
⇔ Kein Beweis von false möglich
⇔ Es gibt ein Modell A der Spezifikation
⇒ Das muss sein!
Definition
Eine Spezifikation ist monomorph
:⇔ Axiome legen Verhalten eindeutig fest
⇔ Je zwei Modelle sind bis auf Umbenennung (Isomorphie) gleich
⇒ Sollte für Datentypen wie natürliche Zahlen etc. so sein
(die Axiome sollten ja nicht versehentlich auch reelle Zahlen erlauben).
⇒ Für Systembeschreibungen oft nicht erforderlich bzw. wünschenswert.
Man will ja gerade Details offenlassen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
103 / 318
Minimale Spez. der natürlichen Zahlen in KIV
specification
sorts nat;
constants 0 : nat;
functions
. +1 : nat →
induction nat generated by 0, +1;
variables m, n : nat;
axioms
0 6= n +1;
m 6= n → m +1 6= n +1;
end specification
nat;
ist konsistent und mononorph
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
104 / 318
Spez. der natürlichen Zahlen mit Add. und Mult.
specification
sorts nat;
constants 0 : nat;
functions
. +1 : nat
→
. + . : nat × nat →
. ∗ . : nat × nat →
induction nat generated by 0, +1;
variables m, n : nat;
axioms
0 6= n +1;
m 6= n → m +1 6= n +1;
m + 0 = m; m + n +1 = (m + n) +1;
m ∗ 0 = 0; m ∗ (n +1) = m * n + m;
end specification
nat;
nat;
nat;
ist konsistent und mononorph
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
105 / 318
Minimale Spez. der Listen in KIV
specification
sorts elem; list;
constants [] : list;
functions
. + . : elem × list
induction list generated by [], +;
variables a, b : elem;
x, y : list;
axioms
[] 6= a + x;
a 6= b ∨ x 6= y → a + x 6= b + y;
end specification
→
list;
ist konsistent und mononorph, wenn die Trägermenge
für die Elemente vorgegeben ist (“monomorph modulo Parameter”)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
106 / 318
Kalkül mit struktureller Induktion
Strukturelle Induktion
Sorte s erzeugt von Konstruktoren c, f ⇒ Jedes Element der
Trägermenge ist darstellbar als Konstruktorterm f (f (. . . f (c)))
Induktionsformeln:
Induktionsregel:
ϕ(c) ∧ (∀ x. ϕ(x) → ϕ(f (x))) → ∀ x. ϕ(x)
` ϕ(c)
ϕ = ∀ y.
V
ϕ(x) ` ϕ(f (x))
Γ`∆
Γ→
W
∆,
y = free(Γ → ∆) \ {x}
Ableitung
Wenn man aus der Spezifikation SP durch Anwendung von
Sequenzenkalkül + Induktions-Regel die Formel ϕ ableiten kann, dann
schreibt man SP `IND ϕ.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
107 / 318
Kalkül mit struktureller Induktion:
Korrektheit und Unvollständigkeit
Satz (Korrektheit)
Es gilt SP `IND ϕ ⇒
SP |= ϕ
Satz (Unvollständigkeit)
Es gibt Spezifikationen und Theoreme mit SP |= ϕ, die aber mit
Induktion nicht beweisbar sind (SP 6`IND ϕ).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
108 / 318
Wie schlimm ist Unvollständigkeit?
• Der Kalkül mit der Induktions-Regel ist fast vollständig“:
•
•
•
•
•
”
Wenn SP |= ϕ, dann gibt es eine Erweiterung SP 0 von SP um neue
rekursiv definierte Hilfsfunktionen, so dass SP 0 `IND ϕ gilt.
Praktisch gesehen: Mit den zusätzlichen Symbolen in SP 0 wird eine
passend (verallgemeinerte) Induktionshypothese für den Beweis von
ϕ ausdrückbar.
Beachte: Mit der Generiertheitsklausel ist die Induktionsregel auch
auf Formeln mit den Hilfsfunktionen anwendbar (die Menge der
möglichen Ind. hypothesen wächst!)
SP 0 ist je nach ϕ verschieden (kein uniformes SP 0 ).
In jedem SP 0 gibt es neue Formeln ψ, die wahr aber nicht ableitbar
sind.
Kreativitität also für Verallgemeinerung und passende
Hilfsfunktionen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
109 / 318
Strukturierte Spezifikation:
Freie Datentypen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
110 / 318
Wie spezifiziert man Datentypen?
Vorgehen:
• Schritt 1: Definiere benötigte Sorten
• Schritt 2: Datentypen auf Rechnern sind generiert
⇒ Definiere Konstruktoren und Generiertheitsklauseln
• Schritt 3(?): Definiere weitere Operationen und ihre Axiome
Problem: Wie geeignete, ,,richtige“ Axiome finden?
Formal ,,richtig“: Sie sollten für den gewünschten Datentyp stimmen
(keine Inkonsistenz!), und sollten ihn möglichst eindeutig charakterisieren.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
111 / 318
Freie und nichtfreie Datentypen
nat
????
nat
????
integer????
set
????
set
????
stack ????
bintree????
graph ????
list
by
by
by
by
by
by
by
by
???? by
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
112 / 318
Freie und nichtfreie Datentypen
Beobachtung: Manche Datentypen sind frei (erzeugt): Zwei verschiedene
Konstruktorterme repräsentieren auch immer zwei verschiedene Elemente.
nat
nat
integer
set
set
stack
bintree
graph
0, +1
0, 1, +
0, +1, −1
∅, ins
∅, {.}, ∪
empty, push
mkleaf, mkbranch
∅, +node, +edge
list
[], +
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
112 / 318
Freie und nichtfreie Datentypen
Beobachtung: Manche Datentypen sind frei (erzeugt): Zwei verschiedene
Konstruktorterme repräsentieren auch immer zwei verschiedene Elemente.
nat
nat
integer
set
set
stack
bintree
graph
freely generated by
generated by
generated by
generated by
generated by
freely generated by
freely generated by
generated by
0, +1
0, 1, +
0, +1, −1
∅, ins
∅, {.}, ∪
empty, push
mkleaf, mkbranch
∅, +node, +edge
list
freely generated by
[], +
8. Juli 2013
0+0=0
0 +1 −1 = 0
ins(a,ins(a,∅)) = ins(a,∅)
{a} ∪ {a} = {a}
∅ +node n +node n
= ∅ +node n
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
112 / 318
Axiome für freie Datentypen
Beispiel: Konstante c, einstellige Funktion f , zweistellige Funktion g
• Verschiedenheit der Konstruktoren c, f und g :
c 6= f (x), f (x) 6= g (y , z), c 6= g (x, y )
• Injektivität der Konstruktoren:
f (x) = f (y ) ↔ x = y , g (x, y ) = g (u, v ) ↔ x = u ∧ y = v
Satz: Die Spezifikation mit diesen Axiomen ist monomorph und
konsistent, sie charakterisiert also genau einen Datentyp.
KIV: Schreibe freely generated by, Axiome werden generiert.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
113 / 318
Freie Erzeugtheitsklauseln
Freie Erzeugtheitsklauseln
A |= S 0 freely generated by C :⇔
• A |= S 0 generated by C
• Für 2 Konstruktorterme t, t 0 ∈ T s ((S, C ), X \ Xs ) mit s ∈ S 0 gilt nur
dann
[[t]] A,v = [[t 0 ]] A,v 0
wenn sie mit den exakt gleichen Konstruktoren gebildet sind,
und die Variablen an gleichen Positionen gleich belegt sind.
Beispiel Listen:
• [[[]]] A,v , [[a + []]] A,v 0 , [[a + b + []]] A,v 00 sind auf jeden Fall
verschiedene Listen (egal wie die Belegungen v , v 0 , v 00 sind)
• [[a + []]] A,v = [[b + []]] A,v 0 gdw. wenn v (a) = v 0 (b).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
114 / 318
Natürliche Zahlen als freier Datentyp
Beispiel: Die natürlichen Zahlen
Nat3 =
specification
sorts nat;
constants 0 : nat;
functions +1 : nat → nat;
variables n : nat;
induction nat freely generated by 0, +1;
end specification
⇒ Neu: Axiome jetzt generiert.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
115 / 318
Listen als freier Datentyp
Beispiel: Listen als freier Datentyp
List2 =
specification
sorts list, elem;
functions
[]
:
→ list;
. + . : elem × list → list;
variables a, b: elem; l, l1 , l2 : list;
induction list freely generated by [], +;
end specification
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
116 / 318
Generierte Axiome für Listen
Generierte Axiome
Spezifikation generiert:
[] 6= a + l,
a + l1 = b + l2 ↔ a = b ∧ l1 = l2
Induktionsregel für die Sorte list
∀ y.
V
Γ→
W
∆, Γa+l
` ∆a+l
l
l
Γ`∆
[]
[]
Γ l ` ∆l
y = free(Γ ` ∆) \ {l}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
117 / 318
Datentyp-Definion (Motivation)
Häufige Situation:
• Freie Erzeugbarkeit mit Konstruktoren ci
• Selektoren, die aus ci (x1 , . . . xn ) die xj selektieren
• Testprädikate ist mit Konstruktor cl gebildet“
”
• Ordnung: ist Unterterm von“
”
• Größenfunktion: Anzahl nichtkonstanter Konstruktoren“
”
⇒ Eigenes Syntaxkonstrukt data specification vermeidet unnötige
Schreibarbeit.
In KIV typischerweise nie freely generated, sondern gleich data
specification
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
118 / 318
Data Specification (Beispiel 1)
Beispiel 1: Wochentage
Weekday2 =
data specification
weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun;
variables w : weekday;
end data specification
Generierte Axiome: Die Konstanten sind paarweise verschieden:
Mon 6= Tue, Mon 6= Wed, Mon 6= Thu, Mon 6= Fri, . . .
Induktionsregel:
ΓMon
` ∆Mon
w
w
. . . ΓSun
` ∆Sun
w
w
Γ`∆
⇒ Beweis durch Fallunterscheidung nach dem Tag
Verallgemeinerung: Aufzählungstypen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
119 / 318
Data Specification (Beispiel 2)
Beispiel 2: Paare
Pair =
data specification
using Elem1, Elem2;
pair = mkpair ( . .1 : elem1; . .2 : elem2 )
variables p : pair;
end data specification
Generierte Axiome: mkpair(a, b).1 = a; mkpair(a, b).2 = b
Induktionsregel:
mkpair(a,b)
mkpair(a,b)
Γp
` ∆p
Γ`∆
⇒ Expandiert Variable p zu mkpair(a, b)
Verallgemeinerung: Tupel
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
120 / 318
Data Specification (Beispiel 3)
Beispiel 3: natürliche Zahlen
Nat =
data specification
nat = 0
| . +1 (. −1 : nat);
variables n : nat → nat;
order predicates . < . : nat × nat;
end data specification
Generierte Axiome: n +1 −1 = n; (: 0 −1 ist unspezifiziert :)
¬ n < n; m < n ∧ n < k → m < k;
¬ n < 0; m < n +1 ↔ (m = n ∨ m < n)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
121 / 318
Data Specification (Beispiel 4)
Beispiel 4: Listen
List =
data specification
using Nat, Elem;
list = . + . (. .first : elem; . .rest : list) with consp
| [] with nilp;
variables l : list;
(: ist Unterterm für Listen = ist Endstück :)
order predicates . . : list × list;
size functions length : list → nat;
end data specification
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
122 / 318
Selektoren als partielle Funktionen
Problem: Was tun, wenn ein Selektor auf den falschen Summand
angewandt wird?
Hier: Was sind [] .first und [] .rest?
.first und .rest sollten für [] gar nicht definiert sein ⇒ Partielle Funktionen
In KIV: []. first und [].rest sind unspezifiziert (i. e. kein Axiom)
Semantik: [].rest ist in jeder Algebra (Datenstruktur) irgendeine andere
Liste ⇒ Echte Implementierung muss irgendeine Liste zurückgeben
Pragmatik: Formeln mit [].rest sollten nicht vorkommen.
Wenn doch, muss die Sequenz ohne die Formeln beweisbar sein.
Bem.: Alternativen sind möglich aber komplizierter (u. a. Fehlerelemente,
echte Partialität, etc.)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
123 / 318
Data Specification (Beispiel 3)
Neue Axiome für List3:
nilp([]);
¬ nilp(a + l);
¬ consp([]);
consp(a + l);
(a + l).first = a; (: kein Axiom für [] .first :)
(a + l).rest = l; (: kein Axiom für [] .rest :)
¬ l [];
l (a + l1 ) ↔ l = l1 ∨ l l1 ;
(: beweisbar, aber der Einfachheit halber generiert :)
¬ l l; l1 l2 ∧ l2 l3 → l1 l3 ;
length([]) = 0;
length(a + l) = length(l) +1;
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
124 / 318
Data Specification allgemein
Definition (Datendefinition)
Eine Datendefinition D hat die Form (optionales in eckigen Klammern):
s = c1 (sel 1,1 : s1,1 ; . . . ; sel 1,n1 : s1,n1 ) [with p1 ]
| ...
| ck (sel k,1 : sk,1 ; . . . ; sel k,nk : sk,nk ) [with pk ];
[order predicate . . : s × s;][size function sz : s → nat;]
Überladen: sel i,j = sel i 0 ,j 0 erlaubt, falls si,j = si 0 ,j 0 ,
ansonsten alle Operationen paarweise verschieden.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
125 / 318
Eigenschaften von Data Specifications
Satz: Alle Data Specifications sind immer konsistent. Sie sind immer
monomorph bis auf unspezifizierte Selektoren und Parameter.
Intuition bei Listen ist also:
1
Wir haben exakt den Datentyp der Listen beschrieben.
2
Für die Realisierung auf einem Rechner ist lediglich offen,
• was für ein Elementtyp verwendet wird und
• was für eine Element bzw. Liste [].first und [].rest zurückgeben.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
126 / 318
Datentyp-Definitionen in Java und Scala
abstract class s {
}
/* Subklasse für Konstruktor c1 */
class c1 extends s {
s11 sel11; // ein Feld pro Selektor
s12 sel12;
...
s1n1 sel1n1;
abstract class s
case class c1(
val s11 sel11,
val s12 sel12,
...
) extends s
/* Konstruktor */
public c1(s11 sel11, s12 sel12, ...) {
this.sel11 = sel1; this.sel12 = sel12; ...
}
}
/* Subklasse für Konstruktor c2 */
class c2 extends s {
...
}
8. Juli 2013
case class c2(
...
) extends s
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
127 / 318
Strukturierte Spezifikation:
Anreicherung um
nichtrekursive und rekursive
Definitionen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
128 / 318
Strukturierte Spezifikationen
Motivation
Spezifikationen werden sehr schnell sehr groß
⇒ Strukturierung erforderlich
1
Übersichtlichkeit & Verständlichkeit
2
Wiederverwendung von Komponenten
3
Unabhängige Entwicklung von Komponenten
4
Strukturierung und Wiederverwendung von Beweisen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
129 / 318
Strukturierte Spezifikationen in KIV
• KIV zeigt strukt. Spezifikationen als Spezifikationsgraph an
• In KIV enthält jeder Knoten neben der Spezifikation außerdem eine
Theorembasis
• Die Theorembasis enthält eine Menge von Theoremen (Sequenzen)
über der Gesamtsignatur
• Für jede Sequenz kann ein Beweis vorhanden sein, der zeigt, daß die
Sequenz aus SP und anderen Theoremen folgt (keine zyklischen
Abhängigkeiten)
• Theoreme aus darunterliegenden Spezifikation werden mit insert
spec-lemma statt insert lemma angewandt
• KIV hat ein Korrektheitsmanagement, um Abhängigkeiten zwischen
Beweisen zu verwalten
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
130 / 318
Strukturierte Spez.: Vereinigung, Anreicherung
• Vereinigung
• Wirft Signaturen + Axiome zusammen
• Syntax: union specification
<SPEC1> + <SPEC2> + ...
end union specification
• Nichtdisjunkte Vereinigung nur, wenn gemeinsamer Teil in gleicher
Unterspezifikation (sonst Gefahr der Inkonsistenz!)
• Anreicherung
• Addiert neue Signaturen + Axiome
• Syntax: enrich <SPEC1>, <SPEC2>, ... with
<signature> <induction> <axioms>
end enrich
• Implizit: Ausgangsspezifikation der Anreicherung ist die Vereinigung
von <SPEC1>, <SPEC2>, ...
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
131 / 318
Anreicherung: Vorgehen
• Neue Axiome hinzuzunehmen macht eine Spezifikation sehr schnell
inkonsistent (siehe Versuch 3!)
⇒ Gewünscht: Nur konsistenzerhaltende“ Anreicherungen
”
• Formaler Begriff: Konsistenzerhaltend = Hierarchiepersistent
• Neue Operationen sollten monomorphieerhaltend“ sein: Wenn
”
genau ein Datentyp spezifiziert, sollte die Operation ebenfalls
eindeutig festgelegt sein
• Formaler Begriff: Monomorphieerhaltend = Eindeutig
Vorgehen: Anreicherung nur durch rekursive und nichtrekursive
Definitionen für neue Operationen. Diese sind hierarchiepersistent und
eindeutig.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
132 / 318
Nichtrekursive Definitionen (Motivation)
• Grundidee: Definition als Abkürzung einer grossen Formel
• Prädikat: p(x) ↔ ϕ (p kommt in Formel ϕ nicht vor)
• Funktion: f (x) = t (f kommt im Term t nicht vor)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
133 / 318
Beispiel: Anreicherung um nichtrek. Prädikat
NatDiv =
enrich Nat with
predicates | : nat × nat;
axioms
m | n ↔ ∃ k. k * m = n;
end enrich
Die Anreicherung NatDiv ist hierarchiepersistent und eindeutig.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
134 / 318
Beispiel: Anr. um nichtrek. Prädikat (mit FU)
NatPrime =
enrich NatDiv with
predicates prime : nat;
axioms
¬ prime(0);
¬ prime(1);
n ≥ 2 → (prime(n) ↔ ∀ m. m | n → m = 1 ∨ m = n);
end enrich
Die Anreicherung NatPrime ist hierarchiepersistent und eindeutig
(FU nach n = 0, n = 1, n ≥ 2 ist vollständig).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
135 / 318
Beispiel: Anreicherung um nichtrek. Fkt.
Nat12max =
enrich Nat with
constants 1 : nat; 2 : nat;
functions max : nat × nat → nat;
axioms
1 = 0 +1;
2 = 0 +1 +1;
m < n → max(m, n) = n;
¬ m < n → max(m, n) = m;
end enrich
Die Anreicherung Nat12max ist hierarchiepersistent und eindeutig
(beachte: In KIV sind die Zahlen 1, 2 schon vordefiniert, die Axiome
werden deshalb nicht benötigt).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
136 / 318
Gegenbeispiel 1: Keine nichtrek. Fkt.def.
illegalNatmax =
enrich Nat with
functions max : nat × nat → nat;
axioms
max(m, n) = k ↔ (m < n ∧ k = n) ∨ (¬ m < n ∧ k = m)
end enrich
Dies ist keine nichtrekursive Definition
Die Definition ist beweisbar äqueivant zu der in Nat12max (insofern kann
sie gerechtfertigt werden).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
137 / 318
Gegenbeispiel 2: Keine nichtrek. Fkt.def.
illegalNatdiv =
enrich Nat with
functions . / . : nat × nat → nat;
axioms
m / n = k ↔ ∃ r. r < n ∧ k * n + r = m
end enrich
Diese Definition ist sogar inkonsistent, es fehlt die Vorbed. n 6= 0.
Generell: Ein Axiom der Form f(x) = y ↔ . . . bildet keine nichtrekursive
Definition (dagegen p(x,y) ↔ . . . schon).
Solche Axiome sollten vermieden werden, da sie leicht zu Inkonsistenz
oder Uneindeutigkeit führen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
138 / 318
Weitere Beispiele für nichtrek. Def.
m ≤ n ↔ ∃ k. m + k = n
m < n ↔ m ≤ n ∧ m 6= n
m>n↔n<m
even(n) ↔ ∃ m. n = m + m
odd(n) ↔ ¬ even(n)
m < n → min(m, n) = m, ¬ m < n → min(m, n) = n
x ≥ 0 → abs(x) = x, x < 0 → abs(x) = −x
last(l + (a + [])) = a (: unvollst. Def :)
((a + l)).first = a (: unvollst. Def :)
a ∈ l ↔ ∃ l 0 , l 00 . l 0 + a + l 00 = l
nodups(l) ↔ ¬ ∃ l1 , l2 , l3 , a. l = l1 + a + l2 + a + l3
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
139 / 318
Nichtrekursive Definitionen allgemein
• Prädikat: p(x) ↔ ϕ (p kommt in Formel ϕ nicht vor)
• Funktion: f (x) = t (f kommt im Term t nicht vor)
• Prädikat mit 2 vollständigen Fällen:
ε → (q(x, y ) ↔ ϕ1 ),
¬ ε → (q(x, y ) ↔ ϕ2 )
(p kommt in ε, ϕ1 , ϕ2 nicht vor)
• Funktionen mit 3 unvollständigen Fällen:
ε ∧ δ → f (x, y ) = t1 ,
ε ∧ ¬ δ → f (x, y ) = t2 ,
¬ ε ∧ δ → f (x, y ) = t3 (f kommt in ε, δ, t1 , t2 , t3 nicht vor)
Satz: Die Hinzunahme einer neuen Operation (Funktion oder Prädikat)
mit nichtrekursiver Definition ist immer hierarchiepersistent. Wenn die
Fälle vollständig sind, ist die Erweiterung sogar eindeutig.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
140 / 318
Rekursive Definitionen (Motivation)
• Datentypen bestehen aus (der Semantik von) Konstruktortermen
• Rekursive Definitionen geben Definition durch Reduktion auf kleinere
Konstruktorterme
• Entsprechen einem rekursiven Programm, das den Term abläuft
Length =
enrich List with
functions length : list → nat;
axioms
length([]) = 0;
length(a + l) = length(l) +1;
end enrich
Satz: Die Hinzunahme einer neuen Operation mit rekursiver Definition
zu einem freien Datentyp ist immer hierarchiepersistent. Wenn die Fälle
vollständig sind, ist die Erweiterung immer eindeutig.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
141 / 318
Keine rekursive Definition
illegalLength =
enrich List with
functions length : list → nat;
axioms
length([]) = 0;
length(l) = length(l.rest) +1;
end enrich
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
142 / 318
Keine rekursive Definition
illegalLength =
enrich List with
functions length : list → nat;
axioms
length([]) = 0;
length(l) = length(l.rest) +1;
end enrich
• Spezifikation ist inkonsistent:
Vorbedingung l 6= [] → fehlt im zweiten Axiom
• Mit Vorbedingung äquivalent zum vorigen Axiom
• Aber: Nicht möglich als Simplifierregel (Endlosschleife!)
• Ausserdem: Induktion/constructor cut/Elimination
ergibt immer a + x, niemals x.rest
• Deshalb: Rekursion immer mit Konstruktoren (niemals mit
Selektoren)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
142 / 318
Beispiel: Anreicherung um rek. Definition
Append =
enrich List with
functions . + . : list × list → list;
axioms
[] + l = l;
(a + l) + l’ = a + (l + l’);
end enrich
Append ist hierarchiepersistent und eindeutig
(+ ist überladen: Sowohl Element vor Liste hängen (rot und schwarz),
als auch 2 Listen zusammenhängen (blau)).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
143 / 318
Beispiel: Anreicherung um rek. Prädikat (FU)
Sorted =
enrich List with
predicates sorted : list
axioms
ordered([]),
ordered(a + []),
ordered(a + b + l) ↔ a < b ∧ ordered(b + l)
end enrich
Ordered ist hierarchiepersistent und eindeutig.
Das zweite und dritte Axiom sind äquivalent zu:
l’= [] → ordered(a + l’),
l’= b + l → ordered(a + l’) ↔ a < b ∧ ordered(l’)
(vollständige Fallunterscheidung). Die Gleichungen vor der Implikation
wurden eingesetzt (bessere Simplifierregel!).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
144 / 318
Rekursive Definition allgemein
Hier speziell: Funktionen/Prädikate mit 3 Argumenten (Definitionen
im ersten rekursiv) und Listen. Allgemein: 1 Axiom pro Konstruktor
• Prädikat: p-base: p([], y , z) ↔ ϕ1
p-rec : p(a + x, y , z) ↔ ϕ2
(x, y , z verschieden. ϕ1 hat keine Aufrufe von p. ϕ2 hat nur Aufrufe
von p der Form p(x, t1 , t2 ))
• Funktion: f-base: f ([], x, y ) = t0
f-rec: f (a + x, y , z) = t
(x, y , z verschieden. t0 hat keine Aufrufe von f . t hat nur Aufrufe
von f der Form f (x, t4 , t5 ))
• Zusätzliche Fallunterscheidung in den Axiomen ist ok.
Z. B. statt f (a + z, y , z) = t 3 unvollständige Fälle:
ε ∧ δ → f (a + x, y , z) = t1 ,
ε ∧ ¬ δ → f (a + x, y , z) = t2 ,
¬ ε ∧ δ → f (a + x, y , z) = t3
(ε, δ, t1 , t2 , t3 enthalten nur Aufrufe von f der Form f (x, t4 , t5 )
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
145 / 318
Strukturierte Spezifikationen:
Umbenennung und Parameter
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
146 / 318
Strukturierte Spezifikationen: Umbenennung
Umbenennung:
• Benennt die Operationen einer Spezifikation um
• Nützlich um 2 Kopien zu erhalten
• Syntax: rename <SPEC> by morphism
<renaming1>;
...
<renamingn>;
end rename
• renaming = <sort/op/var> → <sort/op/var>;
• Identische Umbenennungen weglassen (werden beim Ansehen der
Spezifikation aber angezeigt)
• Nicht 2 Symbole auf dasselbe abbilden: Injektiv umbenennen
• Entweder alle Variablen oder keine umbenennen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
147 / 318
Beispiel Umbenennung: Listen zu Stacks
rename List by morphism
list → stack;
[] → empty;
(: Typangabe für überladenes Symbol :)
+ :: (elem × list → list) → push;
(: pop nicht mehr postfix, Schreibweise also pop(x),
default ist in/prae/postfix uebernehmen :)
.rest → pop prio 0;
(: top soll nun praefix sein :)
.first → top .;
(: eigentlich keine Stack-Operation,
nur um Overloading zu zeigen :)
+ :: (list × list → list) → concat prio 0;
x → st; y → st0; z → st1;
end rename
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
148 / 318
Strukturierte Spez.: Generische Spezifikation
Generische Spezifikation:
• Syntax: generic specification
parameter <SPEC>
using <SPEC1>, ..., <SPECn>
target
<signature>
<induction>
<axioms>
end generic specification
• Wie Anreicherung (von <SPEC>, <SPEC1>, ..., <SPECn>), nur
wird von <SPEC> explizit gesagt, dass es ein Parameter ist.
• Vereinigung und Anreicherung übernimmt den (oder die) Parameter
der Unterspezifikationen
• Variante: generic data specification: Wie data specification nur
mit Parameter
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
149 / 318
Strukturierte Spez. Aktualisierung (1)
Aktualisierung:
• Instanziert Parameter (oder einen Parameter) einer Spezifikation
• Beispiel: Listen beliebiger Elemente → Listen von Zahlen
• Syntax: actualize <SPEC> with <ASPEC1>,...,<ASPECn> by
morphism
<renaming1>;
...
<renamingn>;
end actualize
• renaming = <sort/op/var> → <sort/op/var>;
• Die Vereinigung von <ASPEC1>,...,<ASPECn> heisst aktuelle
Spezifikation
• Identische Umbenennungen weglassen
• Entweder alle Variablen oder keine umbenennen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
150 / 318
Strukturierte Spez. Aktualisierung (2)
Aktualisierung:
• Der Parameter muss in die aktuelle Spez. abgebildet werden
• Abbildung darf nicht-injektiv sein: pair(elem1 , elem2 ) →
pair(nat, nat)
• Der Nicht-Parameter-Teil darf nur injektiv und disjunkt zur aktuellen
Spezifikation umbenannt werden, z. B. list → natlist
• Die instanzierten Axiome des Parameters müssen Axiome in der
aktuellen Spezifikation sein
• Verallgemeinerung instantiated specification:
• Axiome werden bewiesen
• mapping statt morphism erlaubt es, eine Sorte auf ein Tupel von
Sorten abzubilden
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
151 / 318
Aktualisierung: Beispiel (1)
Order =
specification
sorts elem;
constants d : elem;
predicates : elem × elem;
variables a, b, c : elem;
axioms
¬ a a; a b ∧ b c → a c;
¬ a d; (: d ist minimal :)
end specification
List-Ord =
generic data specification
parameter Order
using Nat
list = [] | . + . (. .first : elem; . .rest : list);
size functions length : list → nat;
end generic data specification
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
152 / 318
Aktualisierung: Beispiel (2)
NatList =
actualize List-Ord with Nat by morphism
list → natlist;
elem → nat;
→ <;
d → 0;
a → n; b → n0; c → n1;
end actualize
Die instanzierten Axiome (u. a. ¬ n < 0) sind (modulo Umbenennung) in
Nat vorhanden.
Die Listenoperationen (+, .rest etc.) werden nicht umbenannt (sie
bekommen nur die neuen Argumentsorten).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
153 / 318
Strukturierte Spezifikation:
Nichtfreie Datentypen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
154 / 318
Nichtfreie Datentypen: Der typische Fehler
Orderedlist =
enrich List3 with
predicates
. < . : elem × elem ;
ordered : list
;
axioms
¬ a < a; a < b ∨ a = b ∨ b < a;
a < b ∧ b < c → a < c;
ordered([]); ordered(a + []);
ordered(a + b + l) ↔ a < b ∧ ordered (b + l);
end enrich
NICHT ∀ l. ordered(l) addieren!!! Das wäre INKONSISTENT!!!
Allgemein: Ein generierter Datentyp enthält immer alle Konstruktorterme.
Man kann nicht nachträglich welche ausschliessen. Man kann nur einen
nichtfreien Datentyp bilden, der Terme identifiziert
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
155 / 318
Spezifikation nichtfreier Datentypen
• Spezifikationen nichtfreier Datentypen werden sehr leicht
inkonsistent oder uneindeutig
• Konstruiere nichtfreien Datentyp dadurch, daß alle Terme, die die
gleichen Elemente repräsentieren sollen, in einer Klasse
zusammengefaßt werden
• Deshalb als erstes nach der Bestimmung der Konstruktoren:
Definiere Gleichheit durch Extensionalitätsaxiom: x = y ↔ ϕ(x, y )
• Dann: Die in ϕ benutzten Operationen werden rekursiv definiert
• Damit: Monomorph: Höchstens ein Datentyp spezifiziert
• Vorsicht: Rek. Def. kann inkonsistent sein!
• Jetzt: Arrays, im Praktikum: Mengen (einfacher)
Einzige Ausnahme, bei der das Prinzip nicht funktioniert: integers
(für die KIV-Axiome wurde ein Einzelbeweis für Monomorphie geführt)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
156 / 318
Beispiel: Arrayspezifikation, Teil 1
Array=
specification
using Nat; Elem;
sorts array;
functions
mkar : nat × elem
→
. [ . ] : array × nat × elem →
. [ . ] : array × nat
→
# . : array
→
induction
array generated by mkar, [];
variables d : elem; a, a’ : array;
8. Juli 2013
array;
array;
elem;
nat;
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
157 / 318
Beispiel: Arrayspezifikation, Teil 2
Festlegungen:
• Konstruktor mkar(n, d) bekommt Initialelement d
(Alternative: Unspezifizierte Initialisierung)
• Für m ≥ # a ist Selektion a[m] unspezifiziert
• Für m ≥ # a ist Modifikation Identität: a[m, d] = a
axioms
a = a’ ↔ # a = # a’ ∧ ∀ n. n < # a → a[n] = a’[n];
# mkar(n,d) = n; # a[m , d] = # a;
m < n → mkar(n,d)[m] = d;
m < # a → a[m , d][m] = d; n 6= m → a[m , d][n] = a[n];
end specification
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
158 / 318
Inkonsistente rekursive Definition
• Annahmen:
• Mengen von nat. Zahlen definiert
• Die Mengen sind von ∅ und insert generiert
• Für Mengen gilt: insert(a,insert(a,∅)) = insert(a,∅)
• Rekursive Definition:
sum(∅) = 0,
sum(insert(a, s)) = a + sum(s)
• Inkonsistent, da aus insert(1,insert(1,∅))) = insert(1,∅) folgt:
2 = sum(insert(1,insert(1,∅))) = sum(insert(1,∅)) = 1
• Korrekte Definition:
sum(∅) = 0,
¬ a ∈ s → sum(insert(a, s)) = a + sum(s)
(im Fall a ∈ s ist insert(a, s) = s)
• Operation sum muss mit der Definition der Gleichheit auf Mengen,
i. e. dem Extensionalitätsaxiom verträglich sein!
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
159 / 318
Konsistenz nichtfreier Datentypen
2 Alternativen, um Konsistenz sicherzustellen:
1
2
Semantische Überlegung: Es gibt den spezifizierten Datentyp auf
Rechnern, und er erfüllt die Axiome ⇒ Konsistenz
Beweise über dem freien Datentyp, den man erhält, wenn man:
• Extensionalität x = y ↔ ϕ(x,y) weglässt.
• generated by durch freely generated by ersetzt.
• Idee: Der freie Datentyp ist konsistent und monomorph.
•
•
•
•
Den nichtfreien erhält man, indem man Konstruktorterme, die per
Extensionalität gleich“ sind, in Klassen zusammenwirft.
”
Dazu muss ϕ eine Äquivalenzrelation sein:
ϕ(a, a), ϕ(a, b) → ϕ(b, a), ϕ(a, b) ∧ ϕ(b, c) → ϕ(a, c)
Für gleiche“ Terme t1 , t2 muss Operation f dasselbe liefern:
”
ϕ(t1 , t2 ) → f (t1 ) = f (t2 ) bzw. ϕ(t1 , t2 ) → ϕ(f (t1 ), f (t2 ))
Äquivalenzrel. + Verträglichkeit = Kongruenz
Formeln über dem freien Datentyp beweisbar ⇒ Konsistenz
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
160 / 318
Korrekte Spez. der geordneten Listen (1)
Orderedlist = specification
sorts elem; ordlist;
constants [] : ordlist;
functions
. + . : elem × ordlist → ordlist ;
min
: ordlist
→ elem ;
butmin : ordlist
→ ordlist ;
predicates
. < . : elem × elem ;
variables
a, b, c : elem;
l, l 0 : ordlist;
induction
ordlist generated by [], +;
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
161 / 318
Korrekte Spez. der geordneten Listen (2)
axioms
¬ a < a; a < b ∨ a = b ∨ b < a;
a < b ∧ b < c → a < c;
l = l0 ↔
∨
l = [] ∧ l’ = []
l 6= [] ∧ l’ 6= []
∧ min(l) = min(l0 )
∧ butmin(l) = butmin(l0 );
min(a + []) = a;
a < b → min(a + b + l) = min(a + l);
¬ a < b → min(a + b + l) = min(b + l);
butmin(a + []) = [];
a < b → butmin(a + b + l) = b + butmin(a + l);
¬ a < b → butmin(a + b + l) = a + butmin(b + l);
end specification
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
162 / 318
Zusammenfassung: Datentyp-Spezifikation
Vorgehen zur Spezifikation von Datentypen:
1
Bestimme Datenmengen ⇒ Sorten
2
Bestimme Konstruktoren
3
Falls frei ⇒ data specification
4
Falls nichtfrei ⇒ Extensionalitätsaxiom + (rek. oder nichtrek.)
Definition der dabei verwendeten Funktionen (evtl. Kongruenzbeweis)
5
Für weitere Funktionen: rek. oder nichtrek. Definitionen (enrichment)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
163 / 318
Noethersche Induktion
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
164 / 318
Motivation: Noethersche Relationen
Noethersche Relationen sind direkt verknüpft mit Terminierung:
• Wie kann man formal ausdrücken, dass die Schleife
while test do prog anhält?
• Betrachte Folge der Zustände zu Beginn der Schleife: s0 , s1 , s2 , . . ..
• Terminierung gilt genau dann, wenn für jedes s0 die Folge endlich ist.
• Definiere also: s 0 s ⇔ s erfüllt test und s 0 entsteht aus s durch
Abarbeitung von prog
• Analog für eine rekursive Definition einer Funktion/Methode f:
s 0 s ⇔ Wenn man f mit s aufruft, findet ein rek. Aufruf mit s 0
statt (man erhält jetzt evtl. mehrere s 0 , i. e. einen Aufrufsbaum)
• Kriterium für Terminierung ist: Die Relation enthält keine
unendlichen absteigenden Folgen . . . s2 s1 s0 .
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
165 / 318
Noethersche Relationen
Definition (Noethersche Relationen)
Sei ⊆ A × A. Die Relation heißt noethersch (oder wohlfundiert,
engl. well-founded) wenn es keine unendlichen -Ketten gibt:
· · · a3 a2 a1 a0
Beispiele:
• < auf natürlichen Zahlen ist noethersch, aber nicht >
• < auf ganzen Zahlen ist nicht noethersch
• m n ⇔ n = m + 1 ist noethersch (nicht transitiv)
• ⊂ (echte Teilmenge) ist noethersch auf endlichen Mengen
(Warum nicht auf unendlichen?)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
166 / 318
Eigenschaften noetherscher Relationen
• ist immer irreflexiv
• Die Relation muss nicht transitiv sein, ihre transitive Hülle ist aber
auch noethersch (und transitiv) deshalb häufig o.B.d.A nur
noethersche Ordnungen betrachtet
• Die Relation muss kein eindeutiges kleinstes Element besitzen.
Beispiel: Echte Teilmenge auf nichtleeren Mengen
• Kleinstes Element existiert 6⇒ noethersch.
Beispiel: < auf rationalen Zahlen, die ≥ 0 sind.
• Wenn < noethersch und stärker, i. e. x y → x < y , dann erst
Recht noethersch
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
167 / 318
Bedeutung noetherscher Relationen
Bedeutung:
• Betrachte Folge der Zustände, die ein Programm durchläuft.
Definiere s0 s :⇔ s0 ist Nachfolgezustand von s
Dann gilt: noethersch ⇔ Programm terminiert immer
• Stärkeres Induktionsprinzip als strukturelle Induktion:
Noethersche Induktion
• Nicht behandelt: Zu noetherscher Induktion gehören
wohlfundiert rekursive Definitionen.
(Analog zu: Strukturelle Induktion vs. rekursive Definition)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
168 / 318
Beispiele für noethersche Prädikate
Ordnungsprädikate: Ordnungsprädikate < von Datendefinitionen sind
noethersch. Zur Erinnerung: x < y ⇔ x (als Konstr.term) ist echter
”
Unterterm von y“.
Z. Bsp. bei Listen: x < a + x, x < a + (b + x), x 6= [] → [] < x
Keine Größenordnung, nicht: a + x < a + b + x (außer wenn a = b)
Größenordnung:
Sei size : s → nat. Dann ist noethersch mit
x y :↔ size(x) < size(y )
Beispiele: Länge einer Liste, Anzahl der Knoten eines Baums, Kardinalität
einer Menge etc.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
169 / 318
Noethersche Induktion
Satz (Noethersche Induktion)
Genau für noethersche Relationen gilt:
Wenn für jedes a aus E (a0 ) für alle Elemente a0 a die Aussage E (a)
gefolgert werden kann, so gilt E für alle Elemente:
(∀ a. (∀ a0 . a0 a ⇒ E (a0 )) ⇒ E (a)) ⇒ ∀ b. E (b)
Definition (Noethersche Induktionsregel)
Sei y := free(Γ ` ∆) \ {x} und noethersch. Induktion über x:
V
W x0
∀ y .∀ x 0 . x 0 x → ( Γ →
∆)x , Γ ` ∆
IND()
Γ`∆
0
∀ y .∀ x 0 . x 0 x → ϕxx ` ϕ
speziell für Formel
`ϕ
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
170 / 318
Noethersche Induktion (Beispiele)
Beispiel: Natürliche Zahlen
∀ n0 . n0 < n → ϕ(n0 ) ` ϕ(n)
` ∀ n. ϕ(n)
Beispiel: Listen
∀ l0 . (l0 l) → ϕ(l0 ) ` ϕ(l)
` ∀ l. ϕ(l)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
171 / 318
Noethersche Induktion in KIV
• In KIV ist die Regel induction für noethersche Induktion vorhanden
• Für Variablen x eines freien Datentyps wird angeboten
• Ind. über vordefiniertes Ordnungsprädikat
(pro Sorte eines; Induktion über x wird angeboten)
• Ind. über vordefinierte Größenfunktion
(pro Sorte eine Fkt. #; Induktion über # x)
• Größenfunktionen für nichtfreie Datentypen kann man mit
•
•
•
•
Unit-Add HeuristicInfo“ addieren
”
Es ist auch möglich einen Term anzugeben, über dessen Größe
induziert wird (z.Bsp. # x − # y )
Die Induktionshypothese wird in KIV mit Ind-Hyp abgekürzt
Goal-Again with Ind-Hyp“ zeigt die Induktionshypothese an
”
Anwendung der Induktionshypothese mit apply induction (statt all
left)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
172 / 318
Sequentielle Programme
und
Dynamische Logik
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
173 / 318
Was ist ein SW-System mathematisch?
1. Sicht: Operational
Ein SW-System ist ein Automat
• mit Zustand,
• Zustandsübergängen und
• mit Abläufen.
2. Sicht: Algebraisch
Ein SW-System ist eine Algebra, d. h. ein System von Daten und
Operationen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
174 / 318
Grundidee für Programme
Hilfsmittel: Begriffe von Signatur, Algebra und Belegung aus der
Prädikatenlogik
• Datentypen in den Programmen sind beliebige algebraisch
spezifizierte Datentypen (daher heißen die Programme abstrakte
Programme)
• Programmvariablen sind Variablen der Prädikatenlogik
• Ein Zustand eines Programms ist eine Belegung der Prädikatenlogik
• Kopiersemantik, d. h. Änderung an einer Variablen ändert keine
andere (eine Variable ist kein Zeiger auf ein Objekt)
• Variablen haben keine Adressen (kein &x wie in C)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
175 / 318
Programme: Syntax
Programme Prog(Σ,X ) (Notation: α, β, γ)
• Parallele Zuweisung: x1 := t1 , x2 := t2 , . . . , xn := tn
Variablen aus X , Terme aus T (Σ, X ), kurz: x := t
• { α; β } (geschachtelte { } weglassen)
• Schleife (ε ist quantorenfreie Formel): while ε do α
• Fallunterscheidung: if ε then α else β
• Lokale Variablen: let x1 = t1 , x2 = t2 , . . . , xn = tn in α
• Das Programm, das nichts tut: skip
(Abkürzung: if ε then α ≡ if ε then α else skip)
• Das Programm, das nie terminiert: abort
(kann als Abkürzung definiert werden: while true do skip)
• Prozeduren später
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
176 / 318
Programme: Semantik (1)
Für eine Σ-Algebra A betrachtet man die Menge
S
ST:={v | v : s∈S Xs → As }
der Variablenbelegungen.
Für sequentielle Programme sind nicht alle Zwischenzustände interessant;
es genügt, Anfangs- und Endzustände zu betrachten.
Erster Versuch: Ein Programm überführt einen Anfangszustand in einen
Endzustand:
[[α]] : ST → ST
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
177 / 318
Programme: Semantik (1)
Für eine Σ-Algebra A betrachtet man die Menge
S
ST:={v | v : s∈S Xs → As }
der Variablenbelegungen.
Für sequentielle Programme sind nicht alle Zwischenzustände interessant;
es genügt, Anfangs- und Endzustände zu betrachten.
Erster Versuch: Ein Programm überführt einen Anfangszustand in einen
Endzustand:
[[α]] : ST → ST
Probleme mit dieser Semantik:
• Was ist die Semantik von abort?
• Wie auf indeterministische Programme erweitern?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
177 / 318
Programme: Semantik (2)
Deshalb: Relationale Semantik:
[[α]] ⊆ ST × ST
• (v , v 0 ) ∈ [[α]] bedeutet: Zustand v wird von α in v 0 überführt
• Wenn zu v kein v 0 mit (v , v 0 ) ∈ [[α]] vorhanden ist: α terminiert
nicht, wenn in v gestartet
• Wenn {(v , v 0 ), (v , v 00 )} ⊆ [[α]], so ist das Programm in v gestartet
indeterministisch mit 2 möglichen Endzuständen: v 0 und v 00
• Derzeit betrachtete Programme sind deterministisch: Zu jedem v
höchstens ein v 0
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
178 / 318
Programme: Semantik (3)
Man definiert die relationale Semantik eines Programmes
bzgl. der Algebra A rekursiv wie folgt:
[[abort]] := ∅
[[skip]] := {(v , v ) | v ∈ ST}
[[t ]]
[[x := t]] := {(v , w ) | w = vx A,v }
[[α; β]] := {(u, w ) | es gibt v : (u, v ) ∈ [[α]] und
(v , w ) ∈ [[β]]}
[[if ε then α else β]] := {(v , w ) | A, v |= ε und (v , w ) ∈ [[α]] oder
A, v |= ¬ε und (v , w ) ∈ [[β]]}
[[t ]]
v (x)
[[let x = t in α]] := {(v , wx ) | (vx A,v , w ) ∈ [[α]]}
[
[[while ε do α]] :=
[[(if ε then α)i ; if ε then abort ]]
i∈N
wobei α0 := skip, αi+1 := α; αi
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
179 / 318
Korrektheitsbegriffe für Programme
Partielle Korrektheit: ϕ [α] ψ
Falls zu Beginn ϕ gilt und α terminiert, dann gilt anschließend ψ
Semantik: A |= ϕ [α] ψ ⇔ für jedes v mit A, v |= ϕ und jedes w mit
(v , w ) ∈ [[α]] gilt A, w |= ψ
Totale Korrektheit:
ϕ hαi ψ
Falls zu Beginn ϕ gilt, dann terminiert α und anschließend gilt ψ
Semantik: A |= ϕ hαi ψ ⇔ für jedes v mit A, v |= ϕ gibt es w mit
(v , w ) ∈ [[α]] es gilt A, w |= ψ
ϕ [α] ψ und ϕ hαi ψ heissen häufig Hoare-Tripel
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
180 / 318
Beispiele zur Korrekheit
Partielle Korrektheit:
|=
|=
|=
|=
|=
true
x =2
x =y
x =a∧y =b
x =2
[ x := 2 ]
[ x := x+1 ]
[ x := x +1 ]
[ x := y, y := x ]
[ abort ]
x =2
x =3
x −1 = y
x =b ∧y =a
x >2
Unterschied partielle und totale Korrektheit:
|=
6|=
|=
true
true
y 6= 0
8. Juli 2013
[ if y=0 then abort else x := 1 ]
hif y=0 then abort else x := 1 i
hif y=0 then abort else x := 1 i
x =1
x =1
x =1
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
181 / 318
Hoare-Kalkül
Achtung: In der Literatur findet man nicht ϕ[α]ψ und ϕhαi ψ, sondern
wahlweise {ϕ}α{ψ} oder ϕ{α}ψ (für beides)
Allgemein bekannt ist der Hoare-Kalkül, der ein Kalkül zur Ableitung von
Tripeln ϕ{α}ψ ist. Wir werden einen allgemeineren Kalkül betrachten.
Literatur z.B.:
• Loeckx & Sieber, The Foundations of Program Verificiation, 2nd ed., Teubner
1987, etwas älter, viele Beispiele, kompliziertere (denotationale) Semantik
• Apt, de Boer, Olderog: Verification of Sequential and Concurrent Programs, 3rd
ed, Sptinger 2009. 500 Seiten, PL + SOS informell, Hoare-Kalkül,
Smallstep-Semantik, behandelt auch OO und nebenläufige Programme
• Sperschneider, Antoniou: Logic, a foundation for computer science.
Addison-Wesley 1991. 500 Seiten,mehrsortige Logik, Sequenzenkalkül, Resolution,
Gleichungslogik (Rewriting), Hoare-Kalkül, Modul-Refinement
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
182 / 318
Dynamische Logik
A. Salwicki 1970 (“algorithmische Logik”),
V.R. Pratt 1976, D. Harel 1977
Idee: Erfinde nicht einfach einen komplett neuen Kalkül für neue Objekte
(hier: Hoare-Tripel) sondern bilde Programmformeln und erweitere Kalkül
um diese neuen Formeln.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
183 / 318
Dynamische Logik: Syntax
Die Menge DLFor(Σ,X ) der DL-Formeln über der Signatur Σ und der
Variablenmenge X enthält
• Alle prädikatenlogischen Formeln von For(Σ,X )
• Für α ∈ DLProg(Σ,X ) und ϕ ∈ DLFor(Σ,X ) auch
• [α]ϕ
( box alpha phi“)
”
Informelle Bedeutung: Wenn α terminiert, gilt nachher ϕ“
”
• hαiϕ ( diamond alpha phi“)
”
Informelle Bedeutung: α hält, und nachher gilt ϕ“
”
Klassifikation:
• Dynamische Logik ist eine (Multi-)Modallogik.
• Modallogik mit Formeln ϕ (und 2 ϕ) stammen aus der
Philosophie:
“ich weiss ϕ”, “ich glaube ϕ”, “ϕ ist möglich”
• Temporallogik: “irgendwann wird ϕ wahr sein”
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
184 / 318
Bemerkungen zur Syntax
• Boxen und Diamonds binden stärker als Aussagenlogik:
[α]ψ ∧ χ bedeutet ([α]ψ) ∧ χ
• Schachtelung möglich:
hαihβiψ bedeutet hαi ( hβiψ )
• Auch gemischte Schachtelung ist erlaubt: [α] ∀ x. ϕ ∧ hβiψ
• Auch in DL betrachtet man Sequenzen, z. B. hαiψ, Γ ` ∆.
• Wenn x in α vorkommt, x0 aber nicht, so besagt
hαi x = x0 : “Am Ende von α hat x den Wert, den x0 jetzt hat”
• hαi x = x0 → hβi x = x0 bedeutet:
“Wann immer α in x einen Wert x0 ausrechnet so tut das auch β”
Man kann in DL also über Programmähnlichkeit reden
• Es gilt: [α]ψ ↔ ¬ hαi¬ ψ
Man könnte also Box mit Hilfe von Diamond definieren
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
185 / 318
Semantik der Dynamischen Logik
Die Semantik von Formeln der Prädikatenlogik wird erweitert durch
A, v |= [α]ψ
A, v |= hαiψ
:⇔
:⇔
für alle w : (v , w ) ∈ [[α]] ⇒ A, w |= ψ.
es gibt w : (v , w ) ∈ [[α]] und A, w |= ψ.
Damit gilt
A, v |= ϕ[α]ψ
A, v |= ϕhαi ψ
⇔
⇔
A, v |= ϕ → [α]ψ
A, v |= ϕ → hαiψ,
Hoare-Tripel sind also spezielle Formeln der Dynamischen Logik.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
186 / 318
Dynamische Logik: Beispiele
|= [x := 1] x = 1
|= x = x0 → [x := x + 1] x = x0 + 1
|= x = x0 → hx := x + 1i x = x0 + 1
Unterschied Box/Diamond:
|= x = 5 → [abort] x = 5
6|= x = 5 → haborti x = 5
Sequenzen mit Programmen, Programme auch im Antezedent:
|= x = x0 ` [x := x + 1] x = x0 + 1
|= x > 0 ` hwhile x > 1 do x := x -1i x = 1
|= hif x > 0 then y := 1 else aborti y = y 0 ` y 0 = 1 ∧ x > 0
|= [if x > 0 then y := 1 else abort] y = y 0 ` y 0 = 1 ∧ x > 0 ∨ x = 0
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
187 / 318
Kalkül für Dynamische Logik
Grundidee: Symbolische Ausführung von Programmen
Betrachte Ausführung des Programms
α1 ; α2 ; . . . ; αn (αi ohne ; (compound) auf top-level)
• Annahme: Initialer Zustand erfüllt Vorbedingung ϕ0
• Berechne ϕ1 , die stärkste Formel, die nach α1 gilt
• Berechne ϕ2 , die stärkste Formel, die nach α1 ; α2 gilt
• . . . solange bis das Programm verschwunden ist
• Zum Schluss: Teste ob ϕn die Nachbedingung impliziert
(nur noch Prädikatenlogik)
• Symb. Ausführung geht sowohl im Antezedent als auch im
Sukzedent!
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
188 / 318
DL-Kalkül: Normalisierung
normalize right
Γ ` hαihβiψ, ∆
Γ ` hα; βiψ, ∆
Γ ` [α][β]ψ, ∆
Γ ` [α; β]ψ, ∆
normalize left
hαihβiψ, Γ ` ∆
hα; βiψ, Γ ` ∆
[α][β]ψ, Γ ` ∆
[α; β]ψ, Γ ` ∆
In KIV: Nie explizit angewandt, die erste Anweisung wird bei jeder
Regelanwendung (in allen Programmformeln) immer automatisch
abgespalten. KIV rotiert immer die Programmformeln nach vorne.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
189 / 318
DL-Kalkül: Zuweisungen (1)
assign right (so auch im Hoare-Kalkül)
Γ ` ψxτ , ∆
Γ ` [x := τ ]ψ, ∆
assign right (Dynamische Logik)
0
0
Γxx , x = τxx ` [α]ψ, ∆xx
Γ ` [x := τ ][α]ψ, ∆
0
wobei x 0 eine neue Variable ist (bezeichnet den alten Wert von x)
Beachte: config-Datei des Projekts setzt Option Hoare-assign rule“
”
(ohne Option wird x 0 eine Variable für den neuen Wert, und
Programmvariablen werden umbenannt)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
190 / 318
DL-Kalkül: Zuweisungen (2)
• In KIV: assign right kombiniert beide Regeln:
• Original-Hoare-Regel, falls nach der Zuweisung ψ kein Programm
mehr enthält
• Sonst die DL Regel
• Die Regel gilt genau gleich auch für Diamonds statt Boxen
• Die Regel für Zuweisung auf der linken Seite sieht genauso aus:
assign left
0
0
x = τxx , [α]ψ, Γxx ` ∆xx
[x := τ ][α]ψ, Γ ` ∆
0
wobei x 0 eine neue Variable ist (für den Wert vor der Zuweisung)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
191 / 318
DL-Kalkül: Regeln für if
if right
Γ, ε ` [α]ψ, ∆ Γ, ¬ ε ` [β]ψ, ∆
Γ ` [if ε then α else β]ψ, ∆
if positive right
Γ, ε ` [α]ψ, ∆ Γ ` ε, ∆
Γ ` [if ε then α else β]ψ, ∆
Analog: if negative right, if left etc.. KIV versucht immer die Tests zu
entscheiden (per Simplifier), damit nur eine Prämisse entsteht.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
192 / 318
Invarianten
Definition: Eine (Schleifen-)Invariante ist eine Formel, die vor und nach
jedem Schleifendurchlauf gilt.
Beispiel:
m = 0 ∧ n = n0 →
[
while n 6= 0 do
n := n −1; m := m +1
od
]
m = n0
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
193 / 318
Invarianten
Definition: Eine (Schleifen-)Invariante ist eine Formel, die vor und nach
jedem Schleifendurchlauf gilt.
Beispiel:
m = 0 ∧ n = n0 →
[
while n 6= 0 do
n := n −1; m := m +1
od
]
m = n0
Invariante: m + m = n0
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
193 / 318
Bestimmung von Invarianten
Wie kommt man drauf?
• Schreibe Werte nach k Durchläufen der Schleife auf
• Kann man zunächst für ein konkrete Anfangswerte (z.B. n0 = 5)
machen.
• Bestimme Formel, wie m,n nach k Durchläufen aussehen:
m = k und n = n0 − k
• Daraus Invariante ∃ k. m = k ∧ n = n0 − k
• Diese Formel vereinfachen ergibt m + m = n0
Nebenbemerkung: Die Invariante benötigt +, die Schleife selbst nicht
⇒ manchmal brauchen Invarianten (genau wie beim Verallgemeinern von
Induktionshypothesen) neue Funktionen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
194 / 318
Notwendiges Kriterium für Invarianten
Eine prädikatenlogische Formel INV ist eine Invariante,
wenn sich zeigen lässt:
• Die Formel gilt am Anfang der Schleife
• Die Invariante wird von einem Schleifendurchlauf erhalten:
Es gilt: INV ∧ ε → [α]INV
Für jede Invariante gilt: Wenn die Schleife anhält, dann gilt am Ende die
Invariante, und (offensichtlich) dass der Test am Ende falsch ist.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
195 / 318
Terminierung von Schleifen
Eine Schleife terminiert nur dann, wenn in jedem Schleifendurchlauf
“etwas” abnimmt bezueglich einer noetherschen Ordnung (dann kann es
nicht unendlich oft abnehmen).
Vorgehen also:
• Bestimme einen Term t, der abnimmt
• Häufig: heruntergezählte Variable; Abstand einer hochgezählten
Variable zur oberen Schranke; Größe einer Datenstruktur (z.B.
Listenlänge)
• Um Abnehmen zu zeigen, zeige mit (neuer) Hilfsvariable z zum
Merken des alten Werts:
z = t ∧ ε ∧ INV → hαi t < z
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
196 / 318
DL-Kalkül: While-Regel
invariant right
Γ ` INV , ∆
INV , ε ` [α]INV
INV , ¬ ε ` ψ
Γ ` [while ε do α]ψ, ∆
invariant right
Γ ` INV , ∆
INV , ε, v = t ` hαi(INV ∧ t v )
Γ ` hwhile ε do αiψ, ∆
INV , ¬ ε ` ψ
KIV: Die Schleifeninvariante INV und im zweiten Fall auch die Schranke t
muss von Hand eingegeben werden (v ist neue Variable)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
197 / 318
DL-Kalkül: Regeln für skip und abort
skip right
Γ ` ψ, ∆
Γ ` hskipiψ, ∆
Γ ` ψ, ∆
Γ ` [skip]ψ, ∆
skip left
ψ, Γ ` ∆
hskipiψ, Γ ` ∆
ψ, Γ ` ∆
[skip]ψ, Γ ` ∆
abort right
Γ`∆
Γ ` habortiψ, ∆
Γ ` [abort]ψ, ∆
abort left
habortiψ, Γ ` ∆
8. Juli 2013
Γ`∆
[abort]ψ, Γ ` ∆
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
198 / 318
DL-Kalkül: Lokale Variablen
vardecls right
x0
x 0 = τ , Γ ` hαx iϕ
Γ ` hlet x = τ in αiϕ
vardecls left
x0
hαx iϕ, x 0 = τ , Γ ` ∆
hlet x = τ in αiϕ, Γ ` ∆
x 0 sind neue Variablen (bezeichnen die lokalen Variablen). Dieselben
Regeln gelten auch für Boxen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
199 / 318
Beispiel zur Korrekheit
m := x.first, x0 := x.rest;
while x0 6= [] do
{
if x0.first > m then m := x0.first ;
x0 := x0.rest
}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
200 / 318
Beispiel zur Korrekheit
Maximum einer nichtleeren Liste nat. Zahlen x:
x 6= []
`h
m := x.first, x0 := x.rest;
while x0 6= [] do
{
if x0.first > m then m := x0.first ;
x0 := x0.rest
}
i
m = maxl(x)
wobei maxl([]) = 0, maxl(n + x) = max(n,maxl(x))
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
200 / 318
Zur nächsten Aufgabe
Invarianten vorher überlegen!!!
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
201 / 318
Prozeduren und
Heuristiken für Programme
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
202 / 318
Prozeduren: Syntax
• Neues Programmkonstrukt: Prozeduraufruf p#(t;y)
• p# ist Prozedurname (das # ist übliche KIV-Konvention)
• Terme t der Sorten s sind Eingabe-Parameter
• Paarweise verschiedene Variablen y der Sorten s 0 sind
Ein-Ausgabe-Parameter
• s : s 0 heisst auch der (Aufrufs-)Modus der Prozedur
• Prozeduren p# ∈ Ps:s 0 sind neuer Bestandteil der Signatur einer
Spezifikation
• KIV: Deklaration zwischen predicates und variables per:
procedures p# s1 × ...× sn : s’1 × ...× s’m;
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
203 / 318
Prozeduren: Semantik
• Semantik: Prozeduren sind eine Relation über den Trägern der
Parametersorten: [[p#]] ⊆ As × As 0 × As 0
• (a, b, c) ∈ [[p]] bedeutet: Die Prozedur p#, aufgerufen mit
• Eingaben a für die Eingabe-Variablen
• Eingaben b für die Ein/Ausgabe-Variablen
terminiert mit Ausgabe c in den Ein/Ausgabe-Variablen
• Damit das stimmt: Kein Zugriff auf globale Variablen!
Ersatz: Zusätzliche Ein/Ausgabe-Parameter
• Normalfall in KIV: Funktionale Prozeduren:
Ein/Ausgabe-Variablen dienen nur zur Ausgabe:
c (und Terminierung) hängen nicht von b ab.
• Wenn nicht, Schlüsselwort nonfunctional am Ende der
Prozedurdefinition
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
204 / 318
Prozedurdeklarationen
• Möglich: Axiome für Prozeduren (Vor- und Nachbedingung)
• Normalerweise (hinter den axioms) Prozedurdeklarationen
declarations
f#(x; y)
{
if x = 0
then y := 1
else { f#(x -1;y); y := y * x }
}
• Erlaubt: (Gegenseitige) Rekursion
• Semantik: Prozeduraufruf erhält “die übliche” Semantik.
Formal: Vereinigung aller tiefenbeschränkten Rekursionen
(analog zu: Vereinigung über beschränkte Zahl von Schl.durchläufen)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
205 / 318
Regeln für Prozeduraufrufe
Falls Prozedurdeklaration p#(y ; z).α gegeben:
x
y = σ, Γ ` hαz iϕ, ∆
Γ ` hp#(σ; x)iϕ, ∆
x
call right
y = σ, hαz iϕ, Γ ` ∆
hp#(σ; x)iϕ, Γ ` ∆
call left
Dabei: y sind die lokalen Variablen auf denen p# rechnet.
Sie dürfen in der Sequenz nicht frei vorkommen (evtl. umbenennen)
Die Regel gilt auch für Boxen statt Diamonds.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
206 / 318
Ein Beispiel
procedures MAXL# natlist : nat;
MAX# nat, nat : nat;
declaration
MAX#(m,n; n0)
{
if m < n then n0 := n else n0 := m
};
MAXL#(x; n)
{
if x = [] then n := 0
else { MAXL#(x.rest; n); MAX#(n,x.first;n) }
}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
207 / 318
Programme als Voraussetzungen: execute call
Nützlich bei Induktion, um den Call aus der Induktionsvoraussetzung gegen den gerade aktuellen zu kürzen“.
”
execute call
Γ ` σ = τ, ∆
y
y
hp#(σ; x)i(x = y ), ϕx , Γ ` ψz , ∆
hp#(σ; x)iϕ, Γ ` hp#(τ ; z)iψ, ∆
contract call
Γ`σ=τ
y
y
hp#(σ; x)i(x = y ), ϕx , ψz , Γ ` ∆
hp#(σ; x)iϕ, hp#(τ ; z)iψ, Γ ` ∆
Regeln gelten (so) nur für funktionale (und damit auch deterministische)
Prozeduren (y jeweils neu). Für nichtfunktionale Prozeduren muß in der
ersten Prämisse x = z hinzugefügt werden.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
208 / 318
Zwischenzustände einführen: split left
Die folgende Regeln wird meist für α = Prozeduraufruf angewandt
(x = modifizierte Variablen von α, x 0 neu):
split left
x0
hαix = x 0 , ϕx , Γ ` ∆
hαiϕ, Γ ` ∆
• Führt einen Zustand x 0 am Ende von α ein, über den man “reden”
kann.
• Dieser wird bei der Anwendung von Lemmata der Form
hαi x = x0 ` ϕ
als Instanz für x0 gebraucht
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
209 / 318
Einfache Heuristiken für Programme
• symbolic execution: Wendet alle Regeln für Programme an, die keine
Fallunterscheidung ergeben: assign, if positive/negative, skip, abort,
let
• split left: Wendet die Regel split left an
• contract and execute: Wendet execute call, contract call an
Im Heuristik-Satz DL heuristics“ enthalten (zusammen mit simplifier,
”
quantifier closing, module specific). Kann immer verwendet werden.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
210 / 318
Fallunterscheidungs-Heuristiken
• conditional right split: wendet if right an
• conditional left split: wendet if left an
• dl case distinction: Fallunterscheidung (conjunction right etc.), aber
nur für Programmformeln
Im Heuristik-Satz DL Heuristics + Case Splitting“ enthalten. Sollte man
”
verwenden, wenn Beweisstruktur der Kontrollstruktur der Programme
folgt (meist der Fall).
Heuristik-Satz DL heuristics + Induction“ enthält zusätzlich Heuristiken
”
für (noethersche) Induktion (induction, apply ind once).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
211 / 318
Heuristiken für Prozeduraufrufe
• calls nonrecursive: Führt alle nichtrekursiven Aufrufe aus
• calls concrete: Führt alle Aufrufe aus, die konkrete Parameter haben,
i. e. Terme die höchstens Parametervariablen enthalten
• weak unfold:
• Führt rekursive Prozeduren einmal aus, wenn sie in der
Induktionshypothese vorkommen. Höher in der Aufrufshierarchie
liegende Aufrufe bevorzugt.
• Weitere Aufrufe werden ausgeführt, wenn festgestellt wird, dass deren
Tests so ausgehen, dass kein weiterer rekursiver Aufruf auftritt.
• unfold: Führt zusätzlich rekursive Prozeduren (einmal) aus, bei denen
der rekursive Aufruf schon in der Sequenz vorkommt
DL Heuristics“ enthält weak unfold, DL Heuristics + Induction“ enthält
”
”
zusätzlich unfold.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
212 / 318
Nichtdeterministische
Programme
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
213 / 318
Nichtdet. Programme: Syntax
KIV kennt noch zwei Programmkonstrukte für nichtdeterministische
Programme:
• α or β: Wählt nichtdeterministisch eines der beiden Programme
• choose x with ϕ in α ifnone β
• Bindet lokale Variablen x (wie let) an irgendwelche Werte,
die ϕ erfüllen
• ϕ darf von anderen Programmvariablen als nur x abhängen
• Führt mit den lokalen Variablen α aus.
• Falls überhaupt keine passenden Werte für x existieren, die ϕ erfüllen,
wird β (ohne lokale Variablen) ausgeführt.
• ifnone abort kann weggelassen werden (default).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
214 / 318
Beispiele für choose
Beispiele:
• choose n with true in α:
Rät beliebige natürliche Zahl
• choose n with n < m in α ifnone β:
Wählt natürliche Zahl n, die kleiner m ist, und führt α aus.
Wenn m = 0 gilt, wird stattdessen β ausgeführt.
• choose boolvar with true in if boolvar then α else β
ist äquivalent zu α or β
• if pre(x) choose y with post(x,y) in output := y else abort
ist ein (das allgemeinste) Programm, das äquivalent zur totalen
Korrektheitsaussage pre(x) → hαi post(x,y) ist.
⇒ Programm kann als Spezifikation eingesetzt werden.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
215 / 318
Nichtdet. Programme: Semantik
Semantik von or:
[[α or β]] = [[α]] ∪ [[β]]
Semantik von choose:
[[choose x with ϕ in α ifnone β]]
v (x)
a
a
= {(v , wx ) | es gibt a mit A, vx |= ϕ und (vx , w ) ∈ [[α]]}
a
∪ {(v , w ) | (v , w ) ∈ [[β]] und es gibt kein a mit A, vx |= ϕ}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
216 / 318
Ein Zusatzproblem für die Semantik
Was ist die Semantik von skip?
Was ist die Semantik von skip or abort?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
217 / 318
Ein Zusatzproblem für die Semantik
Was ist die Semantik von skip?
Was ist die Semantik von skip or abort?
Antwort: Beide sind gleich: Identität auf allen Zuständen
Verhalten sich die Programme unterschiedlich?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
217 / 318
Ein Zusatzproblem für die Semantik
Was ist die Semantik von skip?
Was ist die Semantik von skip or abort?
Antwort: Beide sind gleich: Identität auf allen Zuständen
Verhalten sich die Programme unterschiedlich?
Antwort: Ja, skip terminiert garantiert, skip or abort nicht.
Also: Die relationale Semantik kann nicht ausdrücken, dass ein
nichtdeterministisches Programm garantiert terminiert.
Damit kann es auch die dynamische Logik nicht:
hskip or aborti true besagt, dass es einen terminierenden Ablauf gibt.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
217 / 318
Garantierte Terminierung
Definiere die Teilmenge α ↓ ⊆ ST der Zustände (ST = Menge der
Variablenbelegungen), für die α garantiert terminiert. Einige einfache
Fälle (while und Rekursion sind schwierig) sind:
• abort ↓ = ∅
• skip ↓ = ST
• x := e ↓ = ST
• (α ∨ β) ↓ = α ↓ ∩ β ↓
• {α; β} ↓ = {v | v ∈ α ↓ und für alle w mit (v , w ) ∈ [[α]] gilt: w ∈ β ↓}
Beachte: Die Definition der garantierten Terminierung von compounds
benutzt die relationale Semantik!
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
218 / 318
Neuer Operator: strong diamond
Wir addieren einen neuen Operator ( strong diamond“) zur Logik.
”
h|α|i ϕ besagt: α terminiert garantiert, und in allen Endzuständen gilt ϕ
Formal: A, v |= h|α|iψ :⇔ v ∈ α ↓ und für alle w : (v , w ) ∈ [[α]] gilt:
A, w |= ψ.
Bemerkung: Der Operator wurde von E.W. Dijkstra 1976 erfunden, und
schreibt sich in der Literatur meist wp(α,ϕ) (von weakest
”
precondition“). Der Kalkül heisst deshalb auch wp-Kalkül.
Bemerkung: Die strong diamond-Klammern bekommt man mit F12
(KIV-Symbol) und dann { bzw. }.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
219 / 318
Kalkülregeln für or
Das Gute an strong diamonds: Für deterministische Programme sind die
Regeln für strong diamonds genau dieselben wie für diamonds.
or right
Γ ` hαi ψ, hβi ψ, ∆
Γ ` hα ∨ βi ψ, ∆
Γ ` [α] ψ, ∆
Γ ` [β] ψ, ∆
Γ ` [α ∨ β] ψ, ∆
Γ ` h|α|i ψ, ∆
Γ ` h|β|i ψ, ∆
Γ ` h|α ∨ β|i ψ, ∆
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
220 / 318
Kalkülregeln für choose
choose right
y
y
Γ ` ∃ y .ϕx ∧ hαx i ψ, (∀ x.¬ ϕ) ∧ hβi ψ, ∆
Γ ` hchoose x with ϕ in α ifnone βi ψ, ∆
y
y
ϕx , Γ ` [αx ] ψ, ∆
∀ x.¬ ϕ, Γ ` [β] ψ, ∆
Γ ` [choose x with ϕ in α ifnone β] ψ, ∆
y
y
ϕx , Γ ` h|αx |i ψ, ∆
∀ x.¬ ϕ, Γ ` h|β|i ψ, ∆
Γ ` h|choose x with ϕ in α ifnone β|i ψ, ∆
Die Variablen y sind neue Variablen (für die lokalen Versionen von x).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
221 / 318
Kontrakte und
Abstrakte Datentypen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
222 / 318
Motivation
Bisher:
• Spezifikation von Datenstrukturen
• Verifikation von Einzelprogrammen
Ziel: Integration von formalen Methoden in die Entwicklung
sicherheitskritischer Software mit höchsten Korrektheitsanforderungen
Fragestellungen:
• Wie kommt man zu Softwaresystemen?
⇒ formaler Begriff: Abstrakter Datentyp
• Wie kommt man von einer abstrakten (Anforderungs-)Spezifikation
über Design-Spezifikationen bis zu konkretem Code?
⇒ Refinement (entfällt dieses Jahr)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
223 / 318
Vor- und Nachbedingungen, Kontrakte
Ein Kontrakt für eine Prozedur p (oder auch für eine Methode) besteht
(mindestens) aus
• einer Vorbedingung ϕ (präd.log. Formel)
• einer Nachbedingung ψ (präd.log. Formel)
• der Angabe der input-Parameter (incl. gelesene globale Variablen)
• der Angabe der output-Parameter (incl. geschrieben globale
Variablen).
• Dazu kommt natürlich eine informelle Beschreibung: U.a. Name und
Zweck der Operation, Querverweise zu Use Cases, etc.
Bemerkung: Für KIV-Prozeduren fehlen die globalen Variablen. Sie
müssen als I/O-Parameter addiert werden.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
224 / 318
Vor- und Nachbedingungen, Kontrakte
Definition: Eine Methode mit Implementierung mit Rumpf α erfüllt einen
Kontrakt, falls die Parameter korrekt gegeben und der Rumpf total
korrekt bzgl. Vor- und Nachbedingung ist. Formal also muss gelten:
• Im Hoare-Kalkül: ϕ hαi ψ
• In Dynamischer Logik: ϕ → hαi ψ
• für indet. Programme: ϕ → h|α|i ψ
Bemerkung:(Vorbedingung in Kontrakten)
Wenn die Vorbedingung nicht eingehalten wird, darf beliebiges passieren:
Absturz, Exception, Nichtterminierung, reguläres Ergebnis, illegaler
Speicher etc.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
225 / 318
Zwei Beispiekontrakte
Beispiel 1 (Revertieren einer Liste):
• Eingabe und Ausgabe: Liste x
• Vorbedingung: x = y
• Nachbedingung x = reverse(y)
Beispiel 2 (Entfernen eines Element von einem Stack):
• Eingabe: Stack st
• Ausgabe: Modifizierter Stack st und Element a
• Vorbedingung: st = st0 ∧ st 6= emptystack
• Nachbedingung st = pop(st0 ) ∧ a = top(st0 )
y und st0 sind logische Variablen, die nur zur Spezifikation benötigt
werden. Alles andere sind Programmvariablen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
226 / 318
Kontrakte für Java
• Für Java oder C# sind die Argumente Eingabeparameter und das
Ergebnis der einzige Ausgabeparameter.
• Es gibt immer genau einen IO-Parameter: Den Speicher
•
Der Speicher wird gelesen/modifiziert“ ist nicht aussagekräftig
”
• Deshalb: Genauere Angaben, welche Objekte/Assoziationen
gelesen/geschrieben/erzeugt werden sind, in Vor- und
Nachbedingung erforderlich!
• Die Nachbedingung kann auch: Wirft für bestimmte Eingaben eine
”
bestimmte Exception“ lauten. Sinnvollerweise teilt man die
Nachbedingung deshalb in einen regulären und einen Exception-Teil.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
227 / 318
Abstrakte Datentypen
Eine Grundidee zur mathematischen Beschreibung eines Softwaresystems
ist die eines Automaten mit Zuständen und Abläufen. Es gibt dann:
• Eine Menge möglicher Systemzustände (in Vorlesung SWT durch
Klassendiagramm beschrieben).
• Einen Anfangszustand (oder mehrere).
• Eine Anzahl Systemoperationen (Vorlesung SWT!). Die Operationen
bekommen Eingaben, modifizieren den Systemzustand und
produzieren Ausgaben. Dadurch entstehen Abläufe.
Für die Modellierung verwenden wir:
• Belegungen von Variablen mit algebraisch spezifizierten
Datenstrukturen zur Beschreibung von Zuständen
• Kontrakte zur Beschreibung der Systemoperationen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
228 / 318
Abstrakte Datentypen
Ein Abstrakter Datentyp DT = (S, INIT, {OPi }i∈I ) besteht aus
• Einer Zustandsmenge S. Typischerweise besteht S aus der Belegung
eines Vektors von Variablen mit algebraisch spezifizierten
Datentypen.
• Einer Menge von Initialzuständen INIT ⊆ S.
• Einer Menge (für i ∈ I) von (relational definierten) Kontrakten:
OPi ⊆ INi × S × S × OUTi
• Die Kontrakte werden auch Operationen genannt.
• Jede Operation
• hat Eingaben aus INi (kann für einzelne Operationen wegfallen)
• modifiziert den Zustand S
• hat eine Eingabe aus OUTi (kann für einzelne Operationen wegfallen)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
229 / 318
Beispiele: Objekte/Klassen
Ein Java-Objekt kann als Datentyp aufgefasst werden:
• S ist die Menge der möglichen Belegungen der Felder
• INIT sind die Ergebnisse der Konstruktoren
• OPi sind Kontrakte für die Methoden des Objekts
• Die Felder des Objekts sind private (nur über die Methoden
zugänglich)
Eine Java-Klasse kann als Datentyp aufgefasst werden:
• S ist die Menge der möglichen Objektmengen einer Klasse
• INIT (einelementig) ist das Ergebnis der statischen Initialisierung
• OPi sind Kontrakte für die Methoden der Klasse
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
230 / 318
Beispiel: Softwaresysteme
Auch ein ganzes Softwaresystem kann als Datentyp aufgefasst werden
(siehe Softwaretechnik!)
• S ist die Menge der Systemzustände (z.Bsp. die Menge der
möglichen Instanzen eines Konzeptmodells)
• INIT sind Initialzustände
• OPi sind Kontrakte für die Systemoperationen
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
231 / 318
Programmieren
in
Scala
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
232 / 318
Motivation
• Aus Sicht unseres Sotwaretechnik-Lehrstuhls:
Scala ist eine der derzeit modernsten Programmiersprachen
• KIV wird derzeit nach Scala portiert (fast fertig)
• KIV ist dann mit Scala und Java (GUI) programmiert.
• Scala unterstützt Konzepte die vieles mit den Konzepten der
KIV-Spezifikationen gemeinsam haben.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
233 / 318
Was ist Scala?
• Scala ist entwickelt an der Uni Lausanne von Prof. Odersky
http://www.scala-lang.org
• Viele Dokus (Tutotial, etc.) kann man dort finden
• Eclipse-IDE: //http://www.scala-ide.org
• Scala ist eine objektorientierte Sprache
• Alle Konzepte von Java (Methoden, Klassen, Vererbung etc.) gibt es
(z.T. in verbesserter Form) auch in Scala
• Scala wird in ByteCode der JVM compiliert
• Scala unterstützt auch die Konzepte aus funktionalen Sprachen
(Higher-Order Funktionen Pattern Matching etc.)
• Die Syntax von Scala ist etwas anders, und deutlich verbessert
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
234 / 318
Scala: Typen
• Scala kennt wie Java Klassen und generische Klassen
• Oberster Typ ist Any statt Object
• Scala kennt keine primitiven Typen:
• statt int und Integer gibt es nur Int
• analog: bool, Boolean ⇒ Boolean, array, Array ⇒ Array
• generische Typen werden mit eckigen Klammern geschrieben:
Array[Int] statt Array<Int>
• Array-Zugriff mit runden Klammern a(i) (statt a[i])
• Fest vordefiniert sind Tupel mit (für 3-Tupel) Typ (A,B,C). Sie
werden auch als (a,b,c) konstruiert. Die Felder werden z.B. mit
(a,b,c). 2 selektiert (liefert b)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
235 / 318
Scala: Methodendefinition
• Scala kennt wie Java statische und dynamische Methoden
• Java:
type method(argty1 arg1, argty2 arg2, ...){
body
}
• Scala:
def method(arg1:argty1,arg2:argty, ...):type = {
body
}
• Der Typ void heisst Unit in Scala
• Methoden ohne Resultat können vereinfacht als
def method(arg1:argty1, ... ) { body }
geschrieben werden (kein Typ und kein Gleichheitszeichen)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
236 / 318
Scala: Methodenaufruf
• Aufruf wie in Java für statische und dynamische Methoden
type . smethod (arg1, arg2, . . . )
object . dmethod (arg1, arg2, . . . )
• Bei Methoden ohne Argumente dürfen Leerklammern weggelassen
werden (auch schon bei der Definition)
• Konvention: Leerklammern weglassen gdw. keine Seiteneffekte:
z.B. Selektoren (“getter”) und Tests: list.length, list.isEmpty
• Vorteil: Feldzugriff kann lokal auf get-Methode (gleichen Namens)
geändert werden (keine Änderung in anderen Klassen!)
• Dynamischen Methoden mit einem Argument darf man mit
object method arg aufrufen (Infix: weder Punkt noch Klammern!)
• Vorteil: +, * etc. haben keine Sonderrolle mehr
(sie können auch überladen werden).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
237 / 318
Ausprobieren von Scala
• Scala kann man wie Java compilieren und ein Programm
main(arglist:Array[String]):Unit in einem object ausführen.
• Scala kann aber auch mit einem Kommandozeileninterpreter
(entweder von innerhalb Eclipse oder standalone) bedienen
• Aufruf von scala gibt scala>-prompt
• Eintippen von Ausdrücken wertet diese aus
scala>
"Hello
scala>
7
scala>
2
scala>
6
"Hello" + " World!"
World!"
3 + 4
new Array(4,5).length
new Array(5,6)(1)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
238 / 318
Scala: Felder und lokale Variablen
• Scala unterscheidet bei Feldern und Variablen überschreibbare (var)
und nicht überschreibbare (val; Java: final)
• nicht überschreibare Felder/Variablen val x:Int = 5
• überschreibare Felder/Variablen var x:Int = 5
• Scala implementiert eine Typinferenz:
Für die meisten Variablen und initialisierten Felder kann die
Typangabe wegfallen.
• Für das obige Beispiel: val x = 5 ist ok
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
239 / 318
Scala: Methodenrümpfe
• Scala kennt keinen Unterschied zwischen Statement und Expression.
• Statements sind einfach Expressions vom Typ Unit
• Deshalb ist mischen erlaubt, z.B.:
val x = if (y > 5) { val y = 3; y + 2} else 5
• Der ?-Operator von Java ist in Scala überflüssig
• In Scala werden Strichpunkte nur benötigt, wenn zwei Statements
auf derselben Zeile stehen (sehr selten)
• Zeilenumbruch fügt (wo sinnvoll) implizit einen Strichpunkt ein
• Wenn return expr das letzte Statement einer Methode ist, darf nur
expr geschrieben werden.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
240 / 318
Scala: Beispele für Methoden
• Fakultätsfunktion:
def fac(x:Int):Int = {if (x == 0) 0 else fac(x - 1)}
• Länge (wie in Listenklasse vordefiniert):
def length:Int = {if (isEmpty) 0 else tail.length + 1}
• Letztere Funktion würde in Java so aussehen:
int length() {if (isEmpty) return 0;
else return tail.length() + 1;}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
241 / 318
Scala: Klassendefinitionen (1)
• Java Klassen enthalten sowohl statische als auch dynamische
Methoden
• Scala teilt die Methoden auf in dynamische in der Klasse und
statische, die im sog. companion object gleichen Namens stehen
• Beide müssen in dieselbe Datei, eines von beiden darf fehlen
• Wenn nur object ⇒ Singleton.
object A {
def staticmethod(arg:Int):Int = { 2 * arg }
}
class A {
val field = 5
def dynamicmethod(arg:Int):Int = { this.field + arg}
}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
242 / 318
Scala: Klassendefinitionen (2)
• Java Klassen haben immer einen (häufig nutzlosen) nullstelligen
Konstruktor
• meist muss einer definiert werden, der einfach nur Felder initialisiert.
• In Scala stattdessen: Felder, die im Konstruktor initialisiert werden
sollen, als Argumente der Klasse. Kein nullstelliger Konstruktor.
class A(val field1:Int, var field2:Int) {...}
ergibt als möglichen Konstruktoraufruf new A(3,5). Ein nullstelliger
Konstruktoraufruf ist nicht möglich.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
243 / 318
Scala: Abstrakte Datentypen (1)
Scala unterstützt freie Datentypen analog zu KIV-Specs.
Beispiel: arithmetische Ausdrücke.
sealed abstract classed AExp
case class Binop(val e1:AExp, val str:String, val e2:AExp) extends AExp
case class Unop(val str:String, val e:AExp) extends AExp
case class Val(val v:Int) extends AExp
case class Var(val id:String) extends AExp
erlaubt zu schreiben:
Binop(Var("x"),"+",Unop("-",Val(4))))
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
244 / 318
Scala: Abstrakte Datentypen (2)
• Ein abstrakter Datentyp besteht aus einer abstrakten
(Summen-)Klasse (AExp) und einer Anzahl Unterklassen
(Summanden; hier Binop, Unop, Val, Id)
• Alle Klassen werden zusammen in die Datei AExp
der Summenklasse geschrieben
• sealed ⇒ keine (weiteren) Unterklassen in anderen Dateien
• case class: erlaubt Konstruktoraufruf ohne Schlüsselwort new
(und Pattern matching; siehe später)
• Die Felder sind meist nicht schreibbar (val),
sie werden nur vom Konstruktor initialisiert
(“immutable” datatype; entspricht algebraischen Datentypen).
• Gleichheit (i.e. ==) vergleicht case classes strukturell (nicht wie in
Java auf Referenz-Gleichheit).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
245 / 318
Scala: Listen (1)
Listen sind ein vordefinierter freier Datentyp
sealed abstract class List[+A]
case class ::[A](val head:A, tail:List[A]) extends List[A]
case object Nil extends List[Nothing]
erlaubt Konstruktion mit 1::2::Nil
Bem: eigentlich ::(1,::(2::Nil)), aber “::” ist auch eine Infixfunktion auf Listen, die mit
Doppelpunkt endet. Solche Infixfunktionen drehen die Argumentreihenfolge um!
Alternativ: List(1,2) (durch Aufruf der statischen Methode List mit
variabler Argumentzahl im companion object der Klasse List)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
246 / 318
Scala: Listen (2)
• Listen erlauben kein Überschreiben des head oder tail.
• Listen sind kovariant (das bedeuet das + vor dem Typparameter):
jedes x:List[Int] ist auch ein x:List[Any]
jedes x:List[Binop] ist auch ein x:List[AExp]
• allgemein x:List[type1] ist Subtyp von x:List[type2] falls type1 ein
Subtyp (Unterklasse) von type2 ist.
• Arrays sind dagegen nicht kovariant (weil modifizierbar)
• Nothing ist der leere Typ ohne jedes Element (Subtyp von jedem
Typ). Nil ist deshalb vom Typ List[type] für jeden Typ type
• Listen haben viele vordefinierte Funktionen, u.a. ++ (append), x(i)
(get für das i-te Element, 0-basiert); siehe scaladoc
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
247 / 318
Scala: Pattern Matching
• Scala erlaubt Pattern Matching für ADTs
• match verallgemeinert Java’s switch.
• Methode allids (in Klasse AExp) sammelt
alle vorkommenden Variablen des Ausdrucks
• Funktion ++ hängt Listen aneinander.
• Ein Underscore steht für wildcard (beliebig)
def allids:List[String] = {
this match {
case Var(id) => List(id)
case Binop(e1, ,e2) => e1.allids ++ e2.allids
case Unop( ,e0) => allids(e0)
case Val( ) => Nil
}
}
Binop(Var(”x”),”+”,Val(4)).allids ergibt List(”x”)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
248 / 318
Scala: Higher-Order Funktionen
• Scala erlaubt Higher-Order Functions,
i.e. Funktionen, die Funktionen als Argumente bekommen.
• Funktionstypen werden A => B geschrieben.
• Beispiel: Funktion map (in Klasse List[A] definiert)
wendet eine Funktion f auf alle Listenelemente an
def map[B](f:A => B):List[B] = {
this match { Nil => Nil
x :: xs => f(x) :: xs.map(f)
}}
oder alternativ:
def map[B](f:A => B):List[B] = {
if (isEmpty) Nil else f(head) :: tail.map(f)
}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
249 / 318
Scala: lambda-Abstraktionen
• Das Funktionsargument von map kann eine Funktion sein, die mit
def definiert wurde
• Da die Funktion meist nur einmal verwendet wird, gibt es auch die
Möglichkeit, sie als lambda-Abstraktion anzugeben
• x:Int => x + 1 ist die Funktion, die eins addiert
• (x:Int,y:Int) => x + y ist die Additionsfunktion
• Verwendung z.B mit map:
List(1,2,3).map((x:Int) => 2 * x) ergibt List(2,4,6)
• Kurzschreibweise: e(_) statt (x:Int => e(x))
(manchmal ist Typangabe notwendig: e(_:Int)
• Beispiel: List((1,2),(4,5)).map(_._1) == List(1,4)
(mit Selektor . 1 für Paare)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
250 / 318
Scala: Datentyp Map
• Eine Map bildet endlich viele Schlüssel (keys) auf Werte (values) ab.
• Analog zu Liste von Paaren, aber keine doppelten Schlüssel
• Paare kann man sowohl mit (a,b) als auch mit a -> b konstruieren.
• Konstruktion aus Paaren mit Map("x" -> 3, "y" -> 4)
• Das letzte zählt: Map("x" -> 3, "x" -> 4) == Map("x" -> 4)
• Zugriff über Map("x" -> 3, "y" -> 4)("x") ergibt 3
• Addieren: Map("x" -> 3) + ("y" -> 4) ergibt
Map("x" -> 3, "y" -> 4)("x")
• Löschen mit Map("x" -> 3, "y" -> 4) - "x" gibt
Map("y" -> 4)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
251 / 318
Scala: viele weitere Features
Scala hat noch viele andere Features, auf die wir hier nicht eingehen:
• lazy Funktionen und Felder
• interfaces erweitert scala zu traits.
Diese dürfen auch Code definieren.
• implizite Argumente
• selbstdefiniertes Pattern Matching
• erweiterte generische Syntax für Schleifen
• ...
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
252 / 318
KIV-Beweise
in
Scala
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
253 / 318
Scala und KIV
• Im zweiten Scala-Versuch wollen wir “Beweise programmieren”.
• Zunächst einen Aussagenlogik-Beweiser,
• dann einen für partielle Korrektheit.
• Für die Programmierung brauchen wir Teile des aktuellen KIV-Codes.
• Der KIV-Code ist recht gross (300KLoC) und hat sicher noch Bugs.
• Ihr müsst davon aber nur wenige Teile kennen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
254 / 318
Wiederholung: Syntax von Ausdrücken
Ausdrücke e ∈ EXPR s (Σ, X ) der Sorte s ∈ S über der Signatur Σ und
über den Variablen X sind rekursiv definiert durch
• x aus Xs ist ein Ausdruck der Sorte s
• Sind e1 , . . . , en Ausdrücke der Sorten s1 , . . . , sn und
op : s1 , . . . , sn → s 0 , dann ist op(e1 , . . . , en ) ein Ausdruck der Sorte s 0
• Bem.: Schreibe c statt c() für Konstanten (n = 0)
• Sind e1 , e2 Ausdrücke der Sorte s, so ist
e1 = e2 eine Formel (i. e. ein Ausdruck der Sorte bool)
• Ist ϕ eine Formel und x eine Variable, so sind
∀ x.ϕ und ∃ x.ϕ Formeln
EXPR(Σ, X ) :=
S
s∈S
EXPR s (Σ, X ), For (Σ, X ) := EXPR bool (Σ, X )
Terme t ∈ T (Σ, X ) sind Ausdrücke ohne Quantoren und Gleichheit.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
255 / 318
Scala und KIV: Ausdrücke
Expressions sind ein freier Datentyp (hier leicht vereinfacht):
package types
sealed abstract class Expr
// Operation
case class Op(val name:String, val typ:Type) extends Expr
// Variable
case class Xov(val name:String, val sort:Type) extends Expr
// Applikation
case class Ap(val fct:Expr, val termlist:List[Expr]) extends Expr
//Allquantor
case class All(val vl:List[Xov], val fma:Expr) extends Expr
//Existenzquantor
case class Ex(val vl:List[Xov], val fma:Expr) extends Expr
...
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
256 / 318
Scala und KIV: Parsen
• Die “rohen” Konstuktoren All, Ap etc. machen keinen Typcheck
• Konstruktoren mit Typcheck sind mkap, mkall etc.
• Formeleingabe als z.B. mkall(List(x),Op(”true”,. . . )) möglich
• In der Praxis nicht gemacht. Stattdessen Aufruf des Parsers
⇒ Eingabe wie in KIV
• parser.scalaparse.parse expr(”∀ x. true”) (wie in KIV)
parse seq(arg:String):Seq (Sequenzen),
parse spec(arg:String):Spec (Spezifikationen)
• Um Ausdrücke und Sequenzen korrekt zu parsen (Mixfix-Notation!),
muss KIV eine Spezifikation “kennen”: Das geht mit
setcurrentspecsig(sp:Spec):Unit
setcurrentspeclistsig(spl:List[Spec]):Unit
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
257 / 318
Scala und KIV: Pretty-Printing
• Die “rohe” Ausgabe von Formeln ist nur für Debugging relevant
• Normalerweise Ausgabe mit pretty-printer:
printer.prettyprint.xpp(arg:Any):String mit Sonderzeichen
printer.prettyprint.pp(arg:Any):String ASCII-Ausgabe
• Funktioniert für beliebiges Argument arg:Spec, arg:Expr, etc.
• Für Beweisbäume (gleich) ist das Ergebnis nur ”** A TREE **”.
Es wird zusätzlich ein Baumfenster (wie in KIV) geöffnet.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
258 / 318
Scala und KIV: Sequenzen und Bäume
Sequenzen und Beweisbäume sind ebenfalls ein Datentyp:
package types
sealed abstract class Tree
case class Seq(ant:List[Expr], suc:List[Expr]) extends Tree
case class Vtree(concl:Seq, subtr:List[Tree]) extends Tree
Regelbäume lassen sich graphisch (wie in KIV) anzeigen: Entweder per
pretty-printer oder direkt mit printtree.painttree.pp painttree(t:Tree):Unit.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
259 / 318
Scala und KIV: Aussagenlogische Regeln
• Es ist in KIV nicht erlaubt, beliebig Bäume zusammenzubauen
• Stattdessen: Es gibt vordefinierte Regelbäume für Aussagenlogik:
system.basicrules.con r ist der Regelbaum für conjunction right
• Analog: dis r, equiv l, neg l, imp r, ax etc.
• Allerdings: Passen nur auf die erste Formel rechts/links
(der Antezedent ist eine Liste von Formeln, keine Menge)
• Deshalb zusätzlich: leftrotate left, leftrotate right bzw.
righttrotate left, righttrotate right zum Rotieren im ant bzw. suc.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
260 / 318
Scala und KIV: Aufbau von Bäumen
Beispielregel:
$Γ ` $ϕ, $∆
$Γ ` $ψ, $∆
con r
$Γ ` $ϕ ∧ $ψ, $∆
• Regelbäume enthalten Metavariablen wie $ϕ, $ψ und $Γ, $∆ als
Platzhalter für Formeln bzw. Formellisten.
• Metavariablen kommen in normalen Beweisen nicht vor.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
261 / 318
Scala und KIV: Aufbau von Bäumen
• Gegeben ein bestehender Baum (am Anfang: eine Sequenz) so lassen
sich Instanzen von Regeln “anbauen”.
• refine(tree:Tree,i:Int,rule:Tree):Tree wendet die Regel rule auf die i-te
Prämisse P (1-basiert) des Baums tree an.
• Bei der Anwendung werden in ganz R die Metavariablen so durch die
konkreten Formeln aus der Regel instanziert (ergibt I(rule)), so dass
die Konklusion C der Regel zu P = I(C) wird.
rule
I(rule)
C
P
P
tree
tree
G
G
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
262 / 318
Scala und KIV: Failures (1)
• refine wirft Error, falls der Baum nicht genug Prämissen hat, Test
mit i > tree.premno.
• generated.treefuns.prem(tree,i) und generated.treefuns.prems(tree)
ergeben die i-te Prämisse bzw. alle Prämissen eines tree (1-basiert)
des Baums tree
• Eine Regel kann nicht anwendbar sein
⇒ die Regelanwendung schlägt fehl =
refine wirft die Standardexception Failure.
• Für con r. Wenn Sukzedent leer, oder erste Formel keine
Konjunktion, schlägt refine fehl.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
263 / 318
Scala und KIV: Failures (2)
• “Fehlschläge” sind ein Prinzip beim Beweisen:
Regeln, Heuristiken, Simplifierregeln können alle fehlschlagen.
• spezielle Unterstützung: orl(scalaexpr1,scalaexpr2)
• wertet zunächst scalaexpr1 aus (z.B. ein refine).
• Falls das nicht fehlschlägt ist das auch das Ergebnis.
• Nur falls es fehlschlägt, wird auch scalaexpr2 ausgewertet und liefert
das Ergebnis
• Gewolltes Fehlschlagen durch Aufruf von fail:
(i.e. def fail = throw Failure)
• Bem: orl ist in scala als lazy Funktion realisiert.
Erspart es überall zu Schreiben:
try {scalaexpr1} catch {x:Failure => scalaexpr2}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
264 / 318
Scala und KIV: Generisches Matching
• Zu refine gibt es die Verallgmeinerung:
mvmatch[S,T](pattern:T, concrete:T, toinst:S):S
• Stellt fest, ob die Metavariablen in pattern so instanziert werden
können, dass concrete herauskommt.
(ob pattern auf concrete “matcht”)
• Falls das nicht fehlschlägt, werden die Metavariablen in toinst
instanziert, und die Instanz ist das Ergebnis.
• Variante: mvmatchp(pattern:T, concrete:T):Boolean macht einen
Test, ob pattern auf concrete matcht.
• Nützliche Anwendung im Praktikumsversuch:
val whilepat = parse seq(”$Γ ` [while $ε do $α]$ϕ”)
mvmatch(whilepat, seq, parse prog(”$α))
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
265 / 318
Programmierung eines VCG
• Für’s Praktikum wollen wir einen VCG (“Verification Condition
Generator”) für partielle Korrektheit programmieren
• Ein VCG reduziert Korrektheitsaussagen für Programme auf
prädikatenlogische Goals (automatisch, wenn Invarianten gegeben
sind).
• Es zeigt sich: Die Programmierung ist analog zum Aussagenlogischen
Beweiser
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
266 / 318
Regeln für Hoare-Kalkül
• Die DL-Regeln für den Hoare-Kalkül sind analog zu den
aussagenlogischen Regeln implementiert
• Sie enthalten Metavariablen für Programme $α,$β
• 2 Beispiele (vollständige Listen in der Praktikumsdoku):
$Γ ` $ϕ
skip rule
$Γ ` [skip]$ϕ
$Γ, ¬$ε ` [$β] | $ϕ $Γ, $ε ` [$α]$ϕ
if forward rule
$Γ ` [if $ε then $α else $β]$ϕ
• Es gibt kein Normalisieren wie in KIV: Die Regel compound rule
muss selbst angewandt werden
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
267 / 318
Spezielle Regeln:
besondere Regeln für den Versuch:
• while rule(inv:Expr):Tree liefert die while-Regel mit eingefüllter
konkreter Invariante INV
$Γ ` Inv
Inv, $ε ` [$α]Inv Inv, ¬$ε ` $ϕ
(while rule Inv)
$Γ ` [while $ε do $α]$ϕ
•
• prakt assign tactic(tree:Tree,i:Int):Tree wendet die Zuweisungsregel
mit passender Substitution auf die i-te Prämisse an (x0 neue
Variable).
x0 = $τ, $Γ ` ($ϕ)x0
$x
$Γ ` [$x := $τ ]$ϕ
8. Juli 2013
prakt assign tactic)
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
268 / 318
Temporallogik und
parallele Programme
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
269 / 318
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 für einzelne Systemoperationen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
270 / 318
Softwaresysteme allgemein (2)
Die Sicht als atomare Operation ist nicht adäquat für
• Abläufe von Softwaresystemen, die eine Reihe von System-
operationen aufrufen (vgl. Szenarios in Use Cases)
• 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 Vorlesung: Definition einer dazu passenden Logik.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
271 / 318
Motivation - Beispielprogram semaphore
semaphore ≡
while true do
await S > 0; S := S − 1;
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
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
272 / 318
Parallele Programme: Interleaving
Die Wahl der Programmiersprache trifft 3 zentrale Entscheidungen:
Programme werden interleaved parallel ausgeführt und kommunizieren
über gemeinsame (engl. shared) Variablen. Zuweisungen sind atomar.
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).
Alternativen: asynchron/synchron parallel (verschiedene Rechner bzw.
getaktete Hardware). Kommunikation durch Synchronisation (message
passing). Feinere Atomizität (z.B. Lade/Speichere Referenz in Java!).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
273 / 318
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 Trace ist eine
Zustandsfolge (z0 , . . . , zn ) 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
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
274 / 318
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 ) ∈ [[α]]
• Ein unendlicher Ablauf vorhanden gdw. z0 6∈ α ↓
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
275 / 318
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
• Ziel (nächste Vorlesung): lokale Verifikation eines Threads
(engl. thread-local reasoning)
• Beachte: Die bisherigen sequentiellen Programme werden jetzt
innerhalb einer Umgebung betrachtet
• In einem Ablauf (z0 , z00 , z1 , z01 . . . , zn ) wechseln sich ab
• Systemschritte (z0 , z00 ), (z1 , z01 ), . . . des Programms
• Umgebungsschritte (z00 , z1 ) , (z01 , z2 ), . . .
• Der erste Schritt eines Traces ist ein Systemschritt
• Falls endlich, ist der letzte Schritt ein Umgebungsschritt
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
276 / 318
Semantik temporallogischer Formeln
• Temporallogische Formeln sind über einem Ablauf wahr oder falsch:
A, (z0 , z00 , 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 , z00 , z1 , . . . , zn ) |= ϕ ⇔ z0 |= ϕ
• Über zukünftige Zustände redet man mit temporallogischen
Operatoren oder mit Variablen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
277 / 318
Variablen in Temporallogik
• Statische Variablen haben immer denselben Wert im Ablauf.
(Konvention in KIV: Mit Kleinbuchstaben)
• Flexible Variablen ändern ihren Wert:
X, X0 , X00 bezeichnen die Werte in z0 , z00 , z1
(Konvention in KIV: Großbuchstaben)
• Konvention: Falls der Ablauf nur aus einem Zustand besteht,
haben X0 und X00 auch den Wert von X in z0 .
• Definition variables X : nat flexible;
• Die Formeln X = X0 und X0 = X00 besagen:
Der erste System- bzw. Umgebungsschritt ändert X nicht
• Zuweisung X := T macht einen Systemschritt und impliziert X0 = T
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
278 / 318
Temporallogische Formeln: Always und Eventually
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 , z00 , z1 . . . , zn ) |= 2 ϕ ⇔ Für alle 0 ≤ i ≤ n gilt: (zi , . . . , zn ) |= ϕ
(z0 , z00 , z1 , . . . , zn ) |= 3 ϕ ⇔ Es gibt ein 0 ≤ i ≤ n mit (zi , . . . , zn ) |= ϕ
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
279 / 318
Temporallogische Formeln: Beispiele
• 2 safe ≡ System verlässt nie sichere Zustände.“
”
• 2 X0 = X00 ≡ Die Umgebung modifiziert X nie.“
”
• 2 X0 ≥ X ≡ Das System erniedrigt X nie.“
”
• 2 (X = 5 ∧ X0 = 5) ≡ X ist 5 vor und nach jedem Systemschritt“
”
• 3 Result ≡ System erzielt irgendwann ein Ergebnis.“
”
• 2 3 Input ≡ System erhält immer wieder Eingaben.“
”
• 2 (Input → 3 Output) ≡ Jede (irgendwann anliegende) Eingabe
”
führt auch zu einer Ausgabe.“
• 2 (X = 5 → 3 X > 5) ≡ Wann immer X den Wert 5 hat, wird es
”
irgendwann später noch erhöht“
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
280 / 318
Temporallogische Formeln: Until und Unless
Informelle Beschreibung:
ϕ until ψ
d. h. ψ gilt irgendwann, und davor gilt stets ϕ.
ϕ unless ψ d. h. ϕ gilt immer, bis ψ gilt.
Formale Beschreibung:
(z0 , z00 , . . . , zn ) |= ϕ until ψ ⇔ Es gibt ein 0 ≤ i ≤ n mit:
(zi , . . . , zn ) |= ψ
∧ ∀ 0 ≤ j < i.(zj , . . . , zn ) |= ϕ
(z0 , z00 , . . . , zn ) |= ϕ unless ψ ⇔ (2 ϕ) ∨ (ϕ until ψ)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
281 / 318
Temporallogische Formeln: Beispiele
• X = X0 until unlocked ≡ System verändert X nicht, bis irgendwann
”
ist sicher bis irgendwann das Lock freigegeben wird“.
• N = N00 + 1 until N = 0 ≡ N wird bis auf 0 heruntergezählt“
”
• Y00 = Y0 unless X0 6= X ≡ Die Umgebung ändert Y solange nicht,
”
wie das System X nicht modifiziert“
•
Solange sich alle vorherigen Umgebungsschritte
”
an R (rely) gehalten haben, hält sich der nächste
Systemschritt an G (guarantee).“
• G(X,X0 ) unless (G(X,X0 ) ∧ ¬ R(X0 ,X00 ))
• ¬ (R(X0 ,X00 ) until ¬ G(X,X0 ))
(unless lässt sich mit until ausdrücken und umgekehrt).
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
282 / 318
Temporallogische Formeln: Strong und Weak Next
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 , z00 , . . . , zn ) |= ◦ ϕ ⇔ n 6= 0 ∧ (z1 , . . . , zn ) |= ϕ
(z0 , z00 , . . . , zn ) |= • ϕ ⇔ n = 0 ∨ (z1 , . . . , zn ) |= ϕ
(z0 , z00 , . . . , zn ) |= last ⇔ n = 0
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
283 / 318
Temporallogische Formeln: Beispiele
• Eine einzelne Zuweisung impliziert ◦ last ≡ genau ein Schritt“
”
• 3 last ≡ endlicher Ablauf = Terminierung“
”
• 2 ¬ last ≡ keine Terminierung“
”
• 2 (Errorinput → 3 last) ≡ Fehlerhafte Eingabe führt zum
”
Programmstop.“
• 3 (last ∧ Post) ≡ Terminierung und Nachbedingung am Ende“
”
• 2 (last → Post) ≡ Falls Terminierung dann am Ende
Nachbedingung“
”
• (2 X0 = X00 ) → 3 last ≡ Wenn die Umgebung X nie modifiziert,
ist Terminierung sicher.“
8. Juli 2013
”
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
284 / 318
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
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
285 / 318
Zuweisung als Formel
• Temporallogische Zuweisungen nur für flexible Variablen
• X := T impliziert X0 = 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 Liste vl angegeben: [: vl | α]
V 0
• Definition: unch(uvl) ≡
{X = X | X ∈ uvl}
• Damit: [: vl | X := T] ↔ X0 = T ∧ unch(vl \ X ) ∧ ◦ last
Beispiel:
[: X, Y, Z | X := 1] ↔ X0 = 1 ∧ Y0 = Y ∧ Z0 = Z ∧ ◦ last
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
286 / 318
Typische TL Beweisziele
Typisches Beweisziel: α, Pre, Env ` Prop
Programm α gestartet im Zustand Pre
”
hat in Umgebung Env die Eigenschaft Prop“
• α ist ein Programm (mit Variablen X )
• Pre(X) ist eine Startbedingung (Prädikatenlogik)
• Env(X0 ,X00 ) ist eine Annahme an die Umgebung
• Prop(X) ist eine zu zeigende Eigenschaft, z.B.
• 3 last = α terminiert
• 2 safe(x) = Alle erreichten Zustände sind sicher
• 2 (last → post(x)) (Nachbed. für partielle Korr.)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
287 / 318
Beispiel: Beweisverpflichtung semaphore
(: ParallelesProgramm :)
[: S, L1 , L2 | semaphore] ,
(: Umgebungsannahme :)
2 (S 00 = S 0 ∧ L001 = L01 ∧ L002 = L02 )
(: Initialzustand :)
S = 1, ¬ L1 , ¬ L2
` (: Beweisverpflichtung :)
2 ¬ (L1 ∧ L2 )
Programm semaphore erlaubt es nie, dass beide Teilprogramme
”
gleichzeitig im kritischen Abschnitt sind.“
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
288 / 318
Semantik Paralleler Programme
Zuweisung: vl | X := t
• X0 = t
• Alle anderen Variablen in vl unverändert: unch(vl \ X )
• Transition nicht blockiert; terminiert nach einem Schritt
No operation: vl | skip
• Alle Variablen in vl unverändert: unch(vl)
• Transition nicht blockiert; terminiert nach einem Schritt
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
289 / 318
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 (if∗ ohne Schritt)
• Falls ε gilt, dann Transitionen von vl | α, sonst von vl | β
Schleife: vl | while ε do α
• Auswertung von ε benötigt einen Schritt (while∗ ohne Schritt)
• Solange ε gilt, Transitionen von vl | α, sonst Terminierung
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
290 / 318
Semantik Paralleler Programme
Synchronisation: vl | await ε
• Auswertung von ε dauert keinen Schritt
• Sobald ε gilt, sofortige Terminierung (kein Schritt)
• Typische Verwendung: await lock = free; lock := used
Setzt das Lock im selben Schritt, in dem der Test gutgeht
• Bis dahin:
• Programm wartet, und gibt anderen parallelen Programmen Vorrang
• Alle Variablen in vl unverändert: unch(vl)
• Transition ist blockiert (Prädikat blocked)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
291 / 318
Semantik Paralleler Programme
Interleaving: vl | α
f
β
• Generell: nächste (nicht blockierte) Transition von α oder β
• Falls beide Programme blockiert, dann Interleaving blockiert:
Deadlock-Prädikat blocked ist wahr (und unch(vl))
• Beim Ausführen entstehen 2 Fälle:
f
• vl | α < β linke Komponente bevorzugt
f
• vl | α > β rechte Komponente bevorzugt
• Wenn die Komponente blockiert ist, wird die andere versucht
f
• vl | α < b β links blockiert, deshalb doch rechts
f
• vl | α b > β rechts blockiert, deshalb doch links
f
f
nicht bei α b > β (um ihn nicht doppelt zu betrachten)
• Der Fall, dass beide blockiert sind, ist nur bei α < b β möglich,
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
292 / 318
Kalkül: Symbolische Ausführung in DL
• Aktuelle Formel redet über ersten Zustand z0
• Ein (Programm)schritt wird ausgeführt.
• Neue Formeln bezieht sich auf den nächsten Zustand z1
• Neue Variable(n) x0 für alten Zustand der zugewiesenen Variable x.
• Nichtzugewiesene Variablen behalten ihren Wert (keine neue
Variable)
Γxx0 , x = τxx0 ` [α]ψ, ∆xx0
assign right
Γ ` [x := τ ][α]ψ, ∆
Grundidee bei TL ist dieselbe: Führe Programme symbolisch aus!
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
293 / 318
Kalkül: Symbolische Ausführung in TL
• Aktuelle Formel redet über Ablauf (z0 , z00 , z1 . . . , zn )
• Ein (Programm)schritt wird ausgeführt.
• Restformel bezieht sich auf den restlichen Ablauf (z1 , . . . , zn ).
• Für jede Variable X (auch nicht zugewiesene!) zwei neue statische
Variablen x0 und x1 die die Werte alten Zustand z0 vor dem
Programmschritt und z00 vor dem Umgebungsschritt merken.
• Randfall: Der Ablauf ist zu Ende (n = 0)
,y0
Pre(x0 , y0 ), x1 = τXx0,Y
, y1 = y0 , [: X, Y | α] ` ?
Pre(X , Y ), [: X, Y | X := τ ; α] ` Env → Prop
tl assign left
Offene Frage: Was tun mit temporallogischen Formeln Env, Prop?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
294 / 318
Symbolische Ausführung: Randfall leerer Ablauf
• Programm ist zu Ende, der Ablauf besteht nur aus z0 .
• Als Formel ausgedrückt: last ist wahr.
• Dann haben X, X0 , X00 alle denselben Wert.
⇒ alle durch neue statische Variable x0 ersetzen.
• Temporalllogischen Formel vereinfachen sich zu PL:
•
•
•
•
2 ϕ, 3 ϕ, ψ until ϕ sind äquivalent zu ϕ
last → (ψ unless ϕ ↔ ψ ∨ ϕ)
last → (• ϕ ↔ true)
last → (◦ ϕ ↔ false)
• In jedem Fall entsteht eine prädikatenlogische Formel
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
295 / 318
Symbolische Ausführung: Nichtleerer Ablauf
• Grundidee: Alle TL-Formeln können zerlegt werden in
• Schritt-Formeln nur über den ersten Schritt (PL mit X , X 0 , X 00 )
• Next-Formeln = Aussagen über den Restablauf (führendes ◦ oder •)
• Beispiel: 2 ϕ ↔ ϕ ∧ • 2 ϕ
ϕ gilt immer gdw. ϕ gilt jetzt, und
”
falls nächster Zustand ex., dann gilt ϕ ab diesem immer“
• Analog: 3 ϕ ↔ ϕ ∨ ◦ 2 ϕ
ϕ until ψ ↔ ψ ∨ ϕ ∧ ◦ (ϕ until ψ)
• Ein symbolischen Ausführungschritt für zerlegte Formeln
• ersetzt X , X 0 , X 00 in Schritt-Formeln durch x0 , x1 , X
• löscht das führende ◦ oder • in Next-Formeln
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
296 / 318
Symbolische Ausführung: Kalkülregeln
• Zerlegung von TL-Formeln in Schritt- und Next-Formeln
und vorwärts step geht immer, auch wenn man kein Programm hat
⇒ generische step-Regel im KIV-Kalkül
• Sonst enthält der Kalkül Regeln analog zu DL:
tl assign left, tl while left, tl if left, tl ipar left etc.
• Die Regeln führen das Programm aus und machen (wo sinnvoll)
einen step.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
297 / 318
Symbolische Ausführung: Beispiele
Beispiele:
• Umgebungsannahme enthält 2 X 0 = X 00 :
⇒ der erste Schritt erhält die Annahme x1 = X und
der Rest des Ablaufs behält 2 X 0 = X 00 als Annahme
• Zu zeigen ist: 2 X > 0
⇒ der Anfangszustand x0 > 0 erfüllen,
und für den Restablauf muss weiterhin 2 X > 0 gelten.
• Es ist also wegen (Konjunktion rechts!) ein PL-Goal für den
aktuellen Zustand + ein Goal für den Restablauf zu zeigen
• Für 3 X > 0 hat man die Wahl: es reicht, x0 > 0 zu zeigen,
man kann aber auch für den Restablauf 3 X > 0 zeigen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
298 / 318
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 00 + 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
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
299 / 318
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)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
300 / 318
Kalkül: Induktion
apply VD induction
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
301 / 318
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 ` ∆
Γ`∆
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
302 / 318
Kalkül: Sequentialisierung
Insert Proof Lemma
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
303 / 318
Demo
(: Programm :)
[: X | fwhile true do { X := 1 }
{ await X = 1; X := 0; }],
(: Umgebung :)
2 X00 = X0 ,
(: Initialisierung :)
X=0
(: Eigenschaft :)
` 2 X ≤ 1;
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
304 / 318
Modulare Spezifikation
und Verifikation
paralleler Programme
mit Rely-Guarantee
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
305 / 318
Motivation
• Ausführung paralleler Programme führt zu einem exponentiell
großem Zustandsraum
• Direkte Beweisstrategie durch explizite symbolische Ausführung aller
möglichen Interleavings ineffizient.
• Heuristiken zur automatischen Ausführung scheitern oftmals schon
an einfachen Beispielen
• Rely-Guarantee (RG) [Jones 1983]: Spezifiziere und verifiziere jeden
Prozess zunächst einzeln ohne die Umgebung zu kennen.
• Erst wenn mehrere Prozesse kombiniert werden, muss geprüft
werden, dass sie verträglich sind.
• Wenn sie verträglich sind, sollte die Korrektheit des Gesamtsystems
folgen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
306 / 318
Grundidee: Rely-Guarantee (1)
• Gegeben: ein Prozess/Thread mit sequentiellem Programm.
• Vor- und Nachbedingung reichen nicht mehr
• Umgebung des Prozesses hat maßgeblichen Einfluss auf dessen
Ausführung
• Um Nachbedingung zu erfüllen muss der Prozess Mindestannahmen
(engl. rely, assumption) an das Verhalten seiner Umgebung treffen
• Diese werden durch ein Prädikat R(S0 ,S00 ) gegeben
• Die Rely R sollte reflexiv (0 Umgebungsschritte) und transitiv
(mehrere Umgebungsschritte) sein.
• Damit verifizierbar: Wenn Rely für alle Umgebungsschritte gilt, dann
erreicht der Prozess sein Ziel (Nachbedingung).
• Die Rely sollte so schwach wie möglich sein, so dass der Prozess
später möglichst flexibel nutzbar ist.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
307 / 318
Grundidee: Rely-Guarantee (2)
• Wenn Prozesse zu einem System kombiniert werden, hat jeder
Prozess i eine Ri (S’,S”), auf die er sich verlässt.
• Die anderen Prozesse müssen diese garantieren.
• Deshalb von Anfang an: Jeder Prozess i definiert eine Prädikat
Gi (S,S0 ) (engl. guarantee oder commitment), was er in seinen
Schritten schlimmstenfalls tut.
• Die Gi muss zusätzlich zur Nachbedingung gezeigt werden.
• Für Prozesse, die nicht terminieren sollen, ist nur die Garantie
wichtig (z.B. sicherer Zustand führt zu sicherem)
• Prozess i und j sind verträglich (im wesentlichen), wenn
Gi (s,s0 ) → Rj (s,s0 ) und Gj (s,s0 ) → Ri (s,s0 )
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
308 / 318
Rely-Guarantee: Spezifikation eines Prozesses
• Jeder Prozess P# wird mit einem RG-Kontrakt spezifiziert:
• (globale) Variablen X, die er modifiziert
• Vorbedingung Pre(X)
• Nachbedingung Post(X)
• (reflexive, transitive) Annahme R(X0 ,X00 )
• Garantie G(X,X0 )
• Der RG-Kontrakt verallgemeint partielle Korrektheit:
“Wenn der Prozess mit Pre gestartet wird, dann macht er nur
G-Schritte, solange die Umgebung nur R-Schritte macht. Ausserdem
gilt, wenn er terminiert Post”
• In der Literatur oft {Pre, R} α {G, Post}
• In KIV als Formel (analog zu DL):
Pre ` [: X | R, G, true, α] Post
• (statt true kann eine Invariante Inv geschrieben werden;
auf den Folien in Zukunft weggelassen)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
309 / 318
Verifikation von RG-Kontrakten
• Für RG-Aussagen gibt es direkte Kalküle (analog zu Hoare-Kalkül)
die keine Temporallogik brauchen.
• Einschränkung: mit RG lässt sich Fortschritt (Terminierung, oder
Erreichen von Zwischenzielen) nicht ausdrücken
• In KIV ist [: X | R, G, α] Post Abkürzung für TL-Formel.
• Idee: Solange sich die bisherigen Umgebungsschritte an R
”
gehalten haben, hält sich der nächste Systemschritt an G .“
≡ ¬ (R(X0 ,X00 ) until ¬ G(X,X0 ))
• Somit ist [: X | R,G,α] Post ≡
[: X | α] → ¬ (R(X0 ,X00 ) until ¬ (last ⊃ Post(X); G(X,X0 )))
• Es gelten damit auch analoge Regeln zum symbolischen Ausführen.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
310 / 318
Zuweisungsregel für RG
tl assign left:
,y0
Pre(x0 , y0 ), x1 = τXx0,Y
, y1 = y0 ` G(x0 ,y0 ,x1 ,y1 )
,y0
Pre(x0 , y0 ), x1 = τXx0,Y
, y1 = y0 , R(x1 ,y1 ,X,Y)
` [: X,Y| R,G,α]Post
Pre(X,Y) ` [: X, Y | R,G,X := τ ;α]Post
Komplizierter als im sequentiellen Fall:
• Guarantee muss zusätzlich gezeigt werden (Prämisse 1)
• zwischen den Schritten des Programms sind Rely-Schritte
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
311 / 318
Kombination von 2 Prozessen
Gegeben 2 Prozesse mit:
Pre1 ` [: X | R1 , G1 , P1 #(; X )] Post1
Pre2 ` [: X | R2 , G2 , P2 #(; X )] Post2
Zu lösen: Welche RG-Kontrakte erfüllt dann P1 #
f
P2 #?
Schon klar: Die Kombination muss verträglich sein:
G1 (s,s0 ) → R2 (s,s0 ) und G2 (s,s0 ) → R1 (s,s0 )
Welche R, G, Pre, Post fsind dann korrekt in
Pre ` [: X | R, G, P1 # P2 #] Post?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
312 / 318
R + G für die Kombination von 2 Prozessen
Welche Annahme ist für P1 #
Was kann P1 #
8. Juli 2013
f
f
P2 # ok?
P2 # maximal garantieren?
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
313 / 318
R + G für die Kombination von 2 Prozessen
Welche Annahme ist für P1 #
f
P2 # ok?
⇒ Umgebung von beiden muss beide erfüllen: R → R1 ∧ R2
Was kann P1 #
f
P2 # maximal garantieren?
⇒ Alle Schritte sind G1 oder G2 Schritte: G1 ∨ G2 → G
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
313 / 318
Pre + Post für die Kombination von 2 Prozessen
Welche Vorbedingung Pre ist ok?
Kann Post := Post1 ∧ Post2 bewiesen werden?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
314 / 318
Pre + Post für die Kombination von 2 Prozessen
Welche Vorbedingung Pre ist ok?
• Notwendig: Pre(s) → Pre1 (s) ∧ Pre2 (s)
• Reicht nicht:
Pre1 (s) ∧ R1 (s,s0 ) → Pre1 (s0 ) und Pre2 (s) ∧ R2 (s,s0 ) → Pre2 (s0 )
müssen gelten (stabile Vorbedingungen)
Kann Post := Post1 ∧ Post2 bewiesen werden?
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
314 / 318
Pre + Post für die Kombination von 2 Prozessen
Welche Vorbedingung Pre ist ok?
• Notwendig: Pre(s) → Pre1 (s) ∧ Pre2 (s)
• Reicht nicht:
Pre1 (s) ∧ R1 (s,s0 ) → Pre1 (s0 ) und Pre2 (s) ∧ R2 (s,s0 ) → Pre2 (s0 )
müssen gelten (stabile Vorbedingungen)
Kann Post := Post1 ∧ Post2 bewiesen werden?
• Ja aber wieder nur für stabile Nachbedingungen:
Post1 (s) ∧ R1 (s,s0 ) → Post1 (s0 ) und Post2 (s) ∧ R2 (s,s0 ) → Post2 (s0 )
Alle 4 Stabilitätsbedingungen sind lokal für einen Prozess. Man prüft man
am besten gleich bei dessen Spezifikation.
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
314 / 318
Theorem für parallele Komposition
` R1 (s, s)
` R1 (s, s0 ) ∧ R1 (s0 , s1 ) → R1 (s, s1 )
` Pre1 (s) ∧ R1 (s, s0 ) → Pre1 (s0 )
` Post1 (s) ∧ R1 (s, s0 ) → Post1 (s0 )
Pre1 ` [: X | R1 , G1 , P1 #(; X )] Post1
` R2 (s, s)
` R2 (s, s0 ) ∧ R2 (s0 , s1 ) → R2 (s, s1 )
` Pre2 (s) ∧ R2 (s, s0 ) → Pre2 (s0 )
` Post2 (s) ∧ R2 (s, s0 ) → Post2 (s0 )
Pre2 ` [: X | R2 , G2 , P2 #(; X )] Post2
` G1 (s, s0 ) → R2 (s, s0 )
` G2 (s, s0 ) → R1 (s, s0 )
Pre1 ∧ Pre2 ` [: X1 | R1 ∧ R2 , G1 ∨ G2 , P1 #(; X )] (Post1 ∧ Post2 )
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
315 / 318
Beispiel: Parallele ggT-Berechnung
{let Done = false, X = 0, Y = 0 in {
while ¬ Done do {
X := NP.1;
Y := NP.2;
if X > Y then NP.1 := X − Y ;
f if X = Y then Done := true}}}
{let Done = false, X = 0, Y = 0 in {
while ¬ Done do {
X := NP.2;
Y := NP.1;
if X > Y then NP.2 := X − Y ;
if X = Y then Done := true}}}
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
316 / 318
Beispiel: gegebene Teile der Kontrakte
• Eingabe ist ein Paar von Zahlen m,n, so dass NP = (m,n)
• Selektion aus dem Paar mit NP.1 und NP.2
• Ausgabe ist auch NP; am Ende sollte NP.1 = NP.2 = gcd(m,n) sein.
• Folgende Prädikate sind vordefiniert:
• Pre1 (m,n)(NP) := NP.1 = m ∧ gcd(m,n) = gcd(NP.1, NP.2)
• Pre2 (m,n)(NP) := NP.2 = n ∧ gcd(m,n) = gcd(NP.1, NP.2)
• Post2 (m,n)(NP) := gcd(m,n) = NP.1 ∧ NP.1 = NP.2
• Schon definiert G1 := R2 und G2 := R1 (schwächstmöglich, so dass
diese Kombination klappt)
• Noch zu finden: R1 und R2
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
317 / 318
Vorgehen zum Finden der Relys
• Beginne mit true als rely.
• Verstärke so, dass Stabilität der Vor- und Nachbedingung gelten
• Beweise alle prädikatenlogischen Beweisverpflichtungen
• Erst dann beweise die beiden Beweisverpflichtungen für P1 und P2
(gehen beide gleich)
8. Juli 2013
G. Schellhorn, D. Haneberg: Formale Methoden im Software Engineering
318 / 318
Herunterladen