WPsemSemantics of Weakest Preconditions
Set Implicit Arguments.
From SLF Require Export Rules.
Implicit Types f : var.
Implicit Types b : bool.
Implicit Types v w : val.
Implicit Types p : loc.
Implicit Types h : heap.
Implicit Types P : Prop.
Implicit Types H : hprop.
Implicit Types Q : val→hprop.
From SLF Require Export Rules.
Implicit Types f : var.
Implicit Types b : bool.
Implicit Types v w : val.
Implicit Types p : loc.
Implicit Types h : heap.
Implicit Types P : Prop.
Implicit Types H : hprop.
Implicit Types Q : val→hprop.
First Pass
- The use of wp greatly reduces the number of structural rules required,
thus reducing the number of tactics required for carrying out proofs in
practice;
- The predicate wp will serve as guidelines for setting up (in the next chapter) a "characteristic formula generator", which is the key ingredient at the heart of the CFML tool.
- (1) wp and triples are equivalent presentations of the same thing.
- (2) wp has practical benefits, reducing the number of reasoning rules
and tactics that are needed, by a fair amount.
- (3) specifications of functions remain more intuitive to read with triples.
- the notion of weakest precondition, as captured by wp,
- the reformulation of structural rules in wp-style, and
- the reformulation of reasoning rules in wp-style.
Definition of Weakest Preconditions
Definition triple (t:trm) (H:hprop) (Q:val→hprop) : Prop :=
∀ s, H s → eval s t Q. By definition, the predicate wp should be such that H ==> wp t Q is equivalent to triple t H Q. But H ==> wp t Q unfolds to ∀ s, H s → wp t Q s. If we compare ∀ s, H s → eval s t Q with ∀ s, H s → wp t Q s, we see that wp t Q s should match eval s t Q. In other words, wp t Q should correspond to fun s ⇒ eval s t Q.
Remark: the reader may wonder why wp is not just defined to *be* eval,
by simply modifying our earlier definition of eval to take its arguments
in a different order. Certainly, it could be done. However, the benefits of
identifying wp and eval are limited, and there are two orthogonal
motivations for not following that route.
Firstly, the omni-big-step predicate eval s t Q is devised as an immediate
generalization of the big-step predicate eval s t s' v, by generalizing
from out final configuration (s',v) to a set Q of final configurations.
From the perspective of a semantics, we view the configuration (s,t) as an
input and the set Q as an output, thus it would be fairly awckward to
write eval t Q s, with the input state s taken as last argument.
Secondly, we are looking here at a simple Separation Logic where heap
predicates are predicates over the physical state. They have type
heap→Prop, where heap corresponds exactly to the type of of a state
s. More advanced Separation Logic feature something known as "ghost state"
(used, e.g., to represent invariants associated with locks). In such logics,
heap predicates are predicates over both the physical and the ghost state.
In other words, the type heap in general may consist of more than just a
state s. The point of this discussion is that, for more advanced
Separation Logics, wp is more than just eval. Thus, there is no reason
to attempt to identify the two.
As intended, the entailment H ==> wp t Q holds if and only if
triple t H Q does.
Lemma wp_equiv : ∀ t H Q,
(H ==> wp t Q) ↔ (triple t H Q).
Proof using.
iff M. { introv Hs. applys M Hs. } { introv Hs. applys M Hs. }
Qed.
(H ==> wp t Q) ↔ (triple t H Q).
Proof using.
iff M. { introv Hs. applys M Hs. } { introv Hs. applys M Hs. }
Qed.
There are several other ways of defining wp. As we show near the end of
this chapter, they are all equivalent. The definition above is the one that
leads to the simplest proofs for the reasoning rules. Indeed, reasoning
rules must be proved correct with respect to the semantics, and the
semantics is captured by the predicate eval.
Let us now explain why wp is called a "weakest precondition". First,
wp t Q is always a valid precondition for t with respect to the
postcondition Q.
Lemma wp_pre : ∀ t Q,
triple t (wp t Q) Q.
Proof using. intros. rewrite <- wp_equiv. applys himpl_refl. Qed.
triple t (wp t Q) Q.
Proof using. intros. rewrite <- wp_equiv. applys himpl_refl. Qed.
Second, wp t Q is the "weakest" of all valid preconditions for t and
Q, in the sense that, for any other valid precondition H (i.e., such
that triple t H Q holds), it is the case that H entails wp t Q.
Lemma wp_weakest : ∀ t H Q,
triple t H Q →
H ==> wp t Q.
Proof using. introv M. rewrite wp_equiv. applys M. Qed.
triple t H Q →
H ==> wp t Q.
Proof using. introv M. rewrite wp_equiv. applys M. Qed.
Structural Rules in Weakest-Precondition Style
The Frame Rule
The lemma is proved by exploiting the frame property on eval. (It could
also be derived using wp_equiv and triple_frame, but the point here is
to derive properties of wp without mentioning triple.)
Proof using.
intros. unfold wp. intros h HF.
lets (h1&h2&M1&M2&MD&MU): hstar_inv HF.
subst. applys eval_conseq.
{ applys eval_frame M1 MD. }
{ xsimpl. intros h' →. applys M2. }
Qed.
intros. unfold wp. intros h HF.
lets (h1&h2&M1&M2&MD&MU): hstar_inv HF.
subst. applys eval_conseq.
{ applys eval_frame M1 MD. }
{ xsimpl. intros h' →. applys M2. }
Qed.
Looking at the entaileent expressed by wp_frame, the reader may wander
whether the reverse entailment holds, that is, if wp t (Q \*+ H) entails
(wp t Q) \* H. This reverse entailment does not hold in general. Consider
the following counterexample term t, defined as let p = ref 1 in 0. This
term returns 0 and produces a dangling reference cell that can be
described as \∃ p, (p ~~> 1). Let Q be fun r ⇒ \[r = 0] and H
be \∃ p, (p ~~> 1). The term t, executed in the empty heap,
terminates with postcondition Q \*+ H. Therefore, the predicate
wp t (Q \*+ H) holds of the empty heap. However, (wp t Q) \* H does not
hold of the empty heap, because H, which describes one memory cell, cannot
be carved out of the empty heap. We conclude that wp t (Q \*+ H) does not
entail (wp t Q) \* H in general.
The connection between wp_frame and the rule triple_frame is not be
totally obvious. Recall the statement of the frame rule for triples.
triple t H1 Q →
triple t (H1 \* H) (Q \*+ H) Let us replace the pattern triple t H Q with the pattern H ==> wp t Q, following the characteristic equivalence wp_equiv. We obtain the statement shown below.
triple t H1 Q →
triple t (H1 \* H) (Q \*+ H) Let us replace the pattern triple t H Q with the pattern H ==> wp t Q, following the characteristic equivalence wp_equiv. We obtain the statement shown below.
If we exploit transitivity of entailment to eliminate H1, then we obtain
exactly wp_frame, as illustrated by the proof script below.
The Rule of Consequence
Lemma wp_conseq : ∀ t Q1 Q2,
Q1 ===> Q2 →
wp t Q1 ==> wp t Q2.
Proof using. unfold wp. introv M. intros s Hs. applys* eval_conseq. Qed.
Q1 ===> Q2 →
wp t Q1 ==> wp t Q2.
Proof using. unfold wp. introv M. intros s Hs. applys* eval_conseq. Qed.
Here again, the connection with the corresponding reasoning rule for triples
is not totally obvious. Recall the statement of the rule of consequence.
triple t H1 Q1 →
H2 ==> H1 →
Q1 ===> Q2 →
triple t H2 Q2 Let us replace triple t H Q with H ==> wp t Q to obtain the following statement:
triple t H1 Q1 →
H2 ==> H1 →
Q1 ===> Q2 →
triple t H2 Q2 Let us replace triple t H Q with H ==> wp t Q to obtain the following statement:
If we exploit transitivity of entailment to eliminate H1 and H2, then we
obtain exactly wp_conseq, as illustrated by the proof script below.
The Extraction Rules
Replacing triple t H Q with H ==> wp t Q yields the following:
This implication is just a special case of the extraction lemma for pure
facts on the left on an entailment, himpl_hstar_hpure_l:
(P → (H ==> H')) →
(\[P] \* H) ==> H'.
(P → (H ==> H')) →
(\[P] \* H) ==> H'.
Similar reasoning applies to the extraction rule for existentials.
Parameter triple_ramified_frame : ∀ H1 Q1 t H Q,
triple t H1 Q1 →
H ==> H1 \* (Q1 \−−∗ Q) →
triple t H Q.
triple t H1 Q1 →
H ==> H1 \* (Q1 \−−∗ Q) →
triple t H Q.
The ramified frame rule in weakest-precondition style, named wp_ramified,
admits a concise statement and subsumes all the other structural rules of
Separation Logic. Its very elegant statement is as follows.
Lemma wp_ramified : ∀ t Q1 Q2,
(wp t Q1) \* (Q1 \−−∗ Q2) ==> (wp t Q2).
Proof using. intros. applys wp_conseq_frame. applys qwand_cancel. Qed.
(wp t Q1) \* (Q1 \−−∗ Q2) ==> (wp t Q2).
Proof using. intros. applys wp_conseq_frame. applys qwand_cancel. Qed.
The following reformulation of wp_ramified can be more practical to
exploit in practice, because it applies to any goal of the form
H ==> wp t Q.
Lemma wp_ramified_trans : ∀ t H Q1 Q2,
H ==> (wp t Q1) \* (Q1 \−−∗ Q2) →
H ==> (wp t Q2).
Proof using. introv M. xchange M. applys wp_ramified. Qed.
H ==> (wp t Q1) \* (Q1 \−−∗ Q2) →
H ==> (wp t Q2).
Proof using. introv M. xchange M. applys wp_ramified. Qed.
Exercise: 3 stars, standard, especially useful (wp_conseq_of_wp_ramified)
Prove that wp_conseq is derivable from wp_ramified. Concretely, prove wp_conseq using only wp_ramified or wp_ramified_trans, plus properties of the entailment relation.
Lemma wp_conseq_of_wp_ramified : ∀ t Q1 Q2,
Q1 ===> Q2 →
wp t Q1 ==> wp t Q2.
Proof using. (* FILL IN HERE *) Admitted.
☐
Q1 ===> Q2 →
wp t Q1 ==> wp t Q2.
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 2 stars, standard, especially useful (wp_frame_of_wp_ramified)
Prove that wp_frame is derivable from wp_ramified. Concretely, prove wp_frame using only wp_ramified plus properties of entailment.
Lemma wp_frame_of_wp_ramified : ∀ t H Q,
(wp t Q) \* H ==> wp t (Q \*+ H).
Proof using. (* FILL IN HERE *) Admitted.
☐
(wp t Q) \* H ==> wp t (Q \*+ H).
Proof using. (* FILL IN HERE *) Admitted.
☐
If we rewrite this rule in wp style, we obtain this:
H ==> Q v →
H ==> wp (trm_val v) Q. By exploiting transitivity of entailment, we can eliminate H. We obtain the following rule: If you own a state satisfying Q v, then you own a state from which the evaluation of the value v produces Q.
H ==> Q v →
H ==> wp (trm_val v) Q. By exploiting transitivity of entailment, we can eliminate H. We obtain the following rule: If you own a state satisfying Q v, then you own a state from which the evaluation of the value v produces Q.
Lemma wp_val : ∀ v Q,
Q v ==> wp (trm_val v) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_val. Qed.
Q v ==> wp (trm_val v) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_val. Qed.
Parameter triple_seq : ∀ t1 t2 H Q H1,
triple t1 H (fun _ ⇒ H1) →
triple t2 H1 Q →
triple (trm_seq t1 t2) H Q.
triple t1 H (fun _ ⇒ H1) →
triple t2 H1 Q →
triple (trm_seq t1 t2) H Q.
Replacing triple t H Q with H ==> wp t Q gives this:
H ==> (wp t1) (fun _ ⇒ H1) →
H1 ==> (wp t2) Q →
H ==> wp (trm_seq t1 t2) Q. This entailment holds for any H and H1. Let us specialize it to H1 := (wp t2) Q and H := (wp t1) (fun v ⇒ (wp t2) Q).
This leads us to the following rule: If you own a state from which the
evaluation of t1 produces a state from which the evaluation of t2
produces the postcondition Q, then you own a state from which the
evaluation of the sequence t1;t2 produces Q.
H ==> (wp t1) (fun _ ⇒ H1) →
H1 ==> (wp t2) Q →
H ==> wp (trm_seq t1 t2) Q. This entailment holds for any H and H1. Let us specialize it to H1 := (wp t2) Q and H := (wp t1) (fun v ⇒ (wp t2) Q).
Lemma wp_seq : ∀ t1 t2 Q,
wp t1 (fun v ⇒ wp t2 Q) ==> wp (trm_seq t1 t2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_seq. Qed.
wp t1 (fun v ⇒ wp t2 Q) ==> wp (trm_seq t1 t2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_seq. Qed.
Parameter triple_let : ∀ x t1 t2 Q1 H Q,
triple t1 H Q1 →
(∀ v1, triple (subst x v1 t2) (Q1 v1) Q) →
triple (trm_let x t1 t2) H Q.
triple t1 H Q1 →
(∀ v1, triple (subst x v1 t2) (Q1 v1) Q) →
triple (trm_let x t1 t2) H Q.
The rule of trm_let x t1 t2 is very similar to that for trm_seq, the
only difference being the substitution of x by v in t2, where v
denotes the result of t1.
Lemma wp_let : ∀ x t1 t2 Q,
wp t1 (fun v1 ⇒ wp (subst x v1 t2) Q) ==> wp (trm_let x t1 t2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_let. Qed.
wp t1 (fun v1 ⇒ wp (subst x v1 t2) Q) ==> wp (trm_let x t1 t2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_let. Qed.
Functions
The rule for functions follows exactly the same pattern as for values.
Lemma wp_fun : ∀ x t Q,
Q (val_fun x t) ==> wp (trm_fun x t) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_fun. Qed.
Q (val_fun x t) ==> wp (trm_fun x t) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_fun. Qed.
A similar rule holds for the evaluation of a recursive function.
Lemma wp_fix : ∀ f x t Q,
Q (val_fix f x t) ==> wp (trm_fix f x t) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_fix. Qed.
Q (val_fix f x t) ==> wp (trm_fix f x t) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_fix. Qed.
Parameter triple_if : ∀ b t1 t2 H Q,
triple (if b then t1 else t2) H Q →
triple (trm_if (val_bool b) t1 t2) H Q.
triple (if b then t1 else t2) H Q →
triple (trm_if (val_bool b) t1 t2) H Q.
Replacing triple using wp entailments yields
H ==> wp (if b then t1 else t2) Q →
H ==> wp (trm_if (val_bool b) t1 t2) Q A necessary and sufficient condition to prove a proposition of the form ∀ H, (H ==> H1) → (H ==> H2) is H1 ==> H2. Indeed, if we instantiate H with H1, we have (H1 ==> H1) → (H1 ==> H2), thus we deduce H1 ==> H2. Reciprocally, if we have H1 ==> H2 and H ==> H1, then by the transitivity property himpl_trans, we deduce H ==> H2.
Therefore, the previous entailment simplifies to:
wp (if b then t1 else t2) Q ==> wp (trm_if (val_bool b) t1 t2) Q. This is the wp-style reasoning rule for conditionals.
H ==> wp (if b then t1 else t2) Q →
H ==> wp (trm_if (val_bool b) t1 t2) Q A necessary and sufficient condition to prove a proposition of the form ∀ H, (H ==> H1) → (H ==> H2) is H1 ==> H2. Indeed, if we instantiate H with H1, we have (H1 ==> H1) → (H1 ==> H2), thus we deduce H1 ==> H2. Reciprocally, if we have H1 ==> H2 and H ==> H1, then by the transitivity property himpl_trans, we deduce H ==> H2.
wp (if b then t1 else t2) Q ==> wp (trm_if (val_bool b) t1 t2) Q. This is the wp-style reasoning rule for conditionals.
Lemma wp_if : ∀ b t1 t2 Q,
wp (if b then t1 else t2) Q ==> wp (trm_if (val_bool b) t1 t2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_if. Qed.
wp (if b then t1 else t2) Q ==> wp (trm_if (val_bool b) t1 t2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_if. Qed.
Equivalently, the rule may be stated with the conditional around the calls
to wp t1 Q and wp t2 Q.
Exercise: 1 star, standard, optional (wp_if')
Prove the alternative statement of rule wp_if, either from wp_if or directly from eval_if.
Lemma wp_if' : ∀ b t1 t2 Q,
(if b then (wp t1 Q) else (wp t2 Q)) ==> wp (trm_if b t1 t2) Q.
Proof using. (* FILL IN HERE *) Admitted.
☐
(if b then (wp t1 Q) else (wp t2 Q)) ==> wp (trm_if b t1 t2) Q.
Proof using. (* FILL IN HERE *) Admitted.
☐
Parameter triple_app_fun : ∀ x v1 v2 t1 H Q,
v1 = val_fun x t1 →
triple (subst x v2 t1) H Q →
triple (trm_app v1 v2) H Q.
v1 = val_fun x t1 →
triple (subst x v2 t1) H Q →
triple (trm_app v1 v2) H Q.
The corresponding wp rule is:
Lemma wp_app_fun : ∀ x v1 v2 t1 Q,
v1 = val_fun x t1 →
wp (subst x v2 t1) Q ==> wp (trm_app v1 v2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_app_fun. Qed.
v1 = val_fun x t1 →
wp (subst x v2 t1) Q ==> wp (trm_app v1 v2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_app_fun. Qed.
A similar rule holds for the application of a recursive function.
Lemma wp_app_fix : ∀ f x v1 v2 t1 Q,
v1 = val_fix f x t1 →
wp (subst x v2 (subst f v1 t1)) Q ==> wp (trm_app v1 v2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_app_fix. Qed.
v1 = val_fix f x t1 →
wp (subst x v2 (subst f v1 t1)) Q ==> wp (trm_app v1 v2) Q.
Proof using. unfold wp. intros. intros h K. applys* eval_app_fix. Qed.
Parameter triple_conseq_frame : ∀ H2 H1 Q1 t H Q,
triple t H1 Q1 →
H ==> H1 \* H2 →
Q1 \*+ H2 ===> Q →
triple t H Q.
triple t H1 Q1 →
H ==> H1 \* H2 →
Q1 \*+ H2 ===> Q →
triple t H Q.
Let us reformulate this rule using wp, replacing triple t H Q with
H ==> wp t Q.
Exercise: 2 stars, standard, especially useful (wp_conseq_frame_trans)
Prove the combined structural rule in wp style. Hint: exploit wp_conseq_trans and wp_frame.
Lemma wp_conseq_frame_trans : ∀ t H H1 H2 Q1 Q,
H1 ==> wp t Q1 →
H ==> H1 \* H2 →
Q1 \*+ H2 ===> Q →
H ==> wp t Q.
Proof using. (* FILL IN HERE *) Admitted.
☐
H1 ==> wp t Q1 →
H ==> H1 \* H2 →
Q1 \*+ H2 ===> Q →
H ==> wp t Q.
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 2 stars, standard, especially useful (wp_conseq_frame)
Prove the concise version of the combined structural rule in wp style. (Many proofs are possible.)
Lemma wp_conseq_frame : ∀ t H Q1 Q2,
Q1 \*+ H ===> Q2 →
(wp t Q1) \* H ==> (wp t Q2).
Proof using. (* FILL IN HERE *) Admitted.
☐
Q1 \*+ H ===> Q2 →
(wp t Q1) \* H ==> (wp t Q2).
Proof using. (* FILL IN HERE *) Admitted.
☐
Lemma wp_ramified : ∀ t Q1 Q2,
(wp t Q1) \* (Q1 \−−∗ Q2) ==> (wp t Q2). This explaination suggests how one might have come up with the statement of the ramified frame rule.
The lemma wp_equiv captures the characteristic property of wp, that is,
(H ==> wp t Q) ↔ (triple t H Q). The predicate wp can be defined in
terms of eval, like triple. Interestingly, wp may also be defined in
terms of triple. The idea is to define wp t Q as the predicate
\∃ H, H \* \[triple t H Q], which, reading literally, is satisfied by
"any" heap predicate H which is a valid precondition for a triple for the
term t and the postcondition Q.
Exercise: 3 stars, standard, especially useful (wp_equiv_1)
Prove that the alternative definition wp_1 satisfies the characteristic equivalence for weakest preconditions. Hint: use the consequence rule and the extraction rules.
Lemma wp_equiv_1 : ∀ t H Q,
(H ==> wp_1 t Q) ↔ (triple t H Q).
Proof using. (* FILL IN HERE *) Admitted.
☐
(H ==> wp_1 t Q) ↔ (triple t H Q).
Proof using. (* FILL IN HERE *) Admitted.
☐
The concrete definition for wp given above is expressed in terms of
Separation Logic combinators. In contrast to this "high level" definition,
there exists a more "low level" definition, expressed directly as a function
over heaps. In this alternative definition, the heap predicate wp t Q is
defined as a predicate that holds of a heap h if and only if the execution
of t starting in exactly the heap h produces the post-condition Q. The
latter statement is formally captured as triple t (fun h' ⇒ h' = h) Q.
The low-level definition of wp is thus as shown below.
Exercise: 4 stars, standard, optional (wp_equiv_2)
Prove that the low-level definition wp_2 also satisfies the characteristic equivalence H ==> wp Q ↔ triple t H Q. Hint: exploit the lemma triple_named_heap which was established as an exercise in the chapter Triples.
Lemma wp_equiv_2 : ∀ t H Q,
(H ==> wp_2 t Q) ↔ (triple t H Q).
Proof using. (* FILL IN HERE *) Admitted.
☐
(H ==> wp_2 t Q) ↔ (triple t H Q).
Proof using. (* FILL IN HERE *) Admitted.
☐
Equivalent Characterizations of wp
Lemma wp_unique : ∀ wp1 wp2,
(∀ t H Q, (triple t H Q) ↔ (H ==> wp1 t Q)) →
(∀ t H Q, (triple t H Q) ↔ (H ==> wp2 t Q)) →
wp1 = wp2.
Proof using.
introv M1 M2. applys fun_ext_2. intros t Q. applys himpl_antisym.
{ rewrite <- M2. rewrite M1. auto. }
{ rewrite <- M1. rewrite M2. auto. }
Qed.
(∀ t H Q, (triple t H Q) ↔ (H ==> wp1 t Q)) →
(∀ t H Q, (triple t H Q) ↔ (H ==> wp2 t Q)) →
wp1 = wp2.
Proof using.
introv M1 M2. applys fun_ext_2. intros t Q. applys himpl_antisym.
{ rewrite <- M2. rewrite M1. auto. }
{ rewrite <- M1. rewrite M2. auto. }
Qed.
Second, we establish that the property of "being the weakest precondition"
also uniquely characterizes the definition of wp. This property is the
conjunction of two facts: wp t Q must be a valid precondition for a triple
involving t and Q; and wp t Q must be entailed by any valid
precondition of a triple involving t and Q. These two facts correspond
to wp_pre and wp_weakest.
Exercise: 2 stars, standard, especially useful (wp_equiv_iff_wp_pre_and_wp_weakest)
Prove that the conjunction of the properties wp_pre and wk_weakest is equivalent to the property wp_equiv.
Lemma wp_equiv_iff_wp_pre_and_wp_weakest : ∀ wp',
( (∀ t Q, triple t (wp' t Q) Q) (* wp_pre *)
∧ (∀ t H Q, triple t H Q → H ==> wp' t Q)) (* wp_weakest *)
↔
(∀ t H Q, H ==> wp' t Q ↔ triple t H Q). (* wp_equiv *)
Proof using. (* FILL IN HERE *) Admitted.
☐
( (∀ t Q, triple t (wp' t Q) Q) (* wp_pre *)
∧ (∀ t H Q, triple t H Q → H ==> wp' t Q)) (* wp_weakest *)
↔
(∀ t H Q, H ==> wp' t Q ↔ triple t H Q). (* wp_equiv *)
Proof using. (* FILL IN HERE *) Admitted.
☐
Texan Triples
This specification may be equivalently reformulated in the form of an
entailment, as shown below. Note that we purposely leave an empty heap
predicate at the front to indicate where the precondition, if it were not
empty, would go in the reformulation.
In what follows, we describe a chain of transformations that can take us
from the triple form to the wp form, and we establish the reciprocal.
Afterwards, we will formalize the general pattern of the translation from a
triple to a "texan triple", that is, to a wp-based specification.
By replacing triple t H Q with H ==> wp t Q, the specification
triple_ref can be reformulated as follows.
Lemma wp_ref_0 : ∀ v,
\[] ==> wp (val_ref v) (funloc p ⇒ p ~~> v).
Proof using. intros. rewrite wp_equiv. applys triple_ref. Qed.
\[] ==> wp (val_ref v) (funloc p ⇒ p ~~> v).
Proof using. intros. rewrite wp_equiv. applys triple_ref. Qed.
We wish to cast the RHS in the form wp (val_ref v) Q for an abstract
postcondition Q. To that end, we reformulate the above statement by
including a magic wand relating the postcondition (funloc p ⇒ p ~~> v)
with Q.
Lemma wp_ref_1 : ∀ Q v,
((funloc p ⇒ p ~~> v) \−−∗ Q) ==> wp (val_ref v) Q.
Proof using. intros. xchange (wp_ref_0 v). applys wp_ramified. Qed.
((funloc p ⇒ p ~~> v) \−−∗ Q) ==> wp (val_ref v) Q.
Proof using. intros. xchange (wp_ref_0 v). applys wp_ramified. Qed.
This statement can be made slightly more readable by unfolding the
definition of the magic wand for postconditions. Doing so amounts to
quantifying explicitly on the result, named r.
Lemma wp_ref_2 : ∀ Q v,
(\∀ r, (\∃ p, \[r = val_loc p] \* p ~~> v) \−∗ Q r)
==> wp (val_ref v) Q.
Proof using. intros. applys himpl_trans wp_ref_1. xsimpl. Qed.
(\∀ r, (\∃ p, \[r = val_loc p] \* p ~~> v) \−∗ Q r)
==> wp (val_ref v) Q.
Proof using. intros. applys himpl_trans wp_ref_1. xsimpl. Qed.
Interestingly, the variable r, which is equal to val_loc p, can now be
substituted away, further increasing readability. We obtain the
specification of val_ref in "Texan triple style".
Lemma wp_ref_3 : ∀ Q v,
(\∀ p, (p ~~> v) \−∗ Q (val_loc p)) ==> wp (val_ref v) Q.
Proof using.
intros. applys himpl_trans wp_ref_2. xsimpl. intros ? p →.
xchange (hforall_specialize p).
Qed.
(\∀ p, (p ~~> v) \−∗ Q (val_loc p)) ==> wp (val_ref v) Q.
Proof using.
intros. applys himpl_trans wp_ref_2. xsimpl. intros ? p →.
xchange (hforall_specialize p).
Qed.
2. The General Pattern
- the value v may depend on the xi variables,
- the heap predicate H' may depend on r and the xi,
- the number of existentials xi may vary, possibly be zero,
- the equality \[r = v] may be removed if no pure fact is needed about r.
Lemma texan_triple_equiv : ∀ t H A (Hof:val→A→hprop) (vof:A→val),
(triple t H (fun r ⇒ \∃ x, \[r = vof x] \* Hof r x))
↔ (∀ Q, H \* (\∀ x, Hof (vof x) x \−∗ Q (vof x)) ==> wp t Q).
Proof using.
intros. rewrite <- wp_equiv. iff M.
{ intros Q. xchange M. applys wp_ramified_trans.
xsimpl. intros r x →.
xchange (hforall_specialize x). }
{ applys himpl_trans M. xsimpl¬. }
Qed.
(triple t H (fun r ⇒ \∃ x, \[r = vof x] \* Hof r x))
↔ (∀ Q, H \* (\∀ x, Hof (vof x) x \−∗ Q (vof x)) ==> wp t Q).
Proof using.
intros. rewrite <- wp_equiv. iff M.
{ intros Q. xchange M. applys wp_ramified_trans.
xsimpl. intros r x →.
xchange (hforall_specialize x). }
{ applys himpl_trans M. xsimpl¬. }
Qed.
The wp-style specifications of ref, get, and set are presented next.
Lemma wp_get : ∀ v p Q,
(p ~~> v) \* (p ~~> v \−∗ Q v) ==> wp (val_get p) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_get. } { applys himpl_refl. } { xsimpl. intros ? →. auto. }
Qed.
Lemma wp_set : ∀ v w p Q,
(p ~~> v) \* (\∀ r, p ~~> w \−∗ Q r) ==> wp (val_set p w) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_set. } { applys himpl_refl. }
{ intros r. xchange (hforall_specialize r). xsimpl. }
Qed.
Lemma wp_free : ∀ v p Q,
(p ~~> v) \* (\∀ r, Q r) ==> wp (val_free p) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_free. } { applys himpl_refl. }
{ intros r. xchange (hforall_specialize r). }
Qed.
(p ~~> v) \* (p ~~> v \−∗ Q v) ==> wp (val_get p) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_get. } { applys himpl_refl. } { xsimpl. intros ? →. auto. }
Qed.
Lemma wp_set : ∀ v w p Q,
(p ~~> v) \* (\∀ r, p ~~> w \−∗ Q r) ==> wp (val_set p w) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_set. } { applys himpl_refl. }
{ intros r. xchange (hforall_specialize r). xsimpl. }
Qed.
Lemma wp_free : ∀ v p Q,
(p ~~> v) \* (\∀ r, Q r) ==> wp (val_free p) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_free. } { applys himpl_refl. }
{ intros r. xchange (hforall_specialize r). }
Qed.
Alternatively, the specifications of set and free may advertize that the
output value is the unit value.
Parameter triple_set' : ∀ w p v,
triple (val_set p w)
(p ~~> v)
(fun r ⇒ \[r = val_unit] \* p ~~> w).
Lemma wp_set' : ∀ v w p Q,
(p ~~> v) \* (p ~~> w \−∗ Q val_unit) ==> wp (val_set p w) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_set'. }
{ applys himpl_refl. }
{ xsimpl. intros ? →. auto. }
Qed.
Parameter triple_free' : ∀ p v,
triple (val_free p)
(p ~~> v)
(fun r ⇒ \[r = val_unit]).
Lemma wp_free' : ∀ v w p Q,
(p ~~> v) \* (Q val_unit) ==> wp (val_free p) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_free'. }
{ applys himpl_refl. }
{ xsimpl. intros ? →. auto. }
Qed.
End WpSpecRef.
triple (val_set p w)
(p ~~> v)
(fun r ⇒ \[r = val_unit] \* p ~~> w).
Lemma wp_set' : ∀ v w p Q,
(p ~~> v) \* (p ~~> w \−∗ Q val_unit) ==> wp (val_set p w) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_set'. }
{ applys himpl_refl. }
{ xsimpl. intros ? →. auto. }
Qed.
Parameter triple_free' : ∀ p v,
triple (val_free p)
(p ~~> v)
(fun r ⇒ \[r = val_unit]).
Lemma wp_free' : ∀ v w p Q,
(p ~~> v) \* (Q val_unit) ==> wp (val_free p) Q.
Proof using.
intros. rewrite wp_equiv. applys triple_conseq_frame.
{ applys triple_free'. }
{ applys himpl_refl. }
{ xsimpl. intros ? →. auto. }
Qed.
End WpSpecRef.
4. Exercise
Parameter incr : val.
Parameter triple_incr : ∀ (p:loc) (n:int),
triple (incr p)
(p ~~> n)
(fun v ⇒ \[v = val_unit] \* (p ~~> (n+1))).
Parameter triple_incr : ∀ (p:loc) (n:int),
triple (incr p)
(p ~~> n)
(fun v ⇒ \[v = val_unit] \* (p ~~> (n+1))).
Exercise: 3 stars, standard, especially useful (wp_incr)
State a Texan triple for incr as a lemma called wp_incr, then prove this lemma from triple_incr.
(* FILL IN HERE *)
☐
☐
Historical Notes
(* 2024-11-04 20:38 *)