An example proof using the Hoare rules: Let P be the program: while x > 0 do { y := x*y; x := x - 1 } We wish to prove that P computes n factorial (n!) where we start off in an initial state s such that s(x) = n, n is a non-negative number, and s(y) = 1. More precisely, we want to prove: { x = n ^ n >= 0 ^ y = 1} P {y = n!} We'll need an invariant for the while loop. Let I be the assertion: (y * x! = n!) ^ (x >= 0) This captures the intermediate states -- for each iteration of the while loop, we still have to multiply the accumulator y by x, x-1, x-2, ... 1 which is the same as n!. We're going to need the other condition (x >= 0) to ensure that we get out of the loop. We want to show that I is indeed an invariant, that is: {I ^ x > 0} y := x*y; x := x - 1 {I} or expanding out: {y*x! = n! ^ x >= 0 ^ x > 0} y := x*y; x := x - 1 {y*x! = n! ^ x >= 0} From the assignment rule, working backwards, we have: {y * (x-1)! = n! ^ (x-1) >= 0} x := x - 1 {y*x! = n! ^ x >= 0} Again by the assignment rule, we have: {x * y * (x-1)! = n! ^ (x-1) >= 0} y := x*y {y * (x-1)! = n! ^ (x-1) >= 0} So by sequencing, we have: {x * y * (x-1)! = n! ^ (x-1) >= 0} y := x*y; x := x-1 {y*x! = n! ^ x >= 0} Now: I ^ x > 0 == y * x! = n! ^ x >= 0 ^ x > 0 => y*x! = n! ^ x >= 1 => x * y * (x-1)! = n! ^ (x-1) >= 0 Thus, by the rule of consequence: {I ^ x > 0} y := x*y; x := x-1 {I} So I truly is an invariant for the loop. Now applying the rule for while loops, we get: {I}P{I ^ not(x > 0)} Clearly, (x = n) ^ (n >= 0) ^ (y = 1) => I. To see this: (x = n) => x! = n! (y = 1) ^ (x = n) => y * x! = n! (x = n) ^ (n >= 0) => x >= 0 So, (x = n) ^ (n >= 0) ^ (y = 1) => (y * x! = n!) ^ (x >= 0) In addition: I ^ not(x > 0) == y * x! = n! ^ x >= 0 ^ not(x > 0) => y * x! = n! ^ x = 0 => y * 0! = y = n! So by the rule of consequence, we have: {x = n ^ y = 1} P {y = n!} Tah dah! ----------------------------------------------------------------------- Homework for Wednesday, Oct 1st. Hand your work in in class. Write neatly! 1. Prove using the Hoare rules: { 1 <= n } p := 0; c := 1; while c <= n do ( p := p + m; c := c + 1 ) { p = m*n } 2. Find an appropriate invariant to use in the while-rule for proving the following: { i = y ^ x = 1 } while not(y = 0) do (y := y - 1; x := 2*x) {x = 2^i}