Consider the following subprogram, maximum(), which determines the larger of two input parameters passed to it and assigns that value to its lone output parameter.
procedure maximum(in first : int, second : int; out result : int); |[ {pre: first = A ∧ second = B} if first ≥ second —> result := first; [] first ≤ second —> result := second; fi {post: result = A max B} ]| |
Note that maximum() is proper (using Denman's term) in that no input parameters are mentioned in its post-condition and no output parameters are mentioned in its pre-condition. (Input/output parameters, of which there are none in this example, may be mentioned in both pre- and post-conditions.)
Given that maximum() is proper, to show that it is valid requires only that we prove the Hoare triple {pre} S {post}, where S is its body. Using the following definition of the max operator, this is easy (and so we omit it).
Below is a program that uses invocations to maximum() to help it identify the largest element in an array. We focus on those aspects of its correctness proof that involve this subprogram invocation.
|[ con f : array of int; { #f>0 } var big : int; var n : int; n, big := 1, f.0; { loop invariant I: big = (MAX k | 0≤k<n : f.k) ∧ 0≤n≤#f } { bound function t: #f-n } do n ≠ #f —> {I ∧ n≠#f} maximum(big, f.n, big); {I(n:=n+1)} n := n+1; {I} od {Q: big = (MAX k | 0≤k<#f : f.k)} ]| |
As this program is a loop preceded by initialization, we prove its correctness by showing each item in the loop checklist. The only items involving maximum() are (ii) and (v).
Applying the Hoare Triple Catenation Law and the wp Assignment Law, this reduces (as suggested by the annotations in the code) to showing
Supplying the details of I and applying textual substitution, we get the Hoare Triple
{big = (MAX k | 0≤k<n : f.k) ∧ 0≤n≤#f ∧ n!=#f } maximum(big, f.n, big) {big = (MAX k | 0≤k<n+1 : f.k) ∧ 0≤n+1≤#f } |
The second and third conjuncts of the pre-condition simplify to 0≤n<#f. Using this fact, together with
(which is the Law of Conjunctivity), we claim that it suffices to prove the two Hoare Triples
{big = (MAX k | 0≤k<n : f.k) ∧ 0≤n<#f } maximum(big, f.n, big) {0≤n+1≤#f} |
and |
{big = (MAX k | 0≤k<n : f.k) ∧ 0≤n<#f} maximum(big, f.n, big) {big = (MAX k | 0≤k<n+1 : f.k)} |
Consider the first of these. From the fact that the invocation maximum(big,f.n,big) is independent of n and #f (i.e., changes neither of their values), the Independence Theorem tells us that
is valid. But we obtain the first Hoare Triple from this one by strengthening its pre-condition. Hence (by the Strengthening the Precondition Law), the first Hoare Triple is valid.
As for the second Hoare Triple, if we apply Split off Term to the post-condition (justified by the fact that the pre-condition guarantees that 0≤k<n+1 is a non-empty range), we get
{big = (MAX k | 0≤k<n : f.k) ∧ 0≤n<#f} maximum(big, f.n, big) {big = (MAX k | 0≤k<n : f.k) max f.n} |
Denman's Procedure Call Rule says that
{ pre(first, second := big, f.n)(A,B := e0,e1) } maximum(big, f.n, big) { post(result := big)(A,B := e0,e1) } |
is valid, for any choice of expressions e0 and e1 that are independent of the invocation maximum(big, f.n, big). Supplying the details for pre and post, this becomes
{ (first=A ∧ second=B)(first, second := big, f.n)(A,B := e0,e1) } maximum(big, f.n, big) { (result = A max B)(result := big)(A,B := e0,e1) } |
which, applying textual substitution, is
{ (big=A ∧ f.n=B)(A,B := e0,e1) } maximum(big, f.n, big) { (big = A max B)(A,B := e0,e1) } |
{ (big = (MAX k | 0≤k<n : f.k) ∧ f.n = f.n) } maximum(big, f.n, big) { (big = (MAX k | 0≤k<n : f.k) max f.n) } |
The Hoare Triple we seek to prove is obtained from this one by strengthening its pre-condition. Hence, by the Strengthening Precondition Law, we're done.
For reasons that should not need to be explicitly pointed out, this reduces to showing
By the Independence Theorem (and the fact that the invocation maximum(big, f.n, big) is independent of both n and #f), the Hoare Triple
is valid. But the Hoare Triple we seek to show is obtained from this one by strengthening its pre-condition and hence (by the Strengthening the Precondition Law) is also valid.