##### Document information

Discrete aths

• Objectives – to show the use of induction for proving properties of code involving loops

• use induction to prove that functions work – introduce pre- and post- conditions,

loop termination

2. Loop Invariants

Docsity.com

Overview

1. What is a Loop Invariant?

2. Three simple examples – they involve while loops

3. Selection Sort

4. Further Information

Docsity.com

1. What is a Loop Invariant?

• A *loop invariant* is an *inductive* statement
which says something which is always true
about a program loop.

• Loop invariants are useful for: – code specification – debugging

*continued*
Docsity.com

• A loop invariant is typically written as an inductive statement S(n), where n is some changing element of the loop. For example: – the loop counter/index – a loop variable which changes on each

iteration

Docsity.com

2.1. Example 1

int square(int val) { int result = 0; int counter = 0; while (counter < val) { result += val; counter++; } return result; }

Problem: does this function work?

Docsity.com

Pre- and Post-conditions

• We assume that val is a positive integer
– the *precondition* for this function

• square() always returns val2
– the *postcondition*
– we will use the loop invariant to show that this is

true

Docsity.com

The Loop Invariant

• To make the proof clearer, let countern and resultn be the values of counter and result after passing round the loop n times.

• Loop invariant S(n): resultn = val * countern – is this true in the loop for all n >= 0?

Docsity.com

Basis

• S(0) is when the loop has not yet been executed. – result0 = counter0 = 0

• So: result0 = val * counter0 – which means that S(0) is true.

Docsity.com

Induction

• We assume that S(k) is true for some k >= 0, which means that: resultk = val * counterk (1)

• After one more pass through the loop: resultk+1 = resultk + val (2) counterk+1 = counterk + 1 (3)

*continued*
Docsity.com

• Substitute the rhs of (1) for the 1st operand of the rhs of (2): resultk+1 = (val * counterk) + val

= val * (counterk + 1) = val * counterk+1 (by using (3))

– this is S(k+1), which is therefore true.

*continued*
Docsity.com

• For the loop, we now know: – S(0) is true – S(k) --> S(k+1) is true

• That means S(n) is true for all n >= 0 – for all n >= 0, the loop invariant is true:

resultn = val * countern

Docsity.com

Termination

• The loop does actually terminate, since counter is increasing, and will reach val.

• At loop termination (and function return): countern = val

• So in S(n): resultn = val * val

= val2

• So the *postcondition is true*.
The function

works!! Docsity.com

2.2. Example 2

int exp(int b, int m) // return bm { int res = 1; while (m > 0) { res = res * b; m = m - 1; } return res; }

Problem: does this function work?

Docsity.com

Pre- and Post-conditions

• We assume b and m are non-negative
integers
– the *preconditions* for this function

• exp() always returns bm
– the *postcondition*
– we will use the loop invariant to show that this

is true

Docsity.com

The Loop Invariant

• To clarify the proof, let resn and mn be the values of res and m after passing round the loop n times.

• Loop invariant S(n): resn * bmn = bm – is this true in the loop for all n >= 0?

Inventing this is the hardest part.

Docsity.com

Basis

• S(0) is when the loop has not yet been executed. – res0 = 1; m0 = m

• So: 1 * bm = bm – which means that S(0) is true.

Docsity.com

Induction

• We assume that S(k) is true for some k >= 0, which means that: resk * bmk = bm (1)

• After one more pass through the loop: resk+1 = resk * b (2) mk+1 = mk - 1 (3)

*continued*
Docsity.com

• Rearrange the equations: resk = resk+1 / b (2’) mk = mk+1 + 1 (3’)

• Substitute the right hand sides of (2’) and (3’) into (1):

( resk+1 / b ) * b(mk+1 + 1 ) = bm which is

resk+1 * b(mk+1 + 1 - 1 ) = bm which is

resk+1 * bmk+1 = bm

*continued*
Docsity.com

• S(k+1) is: resk+1 * bmk+1 = bm (4)

• So we have shown S(k+1) is true by using S(k).

*continued*
Docsity.com

• For the loop, we now know: – S(0) is true – S(k) --> S(k+1) is true

• That means S(n) is true for all n >= 0 – for all n >= 0, the loop invariant is true:

resn * bmn = bm

Docsity.com

Termination

• The loop does actually terminate, since m is decreasing, and will reach 0.

• At loop termination (and function return): mn = 0

• So in S(n): resn * b0 = bm

so resn = bm
• So the *postcondition is true*.

The function works!!

Docsity.com

2.3. Example 3

int factorial(int num) { int i = 2; int fact = 1; while (i <= num) { fact = fact * i; i++; } return fact; }

Problem: does this function work?

Docsity.com

Pre- and Post-conditions

• We assume num is a positive integer
– the *precondition* for this function

• factorial() always returns num!
– the *postcondition*
– we will use the loop invariant to show that this is

true

Docsity.com

The Loop Invariant

• To clarify the proof, let factn and in be the values of fact and i after passing round the loop n times.

• Loop invariant S(n): factn = (in - 1)! – is this true in the loop for all n >= 0?

Docsity.com

Basis

• S(0) is when the loop has not yet been executed. – i0 = 2; fact0 = 1

• So: fact0 = (i0 - 1)! 1 = (2 - 1)!

1 = 1

which means that S(0) is true.

Docsity.com

Induction

• We assume that S(k) is true for some k >= 0, which means that: factk = (ik-1)! (1)

• After one more pass through the loop: factk+1 = factk * ik (2) ik+1 = ik + 1 (3)

*continued*
Docsity.com

• Substitute the rhs of (1) for the 1st operand of the rhs of (2): factk+1 = (ik - 1)! * ik

= (ik)! = (ik+1 - 1)! (by using (3))

– this is S(k+1), which is therefore true.

*continued*
Docsity.com

• For the loop, we now know: – S(0) is true – S(k) --> S(k+1) is true

• That means S(n) is true for all n >= 0 – for all n >= 0, the loop invariant is true:

factn = (in - 1)!

Docsity.com

Termination

• The loop does actually terminate, since i is increasing, and will reach num+1.

• At loop termination (and function return): in = num+1

• So in S(n): – factn = (in - 1)!

= (num + 1 - 1)! = num!
• So the *postcondition is true*.

The function works!!

Docsity.com

3. Selection Sort void selectionSort(int A[], int num)

{ int i, j, small, temp; for (i=0; i < num-1; i++) { small = i; for( j= i+1; j < num; j++) if (A[j] < A[small]) small = j; temp = A[small]; A[small] = A[i]; A[i] = temp; } }

swap A[small] and A[i]

put index of smallest value in A[i .. num-1]

into small

Docsity.com

Execution Highlights

A 0 1 2 3

25 30 20 10

Start 1st iteration:

A 0 1 2 3

25 30 20 10

sorted

A 0 1 2 3

25 30 20 10

sorted

Start 4th iteration: A 0 1 2 3

25 30 20 10

sorted

Start 2nd iteration:

Start 3rd iteration:

selectionSort(A, 4);

Docsity.com

Pre- and Post-conditions

• We assume num is a positive integer, which
contains the number of elements in the array
– the *precondition* for this function

• selectionSort() sorts the array into ascending
order
– the *postcondition*
– we will use the loop invariant to show that this is

true

Docsity.com

3.1. Consider the Inner Loop

small = i; for( j= i+1; j < num; j++) if (A[j] < A[small]) small = j;

Put index of smallest value in A[i .. num-1] into small

Docsity.com

Pre- and Post-conditions

• We assume i is a positive integer, which is an
index into the array
– the *precondition* for this part of the code

• This code finds the index of the smallest value
in A[i..num-1]
– the *postcondition*
– we will use the loop invariant to show that this is

true

Docsity.com

The Inner Loop Invariant

• To clarify the proof, let smalln and jn be the values of small and j after passing round the loop n times.

• Loop invariant S(n): smalln is the index of the smallest

of A[i .. jn-1] – is this true in the loop for all n >= 0?

Docsity.com

Execution Highlights A 0 1 2 3

25 30 20 10 Start 1st pass: small 0

j A 0 1 2 3

25 30 20 10 small 0

j A 0 1 2 3

25 30 20 10 small 2

j A 0 1 2 3

25 30 20 10 small 3

j

Start 2nd pass:

Start 3rd pass:

Start 4th pass: loop ends

Docsity.com

Basis • S(0) is when the loop has not yet been

executed. – small0 = i; j0 = i+1

• So: small0 is the index of the smallest of A[i .. j0-1] which is A[i..(i+1-1)], or A[i..i], or A[i]

• That means that S(0) is true.

Docsity.com

Induction

• We assume that S(k) is true for some k >= 0, which means that: smallk is the index of the smallest

of A[i .. jk -1]

• The pass through the loop involves two possible branches because of the if.

*continued*
Docsity.com

• *Case 1*. If A[jk] is *not* smaller than the
smallest of A[i.. jk -1]
– then smallk+1 = smallk (no change)

• *Case 2*. If A[jk] is smaller than the smallest
of A[i.. jk -1]
– then smallk+1 = jk

*continued*
Docsity.com

• At the end of the pass: – smallk+1 is the index of the smallest of A[i..jk] – jk+1 = jk + 1

• S(k+1) is: – smallk+1 is the index of the smallest of A[i .. jk+1-1]

• So S(k+1) is true.

*continued*
Docsity.com

• For the inner loop, we now know: – S(0) is true – S(k) --> S(k+1) is true

• That means S(n) is true for all n >= 0 – for all n >= 0, the inner loop invariant is true:

smalln is the index of the smallest of A[i .. jn -1]

Docsity.com

Termination

• The loop does actually terminate, since j is increasing, and will reach num.

• At loop termination: jn = num

• So in S(n): – smalln is the index of the smallest

of A[i .. jn-1], or A[i..num-1]
• So the *postcondition is true*.

The inner loop is proved.

Docsity.com

3.2 The Outer Loop

void selectionSort(int A[], int num)
{
int i, j, small, temp;
for (i=0; i < num-1; i++) {
* small = i;
for( j= i+1; j < num; j++)
if (A[j] < A[small])
small = j;
* temp = A[small];
A[small] = A[i];
A[i] = temp;
}
}

proved

Docsity.com

The Outer Loop Invariant

• To clarify the proof, let im be the value of i after passing round the loop m times.

• Informal loop invariant T(m): im indicates that we have selected m of the

smallest elements and sorted them at the beginning of the array.

Docsity.com

Graphically

A 0

Sorted <

m m-1

current sort position i

num-1

e.g.

10 12 15 20 22 21 19

i

m

smaller values in array

larger values in array

Docsity.com

More Formally

• Loop invariant T(m): – a) A[0..im-1] are in sorted order;

– b) All of A[im..num-1] are >= all of A[0..im-1]

Docsity.com

Basis

• T(0) is when the loop has not yet been executed. i0=0 – a) Range is A[0..-1], which means no

elements. – b) Range is A[0..num-1] which means

everything > A[0..-1]

• So T(0) is true.

Docsity.com

Induction

• We assume that T(k) is true for some k >= 0, which means that: – a) A[0..ik-1] are in sorted order;

– b) All of A[ik..num-1] are >= all of A[0..ik-1]

*continued*
Docsity.com

• By the end of the inner loop, we know
that A[small] is the smallest element in
A[ik..num-1]
– the *postcondition of the inner loop*

• The next three lines swap A[small] and A[ik] – now A[ik] contains the smallest element

*continued*
Docsity.com

Graphically

A 0

Sorted <

k k-1

current sort position ik

num-1

10 12 15 20 22 21 19

ik

k

small

swapped

small e.g.

*continued*
Docsity.com

• By the end of the outer loop, we know: – a) A[0..ik] are in sorted order;

– b) All of A[ik+1..num-1] are >= all of A[0..ik]

– ik+1 = ik +1

• This shows that T(k+1) is true.

*continued*
Docsity.com

• For the outer loop, we now know: – T(0) is true – T(k) --> T(k+1) is true

• That means T(m) is true for all m >= 0 – a) A[0..im-1] are in sorted order;

– b) All of A[im..num-1] are >= all of A[0..im-1]

Docsity.com

Termination

• The outer loop does actually terminate, since i is increasing, and will reach num-1.

• At loop termination (and function return): im = num-1

*continued*
Docsity.com

• So in T(m): – a) A[0..im-1] are in sorted order – so A[0..num-1-1] is sorted – so A[0..num-2] is sorted

– all the array up to the last element is sorted

*continued*
Docsity.com

– b) All of A[im..num-1] are >= all of A[0..im-1] – so, A[num-1..num-1] >= all A[0..num-1-1] – so, A[num-1] >= all A[0..num-2]

– so the last element is bigger than all the other array elements

• So the function does sort the array into
ascending order: *the postcondition is true*

Docsity.com

4. Further Information

• *Discrete Mathematics Structures in
Computer Science*
B. Kolman & R. C. Busby
Prentice-Hall, 1987, 2nd ed.
Section 1.6

Docsity.com