Aussagen in EProg

Aussagen werden als Kommentare in den Code geschrieben, sie sind Seiteneffektfrei (i++ is keine Aussage) und befassen sich nur mit den ganzen Zahlen .

Ganze Zahlen

Watch out for integer division in Java. x = 1 then x / 2 = 0 not x > 0 as 2 / 1 = 0 in Java

When undoing division by multiplication watch out for this.

Hoare Triples

A Hoare-Triple is made up of 3 parts:

  • Precondition {P}
  • Anweisung S
  • Postcondition {Q}

We want to be able to show that for a postcondition {Q} our chosen precondition {P} holds. We will use Rückwertsschließen to find a precondition to match our postcondition based on the statements in the Anweisungen.

A Hoare Triple is valid if for any assignments for which P is valid, Q is valid. Otherwise it’s invalid. We can say that for any state where P is true, if Q is true after execution, then the Triple holds.

Precondition for statements x = e

Establish that the postcondition {Q} holds:

{x > a}
y = x + b
{y > c}

We can replace the y in Q to get a Q' = x + b > c and we know x > a thus x > a => x + b > c if and only if a a - b > c. Through systematic replacements we can verify the Triple.

Stronger and weaker Preconditions

If P_1 implies P_2 then we can say that P_1 is a stronger precondition than P_2.

Thus the strongest precondition is false since it implies everything. The weakest precondition

The weakest precondition is true since true only implies true.

Thus if we have to find the weakest precondition for a triple, we want to find the weakest one that still implies the postcondition.

  • if the postcondition is truethen the weakest precondition has to be true as everything implies true and true implies true
  • If the postcondition is false then the weakest and only precondition is false as it’s the only thing to imply false.

Combining Triples

  • {P1} S1 {Q1}; {P2} S2 {Q2}; if .
  • {P1}{P2} S {Q1}; if
  • {P1} S {Q1}{Q2}; if

In the same way:

if we have {P} S1; S2 {Q} iff exists valid {P} S1 {R} and {R} S2 {Q}.

Invarianten bei Ifs

Bei einer Verzweigung:

// {P}
if (a) {
	S1;
} else {
	S2;
}
// {Q}

Muss man zwei Fälle checken:

  • when S1; is executed.
  • when S2; is executed.

Dann kann man mit einem || beide Fälle in der Precondition verbinden:

  • a && precondition1 OR !a && precondition2

Establish Invariant for Loops

Die L.I. muss gelten:

  1. Vor dem Loop gelten
  2. Während dem Loop (nach der Execution des Loop-Bodys)
  3. Nach der Schleife

Wir müssen eine Invariante finden, die diese Bedingungen erfüllt. Diese wird sehr oft anhand der Postcondition zu finden sein.

Die Invariante muss auch nach dem Loop noch die Postcondition implizieren! Deshalb muss sie limits für die counter Variable beinhalten.

Recipe:

k = 5;
i = 0;
result = 1;
while (i < n) {
	result = result * k;
	i = i + 1;
}
return result; // Postcondition {result == 5^n}
  1. Combine Loop Condition and Termination Condition
    1. i <= n (the equality holds as we execute + 1 after the final execution)
  2. Combine Postcondition and Loop Body
    1. result == 5^n becomes result == 5^i
  3. Set conditions for used methods and formulas
    1. k == 5 (this wasn’t in the precondition so it’s important!)

We can find the formula (the way to modify the postcondition into the loop condition) by using a table that looks at internal state over the execution of the loops.

Tips

Keep in mind the loop variable is incremented (or decremented) after the loop body execution, which has to be taken into consideration when writing the invariant! This also affects the final condition: a x < n becomes x <= n and x <= n becomes x <= n + 1!