CSE 127: Lecture 14

The topics covered in this lecture include the sort procedure from the previous lecture, it is rewritten here to make it easy for you to go through the rest of the lecture.Then, under the heading loop invariants and mathematical induction, we prove that this sort procedure is correct.

Sort Procedure

1.  void sort(int *arr, int nelt) {
2.      int mid, smallix, bigix, t;
3.      if (nelt <= 1) return;
4.
5.      mid = arr[0];
6.      smallix = 0;
7.      bigix = nelt;
8.
9.      while (smallix < bigix) {
10.         while (smallx < nelt && arr[smallix] <= mid)
11.             ++smallix;
12.         while (bigix > 0 && arr[bigix-1] > mid)
13.             bigix--;
14.         if (!(smallix==nelt || 0 == bigix || smallix == bigix)) {
15.             t = arr[smallix];
16.             arr[smallix] = arr[bigix - 1];
17.             arr[bigix - 1] = t;
18.         }
19.     }
20.     t = arr[0]; arr[0] = arr[smallix - 1]; arr[smallix - 1] = t;
21.     sort(arr, smallix - 1);
22.     sort(arr + smallix, nelt - smallix);
23. }

Loop Invariants & Mathematical Induction

Basically, there are 2 steps in proving the code correct :-

1) Write the loop invariants and
2) Use induction to show that if the loop invariant is true for ( i ), it is also true for (i  + 1).

In the above sort procedure, the loop invariants are :-

• for all i, 0 <= i < smallix : arr[i] <= mid
• for all i, bigix <= i < nelt :  mid < arr[i]
• there exist phis , for all i, 0 <= i < nelt : phi permutes0..................... nelt -1 such that arr'[phi(i)] = arr[i]
Certain claims that we can make about the procedure :-
• After, every iteration of the outer while loop (line 10), all we are doing is permutting element we are not overwriting them.
• We can pick the identity permutaion( phi0 ) at line 8.
• Line 14, smallix <> nelt , bigix <> 0, smallix <> bigix (<> means "not equal to"), all of these need to hold before we can enter the body of the loop.
Also, need to check whether these conditions hold true :-
• 0 <= smallix             Always true, smallix starts at 0 and always incremented.
• bigix <= nelt             Always true, bigix starts at nelt and always decremented.
• smallix <= bigix        Always true, smallix > bigix, an impossibe case ( Reason: Smallix stops when it has an element >= mid , and bigix stops when it contains an element = mid, at this point smallix and bigix may overlap, but they will never pass each other.)
Conclusion : 0 <= smallix <= bigix <= nelt

Now, apply these predicates to the loop body:

15.             t = arr[smallix];
16.             arr[smallix] = arr[bigix - 1];
17.             arr[bigix - 1] = t;

and we can easily say that the loop maintains a permutation phis relating the current state of the array with its initial state phi0.

What do we know about the outer while loop?

smallix = bigix (We know this from the loop invariant)

20.     t = arr[0]; arr[0] = arr[smallix - 1]; arr[smallix - 1] = t;

It is safe to do the swap. Even though it seems that when smallix = 0, smallix -1 will give us -1, means we are accessing arr[-1](which is Incorrect!). But, look at the inner while loop of smallix carefully, and we will notice its going to be executed at least once, so the array range is within bounds.

21.     sort(arr, smallix - 1);
22.     sort(arr + smallix, nelt - smallix);

Similarly, for the above two recursive calls the array range is going to be within bounds.

Finally, by induction hypothesis we can say that the code is correct and the array is going to be sorted.