Sie sind auf Seite 1von 36

Übung 05

Hoare-Logik

Software
Engineering

Hoare-Kalkül

• Formales System mit logischen Regeln um Korrektheit von Programmen


nachzuweisen

• Semantik

• Nicht einfach

• Fehleranfällig

2
Lernziele

• Kennenlernen der Hoare-Logik und deren Regeln

• Anwenden der Regeln zur Veri kation kleiner Programme

• Verständnis, wie werkzeugbasierte Programmveri kation funktioniert um


entsprechende Tools nutzen zu können

3
fi
fi
{P} S {Q}
Precondition Postcondition

• Korrektheit des Programms (Q) unter den Vorbedingungen (P)

• S ist partiell korrekt, wenn Q erfüllt ist wenn S terminiert

• S ist total korrekt wenn es partiell korrekt ist und immer terminiert

4
Beispiele
{x 0}
y = x*x;
valid
{y > 0}
{x > 0}
x = y;
invalid
{x > 0}
{x ≥ 0}
y = 2*x;
invalid
{y > x}
{y ≥ x} valid

5

Elementare Mathematik
• Angenommen wir wollen • In der Regel benötigen wir
folgendes für Integer beweisen:
weitere Theorien, z.B. Arithmetik
mit Integern, um die Korrektheit
{x > 0} A {y ≥ 0} von Programmen zu beweisen

• Mit einem Beweis haben wir • Ergebnisse dieser Theorien


jedoch folgendes gezeigt:
übernehmen wir ohne Beweis
und markieren diese mit [EM] für
{x > 0} A {y = z2} “elementare Mathematik”

• Aus der Arithmetik wissen wir: • Beispiel: y = z2 implies y ≥ 0 [EM]


aus y = z2 folgt y ≥ 0

6
Variablen

• logische Variablen (zustandsfrei)

• Programmvariablen (ändern Wert während Ausführung des Programms)

• Abstraktion des Programmzustands durch Logik

7
Motivation
x y
{n ≥ 0}
4 1
x = n;
• Eingabe: n (Integer)

3 4
y = 1;

while (x 0) {
• Was wird hier berechnet?
2 12

1 24
y = y * x;

• y = n!

x = x - 1;
0 24

} • Wie können wir das beweisen?


{y = n!}

8

Motivation
x y
{n ≥ 0}
4 1
x = n;

y = 1;
• Symbolische Berechnung, welche Werte die 3 4
Variablen über den Programmverlauf annehmen 2 12
while (x 0) {
können

1 24
y = y * x;

x = x - 1;
• Zusicherungen über Werte von Variablen im 0 24
Programm aufschreiben und beweisen
}
{y = n!}

9

Zusicherungen
Vorbedingung

{n ≥ 0} (precondition)
x = n;
Eine Zusicherung ist eine
{x ≥ 0 ∧ n ≥ 0 ∧ x = n}
Zwischenliegende
logische Formel an einer Stelle
y = 1;
Zusicherung
{y = 1 ∧ x ≥ 0 ∧ n ≥ 0 ∧ x = n} im Programm. Es wird
while (x 0) { angenommen, dass diese
y = y * x;

x = x - 1;

Formel an dieser Stelle im


} Programm erfüllt ist
Nachbedingung

{y = n!}
(post condition)
10

{P} S {Q}

• Syntaktische Regeln zur Herleitung des Beweises

• Wie oft können wir eine Schleife durchlaufen?

• Iterationen (Schleifen) entsprechen Rekursion, induktiver Beweis

• Induktionsannahme = Invariante

11
Schlussregeln
Prämissen
Konklusion

• Regeln ohne Prämisse: Axiome

• Kalkül: Menge von Regeln

• Beispiel: Modus Ponens p ⟹ q, p


q

12
Hoare-Kalkül
• A0. Zuweisung
• R1. Konsequenzregel

• R0. Konstanzregel
• A3. Kompositionsregel

• A1. Schwächere Nachbedingung


• A5. Bedingungsregel

• A2. Stärkere Vorbedingung


• A4. Schleifenregel

Die Regeln A* sind aus der


Vorlesung bekannt, die
Regeln R* werden neu
13 eingeführt!
A0. Zuweisung
{P[e/x]} x = e {P}
• x ist eine Variable, e ein Ausdruck ohne Seitene ekte

• P[e/x]: Substitution von x durch e in P

{5 < 10} {E = x} {x+1 = n+1} {y > z-2}


x = 5;
v = E;
x = x+1;
x = x+1;

{x < 10} {v = x} {x = n+1} {y > z-2}

{x+1 < 10} {y = 2} {y > 0} {2*x = a}


x = x+1;
x = 2;
x = y;
x = 2*x;

{x < 10} {y = x} {x > 0} {x =a}


14
ff
A0. Zuweisung (Arrays)
{P [if k=i then e/a[k] else a[k]/a[k]]} a[i]=e {P}

Wenn i=3, dann folgt


{ (3=i ∧ 2=2) ∨ (3 i ∧ a[3]=2) } durch die Zuweisung
a[i] = 2;
a[i]=2, dass {a[3]=2}
{ a[3] = 2 } nach der Zuweisung
erfüllt ist.

Wenn i 3, dann muss
die Zusicherung {a[3]=2}
bereits vor der
15 Zuweisung gelten.


R0. Konstanzregel {P} A {Q}, FV(R) ∩ modi es(A) = ∅
{P ∧ R} A {Q ∧ R}
• "Was wir nicht ändern bleibt so wie es ist"

• FV: Freie Variablen

• modi es(A): Variablen, denen A Werte zuweist


{y = 3} {bob.age = 65} {∀y 0: y2 > 0}
x = 5;
tony.age = 78;
y = y+1;

{y = 3} {bob.age = 65} {∀y 0: y2 > 0}

Scope der Variablen beachten!


Nur wenn bob tony

16


fi

fi
A1. Schwächere Nachbedingung
{Q ⟹ R},{P}S{Q}
{P} S {R}

{(x>0) ⟹ (x≥0)},{P}S{x>0}
{P} S {x ≥ 0}

17
A2. Stärkere Vorbedingung
{P ⟹ Q},{Q}S{R}
{P} S {R}

{(x>0) ⟹ (x≥0)},{x≥0}S{Q}
{x > 0} S {Q}

18
R1. Konsequenzregel
P‘ ⟹ P,Q ⟹ Q’,{P} A {Q}
{P‘} A {Q‘}

P’ P Q Q’ P Q
{(x>0) ⟹ (x≥0)}, {(y>3) ⟹ (y≥0)} ,{x≥0} S {y>3}
{x > 0} S {y ≥ 0}
P’ Q’

19
A3. Kompositionsregel {P} A {Q}, {Q} B {R}
{P} A; B {R}

• Sequenz von Anweisungen

{x > 0} {x > 0}
x = x+3; x = x+3;
{x > 0} {x > 0}
{x > 3} {x > 3}
x = x+3; x = x+3;
{x ≥ 3} (A1)
x = x+1; x = x+1;
{x > 3} {x ≥ 3}
{x > 4} {x ≥ 4}
x = x+1; x = x+1;
{x > 4} {x ≥ 4}
20 Alle verwendeten Regeln angeben!
A5. Bedingungsregel {P ∧ c} A {Q}, {P ∧ ¬c} B {Q}
{P} if (c) then A else B end {Q}

{P}
if (c) then

{P ∧ c}

• Beide Zweige enden in der A;


selben Nachbedingung Q {Q}
else
{P ∧ ¬c}
B;

{Q}
end
{Q}
21
A5. Bedingungsregel {P ∧ c} A {Q}, {P ∧ ¬c} B {Q}
{P} if (c) then A else B end {Q}
{y > 0}
if (x > 0) then y = y+x; else y = y-x; end
{y > 0}
{y > 0} if ( x > 0 ) then

{y > 0 ∧ x > 0}
y = y+x;
{y > 0}
else
{y > 0 ∧ x ≤ 0}
y = y-x;

{y > 0}
end
{y > 0}
22
A4. Schleifenregel (Partielle Korrektheit)
{P ∧ c} A {P}
• while-loop
{P} while (c) do A end {P ∧ ¬c}

• Idee:

• Wenn P eine Invariante des Schleifenrumpfs A ist, während c erfüllt ist,


dann ist P eine Invariante der gesamten Schleife.

• Wenn die einmalige Ausführung von A die Invariante P erfüllt, dann


erfüllt die mehrfache Ausführung von A ebenfalls P.

23
A4. Schleifenregel (Partielle Korrektheit)
{P ∧ c} A {P}
• Induktion
{P} while (c) do A end {P ∧ ¬c}

• Bei (natürlicher) Induktion zeigen wir,


dass die gleiche Eigenschaft P für 0 gilt,
{P}
und dass wenn sie für P(n) gilt, daraus
folgt, dass sie für P(n + 1) gilt.
while (c) do
{P ∧ c}
• Analog dazu benötigen wir hier eine
A;

Invariante P, die sowohl vor als auch


nach dem Schleifenrumpf gilt {P}
(dazwischen muss die Invariante nicht end
immer gelten) {P ∧ ¬c}

24
A4. Schleifenregel (Partielle Korrektheit)
{P ∧ c} A {P}
{P} while (c) do A end {P ∧ ¬c}

{x ≤ 10}
{P}
while (x < 10) do
while (c) do
{x ≤ 10 ∧ x < 10}
{P ∧ c}
{x+1 ≤ 10}

A;

x = x+1;

{P}
{x ≤ 10}
end
end
{P ∧ ¬c}
{x ≤ 10 ∧ ¬(x < 10)}
25 Alle verwendeten Regeln angeben!
Was beschreibt eine Schleifeninvariante?

• Zustand des Programms

• Was in vorherigen Iterationen erreicht wurde

• Was in folgenden Iterationen erreicht werden soll

• Stellt das gewünschte Ergebnis dar

26
Wie ndet man eine Schleifeninvariante?

• Kreativität

• Faustregel

• Ausgehend von der Nachbedingung (gewünschtes Ergebnis)

• Umformulierung der Nachbedingung in Abhängigkeit zu den lokalen


Variablen

• … sodass beim Verlassen der Schleife die Invariante der


Nachbedingung entspricht

27
fi
{n ≥ 0} Beispiel
x = n;
Was wissen wir?

x y
y = 1;

{Invariante}
4 1 • Zu Beginn x=n, y=1

3 4
while (x 0) { • Am Ende x=0, y=n!

2 12
{Invariante ∧ (x 0)}
y = y * x;

1 24 • In jeder Iteration:

0 24
x = x - 1;
• y wird größer, x wird kleiner

{Invariante}
} • y hält das Zwischenergebnis

x! * y = n!
{Invariante ∧ ¬ (x 0)}
• x! muss noch berechnet werden

{y = n!}
28 • n! ist das gewünschte Ergebnis



{n ≥ 0}
x = n;
Beispiel
y = 1;

{x! * y = n!}
while (x 0) {
{x! * y = n! ∧ (x 0)}
{(x-1)! * y *x = n!} {x!*y = n! ∧ x=0} // 0!=1
y = y * x;
{y=n! ∧ x=0}
{(x-1)! * y = n!}

x = x - 1;

{x! * y = n!}
}
{x! * y = n! ∧ ¬ (x 0)}
{y = n!} 29 Alle verwendeten Regeln angeben!



{n > 0 ∧ m ≥ 0} Beispiel: n (3 )
m 4

r = 1;
 Was wissen wir?

r s
s = 0;

1 0 • Zu Beginn r=1, s=0

{Invariante}
3 1
while (s<m) { • Am Ende r=nm, s=m

9 2
{Invariante ∧ (s<m)}
27 3
• In jeder Iteration:

r=r*n;

s = s+1;
81 4 • s wird größer, r wird größer

{Invariante}
• r hält das Zwischenergebnis ns

} r*n(m-s) = nm
r = ns • n(m-s) muss noch berechnet werden

{Invariante ∧ ¬(s<m)}
{r = nm}
• nm ist das gewünschte Ergebnis
30
{n > 0 ∧ m ≥ 0}
r = 1;
 Beispiel: n m
s = 0;

{r = ns}
while (s<m) { • s≥m, aber wir benötigen s=m, um von r = ns auf
{r = ns ∧ (s<m)} r = nm zu schließen

{r*n = ns+1}
• Zwei mögliche Lösungen:

r=r*n;

{r = ns+1} • Änderung des Codes: while (s m) do

s = s+1;

• Erweiterung der Invariante: {r = ns ∧ s≤m} 



{r = ns} so dass: s≤m ∧ ¬(s<m) ⟹ s=m
}
{r = ns ∧ ¬(s<m)}
{r = nm} 31

A4. Schleifenregel (Totale Korrektheit)
{P ∧ c ∧ (V in D) ∧ V=z} A {P ∧ (V in D) ∧ V<z}
{P ∧ (V in D)} while (c) do A end {P ∧ ¬c ∧ (V in D)}

• Terminierung allgemein nicht entscheidbar (Halteproblem)

• D ist eine Domäne (z.B. Integer) mit Ordnung (z.B. "<")

• V nimmt Werte aus dieser Domäne an

• Mit jeder Iteration wird V kleiner: {V=z} A {V<z}

• Wenn V einen Grenzwert erreicht hat, dann terminiert die Schleife

• V ist eine Schleifenvariante


32
A4. Schleifenregel (Totale Korrektheit)
{y = 0 ∧ x ≥ 0}
{x+y = xold ∧ x≥0}
{P ∧ c ∧ (V in D) ∧ V=z} A {P ∧ (V in D) ∧ V<z}
{P ∧ (V in D)} while (c) do A end {P ∧ ¬c ∧ (V in D)}
while (x>0) {
{x+y = xold ∧ x≥0 ∧ x>0}
{x=z ∧ x>0}
{x-1 < z}
Invariante: {x+y = xold ∧ x≥0}
y = y + 1;

Variante: x
{x-1 < z}
x = x – 1;

{x+y = xold ∧ x≥0}


{x<z}
}
{x+y = xold ∧ x≥0 ∧ ¬(x>0)}
xold speichert Eingabewert von x
{y = xold} 33
P: {Dividend>=0 , Divisor>0}
public Result dividiere(int Dividend, int Divisor){
Result r = new Result();

r.Quotient = 0;

r.Rest = Dividend;

while(Divisor<=r.Rest){
r.Rest = r.Rest-Divisor;
{x>=0, y>0}
r.Quotient = r.Quotient+1;
q = 0;

} r = x;

return r;
while(y<=r) {
}
r = r-y;
Q: {r.Quotient = Dividend/Divisor, r.Rest = q = q+1;
Dividend%Divisor} }
{q = x/y, r = x%y}

34
{x>=0, y>0}
{x>=0, y>0, 0=0, x=x} EM
x y q r
Invariante: x = r + q*y
q = 0;
Variante: r-y
13 3 0 13
{x>=0, y>0, q=0, x=x} A0

r = x;
13 3 1 10 {r-y=z, y≤r, y>0}
{x>=0, y>0, q=0, r=x} A0, A3
{r-y-y<z}
13 3 2 7 A0

{x = r+q*y} A4
r = r-y;

while(y<=r) { 13 3 3 4
{r-y<z} A0

{x = r+q*y, y<=r} A4
13 3 4 1 q = q+1;

{x = r-y+q*y+y} A0, EM
{r-y<z}
r = r-y;

{x = r+(q+1)*y} A0, A3

q = q+1;
{x = r+q*y} A4

}
{x = r+q*y, y>r} A4

{x>=0, y>0} R0

{q = x/y, r = x%y} EM 35 Alle verwendeten Regeln angeben!


Zusicherungen in Java

Enabling runtime evaluation of assertions: java -ea ...36

Das könnte Ihnen auch gefallen