Thinking about Contracts (HW2)
Another Look at Amortized Analysis
An example: Multi-dequeue
Let's look at the implementation of linear search as given in homework 2:
There are two loop invariants that we can write for this loop:
Let's see why these invariants are correct for this loop.
Look at the first invariant. Is this invariant true when the loop condition
is tested the first time. Clearly it is since i = n-1. Now, if the invariant
is true at the start of an iteration, is it true at the end of that iteration
(just before the loop condition is tested again)?
That is, is -1 ≤ i' && i' ≤ n-1 true at the end of the iteration?
Since i' = i - 1 and we want to show that
-1 ≤ i-1 && i-1 ≤ n-1
0 ≤ i && i ≤ n
Using the assumption that the invariant is true at the start of the iteration,
we assume that i is between -1 and n-1. Can we also state that it is
between 0 and n? In this case, yes, because the loop only runs when i ≥ 0
and i can't be n since i starts at n-1 and is decremented each time the loop
runs. So
0 ≤ i && i ≤ n
is a true statement. (Remember this is stating something about i, not i'.)
Now looking at the 2nd invariant, is i == n-1 || A[i+1] > x true when
the loop condition is tested for the first time? Yes, since i = n -1.
Now if we assume the invariant is true at the start of the iteration,
is the following true at the end of the iteration:
i' == n-1 || A[i'+1] > x
Since i' = i - 1, we need to show the following is true:
i == n || A[i] > x
By our previous argument, i can't ever be n since we're decrementing i
starting from n-1. So for the expression to be true, we have to show
that A[i] > x. We know that the loop runs
since A[i] ≥ x and to get to the end of the iteration, A[i] is not
equal to x, therefore, A[i] > x must be true at the end of the iteration.
(Again, keep in mind you're stating something here about i, not i'.)
Thus, we've shown that both invariants hold at the end of each iteration
if they hold at the start of each iteration.
Thinking about Contracts (HW2)
int find(int x, int[] A, int n)
//@requires 0 <= n && n <= \length(A);
//@requires is_sorted(A, 0, n);
{ int i = n-1;
while (i >= 0 && A[i] >= x)
{ if (A[i] == x) return i;
i = i - 1;
}
return -1;
}
//@loop_invariant -1 <= i && i <= n-1;
//@loop_invariant i == n-1 || A[i+1] > x;
The first invariant is an obvious one that deals the range of the loop
variable itself. (Remember to include the final value of the loop variable
in the invariant.) The second invariant says that when you're at position i,
the element to its right (and all the others to the right since the array
is sorted) is greater than the element you're looking for. Of course, this
doesn't apply the first time you test the loop since you haven't looked
at any elements yet which is why the first part of this invariant is needed.