Formale Spezifikation

Werbung
96
5. Theorem-Beweisen
• Vor.: formale Spezifikation und formale Semantik der Programmiersprache
• Idee: formaler Beweis, dass Programm Spezifikation erfüllt
• notwendig: Unterstützung durch (semi-automatisches) Beweis-Werkzeug
(Theorem-Prover (sonst unklar, ob Beweis korrekt)) bzw. Model-Checker
• häufig verwendete Theorembeweiser: Isabelle/HOL, PVS
• heutiger Stand: in Entwicklung
• geeignet insbesondere bei extrem sicherheitskritischen Anwendungen
97
Programmverifikation am Beispiel der Sprache IMP
Syntax der einfachen, imperativen Sprache IMP
• Z ganze Zahlen; z, z 0, z1, z2, . . .
• IB := {true, f alse} boolesche Werte; β, β1, β2
• Operationssymbole Op := Aop ∪ Bop ∪ Relop
= {+, −, ∗, . . .} ∪ {∨, ∧, ¬} ∪ {==, <=, . . .}
• V ar Variablen; x, y, x0, y 0, . . .
• Aexp arithm. Ausdrücke; e, e0, e1, e2, . . .
• Bexp bool. Ausdrücke; b, b0, b1, b2, . . .
• Com Anweisungen; c, c0, c1, c2, . . .
98
Syntax von IMP (Forts.)
• Mengen Z, IB, Op, V ar vorgegeben
• Mengen Aexp, Bexp, Com gemäß folgender Backus-Naur-Form (BNF)
Aexp : e ::= z | x | e1 ⊕ e2
⊕ ∈ Aop
Bexp : b ::= true | false | e1 e2 | ¬b | b1 ⊗ b2
mit ∈ Relop, ⊗ ∈ Bop − {¬}
Com :
c ::= skip | x := e | c1; c2 |
if b then c1 else c2 | while b do c
99
Beweis von Programmeigenschaften
• Zusicherungen (assertions) der Form
{A}
|{z}
Vorbedingung
c
{B}
|{z}
Nachbedingung
• hier: Zusicherungen partieller Korrektheit:
? nach erfolgreicher (terminierender!) Ausführung von c in einem Zustand,
der A erfüllt, erreicht man einen Zustand, der B erfüllt
• alternativ: Zusicherung totaler Korrektheit [A] c [B]:
partielle Korrektheit + Termination
100
Zusicherungssprache Assn
Aexpv : a::= z | x | i | a1 ⊕ a2
Assn :
i ∈ Intvar (Integervariable)
A::= true | false | a1 a2 | A1 ⊗ A2 |
¬A1 | A1 ⇒ A2 | ∀i.A | ∃i.A
(∼ Prädikatenlogik 1. Stufe)
• jede Integer-Variable “muss zu einem Quantor (∃, ∀) gehören”
(keine freien Integer-Variablen!)
• Notation: |= A:
A “ist wahr” (unabhängig von Belegung der Variablen)
Vor.: formale Semantik von A
101
Beweisregeln für partielle Korrektheit (Hoare-Logik)
• Syntax-orientiert
1) {A} skip {A}
2) {B[x/e]} x := e {B}
3)
{A} c1 {C}, {C} c2 {B}
{A} c1; c2 {B}
4)
{A ∧ b} c1 {B}, {A ∧ ¬b} c2 {B}
{A} if b then c1 else c2 {B}
5)
{A ∧ b} c {A}
{A} while b do c {A ∧ ¬b}
|= (A ⇒ A0) {A0} c {B 0}
6)
{A} c {B}
|= (B 0 ⇒ B)
(Konsequenz-Regel)
102
Hoare-Logik (2)
• mit den Beweisregeln können Theoreme
über das betrachtete Programm bewiesen werden
Schreibweise:
` {A} c {B}
für {A} c {B} ist ein Theorem.
Satz:
Sei {A}c{B} eine Zusicherung partieller Korrektheit.
Wenn ` {A}c{B}, dann |= {A}c{B}
(ohne Beweis)
Bemerkung: Die Umkehrung gilt nicht
(→ Gödel’scher Unvollständigkeitssatz!)
103
Beispiel: Hoare-Logik
Beispiel:
P:
while x>0 do (y:= x*y; x:= x-1)
zeige: P berechnet n! (falls x = n, y = 1)
genauer: {x = n ∧ y = 1 ∧ x ≥ 0} P {y = n!}
wähle: Inv := y ∗ x! = n! ∧ x ≥ 0 als Invariante für while-Schleife
nach Regel 5) für while-Schleife und Lemma (s.u.): {Inv} P {Inv ∧ x ≤ 0}
weiter: x = n ∧ n ≥ 0 ∧ y = 1 ⇒ Inv
≡ y ∗ x! = n! ∧ x ≥ 0 ∧ x ≤ 0
⇒ y ∗ x! = n! ∧ x = 0
⇒ y ∗ 0! = n!
⇒ y = n!
und Inv ∧ x ≤ 0
insgesamt mit der Konsequenzregel 6):
{x = n ∧ n ≥ 0 ∧ y = 1} P {y = n!}
2
104
Lemma: {Inv ∧ x > 0} y:= x*y; x:=x-1 {Inv}
Beweis:
{
Inv[x/(x − 1)]
|
{z
}
} x:= x-1 {Inv}
→ 2) *
=y∗(x−1)!=n! ∧ (x−1)≥0
weiter:
{x ∗ y ∗ (x − 1)! = n! ∧ (x − 1) ≥ 0} y:= x*y {Inv[x/(x − 1)]} → 2) **
nach * und ** mit Regel 3) für Sequenz:
{x ∗ y ∗ (x − 1)! = n! ∧ (x − 1) ≥ 0} y:= x*y; x:= x-1 {Inv}
weiter: nach Def. “!”, Komm. u. Ass. von “*”, “≥”
Inv ∧ x > 0 ⇒ x ∗ y ∗ (x − 1)! = n! ∧ (x − 1) ≥ 0
{Inv ∧ x > 0} y:= x*y; x:= x-1 {Inv}
→ 6) 2
105
Bemerkung:
• die Schleifen-Invariante muss “stark genug” gewählt werden
(Wertebereich der Variablen einschränken!)
• bei Sequenzen von rechts nach links vorgehen
• Korrektheitsbeweise sind meist nicht-trivial (→ autom. Beweisen)
Herunterladen