4 Spezifikation und Verifikation

Werbung
4 Spezifikation und Verifikation
Program testing can at best show the presence of errors, but never their absence.
—Dijkstra, http://www.cs.utexas.edu/users/EWD
Beware of bugs in the above code; I have only proved it correct, not tried it.
—Donald E. Knuth, http://www-cs-faculty.stanford.edu/∼knuth/faq.html
Da Computerprogramme auch zur Steuerung kritischer Prozesse eingesetzt werden, ist die Korrektheit von Programmen nötig. Korrektheit von Programmen bezieht sich dabei auf:
• syntaktische Korrektheit,
• semantische Korrektheit, sofern das Programm als syntaktisch korrekt erkannt wurde.
Die Korrektzeit eines Programms bezieht sich auf die Zusicherung von Programmeigenschaften. Ein erster Schritt zur Erstellung korekter Programme ist die Spezifikation der Programmeigenschaften und ggf. anschließende Programmverifikation.
Bei der Spezifikation wird genau festgelegt, was das Programm leisten soll. Bei der Verifikation
wird bewiesen, dass die Spezifikation korrekt ist.
4.1 Formale Spezifikation
Formale Spezifikation ist die Voraussetzung für formale Verifikation.
2 Spezifizieren einer Funktion sqrt(x), die einen Wert w liefert, der die folgenden Eigenschaften
für alle Eingaben x ≥ 0 hat:
1. |w2 − x| < ,
2. w ≥ 0.
x
4.1.1 Formale Spezifikation von Funktionen
Mittels Aussagen- oder Prädikatenlogik werden Vor- und Nachbedingungen formuliert, die für
f jeweils erfüllt sind.
• Syntax: Signatur angeben:
f: E →A
1
• Semantik:
– Der Definitionsbereich Df ⊆ E wird durch ein charakterisierendes Prädikat P eingeschränkt:
Df = {x | x ∈ E ∧ P (x)}
P heißt Voraussetzung (precondition, Vorbedingung).
– Das Ergebnis y = f (x) wird durch ein Prädikat Q(x, y) charakterisiert.
Q heißt Effekt (postcondition, Konsequenz, Nachbedingung)
2 Fortsetzung von w = sqrt(x)):
Signatur:
sqrt : R → R
Precondition: (bspw.) P (x) ≡ x ≥ 0
Postcondition: (bspw.) Q(x, y) ≡ |y 2 − x| < ∧ y ≥ 0
Formalsprachliche Formulierung beispielsweise mittels formaler Spezifikationssprache oder
evtl. deklarativer Programmiersprache, z.B. mit Haskell:
sqrt :: Float -> Float
sqrtP x = x >= 0
sqrtQ x y = abs (y * y - x) < eps && y >= 0
x
Für ein automatisiertes Beweisverfahren ist die formale Beschreibung der Effekte von elementaren Anweisungen nötig.
4.1.2 Formale Spezifikation von Anweisungen und
Programmabschnitten
Die Semantik einer Anweisung (bzw. eines Programmabschnitts) S wird durch einen Anfangszustand z angegeben, der vor Ausführung der Anweisung gültig ist, sowie einen Endzustand z 0 ,
der nach Ausführung gültig ist. z, z 0 ∈ Z mit Z als Menge aller Zustände.
S: Z → Z
• Als Precondition wird ein charakteristisches Prädikat P für den Anfangszustand angegeben: P (z)
• Als Postcondition wird ein Prädikat Q für das Ergebnis des Zustandsübergangs von z
nach z 0 angegeben: Q(z, z 0 ).
2 Die Anweisung S operiere auf einem Feld int[] a = new int[n], das mindestens eine
positive Zahl b enthält. Nach Ausführung von S sollen alle Feldelemente gleich b sein. Beachte:
Irgendein positives b genügt!
• Der Zustandsraum A wird durch alle Kombinationen der möglichen Werte der Feldelemente a[i] (i = 0 . . . n − 1) bestimmt.
2
• Semantik:
– Precondition:
P (a) ≡ ∃n−1
i=0 a[i] > 0
– Postcondition:
n−1 0
Q(a, a0 ) ≡ ∃n−1
i=0 (a[i] > 0 ∧ ∀k=0 a [k] = a[i])
x
4.1.3 Eigenschaften von Spezifikationen
Es bezeichnet (P, Q) die Spezifikation einer Anweisung, eines Programmabschnitts oder eines Algorithmus S. P bestimmt die erlaubten Zustände vor Ausführung von S. Q bezeichnet
die Effekte, die S nach sich zieht.
• Z (Zustandsmenge)
• (P, Q) (Voraussetzung P und Effekt Q)
Man möchte später beweisen, dass der Algorithmus S korrekt arbeitet (die Spezifikation erfüllt).
Man unterscheidet
• Partielle Korrektheit: Wenn S terminiert, dann liefert er ein korrektes Ergebnis, d.h. hat
den gewünschten Effekt.
• Totale Korrektheit: Der Algorithmus S terminiert und liefert ein korrektes Ergebnis.
Mögliche Sonderfälle:
• (true, Q): S (terminiert und) bewirkt Q ohne Voraussetzung“.
”
• (P, true): Unter der Voraussetzung P bewirkt S irgendetwas“.
”
• (P, P ): P ist Invariante unter S, d.h. S ist ohne Wirkung bzgl. P .
Auszuschließende Sonderfälle:
• (false, Q): Voraussetzung ist nicht erfüllbar.
• (P, false): Effekt ist nicht erfüllbar, S terminiert nicht.
Hierzu zwei Definitionen:
Definition. Eine Spezifikation (P, Q) heißt konsistent, wenn
1. ∃z ∈ Z : P (z), d.h. P ist erfüllbar, P 6≡ false,
2. ∀z ∈ Z : (P (z) ⇒ ∃z 0 ∈ Z : Q(z, z 0 )), d.h. wenn P erfüllt ist, ist Q erfüllbar.
PQ (z) ≡ ∃z 0 ∈ Z : Q(z, z 0 ) heißt schwächste Voraussetzung (weakest precondition) für Q.
3
Definition. Eine Spezifikation (P, Q) heißt vollständig, wenn es zu jedem Zustand z, der die
Voraussetzung P erfüllt, genau einen Effekt Q gibt, der aus der Ausführung von S resultiert:
∀z ∈ Z : P (z) ⇒ |{z 0 : z 0 ∈ Z, Q(z, z 0 )}| = 1.
2 Z = R, (P, Q) = (z > 0, |z − z 0 2 | < ) ist konsistent, denn
• es existiert ein z ∈ R mit z > 0,
√
• für jedes z > 0 erfüllt z 0 := z sogar |z − z 0 2 | = 0.
P ist eine schwächste Voraussetzung PQ (z) ≡ ∃z 0 ∈ Z : |z − z 0 2 | < , allerdings
ist z > 0
√
unnötig stark, da z ≥ 0 bereits genügt. (P, Q) ist nicht vollständig, denn ± z sind erlaubt,
ferner alle Näherungswerte im Intervall (z 0 − , z 0 + ).
x
Definition. Eine Spezifikation (P1 , Q1 ) heißt stärker als (P2 , Q2 ), in Zeichen (P1 , Q1 ) ⇒
(P2 , Q2 ), wenn
Q1 ⇒ Q2 ∧ P1 ⇐ P2 .
Das bedeutet: Eine Anweisung, die der Spezifikation (P1 , Q1 ) genügt, genügt auch (P2 , Q2 ).
Beachte: Q1 ⇒ Q2 muss für alle möglichen Zustände erfüllt sein, d.h.
Q1 ⇒ Q2 := ∀z,z0 ∈Z Q1 (z, z 0 ) ⇒ Q2 (z, z 0 ).
4.2 Formale Verifikation
Problemstellung: Gegeben ist eine Spezifikation (P, Q) und Implementierung S. Gesucht ist
ein formalisierbarer (und ggf. automatisierbarer) Beweis, dass S die Spezifikation (P, Q) erfüllt.
Idee: Die Wirkung eines Algorithmus, Programmabschnitts oder Programms S wird durch
eine möglichst schwache Vorbedingung (weakest precondition), gegeben durch eine logische
Formel Q, und eine möglichst starke Nachbedingung, gegeben durch eine logische Formel R,
charakterisiert.
Notiert in der Korrektheitsformel:
{P }S{Q}
lies: Wenn die Bedingung P für einen Anfangszustand z erfüllt ist, dann gilt nach Ausführung
von S die Bedingung Q für den Endzustand z 0 , genauer: ∀z, z 0 ∈ Z : P (z) ⇒ wird S in Zustand z gestartet, gilt nach Beendigung von S Q(z, z 0 ). {P }S{Q} wird auch als Zusicherung
(assertion) bezeichnet für S bezeichnet.
Beachte:
1. Es gilt: {P }S{Q} ∧ ((P, Q) ⇒ (P 0 , Q0 )) ⇒ {P 0 }S{Q0 }. Anmerkung: Dies ist eine
andere Notation der weiter unten eingeführten Konsequenzregel (CONS).
4
2. {P }S{Q} schließt nicht aus, dass sogar {P 0 }S{Q0 } mit (P, Q) ; (P 0 , Q0 ) gilt,
d.h. (P 0 , Q0 ) ist stärker als oder nicht vergleichbar mit (P, Q).
Wie bereits geschrieben, unterscheidet man partielle und totale Korrektheit. Hierzu zwei Definitionen:
Definition. Eine Korrektheitsformel {P }S{Q} heißt partiell korrekt, wenn jede terminierende
Berechnung von S, die mit der Voraussetzung P startet, im Effekt Q terminiert.
Definition. Eine Korrektheitsformel {P }S{Q} heißt total korrekt, wenn jede Berechnung von
S, die mit der Voraussetzung P startet, terminiert und in ihrem Endzustand Q erfüllt.
Vorgehen bei der Verifikation: Jedem zusammengesetzten Programmteil wird eine Ableitungsregel zugeordnet, mit deren Hilfe sich aus den Vor- und Nachbedingungen seiner Komponenten die Vor- und Nachbedingung dieses Programmteils gewinnen lässt.
Die Axiome und Ableitungsregeln für elementare und zusammengesetzte Anweisungen einer
Sprache
• bilden eine axiomatische Semantik der Sprache und
• erlauben die formale Verifikation von Programmeigenschaften (Floyd 1967, Hoare
1969ff. Hoare-Kalkül“).
”
I Literaturempfehlungen:
— C.A.R. Hoare: An Axiomatic Basis for Computer Programming. Communications of the
ACM 12/10 (1969) 576-588, 583.
— K.R. Apt, E.-R. Olderog: Programmverifikation. Springer-Verlag, Berlin, 1994.
— E. Fehr: Semantik von Programmiersprachen. Springer-Verlag, Berlin,1989.
4.2.1 Übersicht
Gegeben sei eine Sprache mit folgender Grammatik:
S ::= skip | u := t | S1; S2 | if B then S1 else S2 | while B do S.
Informelle Beschreibung der Semantik der Sprachelemente: skip ist die leere Anweisung,
u ist eine Variable, t steht für einen Ausdruck, B für einen Booleschen Ausdruck. In einer
Zuweisung müssen u und t von demselben Typ sein. S1; S2 ist die Sequenz, d.h. S2 wird
unmittelbar nach S1 ausgeführt. . . (u.s.w. in kanonischer Weise)
Es wird noch folgende Vereinfachung der bedingten Anweisung definiert:
if B then S1 ≡ if B then S1 else skip.
5
{P }skip{P }
(SKIP)
Zuweisungsaxiom:
{P [u := t]} u := t {P }
(ASS)
Sequenzregel:
{P }S1{R}, {R}S2{Q}
{P }S1; S2{Q}
(SEQ)
Skip-Anweisung:
Bedingte Anweisung:
{P ∧ B}S1{Q}, {P ∧ ¬B}S2{Q}
{P } if B then S1 else S2{Q}
Schleife I:
(Partielle Korrektheit)
{I ∧ B}S{I}
{I} while B do S {I ∧ ¬B}
Schleife II:
(Totale Korrektheit)
{I ∧ B}S{I}, {I ∧ B ∧ t = z}S{t < z}, I ⇒ t ≥ 0
{I} while B do S {I ∧ ¬B}
Konsequenzregel:
P ⇒ P 1, {P 1}S{Q1}, Q1 ⇒ Q
{P }S{Q}
(IF)
(WHILE)
(WHILEtot )
(CONS)
Wir nehmen im folgenden an, dass alle Programme syntaktisch korrekt sind.
4.2.2 Zuweisung
Das Zuweisungsaxiom
{P [u := t]} u := t {P }
(ASS)
gilt, sofern die Auswertung von t erfolgreich und ohne Nebenwirkungen ist. Man geht von
der Nachbedingung P und bestimmt daraus durch Rückwärtssubstitution die Vorbedingung
P [u := t].
Andere übliche Schreibweisen: {P [t/u]} u := t {P } und sogar {P [u/t]} u := t {P }.
Vorgehen: Es wird die Nachbedingung P , gefolgt von der Zuweisungsoperation in eckigen
Klammern, hingeschrieben und jedes Vorkommen von u durch den Ausdruck t ersetzt.
2 Behauptung: {true} x := 7 {x = 7}
Beweis: Zu zeigen ist
{true} x := 7 {x = 7}.
Rückwärtssubstitution ergibt
(x = 7)[x := 7] ≡ (7 = 7).
Mit Wertzuweisungsaxiom (ASS) folgt daraus
{7 = 7} x := 7 {x = 7}.
Da zweifellos (true ⇒ (7 = 7)) gilt, folgt mit der Konsequenzregel (CONS)
6
(true ⇒ (7 = 7)), {7 = 7} x := 7 {x = 7}, ((x = 7) ⇒ (x = 7))
{true} x := 7 {x = 7}
Gilt das Obere, kann man das Untere daraus schließen.
x
2 Behauptung: {x > y} x := x − y {x ≥ 0}
Beweis: Rückwärtssubstitution ergibt
(x ≥ 0)[x := x − y] ≡ ((x − y) ≥ 0).
Mit (ASS) folgt:
{(x − y) ≥ 0} x := x − y {x ≥ 0}.
Zweifellos gilt
(x > y) ⇒ x − y ≥ 0.
Mit (CONS) gilt deshalb auch die Behauptung:
((x > y) ⇒ ((x − y) ≥ 0)), {(x − y) ≥ 0} x := x − y {x ≥ 0}
{x > y} x := x − y {x ≥ 0}
Beweis (2. Möglichkeit, von hinten nach vorne“):
”
Mit (CONS):
((x > y) ⇒ ((x − y) ≥ 0)), {(x − y) ≥ 0} x := x − y {x > 0}, ((x > 0) ⇒ (x ≥ 0))
{x > y} x := x − y {x ≥ 0}
Mit (ASS):
{(x − y) > 0} x := x − y {x > 0}
Dies gilt, da
(x > 0)[x := x − y] ≡ ((x − y) > 0).
x
2 Behauptung: {x = X ∧ y 6= 0} x := x/y {x · y = X} für x, y ∈ R
Beweis: Rückwärtsersetzung
(x · y = X)[x := x/y] ≡ ((x/y) · y = X).
Mit (ASS) und (CONS):
?
{x = X ∧ y 6= 0} ⇒ {(x/y) · y = X} x := x/y {x · y = X}
Frage: Gilt die Implikation x = X ∧ y 6= 0 ⇒ x = X?
1. Entweder: Herausfinden durch Überlegen und Argumentieren,
2. oder modifizierte Beweisführung: Geeignetes Verstärken der Nachbedingung von x :=
x/y, z.B.
((x · y = X) ∧ (y 6= 0)) ⇒ (x · y = X).
7
Wir nehmen 2.:
{x = X ∧ y 6= 0}
⇒
{(x/y) · y = X ∧ y 6= 0}
x := x/y
{(x · y = X) ∧ (y 6= 0)}
⇒
{x · y = X}
x
4.2.3 Sequenz
Die Vorbedingung für S2 ist die Nachbedingung von S1:
{P }S1{R}, {R}S2{Q}
{P }S1; S2{Q}
(SEQ)
Kurzschreibweise: Man bildet für eine Korrektheitsformel {P }S{Q} eine Kette der Form
{P }S1{P 1}S2 . . . Sk−1 {Pk−1 }Sk {Q},
wobei für jede Teilfolge der Form
{Pv−1 }Sv {Pv }
gilt: Entweder ist sie eine gültiges Axiom, eine Ableitungsregel oder eine prädikatenlogische
Schlussfolgerung (⇒).
2 Behauptung: {x = y} x := x + 1; y := y + 1 {x = y}
Beweis:
{(x = y + 1)[x := x + 1]}
{x + 1 = y + 1}
{x = y} ⇒
{x = y}
{(x = y)[y := y + 1]}
{x = y + 1}
x := x + 1;
{x = y + 1}
x := x + 1;
{x = y + 1}
{x + 1 = y + 1}
{x + 1 = y + 1}
x := x + 1;
x := x + 1;
{x + 1 = y + 1}
x := x + 1;
x := x + 1;
{x = y + 1}
x
2 Behauptung: {true} h := x; x := y; y := h; {x = Y ∧ y = X}
Beweis: (von unten nach oben nachvollziehen!)
{T }
{y = Y ∧ x = X}
h := x;
{y = Y ∧ h = X}
8
y := y + 1; {x = y}
y := y + 1; {x = y}
(RWSubst)
(ASS)
(RWSubst)
(ASS)
y := y + 1; {x = y}
y := y + 1; {x = y}
(SEQ)
y := y + 1; {x = y}
y := y + 1; {x = y}
(CONS)
x := y;
{x = Y ∧ h = X}
y := h;
{x = Y ∧ y = X}
x
2 Behauptung: Für a, b ∈ N gilt:
{b 6= 0}
q := a / b;
r := a % b;
{a = qb + r ∧ r < b}
Beweis:
{b 6= 0} ⇒
true
z
}|
{
{b > 0 ∧ a = (a/b) · b + a%b}
q := a / b;
{b > 0 ∧ a = qb + a%b}
true
z }| {
{b > 0 ∧ a = qb + a%b ∧ a%b < b}
r := a % b;
{a = qb + r ∧ r < b}
x
4.2.4 Bedingte Anweisung
Unabhängig von B muss nach der Ausführung Q gelten:
{P ∧ B}S1{Q}, {P ∧ ¬B}S2{Q}
{P } if B then S1 else S2{Q}
(IF)
Beweisplan: Zum Beweis von {P } if B then S1 else S2{Q} ist unabhängig zu zeigen:
1. {P ∧ B}S1{Q} und
2. {P ∧ ¬B}S2{Q}
und schließlich
3. die Schlussregel (IF) anzuwenden.
Beachte: Die Auswertung von B darf keinen Effekt (Seiten-/Nebeneffekt) bewirken!
2 Behauptung: {true} if (x > y) then max := x else max := y {max ≥ x ∧ max ≥ y}
Beweis: Mit P ≡ true und B ≡ x > y
9
1. Zu zeigen: {P ∧ B} max := x {max ≥ x ∧ max ≥ y}.
Rückwärtsersetzung und (ASS) ergibt:
{x ≥ x ∧ x ≥ y} max := x {max ≥ x ∧ max ≥ y}
Mit
P ∧B ⇒ x≥x∧x≥y
true ∧ x > y ⇒ x ≥ x ∧ x ≥ y
und (CONS) folgt:
{P ∧ B} ⇒ {x ≥ x ∧ x ≥ y} max := x {max ≥ x ∧ max ≥ y}
2. Gültigkeit von {P ∧ ¬B} max := y {max ≥ x ∧ max ≥ y} wird analog gezeigt.
3. Schließlich: Anwenden der Schlussregel (IF).
Anmerkung: Wieso ist die Nachbedingung Q ≡ (max ≥ x) ∧ (max ≥ y) erfüllbar?
Q ≡ (max ≥ x) ∧ (max ≥ y) ≡ ((max > x) ∨ (max = x)) ∧ ((max > y) ∨ (max = y)))
x
if (x > y) then (max = x) ⇒
else (max = y)
⇒
Q ≡ ((max > x)∨(max = x))∧((max > y)∨(max = y))
Q≡
(false ∨
true)
∧ (true ∨ false)
Q≡
(true
∨ false) ∧ (false ∨ true)
2 Behauptung: {true} if (x < 0) then x := −x else skip {x ≥ 0}
Beweis: (von innen nach außen nachvollziehen!)
{true}
if (x < 0)
{true ∧ (x < 0)} ⇒ {−x ≥ 0}
x := −x
{x ≥ 0}
else
{true ∧ ¬(x < 0)} ≡ {x ≥ 0}
skip
{x ≥ 0}
{x ≥ 0}
x
4.2.5 Schleifen
4.2.5.1 Partielle Korrektheit
Schlussregel zum Beweis der partiellen Korrektheit:
{I ∧ B}S{I}
{I} while B do S {I ∧ ¬B}
10
(WHILE)
• I wird als Invariante bezeichnet, da sie sowohl vor als auch nach Schleifendurchlauf
gültig ist, solange B gilt.
• Mit Verlassen der Schleife gilt ¬B
Beachte: Die Auswertung von B darf keinen Effekt (Seiten-/Nebeneffekt) bewirken!
Allgemeiner Beweisplan für Algorithmen mit while-Schleifen:
{P }
S1
{I}
while B do S
{I ∧ ¬B}
S2
{Q}
Im Einzelnen:
1. Finden einer geeigneten Invariante I und Zeigen der Invarianz, d.h. oberer Teil der
Schlussregel (WHILE):
{I ∧ B}S{I}
2. Zeigen von {P }S1{I} (Initialisierung),
3. Zeigen von {I ∧ ¬B}S2{Q} (Finalisierung).
2 Gegeben: Algorithmus DIV zur Berechnung von Quotient und Rest zweier Zahlen x und y.
Behauptung:
{P } ≡ {x ≥ 0 ∧ y ≥ 0}
q := 0;
r := x;
while (r ≥ y) do
q := q + 1;
r := r − y;
{Q} ≡ {x = q · y + r ∧ 0 ≤ r < y}
Beweis: Wählen einer geeigneten Schleifeninvariante I: Wir wählen ausgehend von Q unter
Weglassen von r < y:
I ≡ x = q · y + r ∧ r ≥ 0.
Zu zeigen sind folgende Fakten:
1. Zu Beginn der Schleife gilt I, d.h. {P } q := 0; r := x {I}.
2. I ist tatsächlich die Schleifeninvariante, d.h. {I ∧ (r ≥ y)} q := q + 1; r := r − y; {I}.
11
3. Terminierung der Schleife impliziert Q, d.h. {I ∧ ¬(r ≥ y)} ⇒ {Q}.
Zu 1.:
Mit (ASS) folgt {x = q · y + x ∧ x ≥ 0} r := x; {I}.
Mit (ASS) folgt {x = 0 · y + x ∧ x ≥ 0} q := 0; {x = q · y + x ∧ x ≥ 0}.
Mit (SEQ) folgt {x = 0 · y + x ∧ x ≥ 0} q := 0; r := x; {I}.
Es gilt offensichtlich {x ≥ 0 ∧ y ≥ 0} ⇒ {x = 0 · y + x ∧ x ≥ 0}.
Mit (CONS) folgt somit tatsächlich {P } q := 0; r := x; {I}.
Zu 2.:
Mit (ASS): {x = q · y + (r − y) ∧ (r − y) ≥ 0} r := r − y; {I}.
Mit (ASS): {x = (q+1)·y+(r−y)∧(r−y) ≥ 0} q := q+1; {x = q·y+(r−y)∧(r−y) ≥ 0}.
Mit (SEQ): {x = (q + 1) · y + (r − y) ∧ (r − y) ≥ 0} q := q + 1; r := r − y; {I}.
Es gilt offensichtlich {I ∧ (r ≥ y)} ⇒ {x = (q + 1) · y + (r − y) ∧ (r − y) ≥ 0}.
Mit (CONS) folgt tatsächlich {I ∧ (r ≥ y)} q := q + 1; r := r − y; {I}.
Zu 3.: Offensichtlich.
x
4.2.5.2 Totale Korrektheit
Schlussregel zum Beweis der totalen Korrektheit:
{I ∧ B}S{I}, {I ∧ B ∧ t = z}S{t < z}, I ⇒ t ≥ 0
{I} while B do S {I ∧ ¬B}
(WHILEtot )
• Hinzugekommene Bedingungen garantieren Terminierung der Schleife.
• Ausdruck t heißt Terminierungsfunktion oder Schrankenfunktion.
• Variable z wird benutzt, um Anfangswert von t festzuhalten.
• z darf nicht in I, B, t oder S vorkommen!
• Zweite Bedingung besagt, dass Wert von t mit jedem Schleifendurchlauf kleiner wird.
• Dritte Bedingung besagt, dass Wert von t nach jedem Schleifendurchlauf nicht-negativ
ist.
2 Gegeben ist der Algorithmus DIV aus dem vorigen Beispiel. Zu zeigen ist die totale Korrektheit
von
{x ≥ 0 ∧ y > 0} DIV {x = q · y + r ∧ 0 ≤ r < y}.
Beweis:
• Wählen der Schleifeninvariante
I 0 ≡ I ∧ y > 0 ≡ x = q · y + r ∧ r ≥ 0 ∧ y > 0.
12
• Wählen der Terminierungsfunktion: t ≡ r
Zu zeigen sind folgende Fakten:
1. {x ≥ 0 ∧ y > 0} q := 0; r := x {I 0 }.
2. {I 0 ∧ (r ≥ y)} q := q + 1; r := r − y; {I 0 }.
3. {I 0 ∧ (r ≥ y) ∧ (r = z)} q := q + 1; r := r − y; {r < z}.
4. I 0 ⇒ r ≥ 0.
5. {I 0 ∧ ¬(r ≥ y)} ⇒ {x = q · y + r ∧ 0 ≤ r < y}.
(Fertigstellung als Übung!)
x
4.2.6 Verifikation rekursiver Prozeduren
Beweis erfolgt durch vollständige Induktion:
• Entweder explizit: beweisen, daß
1. Prozedur total korrekt, falls kein Aufruf (Induktionsvoraussetzung)
2. Prozedur total korrekt, falls die rekursiven Aufrufe terminieren, korrektes Ergebnis
liefern und Parameter sich wie die Funktion t (bei Schleifen) verhalten.
• oder implizit:
1. partielle Korrektheit
2. Termination der Rekursion
2 Gegeben ist eine rekursive Prozedur zur Berechnung von f = n!. Das Ergebnis soll in int f;
stehen.
1
2
3
4
5
6
7
8
9
10
11
void fact(int n)
/* pre: n >=
* post: f =
*/
if (n == 0)
f = 1;
else {
fact(n f *= n;
}
}
{
0 [else non-termination]
n!
1);
1. Beweis durch vollständige Induktion
13
1. n = 0: fact(0) terminiert und bewirkt korrekt f = 1 = 0!.
2. fact(n) sei total korrekt für ein bestimmtes n ≥ 0. Bei Ausführung von fact(n+1)
wird der else-Zweig durchlaufen. Dort terminiert nach Voraussetzung fact(n) mit
f = n!. Nach f *= n + 1 gilt somit f = (n + 1)!. Also terminiert auch fact(n+1)
mit dem richtigen Ergebnis, und damit ist fact(n) total korrekt (für alle n ≥ 0).
2. Beweis der partiellen Korrektheit mittels Hoare-Kalkül
{n ≥ 0}
if (n == 0)
{n = 0}
{1 = n!}
f = 1;
{f = n!}
else {
{n > 0}
{n − 1 ≥ 0}
fact(n - 1);
{f = (n − 1)!}
{n · f = n!}
f = n * f;
{f = n!}
}
{f = n!}
x
14
Herunterladen