SE 504 Spring 2022
HW #4: Repetition
Due: 4pm, Friday, March 11

{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 in [1..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]   (or, equivalently, [I ∧ t ≤ 0 ⟹ ¬BB]) (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 in [1..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 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:

  1. Definition of min: (x = x min y) ≡ (x ≤ y)
  2. Theorem Min.1: (x = x min y) ∨ (y = x min y)
  3. Theorem Min.2: x = x min x

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  |
  +-------------+------------+-------------+------------+

   
|[ 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))
   }
]|