Martin Ward
1 Transformations
Theorem 1
Proving Termination: If
t0
and
and
S then if
is a
t0
S then if
(2)
If
and
then
join
This
transformed into e
ient algorithms. It also illustrates the appli
ation of the theorem on re
ursive
implementation of statements (Theorem 2) and the renement rules.
2.1 Notation
We use a : : b to represent the sequen
e of integers from a to b in
lusive. If A is an array then
A[a : : b represents the sequen
e of array elements A[a to A[b in
lusive. On the left hand side of an
assignment it indi
ates that A takes on a new value with only those elements
hanged. If m is less
than every element of A[a : : b we write m < A[a : : b. Similarly if ea
h element of A[a : : b is less
than every element of A[a : : b we write A[a : : b < A[a : : b. The array A is sorted if ea
h element
0
An array
A is a permutation
of
(A[a : : b; A [a : : b) =DF 9 : a : : b
perm
a : : b: 8a 6 i 6 b: A[i = A [ (i)
0
sorted and whi h a hieves this end by arrying out a permutation of the elements of the
where
SORTED
and
PERM
This
on
isely expresses what a sorting algorithm is to a
hieve without being biased to any
parti
ular implementation (the dire
t translation: try every possible sorted array until one is found
whi
h is a permutation of the original
annot be regarded as an algorithmparti
ularly if the set
of possible element values is innite!). An important thing to note about this spe
i
ation is that
Theorem 3 provides a simple way to test the
orre
tness of a possible implementation: test that it
renes both
omponents of the
join.
So one way (not ne essarily the learest!) to write a program to sort the array
b > a is:
SORT (a; b)
A[a : : b
Swap
where
A[a := x;
for i := a + 1 to b step 1 do
hxi=hi:(x > A[i 1);
A[i := x od nioj.
A[i
QSORT
(a; b) =
begin p :join PERM (a; b)
t hA[a : : b; pi := hA [a : : b; p i:Q nioj;
SORT (a; p
1); SORT (p + 1; b) end
of QSORT thus:
QSORT
where
PERM
A[a : : p
join
statement).
QSORT :
(a; b) =
begin p :join hA[a : : b; pi := hA [a : : b; pi:perm(A[a : : b; A [a : : b)
t hA[a : : b; pi := hA [a : : b; pi:(A [a : : p 1 6 A [p 6 A [p + 1 : : b) nioj;
SORT (a; p
1); SORT (p + 1; b) end
QSORT
(a; b).
> b (when the array is already sorted) we an use the theorem on re ursive implementation of
A[a : : p
we
We will implement this using a loop: for the loop invariant we weaken the ondition by introdu ing two variables
i; j
to repla e
p.
begin i := a; j := b 1 :
while i 6 j do
fA[a : : i 6 A[b 6 A[j : : bg;
hA[a : : b; i; j i := hA [a : : b; i ; j i:
perm(A[a : : b; A [a : : b) ^ (i > i _ j < j ) ^ (A[a : : i
1 6 A[b 6 A[j + 1 : : b) od;
hA[j + 1; A[bi := hA[p; A[j + 1i; p := j end
To prove that this
orre
tly renes the join above we
an use the theorem on termination of
re
ursion (Theorem 1) to prove that the while loop terminates (rst using the denitional transformation of while to express it as a suitable tail re
ursion). The term max(j
i; 1) is redu
ed at ea
h exe
ution of the body and always >
1 and the body of the loop must terminate.
The invariant plus termination
ondition together prove that the loop establishes A[a : : p
1 6
A[p 6 A[p + 1 : : b. Finally, note that the body of the loop is a renement of: hA[a : : b; i; j i :=
hA [a : : b; i ; j i:perm(A[a : : b; A [a : : b) ^ (i > i _ j < j ) and a loop with this body is a renement of PERM . So by Theorem 3 this is a
orre
t renement of the join.
0
A[j
or de rement
as appropriate.
tests in the inner loop than ne
essary. To ensure the best e
ien
y it is ne
essary to try to split the
array into roughly equal-sized
omponents at ea
h step. Sedgewi
k [4 suggests using the median
of three elements taken from the array as the pivot. The elements being the rst, last and middle
elements in the array. Naturally, this is only sensible when there are at least three elements in the
array. With this
hoi
e the re
ursive program looks like this:
The next stage is to use program transformations to turn this into an e
ient algorithm. First
we resolve the nondetermina
y in the
if
preferen
e to the others (this ensures that the subarrays are more equal in size when there are many
equal elements):
Next we do an entire loop unroll whi h opies the loop into one terminal position:
begin i := a + 1; j := b 2 :
fA[i 6 A[b 1 6 A[j g;
while i 6 j do
if A[i < A[b 1 then i := i + 1;
while i 6 j ^ A[i < A[b 1 do i := i + 1 od
elsif A[j > A[b 1 then j := j 1
else hA[i; A[j i := hA[j ; A[ii; i := i + 1; j := j 1 od;
p := j + 1 end
For the inner while loop we know that A[i + 1 < A[b
1 ) i 6 j be
ause from the loop invariant
A[j > A[b 1. So we
an remove this test from the while. We
an insert a similar loop in the
se
ond arm of the if statement to get:
begin i := a + 1; j := b 2 :
fA[i 6 A[b 1 6 A[j g;
while i 6 j do
if A[i < A[b 1 then i := i + 1;
while A[i < A[b 1 do i := i + 1 od
elsif A[j > A[b 1 then j := j 1
while A[j > A[b 1 do j := j 1 od
else hA[i; A[j i := hA[j ; A[ii; i := i + 1; j := j 1 od;
p := j + 1 end
After the rst inner while loop we have A[i > A[b
1. If we sele
tively unroll the body of the
loop with the extra test A[j > A[b
1 then we
an prune it as follows:
begin i := a + 1; j := b 2 :
fA[i 6 A[b 1 6 A[j g;
while i 6 j do
if A[i < A[b 1
then i := i + 1;
while A[i < A[b 1 do i := i + 1 od;
if A[j > A[b 1 then j := j 1
while A[j > A[b 1 do j := j 1 od
else hA[i; A[j i := hA[j ; A[ii; i := i + 1; j := j 1
elsif A[j > A[b 1
then j := j 1
while A[j > A[b 1 do j := j 1 od
else hA[i; A[j i := hA[j ; A[ii; i := i + 1; j := j 1 od;
p := j + 1 end
At the point we have A[i > A[b
1 and A[j 6 A[b 1 so if we unroll here the body redu
es to
if i 6 j then hA[i; A[j i := hA[j ; A[ii; i := i + 1; j := j 1 . With some simple manipulation,
the body of the rst if
lause be
omes:
5
1 od;
i6j
exit an be removed.
loop by initialising to
is true initially and true at the end of the loop body, so the rst test for
inversion:
begin i := a; j := b 1 :
fA[i 6 A[b 1 6 A[j g;
do do i := i + 1;
if A[i > A[b 1 then exit od;
do j := j 1;
if A[j 6 A[b 1 then exit od;
if i > j then exit ;
hA[i; A[j i := hA[j ; A[ii od;
p := j + 1 end
Here we have repla
ed while loops by loops with multiple exits,
for these
onstru
ts are given in [6, their use is argued by Bo
hmann [1 and Taylor [5 among
others.
This is a highly optimised version; the inner loops basi
ally do a single test and in
rement.
However, a simple insertion sort is still more e
ient for small partitions. We
an get the best of
both worlds by using qui
ksort on the large partitions and ignoring small partitions. This results
in a le whi
h is nearly sorted and whi
h
an be sorted e
iently in linear time using insertion
sort. To develop this algorithm repla
e the original SORT spe
i
ation by the following NSORT
(nearly sort):
NSORT
where
nsorted
where
k is the size of the partitions to ignore (with k = 1, NSORT is equivalent to SORT ). With this
b a +1 < k, NSORT is rened by skip. This leads to the following nearly-sorting
begin i; j; v;
:= hi;
AS
AS
do if b a + 1 > k
then j := b(a + b)=2
;
if A[a > A[j then hA[a; A[j i := hA[j ; A[ai ;
if A[a > A[b then hA[a; A[bi := hA[b; A[ai ;
if A[j > A[b then hA[j ; A[bi := hA[b; A[j i ;
hA[j ; A[b 1i := hA[b 1; A[j i;
i := a; j := b 1; v := A[b 1;
do do i := i + 1;
if A[i > j then exit od;
do j := j 1;
if A[j 6 j then exit od;
if i > j then exit ;
hA[i; A[j i := hA[j ; A[ii od;
A[b 1 := A[j + 1; A[j + 1 := v ;
if j a > b j 2
then AS a; AS j ; a := j + 2
else AS j + 2; AS b; b := j
else if AS = hi then exit
else b AS ; a AS od;
for i := a + 1 to b step 1 do
v := a[i; j := i;
7
and
we get
1 od;
Here, the rst loop uses nearly-qui
ksort to get A sorted to within
determined), then the
Bibliography
[1 G. V. Bo
hmann, Multiple exits from a loop without the goto, Comm. ACM 16 (July, 1973),
443444.
[2 D. Gries, The S
ien
e of Programming , Springer-Verlag, New YorkHeidelbergBerlin, 1981.
[3 C. A. R. Hoare, Qui
ksort, Comput. J. 5 (1962).
[4 R. Sedgewi
k, Algorithms , Addison Wesley, Reading, MA, 1988.
[5 D. Taylor, An Alternative to Current Looping Syntax, SIGPLAN Noti
es 19 (De
., 1984), 48
53.
[6 M. Ward, Proving Program Renements and Transformations, Oxford University, DPhil Thesis, 1989.