Correctness and Invariants¶
Learning objectives¶
- Express an algorithm as a contract.
- Use initialization, maintenance, and termination to justify a loop.
- Distinguish partial correctness from termination.
Contracts¶
A precondition describes valid inputs. A postcondition describes the required output. For a method that returns the maximum element:
- precondition: the sequence is non-empty;
- postcondition: the returned value belongs to the sequence and is greater than or equal to every element in it.
An algorithm is partially correct if its postcondition holds whenever it terminates. It is totally correct if it is partially correct and terminates for every input satisfying its precondition.
A loop invariant¶
Consider this method:
static int maximum(int[] values) {
if (values.length == 0) {
throw new IllegalArgumentException("values must not be empty");
}
int best = values[0];
for (int i = 1; i < values.length; i++) {
if (values[i] > best) {
best = values[i];
}
}
return best;
}
At the start of each iteration with index i, use the invariant:
bestis the maximum ofvalues[0..i).
Initialization: before the first iteration, [0, 1) contains only
values[0], so the invariant holds.
Maintenance: comparing values[i] with best produces the maximum of the
old prefix plus the new element. The invariant therefore holds for the next
prefix.
Termination: when i == values.length, the prefix is the entire array, so
the invariant implies the postcondition.
The loop terminates because i increases and is bounded above by the finite
array length. The variant values.length - i is a non-negative integer that
strictly decreases.
Common proof patterns¶
| Construct | Typical argument |
|---|---|
| Sequential composition | The first postcondition establishes the second precondition |
| Loop | Invariant plus a decreasing variant |
| Recursion | Base case plus an inductive hypothesis on smaller inputs |
| Greedy method | Exchange argument or stays-ahead argument |
| Dynamic programming | Induction over the dependency order of subproblems |
Exercises¶
- State a useful invariant for insertion sort.
- Explain why “the tests pass” is evidence, but not a proof for all inputs.
- Give a partial-correctness argument for a loop that may never terminate.
References¶
See Cormen et al. and Hoare in the bibliography.