Algorithm / Program Verification

An important use of mathematical induction is to prove the correctness of algorithms. Because we will use induction in this way repeatedly over the course of the term I wrote up this sample proof for you.

The idea is that we will annotate an algorithm or program with statements that assert what is true at that point in the program. We will also provide these algorithm with conditions on the input and output (sometimes as expressed as pre-conditions and post-conditions). These are statements about the input to the algorithm and about the final values of variables after the program has been executed.

We illustrate with a program to raise numbers to powers:

Algorithm Power(base, exp);
Inputs:  base (integer), exp (non-negative integer);
Outputs:  Answer (integer)

begin
	Answer := 1;
	base' := base;
	exp' := exp;
	while exp' > 0 do {INV1}
		if odd(exp') then
			Answer := Answer * base';
			exp' := exp' - 1
		else
			base' := base' * base';
			exp' := exp' div 2
		end
	end
end  {POST1}
The comments {INV1} and {POST1} show where the invariant and post-condition in the program belong. The actual statements are as follows:
INV1:  Answer * base'exp' = baseexp & exp' >= 0

POST1:  Answer = baseexp
Thus the post-condition asserts that the algorithm really does compute the value of raising the first argument to the power given by the second argument.

How can we prove the post-condition is true? It is a little tricky since we don't know in advance how many times we will go through the loop of the program (it depends on the value of exp). However, it turns out that if we know the invariant is always true when the program comes to the top of the while loop, it is easy to show that the post-condition holds. First we show the invariant always holds.

Lemma: Every time that execution reaches the top of the while statement the invariant will be true.

Proof: The proof is by induction (of course) on the number of times the program reaches the top of the while statement.

Base case: n = 1. The first time execution reaches the top of the while loop, Answer = 1, base' = base, and exp' = exp. As a result, Answer * base'exp' = 1*baseexp = baseexp. Thus the invariant holds.

Induction case:
Induction hypothesis: Suppose the invariant is true the nth time the program reaches the top of the while statement.

To complete the proof we must show that if the program reaches the top of the while statement n+1 times, then the invariant will be true that (n+1)st time.

The first thing we notice is that we will only get to the top of the while loop the (n+1)st time if exp' > 0 the nth time we are there. Thus, for the rest of the proof, we assume that exp' > 0 at the nth time the program is at the top of the while loop.

By the induction hypothesis, we assume that

	Answer * base'exp' = baseexp & exp' >= 0
the nth time the program is at the top of the while loop. To keep track of the changing values of the variables between the nth and (n+1) st times of reaching the top of the while loop. We write Answerold for the value of Answer at the nth time, and Answernew for the value the (n+1)st time. Note that by the previous remark, we are also allowed to assume that exp'old > 0. Thus in reality we will use:
	Answerold * (base'old)(exp'old) = baseexp & exp' > 0
There are two cases, depending on which branch of the if statement is executed:

Case i: odd(exp'old) is true - i.e. exp'old is odd. Then it follows from the code that:

	Answernew = Answerold * base'old,
	base'new = base'old, 
	exp'new = exp'old - 1.
Thus
 
Answernew * (base'new)(exp'new) 
	= (Answerold * base'old) * (base'old)(exp'old - 1)
	= Answerold * (base'old)(exp'old)
	= baseexp
where the last equality follows by the induction hypothesis.

Notice also that exp'new = exp'old - 1 > 0 - 1 >= 0.

Thus the invariant holds for the values of the variables when it reaches the top of the while loop for the (n+1)st time.

Case ii: odd(exp'old) is false - i.e. exp'old is even. Then it follows from the code that:

	Answernew = Answerold, 
	base'new = base'old  * base'old, 
	exp'new = exp'old div 2.
Thus
	Answernew * (base'new)(exp'new) 
		= Answerold * (base'old * base'old)(exp'old div 2)
		= Answerold * (base'old)2 * (exp'old div 2)
		= Answerold * (base'old)exp'old
		= baseexp
where the last equality follows from the induction hypothesis.

Note also that

	exp'new = exp'old div 2 
                           > 0 div 2 
                           = 0.
where the inequality follows from the induction hypothesis. Thus exp'new >= 0, as desired, and the invariant again holds for the values of the variables when it reaches the top of the while loop for the (n+1)st time.

End of proof of lemma.

Now we can easily prove that the postcondition holds when the algorithm exits.

Theorem: When the algorithm exits, Answer = baseexp.

Proof: Just before the algorithm exits, it is at the while loop for the last time, and then falls through to the end because exp' > 0 fails.

By the lemma, when it is there for the last time, the invariant holds. Thus

	Answer * base'exp' = baseexp & exp' >= 0
but because we exit, exp' <= 0, as well. It follows from this and the last part of the invariant that exp' = 0. If we write the remaining part of the invariant in reverse we get
    baseexp = Answer * base'exp'
                       = Answer  * base'0
                       = Answer  * 1
                       = Answer
Thus Answer = baseexp, as desired.

End of proof of Theorem

Notice that we proved the Lemma by induction, but induction was not needed for the proof of the theorem.

kim@cs.williams.edu