Partial correctness {P }S {Q} P holds if and S terminates the final state satisfies Q then Total correctness {P }S {⇓Q} if P holds then S is guaranteed to terminate and the final satisfies Q 1 Total correctness rules as for partial correctness, but (p. 192) { P (z+1) ∧ z ≥ 0 } S { ⇓ P (z) ∧ z ≥ 0 } { ∃z.P (z) ∧ z ≥ 0 } while b do S { ⇓ P (0) } where P (z+1) ∧ z ≥ 0 ⇒ b, P (0) ⇒ ¬b. This rule is impractical, I propose [while0t ] {b ∧ P ∧ t=z}S {⇓P ∧ t<z} if P ⇒ t ≥ 0 { P } while b do S { ⇓ ¬b ∧ P } where t is an integer expression and z is a variable that does not appear in P, b, t or S. 2 Total correctness rules [asst ] { P [x7→a] } x := a { ⇓ P } ··· [ift ] ··· { b ∧ P } S1 { ⇓ Q } { ¬b ∧ P } S2 { ⇓ Q } { P } if b then S1 else S2 { ⇓ Q } [while0t ] {b ∧ P ∧ t=z}S {⇓P ∧ t<z} if P ⇒ t ≥ 0 { P } while b do S { ⇓ ¬b ∧ P } where t is an integer expression and z is a variable that does not appear in P, b, t or S. [const ] { P 0 } S { ⇓ Q0 } if P ⇒ P 0 and Q0 ⇒ Q {P }S {⇓Q} 3 EXAMPLE. Proving {x > 0 ∧ x = n} y := 1; while ¬(x = 1) do (y := y ∗ x; x := x − 1) { ⇓ y = n! ∧ n > 0 } Introduce a bound function t = x and a loop invariant INV = (x > 0 ∧ y ∗ x! = n! ∧ n ≥ x). From [asst ] We have INV ⇒ t ≥ 0. Let I = INV ∧ x < z. `t { I[x 7→ x−1] } x := x−1 { ⇓ I } `t { (I[x 7→ x−1])[y 7→ y ∗ x] } y := y ∗ x { ⇓ I[x 7→ x−1] } [compt ] gives 7 x−1])[y 7→ y ∗ x] } y := y ∗ x; x := x−1 { ⇓ I } `t { (I[x → The last precondition is x! z }| { x − 1 > 0 ∧ y ∗ x ∗ (x−1)! = n! ∧ n ≥ x − 1 ∧ x − 1 < z ⇑ ( b ∧ INV ∧ t = z ) = ( x 6= 1 ∧ x > 0 ∧ y ∗ x! = n! ∧ n ≥ x ∧ x = z ) 4 By [const ] `t { b ∧ INV ∧ t = z } y := y ∗ x; x := x−1 { ⇓ INV ∧ x < z } And by [while0t ] `t { INV } while ¬(x=1) do (y := y ∗ x; x := x−1) { ⇓ x=1 ∧ {zINV} } | ⇓ y = n! ∧ n > 0 Also `t { x > 0 ∧ x = n } y := 1 { ⇓ x > 0 ∧ x = n ∧ y = 1 } {z } | ⇓ INV By [const ] and [compt ] `t { x > 0 ∧ x = n } y := 1; while ¬(x=1) do . . . { ⇓ y = n! ∧ n > 0 } ( Remember, INV = x > 0 ∧ y ∗ x! = n! ∧ n ≥ x. ) 5 Proof outlines for total correctness. Example. {x > 0 ∧ x = n} y := 1; { invariant : INV } { boundfunction : x } while ¬(x=1) do ( { ¬(x=1) ∧ (x > 0 ∧ y ∗ x! = n! ∧ n ≥ x) ∧ x = z } { x−1 > 0 ∧ y ∗ x ∗ (x−1)! = n! ∧ n ≥ x−1 ∧ x−1 < z } y := y ∗ x; { (INV ∧ x < z)[x 7→ x−1] } x := x−1 { IN V ∧ x < z } ) { x=1 ∧ INV } { y = n! ∧ n > 0 } Where INV = (x > 0 ∧ y ∗ x! = n! ∧ n ≥ x) 6