{loop invariant I : ... } {bound function t : ... } do B1 ⟶ S1 [] B2 ⟶ S2 [] ... [] Bm ⟶ Sm od |
Consider a Hoare Triple {P} Sinit; LOOP {Q} in which Sinit is an assignment command (used for initialization) and LOOP is a repetition command annotated with a loop invariant and bound function, as in the template to the right.
To prove the Hoare Triple, you show each of the five items on the loop checklist:
Items (i) and (ii) together show that I is, as claimed, an invariant of the loop. Item (iii) shows that, if and when the loop terminates, the postcondition Q holds. Items (iv) and (v) together show that the loop eventually terminates.
Note that any precondition regarding only constants (e.g., N ≥ 0) can be considered to be an implicit conjunct of the loop invariant.
1. Prove that the following program is correct. Notice that the loop guard and the main conjunct of the loop invariant were derived (using the delete a conjunct heuristic) from the strengthened version Q' of the postcondition, which was obtained from the original postcondition Q using the replace a constant by a fresh variable heuristic.
|[ con N : int;
var k,m : int;
{P: N ≥ 0}
k,m := 0,0;
{loop invariant I: m = k2 ∧ 0≤k≤N}
{bound function t: N - k}
do k ≠ N ⟶ k,m := k+1,m+k+k+1
od
{Q': m = k2 ∧ k=N }
{Q: m = N2 }
]|
2. Consider the recursive function f, defined as follows:
f.0 | = | 1 | |
f.1 | = | 2 | |
f.k | = | 2·f.(k−1) − f.(k−2) | (k≥2) |
The program below computes f.N, placing the result in the
variable crrnt. Prove the program's correctness.
|[ con N : int;
var i,crrnt,next : int;
{P: N ≥ 0}
i, crrnt, next := 0, 1, 2;
{loop invariant I: 0≤i≤N ∧ crrnt = f.i ∧ next = f.(i+1)}
{bound function t: N-i}
do i ≠ N ⟶ i, crrnt, next := i+1, next, 2*next - crrnt;
od
{Q: crrnt = f.N}
]|
3. Prove the correctness of the following program, which finds
a minimum element in the integer array b[].
Note that the 2nd conjunct of the loop invariant corresponds to the
statement that either b.p or b.q is the minimum among the values
occurring anywhere in b[0..p] or b[q..#b).
|[ con b : array of int;
var p,q : int;
{P: #b > 0}
p,q := 0, #b-1;
{loop invariant I:
0≤p≤q<#b ∧
b.p min b.q = (MIN i | 0≤i≤p ∨ q≤i<#b : b.i) }
{bound t: q-p}
do p ≠ q ∧ b.p ≥ b.q ⟶ p := p+1;
[] p ≠ q ∧ b.p ≤ b.q ⟶ q := q-1;
od
{Q: 0≤p<#b ∧ b.p = (MIN i | 0≤i<#b : b.i) }
]|
In doing the proof, you may find useful this following definition of, and theorems pertaining to, the min operator:
It is recommended that you prove ¬BB ≡ p=q (equivalently, BB ≡ p≠q) as a lemma, which you could then use in proving items (iii) and (iv).
4. Complete the following program, which performs Red-White-Blue partitioning on an array. You need not provide a proof (as you don't yet have the machinery by which to formally reason about assignments to array elements), but you should justify the choices that you made. Notice that the loop invariant was derived from the postcondition using the replace an occurrence of a variable by a fresh variable heuristic. Specifically, an occurrence of k was replaced by r. All modifications to array elements must be done via calls to a swap() method (e.g., swap(b,i,j)) that interchanges the values in two specified locations of the array. A diagrammatic depiction of the loop invariant is as follows:
0 k r m #b +-------------+------------+-------------+------------+ b | all Red | ? | all White | all Blue | +-------------+------------+-------------+------------+ |
|