 # Reasoning About Code; Hoare Logic, continued

## Presentation on theme: "Reasoning About Code; Hoare Logic, continued"— Presentation transcript:

Reasoning About Code; Hoare Logic, continued

Announcements HW0 was due today
Submit through SVN We will grade your last commit before 2pm HW1 will be available later today after class Check Homeworks page, then update QUIZ 1 today. You have 10 minutes

So Far We discussed Formal reasoning about code: Hoare Logic
Specifications Preconditions and postconditions Forward reasoning and backward reasoning Formal reasoning about code: Hoare Logic Hoare triples Condition strength Rules for assignment, sequence and if-then-else Spring 15 CSCI 2600, A Milanova

So Far Forward reasoning: given a precondition, derive the postcondition Intuitive, simulates the code, collects facts in the direction of program execution Backward reasoning: given a postcondition, derive the precondition Generally less intuitive, collects facts in direction opposite of program execution Spring 15 CSCI 2600, A Milanova

Outline Hoare Logic Rules for assignment, sequence, if-then-else
Rule for method call Reasoning about loops Total correctness = partial correctness + termination Loop invariants Computation induction (to prove partial correctness) Decrementing functions (to prove termination) Spring 15 CSCI 2600, A Milanova

Rule for Assignment { wp(“x=expression”,Q) } x = expression; { Q } Rule: the weakest precondition wp(“x=expression”,Q) is Q with all occurrences of x in Q replaced by expression

Rule for Sequence { wp(S1,wp(S2,Q)) } S1; // statement { wp(S2,Q) }
// find weakest precondition for sequence S1;S2 and Q { wp(S1,wp(S2,Q)) } S1; // statement { wp(S2,Q) } S2; // another statement { Q } Working backwards: precondition is wp(S1;S2, Q) = wp(S1, wp(S2,Q)) Precondition is {true}, which is the weakest preconditions of all. This means the code imposes no restrictions at all.

Exercise { x y > 1 } equiv. to { x + y > 0 } x = x + 1; { x + y > 1 } y = x + y; { y > 1 } Spring 15 CSCI 2600, A Milanova

Rule for If-then-else // wp: ?? if (b) { S1; } else { S2; { Q }
(b ∧ wp(S1,Q)) ∨( b ∧ wp(S2,Q)) b true false wp(S1,Q) wp(S2,Q) S1 S2 { Q } { Q } { Q } Spring 15 CSCI 2600, A Milanova

Exercise { (x>0) ∨ (x=0 ∧ 0>-1) } equiv. { x>=0 }
z = 0 { (x!=0 ∧ x>0) ∨ (x=0 ∧ z>-1) } Precondition: ?? z = 0; if (x != 0) { z = x; } else { z = z+1 } Postcondition: z > 0; x!=0 true false { x > 0 } { z > -1 } z = x z = z+1 { z>0 } { z>0 } { z>0 } Spring 15 CSCI 2600, A Milanova (example due to Michael Ernst, UW)

Why Not This Rule? wp(S1,Q) ∧ wp(S2,Q)
// wp: ?? if (b) { S1; } else { S2; { Q } b true false wp(S1,Q) wp(S2,Q) S1 S2 Precondition is too strong! In example on the previous slide, this precondition cannot be satisfied! { Q } { Q } { Q } Spring 15 CSCI 2600, A Milanova

Why Not This Rule? wp(S1,Q) ∨ wp(S2,Q)
// wp: ?? if (b) { S1; } else { S2; { Q } b true false wp(S1,Q) wp(S2,Q) S1 S2 { Q } { Q } { Q } Spring 15 CSCI 2600, A Milanova

Exercise // precondition: ?? if (x < 5) { x = x*x; } else {
// postcondition: x ≥ 9 Spring 15 CSCI 2600, A Milanova (example due to Michael Ernst, UW)

If-then Statement // precondition: ?? if (y > x) { z = x; x = y;
y = z; } // postcondition: y < x Answer: x!=y Spring 15 CSCI 2600, A Milanova

Rules for Backward Reasoning: Method Call
// precondition: ?? x = foo() // postcondition: Q If method has no side-effects, just like assignment x = Math.abs(y) // postcondition: x = 1 Precondition is y = 1 ∨ y = -1 Method calls make reasoning incredibly hard… Things are a LOT harder here! Spring 15 CSCI 2600, A Milanova

Group Exercise // precondition: ?? y = x + 4 if (x > 0) {
y = x*x – 1; } else { y = y+x; } { y = 0 } x = x/y; // postcondition: Divide-by-zero Find what input causes divide-by-zero at the last statement. Answer: Precondition: x=1 V x=-2 These are the inputs that cause divide-by-zero error

Outline Hoare Logic Rules for assignment, sequence, if-then-else
Rule for method call Reasoning about loops Total correctness = partial correctness + termination Loop invariants Computation induction (to prove partial correctness) Decrementing functions (to prove termination) Spring 15 CSCI 2600, A Milanova

Unknown number of iterations and unknown number of paths. Recursion poses similar issues We cannot enumerate all paths Key is to guess a loop invariant Two things to prove about loops 1. It computes correct values (partial correctness) 2. It terminates (does not go into infinite loop) total correctness = partial correctness + termination

Example: Partial Correctness + Termination
i=x and z=0 give us that i+z = x holds at 0th iteration of loop // Base case Assuming that i+z = x holds after kth iteration, we show it holds after (k+1)st iteration // Induction znew = z and inew = i – 1 thus znew + inew = z i – 1 = z+i = x If loop terminated, we know i = 0. Since z+i = x holds, we have z = x Loop terminates. The precondition x≥0 guarantees i≥0 before loop. At every iteration i decreases by 1, thus it eventually reaches 0. Precondition: x >= 0; i = x; z = 0; while (i != 0) { z = z+1; i = i-1; } Postcondition: x = z; 1. Does x = z hold after the loop? 2. Does loop terminate? Invariant: i + z = x

i+z = x is a loop invariant (a fact that holds true before and after each loop iteration) Even though i and z change, i+z=x stays true We just made an inductive argument over the number of iterations of the loop Computation induction Established that loop invariant holds at 0th iteration Assuming that loop invariant holds after kth iteration, show that it holds after (k+1)st iteration

Partial correctness Establish and prove loop invariant using computation induction Loop exit condition and loop invariant must imply the desired postcondition i = 0 (loop exit condition) and i+z = x imply z = x Termination (Intuitively) Establish “decrementing function” D. D ≥ 0 before loop, each iteration decrements D, D at 0 implies loop exit condition We will discuss Partial Correctness first

Another Example Partial Correctness + Termination
Let us prove that sum is correct: Precondition: len ≥ 0 ∧ arr.length = len double sum = 0.0; int i = 0; while (i < len) { sum = sum + arr[i]; i = i+1; } Postcondition: sum = arr+…+arr[arr.length-1] Spring 15 CSCI 2600, A Milanova

Another Example: Partial Correctness
Σj: 0 to i-1 arr[j] stands for arr+arr+…+arr[i-1] Loop invariant: i <= len ∧ sum = Σj: 0 to i-1 arr[j] 1) i <= len ∧ sum = Σj: 0 to i-1 arr[j] holds before loop 2) Assume sum = Σj: 0 to i-1 arr[j] holds after kth iteration sumnew = sum + arr[i]; inew = i+1; Thus sum = Σj: 0 to i-1 arr[j] holds after (k+1)st iteration i <= len also holds (had we had i = len after kth iteration, there wouldn’t have been a (k+1)st iteration!) i <= len ∧ sum = Σj: 0 to -1 arr[j] is our loop invariant.

Another Example: Partial Correctness
Σj: 0 to i-1 arr[j] stands for arr+arr+…+arr[i-1] 3) (i < len) which is i >= len plus loop invariant i <= len ∧ sum = Σj: 0 to i-1 arr[j] imply sum = Σj: 0 to len-1 arr[j], which with precondition arr.length=len gives us desired postcondition sum = arr+…+arr[arr.length-1] We still must argue termination! i <= len ∧ sum = Σj: 0 to -1 arr[j] is our loop invariant.

Another Example: Termination
Precondition: len ≥ 0 ∧ arr.length = len double sum = 0.0; int i = 0; while (i < len) { sum = sum + arr[i]; i = i+1; } 4) We now argue termination (informally). At each iteration i increases by one, while len stays the same. Thus, eventually i reaches len. i = len implies loop exit condition. More on termination later! Spring 15 CSCI 2600, A Milanova

Partial Correctness, More Formally
{ P } while (b) S { Q } We need to “guess” a loop invariant Inv such that P => Inv // Inv holds before loop. Base case { Inv ∧ b } S { Inv } // Assuming Inv held after kth iteration and execution took a (k+1)st iteration, then Inv holds after (k+1)st iteration (Inv ∧ b) => Q // The exit condition and loop invariant imply desired postcondition Most of the time, we won’t have to use condition b to prove the loop invariant. E.g., we didn’t need it in the first example, and we didn’t need it for the sum part of the invariant in our sum example. But we do need to use b sometimes. We used b to prove that the i <= len part of the invariant holds in the sum example. Remember !b (not b) is the exit condition. Once !b holds, the loop exits. Spring 15 CSCI 2600, A Milanova

Choosing Loop Invariant
What is a suitable loop invariant? Precondition: x >= 0; i = x; z = 0; while (i != 0) { z = z+1; i = i-1; } Postcondition: x=z Inv: i+z = x Spring 15 CSCI 2600, A Milanova

Choosing Loop Invariant
What is a suitable loop invariant? Precondition: x >= 0 & y = 0 while (x != y) { y = y+1; } Postcondition: x=y Inv: y<=x Spring 15 CSCI 2600, A Milanova

Choosing Loop Invariant
What is a suitable loop invariant? Precondition: len ≥ 0 ∧ arr.length = len double sum = 0.0; int i = 0; while (i < len) { sum = sum + arr[i]; i = i+1; } Postcondition: sum = arr+…+arr[arr.length-1] Inv = i <= len ∧ sum = Σj: 0 to i-1 arr[j] Spring 15 CSCI 2600, A Milanova

Choosing Loop Invariant
What is a suitable loop invariant? Precondition: n >= 0 i = 0; r = 1; while (i < n) { i = i+1; r = r*i; } Postcondition: r = n! Inv: i<=n ∧ r = i! i-new = i+1 r-new = r*i-new r-new = (i-new – 1)! * i-new = i-new ! i>=n & i<=n implies i = n Spring 15 CSCI 2600, A Milanova

Termination, More Formally
We must “guess” a decrementing function D Maps state to natural numbers: 0, 1, 2, … { P } while (b) S { Q } We need D, with range in the natural numbers, such that { Inv ∧ b } S { Dafter < Dbefore } //Execution of loop reduces the value of D (Inv ∧ D=0) => b // Inv + D reaching 0 (D’s minimal value), must imply the loop exit condition Spring 15 CSCI 2600, A Milanova

Choosing Decrementing Function
What is a suitable decrementing function? Precondition: x >= 0; i = x; z = 0; while (i != 0) { z = z+1; i = i-1; } Postcondition: x=z D = i Spring 15 CSCI 2600, A Milanova

Choosing Decrementing Function
What is a suitable decrementing function? Precondition: x >= 0 & y = 0 while (x != y) { y = y+1; } Postcondition: x=y D = x - y Spring 15 CSCI 2600, A Milanova

Choosing Decrementing Function
What is a suitable decrementing function? Precondition: len ≥ 0 ∧ arr.length = len double sum = 0.0; int i = 0; while (i < len) { sum = sum + arr[i]; i = i+1; } Postcondition: sum = arr+…+arr[arr.length-1] D = len - i Spring 15 CSCI 2600, A Milanova

Choosing Decrementing Function
What is a suitable decrementing function? Precondition: n >= 0 i = 0; r = 1; while (i < n) { i = i+1; r = r*i; } Postcondition: r = n! D = n - i i-new = i+1 r-new = r*i-new r-new = (i-new – 1)! * i-new = i-new ! i>=n & i<=n implies i = n Spring 15 CSCI 2600, A Milanova

For non-looping code, weakest precondition enables proof For loops, we have to guess The loop invariant The decrementing function Then use the proof techniques we discussed If the proof doesn’t work Maybe you chose wrong invariant/function: Fix Maybe the loop is incorrect! Spring 15 CSCI 2600, A Milanova (slide based on slide by Michael Ernst, UW)

Why Study Formal Proofs
Helps us write correct programs! Most of the time, our loops don’t need proofs for i in seq: print i Sometimes we have to write more complex loops Establish precondition and postcondition Establish a loop invariant Reason about correctness and termination MORE HERE! Spring 15 CSCI 2600, A Milanova

Goal of reasoning about a loop is to prove the loop correct Proving the loop correct entails the usual: (informally) prove that if the precondition holds, after running the loop, the postcondition holds Spring 15 CSCI 2600, A Milanova

total correctness=partial correctness+termination Partial correctness “Guess” and prove loop invariant Loop exit condition and loop invariant must imply the postcondition This gives us: “If the loop terminated then the postcondtion holds”. But does the loop terminate? Termination (Intuitively) “Guess” decrementing function D. Each iteration decrements D, D at its minimum value (usually 0) must imply loop exit condition

Example: Another Factorial
Precondition: n >= 0 r = 1; n = t; while (n != 0) { r = r*n; n = n-1; } Postcondition: r = t! Inv: r = t/n! Spring 15 CSCI 2600, A Milanova (example due to Michael Ernst, UW)

Example: Integer Division x/y
Pre: x >= 0, y >= 0 r = x; q = 0; while (y <= r) { r = r-y; q = q+1; } Postcondition: x = y*q + r ∧ r < y Spring 15 CSCI 2600, A Milanova (example due to Michael Ernst, UW)

Example: Greatest Common Divisor
Precondition: x1 > 0 ∧ x2 > 0 y1 = x1; y2 = x2; while (y1 != y2) { if (y1 > y2) { y1 = y1-y2 } else { y2 = y2-y1; } Postcondition: y1 = gcd(x1,x2) Spring 15 CSCI 2600, A Milanova (example due to Michael Ernst, UW)