Weakest Preconditions When constructing proofs of program correctness, one has to come up with appropriate assertion at certain points in the program. For instance, if I want to prove: {P} c1; c2 {Q} I must come up with an appropriate assertion such that {P} c1 {R} and {R} c2 {Q} hold. Although a programmer can often come up with the appropriate assertion {R}, we'd like to know if such assertions always exist and if they can be computed automatically. It turns out that the answer is yes -- such assertions always exist and can be expressed using our assertion language; but the proof is fairly involved and we will omit discussing if (see Winskel for details). The process of finding the assertions that we need for command sequences is related to the notion of _weakest preconditions_. Given a command c and a post-condition Q, we want to find out what is the "best" pre-condition that would give us a valid triple: {?} c {Q} Here, "best" means the assertion that most accurately describes those input states for which c either does not terminate, or else ends up in a state satisfying B. In other words, "best" means "weakest": any other valid pre-condition is stronger than (i.e., implies) this best pre-condition. The weakest precondition of command c and post-condition Q is usually denoted as wp(c,Q). [Note: sometimes it is referred to as weakest "liberal" precondition, written wlp(c,B), where the term "liberal" indicates that it refers to partial correctness and includes the non-termination cases.] We can precisely describe weakest pre-conditions as follows: wp(c,B) is a weakest pre-condition if: forall s: s |= wp(c,Q) <=> C[[c]] not defined for s or C[[c]]s |= Q A closer look at this formula reveals that the left-to-right implication says that wp(c,Q) is a valid pre-condition: |= {wp(c,B)} c {Q}. And the right-to-left implication says it is the weakest: if P is such that {P} c {Q}, then wp(c,Q) => P. It can be shown that weakest preconditions are unique up to formula equivalence. Here is a graphical representation of weakest preconditions. If we think of the spectrum of possible preconditions going from false (the strongest) to true (the weakest), and take the "safe" subset of formulas for which the partial correctness statement holds, then wp(c,B) is the lower bound of the safe subset: strongest {false} c {Q} \ | ... > valid assertions | weakest pre {wp(c,Q}} c {Q} / ... \ > invalid weakest {true} c {Q} / Constructing weakest preconditions What we really care about is how to construct weakest preconditions. Consider the following definition: wp(skip, Q) = Q wp(skip, x := a) = Q[a/x] wp(c1;c2, Q) = wp(c1, wp(c2,Q)) wp(if b then c1 else c2) = (b => wp(c1,Q)) /\ (neg b => wp(c2,Q)) The definition for wp(while b do c) is trickier and involves an infinite conjunction: wp(while b do c) = exists n. P_n, where P_0= true and P_{i+1} = (b => wp(c,P_i)) /\ (\neg b => Q). This essentially makes it impractical to automatically compute weakest preconditions for while loops. The above is an induction definition of a set of formulas. But how do I know that these are really weakest preconditions? One has to prove that they indeed meet the conditions for being weakest preconditions (and not take them for granted). For instance, I can show that by structural induction that |- {wp(c,Q)} c {Q} (and by the soundness of Hoare logic, |= {wp(c,Q)} c {Q}, too). To give you a flavor of the proof, let me consider the case for if commands. First, I'll show that |- {wp(c1;c2)} c {Q} given that |- {wp(c1,Q)} c {Q} and |- {wp(c2,Q)} c {Q} hold for all Q. If |- {wp(c1,Q)} c1 {Q} holds for all Q, I can use wp(c2,Q) instead of Q and I get: |- {wp(c1,wp(c2,Q))} c1 {wp(c2,Q)}. But I also know that |- {wp(c2,Q)} c2 {Q}. SO I can apply the Hoare rule for sequences: {wp(c1,wp(c2,Q))} c1 {wp(c2,Q)} {wp(c2,Q)} c2 {Q} ------------------------------------------------- {wp(c1,wp(c2,Q))} c1; c2 {Q} So I proved that |- {wp(c1,wp(c2,Q))} c {Q}, that is, |- {wp(c1;c2)} c {Q}. And this completes this case of the induction proof. Similarly, one can show by structural induction on c that the formulas wp(c,Q) defined above are such that if |= {P} c {Q} then P => wp(c,Q). But we will omit this proof. Now I convinced myself that the inductive definition of wp(c,Q) yields weakest preconditions. So I can use it for some concrete examples. For instance: {?} if (x>0) then x := x+1 else y := y-2 {y > x} wp (if (x>0) then x := x+1 else y := y-2, y>x) = = (x>0 => wp(x:=x+1, y>x) /\ ((x<=0 => wp(y:=y-2, y>x)) = (x>0 => y > x+1) /\ (x<=0 => y-2 > x)