SE 504 Spring 2019
HW #4: Repetition and Invariants
Due: 10pm, Thursday, March 7

{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. Prove this program's correctness:

   |[ con X, Y : int;
      var x,y,z : int;
      {P: X ≥ 0  ∧  Y ≥ 0}
      x,y,z := X,Y,0;
      {loop invariant I: z = 2(Y-y) + (X-x)  ∧  x ≥ 0  ∧  y ≥ 0 }
      {bound function t: 2y + x}
      do x > y  ⟶  x,z := x-1,z+1
      [] y > 0  ⟶  x,y := x+1,y-1; z := z+1
      od
      {Q: z = 2Y + X }
   ]|

In completing the proof, you may appeal to "obvious" theorems of number theory. For example:

m≥0 ∧ n≥0 ∧ (m>0 ∨ n>0) ⇒ m+n > 0

a>0 ⇒ (r>0 ⇒ a×r > 0)

m>n ∧ n≥0 ⇒ m>0

You may also find that Contrapositive (3.61) is useful in showing item (iii) on the loop checklist.


3. (List Reversal)
Prove the correctness of the following program, which reverses a list. Regarding notation,

You may make use of the following axioms and theorems.

For all  b:elem  and  x,y,z : list of elem :
Axiom 1: empty | z = z (empty: left identity of  | )
Axiom 2: z | empty = z (empty: right identity of  | )
Axiom 3: (x | y) | z = x | (y | z) (associativity of  | )
Axiom 4: head.([b] | z) = b (definition of head)
Axiom 5: tail.([b] | z) = z (definition of tail)
Axiom 6: (z ≠ empty) ⇒ (z = [head.z] | tail.z) (universality of head/tail)
Axiom 7a: rev.empty = empty (definition of rev)
Axiom 7b: rev.([b] | z) = rev.z | [b] (definition of rev)
Axiom 8a: length.empty = 0 (definition of length)
Axiom 8b: length.([b] | z) = 1 + length.z (definition of length)
Theorem 1: length.z ≥ 0 (length lower bound)
Theorem 2: (z≠empty) ⇒ (length.z = 1+length.(tail.z)) (length induction)

Here is the program:

  |[ var x, y : list of elem  {x = X};
     y := empty;
     {invariant I: rev.y | x = X}  
     {bound t: length.x}
     do x != empty ⟶ x,y := tail.x, [head.x] | y
     od
     {rev.y = X}                       
  ]| 

4. Apply the replace a constant by a variable heurisic to rewrite the postcondition Q in the program below, which computes the product of the elements of an array of integers. Specifically, replace 0 by the fresh variable k and add the new conjunct k=0 to obtain a stronger postcondition Q'. (Repeating: Replace 0 by k; do not replace #B by k.)

Then take one of the conjuncts of Q' to be a loop invariant and the negation of the other conjunct to be the loop guard. (That is, apply the "delete a conjunct" heuristic.)

Complete the pre-loop assignment command so that k and prod are initialized in such a way as to truthify the loop invariant. Then complete the assignment command forming the loop body so that its execution preserves the truth of the invariant and "makes progress towards termination". (Derive the right-hand side of the assignment to prod via calculation.) To show the latter will require you to describe a bound function, and to show that this function cannot go below zero without falsifying the loop guard may require you to include in the loop invariant a conjunct that imposes lower and upper bounds upon k.

Show your completed program and a proof of its correctness.

   |[ con B : array of int;
      var prod : int;
      var k : int;

      k,prod := ?,?;
      {loop invariant I: ?}
      {bound function t: ?}
      do ? ⟶
         k,prod := ?,?;
      od
      { Q: prod = (×j | 0≤j<#B : B.j) }
   ]|