Posted: Feb 23, 2006
Due: March 9, 2006
You have been given two weeks for this assignment because of an intervening midterm. However, solving the problem in substance before the midterm will help you prepare for the exam as well.
The requirement in this assignment is to develop a program in C or Pascal involving loops that is based on a given invariant and a method for making progress while maintaining this invariant. The resulting program is intended to carry out a particular task. However, to receive a grade for this assignment, it is critical that you design the program based on the given invariant--simply writing any program that does the task will not suffice.
In addition to developing the program, you should also do the following:
The programming task is the one described in the text in Exercise 3.11 and can be restated as follows: to write a function that, given a (sub)array A[m..n] and a value v, rearranges the elements in A[m..n] into two subparts A[m..i] and A[i+1..n] such that all the elements in the first subpart are less than or equal to a given value v and all the elements in the second subpart are greater than or equal to v. Specifically, you should think of m, n and v as being the input arguments to this function, i as being the output and the modifications to the array cells being a side effect. The correctness argument can then be boiled down to one for the body of the function. In particular, for the partial condition part, you should start out by stating a suitable precondition for the point before the body of the function and a postcondition for the point at its end. Clearly, these conditions should involve the program variables A, m, n, v and i.
To keep the assignment simple, assume that the values that you are dealing with are integers. A pictorial depiction of the desired state of affairs when the function finishes its execution appears as part of Exercise 3.11 on page 97. This picture is only suggestive and not a complete description as is made clear below. As explained in Exercise 3.11, this function, which I will refer to as partition, finds utility in a sorting algorithm referred to as quicksort: the quicksort algorithm, that you are not required to implement, consists of partitioning arrays in the manner outlined and then calling quicksort recursively on the two partitions.
As is to be expected, the main part of the partition function will be a loop. You may use one of two loop invariants and an associated method for progressing towards the desired goal while preserving this invariant. These two possibilities are described below. The second one is more involved than the first and so will carry an extra credit of 10%. Of course, there is a hazard in doing it the second way in that you may have more difficulty in getting things right. For this reason, you should choose to do it the second way only if you know what you are doing.
You must clearly state which of the two invariants and method of progress you decide to base your program on.
First Loop Invariant
This loop invariant, and the method for progressing towards the desired goal while preserving this invariant, is the one described in Exercise 3.11. This invariant refers to the values in the array A and to two variables i and k that are indices into the array and whose values may change in the course of executing the program. The relevant invariant can be restated in mathematical notation as follows:
m <= (i + 1) <= k <= (n + 1) and, for all j such that m <= j <= i, it is the case that A[j] < v and for all l such that (i + 1) <= l < k it is the case that A[l] => v and the values in A[m..n] are some permutation of the values in these cells at the beginning of the function body.Read <= as ``less than or equal to'' and => as ``greater than or equal to'' in the above display. Notice that, in this description, m, n and v are intended to represent certain fixed input values and that we have assumed that we have some way of referring to the original values in A[m..n]. The method for making progress is described fairly clearly in the mentioned exercise in the book and I will let you look this up for yourself.
Second Loop Invariant
This loop invariant, and the method of progressing towards the desired goal while preserving this invariant, is the one described in Exercise 3.12. This invariant refers to the array A and to the variables i and j that are indices into this array and whose values, again, change during program execution. The invariant can be stated in mathematical notation as follows:
m <= i,j <= n and, for all k such that m <= k <= i it is the case that A[k] <= v and for all l such that j <= l <= n it is the case that A[l] => v and the values in A[m..n] are some permutation of the original values in these cells.Read <= as ``less than or equal to'' and => as ``greater than or equal to'' in the above display. You should assume that, at the outset, A[m] <= v and A[n] => v. This assumption is satisfied in the context that the function partition is to be used. (If you are curious as to why this is the case, post an article to HyperNews and I will answer it if nobody else does.) If you use this approach, then your function body will most likely have two additional loops and this assumption will also be useful in simplifying the termination condition for these loops. Once again, the method for making progress is described quite clearly in the book and I will let you look this up for yourself.