0% found this document useful (0 votes)
37 views

Loop Invariant Extra Exercises

The document contains two problems proving the correctness of algorithms using loop invariants: 1) It proves that a function for summing array elements is correct by using a loop invariant stating that the sum variable equals the sum of the first i elements, and i is between 0 and the array size n. 2) It proves that insertion sort is correct by using a loop invariant stating that the first i elements are in order, the elements are originally from the array, and i is between 1 and the array size n. The invariant is used to show each iteration maintains the properties.

Uploaded by

djouabidir2003
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
37 views

Loop Invariant Extra Exercises

The document contains two problems proving the correctness of algorithms using loop invariants: 1) It proves that a function for summing array elements is correct by using a loop invariant stating that the sum variable equals the sum of the first i elements, and i is between 0 and the array size n. 2) It proves that insertion sort is correct by using a loop invariant stating that the first i elements are in order, the elements are originally from the array, and i is between 1 and the array size n. The invariant is used to show each iteration maintains the properties.

Uploaded by

djouabidir2003
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Loop Invariant Extra Exercises

Jim Glenn

January 21, 2020

1
Problem 1 Prove with a loop invariant that the the following function correctly sums the
elements in the array passed to it.

def sum(A, n):


i = 0
sum = 0
while i < n:
sum = sum + A[i]
i = i + 1
return sum

Preconditions:

• A is an array of real numbers (indexed starting from 0),


• n is the size of the array A (so n is an integer such that n ≥ 0)

Pn−1
Postcondition: sum = k=0 A[k]

Solution We use the following invariant:

Pi−1
(a) sum = k=0 A[k] (that is, sum is the sum of the first i elements of A)
(b) i is an integer such that 0 ≤ i ≤ n

Basis/Initialization:

(a) sum and i are initialized to 0 and with i = 0, i−1


P
Pi−1 k=0 A[k] = 0 because the sum is empty,
so sum = k=0 A[k] since both are equal to 0.
(b) i is initially 0, which is an integer, and 0 ≤ 0 = i. Also, i = 0 ≤ n by the precondition
on n. Putting those together gives 0 ≤ i ≤ n.

Induction: Suppose the invariant is true before one iteration of the loop and the guard i < n
is true.

Piold −1
(a) Since the invariant is true before the loop, we have sumold = k=0 A[k]. The first
Piold −1
statement inside the loop sets sumnew = sumold + A[iold ] = k=0 A[k] + A[iold ] =
Piold
k=0 A[k]. The second statement sets Pinew = iold + 1. Substituting that into the result
new −1
of the first statement gives sumnew = ik=0 A[k], which is part (a) of the invariant
with the new values of the variables.

2
(b) By the invariant, iold is an integer such that 0 ≤ iold ≤ n. Since the guard is true,
iold < n, which is equivalent to iold ≤ n−1 since i and n are integers. So 0 ≤ iold ≤ n−1
and 0 ≤ iold < iold + 1 ≤ n. Since the second statement in the loop sets inew = iold + 1,
we can rewrite that as 0 ≤ inew ≤ n, which is part (b) of the invariant with the new
values of the variables.

Termination: i increases each time through the loop, so eventually i ≥ n and the guard
becomes false to terminate the loop.

Postcondition: The falsity of the guard when the loop terminates means that i ≥ n. Part
(b) of the invariant says i ≤ n. The only way i ≥ n and iP
≤ n can both be true is if i = n.
n−1
Plug that into part (a) of the invariant yields sum = k=0 A[k], which is the required
postcondition for the function.

Problem 2 Prove that insertion sort is correct, using the invariant from class.

InsertionSort(A, n)
i = 1
while i < n
insert A[i] into correct location among A[0], ..., A[i-1]
i = i + 1

The ”insert...” line is either an inner loop or, as we will treat it, a call to a function insert(A,
i) that, given an array with the first i elements in sorted order, modifies A so that its first
i + 1 elements are unchanged but are reordered to be sorted, and does not change any of the
other elements in A (so insert has preconditions 1) A is a non-empty array of real numbers,
2) 0 ≤ i < len(A), and 3) A[0] ≤ · · · ≤ A[i − 1]; and postconditions 1) A[0] ≤ · · · ≤ A[i],
2) those 1st i + 1 elements are unchanged but may be reordered, and 3) the elements after
them are unchanged). (Fun exercise: write insert and prove that it is correct using a
loop invariant. This is how we tackle nested loops: treat the innermost loop as a separate
function, prove that it does what it is supposed to do, and then work on the next outer
loop.)

Preconditions:

• A is a non-empty array of real numbers

• n is the size of A (so n is an integer such that n ≥ 1)

3
Postcondition: A[0] ≤ · · · ≤ A[n − 1] and A has the same elements as before (but possibly
in a different order).

Invariant:

(a) A[0] ≤ A[1] ≤ · · · ≤ A[i − 1]


(b) A[0], . . . , A[i − 1], are the original first i elements of A, possibly in a different order
(c) A[i], . . . , A[n] contain their original values
(d) i is an integer such that 1 ≤ i ≤ n

Solution Basis:

(a) i is initialized to 1, and when i = 1 part (a) is vacuously true


(b) i is initialized to 1 and there are no assignments to A before the loop, so A[0] has its
original value, which is part (b) of the invariant when i = 1.
(c) There are no assignments to A before the loop, so A[1], . . . , A[n − 1] all have their
original values, which is part (c) of the invariant when i = 1.
(d) i is initialized to 1, which is an integer. The precondition on n yields n ≥ 1. So
i = 1 ≤ n. Relaxing 1 = i to 1 ≤ i and combining with i ≤ n yields 1 ≤ i ≤ n.

Induction: Suppose the invariant is true before an iteration of the loop and that the guard
i < n is also true.

(a) By part (a) of the invariant, A[0]old ≤ · · · ≤ A[iold − 1]old , and by part (d) and the
guard, 0 ≤ iold < n. Those are the preconditions for the call insert(A, i), so after
that call we have A[0]new ≤ · · · ≤ A[iold ]new by the postconditions of insert. By the
last statement in the loop, we have inew = iold + 1, so we can rewrite the previous
results as A[0]new ≤ · · · ≤ A[inew − 1]new , which is part (a) of the invariant using the
new values of the variables.
(b) By part (b) of the invariant, A[0]old , . . . , A[iold −1]old are the original first iold values from
A in some order. From part (c), A[iold ]old is its original value. Now the postcondition
of insert says those elements are reordered but not changed, so the new values are
the original first iold + 1 = inew values from A in some order, which is part (b) of the
invariant with the new values of the variables.
(c) By part (c) of the invariant, A[iold + 1], . . . , A[n] are their original values. There are no
assignments to them in the loop, and the postcondition of insert guarantees that they
are not changed. So they still hold their original values. Rewriting using inew = iold + 1
yields A[inew ], . . . , A[n] have their original values, which is part (c) of the invariant
using the new values of the variables.

4
(d) 0 ≤ iold ≤ n by part (d) of the invariant. iold < n since the guard is true and
hence iold ≤ n − 1 since i and n are integers (by the part (d) of the invariant and the
precondition on n respectively). Therefore, 0 ≤ iold < iold +1 ≤ n. Since inew = iold +1,
we can rewrite that as 0 ≤ inew ≤ n, which is part (d) of the invariant with the new
values of the variables.

Termination: i increases each time through the loop, so eventually we have i ≥ n, which
breaks the loop.

Postconditions: When the loop terminates, we have i ≥ n from the guard being false, and
i ≤ n from part (d) of the invariant, so i = n at termination. Substituting n for i into parts
(a) and (b) of the invariant then yields A[0] ≤ · · · ≤ A[n − 1] and A[0], . . . , A[n − 1] are their
original values, reordered, which are the postconditions for sorting A.

Now that we’ve done some work with loop invariants including conditions on the loop coun-
ters, let’s cut that tedious part out. If there is a variable x that is initialized to x = c1 before
the loop, the guard on the loop is x < c2 for some c2 >= c1 , c1 and c2 are integers, and
the only assignment to x inside the loop is x = x + 1 (which is not in any other inner loop
or conditional), then we may conclude that x is always an integer such that c1 ≤ x ≤ c2 ,
and that the loop terminates when x = c2 . (Corollary: under the same conditions, but with
guard P ∧ x < c2 , then the conditions on x still hold, but at the termination of the loop all
we know is ¬P ∨ x = c2 ).

You might also like