SE 504 Spring 2020
HW #4: Repetition
Due: 7:20pm, Thursday, February 27

{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:

  1. {P} Sinit {I}, which guarantees that the initialization establishes the loop invariant (just before the loop's first iteration).
  2. {I ∧ Bi} Si {I}   (for each i satisfying 1≤i≤ m), which guarantees that each iteration of the loop preserves the truth of the loop invariant.
  3. [I ∧ ¬BB    Q]   (where BB is B1 ∨ ... ∨ Bm, the disjunction of the loop guards), which guarantees that, if the loop terminates, the postcondition will hold at that time.
  4. [I ∧ BB    t > 0]   (where again BB is the disjunction of the loop guards), which guarantees that, as long as more iterations are to occur, the bound function has not yet descended to its threshold of zero.
  5. {I ∧ Bi ∧ t = C} Si {t < C}   (for each i satisfying 1≤i≤m), which guarantees that each iteration of the loop causes the value of the bound function to decrease.

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 maximum 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 maximum 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 max b.q  =  (MAX i | 0≤i≤p ∨ q≤i<#b : b.i) }
      {bound t: q-p}
      do p ≠ q ⟶
         {I ∧ p≠q}
         if b.p ≤ b.q  ⟶  p := p+1;
         [] b.p ≥ b.q  ⟶  q := q-1;
         fi
         {I}
      od
      {Q: 0≤p<#b  ∧  b.p = (MAX i | 0≤i<#b : b.i) }
   ]|

In doing the proof, you may find useful these theorems with respect to the max operator:

  1. (x ≥ y) = (x = x max y) (This defines max.)
  2. (x = x max y) ∨ (y = x max y)
  3. x = x max x

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. As in lecture, it is expected that all modifications made to array elements are as a result of calls to a swap() method that interchanges the values in two specified locations of the array.

   
   |[ var b : array of T;
      var k,m : int;
      {P: (∀i | 0≤i<#b : isRed(b.i) ∨ isWhite(b.i) ∨ isBlue(b.i)) }
      k,m := ?, ?;
      { Loop invariant I: 0≤k≤r≤m≤#b ∧
         (∀i | 0≤i<k : isRed(b.i)) ∧
         (∀i | r≤i<m : isWhite(b.i)) ∧
         (∀i | m≤i<#b : isBlue(b.i))
      }
      { bound function t: ?? }
      do ? ⟶
         ???
      od
      {Q: 0≤k≤m≤#b ∧
          (∀i | 0≤i<k : isRed(b.i)) ∧
          (∀i | k≤i<m : isWhite(b.i)) ∧
          (∀i | m≤i<#b : isBlue(b.i))
      }