HimplHeap Entailment
First Pass
Lemma triple_conseq_frame : ∀ H2 H1 Q1 t H Q,
triple t H1 Q1 →
H ==> (H1 \* H2) →
(Q1 \*+ H2) ===> Q →
triple t H Q. This chapter presents:
- the formal definition of the entailment relations for heap predicates and for postconditions,
- the lemmas capturing the interaction of entailment with the star operator, and
- the features of the tactics xsimpl and xchange, which are critically useful for manipulating entailments in practice.
Definition of Entailment
Definition himpl (H1 H2:hprop) : Prop :=
∀ (h:heap), H1 h → H2 h.
Notation "H1 ==> H2" := (himpl H1 H2) (at level 55).
∀ (h:heap), H1 h → H2 h.
Notation "H1 ==> H2" := (himpl H1 H2) (at level 55).
Entailment is reflexive, transitive, and antisymmetric. It thus forms an
order relation on heap predicates.
Lemma himpl_refl : ∀ H,
H ==> H.
Proof using. intros h. hnf. auto. Qed.
Lemma himpl_trans : ∀ H2 H1 H3,
(H1 ==> H2) →
(H2 ==> H3) →
(H1 ==> H3).
Proof using. introv M1 M2. intros h H1h. eauto. Qed.
H ==> H.
Proof using. intros h. hnf. auto. Qed.
Lemma himpl_trans : ∀ H2 H1 H3,
(H1 ==> H2) →
(H2 ==> H3) →
(H1 ==> H3).
Proof using. introv M1 M2. intros h H1h. eauto. Qed.
Exercise: 1 star, standard, optional (himpl_antisym)
Prove the antisymmetry of entailment result shown below. Hint: use predicate_extensionality.
Lemma himpl_antisym : ∀ H1 H2,
(H1 ==> H2) →
(H2 ==> H1) →
H1 = H2.
Proof using. (* FILL IN HERE *) Admitted.
☐
(H1 ==> H2) →
(H2 ==> H1) →
H1 = H2.
Proof using. (* FILL IN HERE *) Admitted.
☐
Entailment for Postconditions
Definition qimpl (Q1 Q2:val→hprop) : Prop :=
∀ (v:val), Q1 v ==> Q2 v.
Notation "Q1 ===> Q2" := (qimpl Q1 Q2) (at level 55).
∀ (v:val), Q1 v ==> Q2 v.
Notation "Q1 ===> Q2" := (qimpl Q1 Q2) (at level 55).
In other words, Q1 ===> Q2 holds if and only if, for any value v and any
heap h, the proposition Q1 v h implies Q2 v h.
Entailment on postconditions also forms an order relation:
Lemma qimpl_refl : ∀ Q,
Q ===> Q.
Proof using. intros Q v. apply himpl_refl. Qed.
Lemma qimpl_trans : ∀ Q2 Q1 Q3,
(Q1 ===> Q2) →
(Q2 ===> Q3) →
(Q1 ===> Q3).
Proof using. introv M1 M2. intros v. eapply himpl_trans; eauto. Qed.
Q ===> Q.
Proof using. intros Q v. apply himpl_refl. Qed.
Lemma qimpl_trans : ∀ Q2 Q1 Q3,
(Q1 ===> Q2) →
(Q2 ===> Q3) →
(Q1 ===> Q3).
Proof using. introv M1 M2. intros v. eapply himpl_trans; eauto. Qed.
Exercise: 1 star, standard, optional (qimpl_antisym)
Prove the antisymmetry of entailment on postconditions. Hint: exploit functional_extensionality.
Lemma qimpl_antisym : ∀ Q1 Q2,
(Q1 ===> Q2) →
(Q2 ===> Q1) →
(Q1 = Q2).
Proof using. (* FILL IN HERE *) Admitted.
☐
(Q1 ===> Q2) →
(Q2 ===> Q1) →
(Q1 = Q2).
Proof using. (* FILL IN HERE *) Admitted.
☐
Frame Rule for Entailment
Rules for Proving Entailments
Exercise: 2 stars, standard, especially useful (himpl_hstar_hpure_r).
Prove the rule himpl_hstar_hpure_r.
Lemma himpl_hstar_hpure_r : ∀ (P:Prop) H H',
P →
(H ==> H') →
H ==> (\[P] \* H').
Proof using. (* FILL IN HERE *) Admitted.
☐
P →
(H ==> H') →
H ==> (\[P] \* H').
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 2 stars, standard, especially useful (himpl_hstar_hpure_l).
Prove the rule himpl_hstar_hpure_l.
Lemma himpl_hstar_hpure_l : ∀ (P:Prop) (H H':hprop),
(P → H ==> H') →
(\[P] \* H) ==> H'.
Proof using. (* FILL IN HERE *) Admitted.
☐
(P → H ==> H') →
(\[P] \* H) ==> H'.
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 2 stars, standard, optional (himpl_hexists_r).
Prove the rule himpl_hexists_r.
Lemma himpl_hexists_r : ∀ A (x:A) H J,
(H ==> J x) →
H ==> (\∃ x, J x).
Proof using. (* FILL IN HERE *) Admitted.
☐
(H ==> J x) →
H ==> (\∃ x, J x).
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 2 stars, standard, especially useful (himpl_hexists_l).
Prove the rule himpl_hexists_l.
Lemma himpl_hexists_l : ∀ (A:Type) (H:hprop) (J:A→hprop),
(∀ x, J x ==> H) →
(\∃ x, J x) ==> H.
Proof using. (* FILL IN HERE *) Admitted.
☐
(∀ x, J x ==> H) →
(\∃ x, J x) ==> H.
Proof using. (* FILL IN HERE *) Admitted.
☐
Extracting Information from Heap Predicates
The proof of this result exploits a result on finite maps. Essentially, the
domain of a single singleton map that binds a location p to some value is
the singleton set \{p}, so such a singleton map cannot be disjoint from
another singleton map that binds the same location p.
Check disjoint_single_single_same_inv : ∀ (p:loc) (v1 v2:val),
Fmap.disjoint (Fmap.single p v1) (Fmap.single p v2) →
False.
Using this lemma, we can prove hstar_hsingle_same_loc by unfolding the
definition of hstar to reveal the contradiction on the disjointness
assumption.
Check disjoint_single_single_same_inv : ∀ (p:loc) (v1 v2:val),
Fmap.disjoint (Fmap.single p v1) (Fmap.single p v2) →
False.
Proof using.
intros. unfold hsingle. intros h (h1&h2&E1&E2&D&E). false.
subst. eapply Fmap.disjoint_single_single_same_inv. eapply D.
Qed.
intros. unfold hsingle. intros h (h1&h2&E1&E2&D&E). false.
subst. eapply Fmap.disjoint_single_single_same_inv. eapply D.
Qed.
More generally, a heap predicate of the form H \* H is usually suspicious
in Separation Logic. In the simple variant of Separation Logic that we
consider in this course, there are only three typical situations where
H \* H makes sense:
- (1) if H is the empty heap predicate \[],
- (2) if H is a pure heap predicate of the form \[P], or
- (3) if H has the form \∃ (H0:hprop), H0, which will be written \GC in chapter Affine.
Rules for Naming Heaps
Exercise: 3 stars, standard, optional (hexists_named_eq)
Prove that a heap predicate H is equivalent to \∃ h, \[H h] \* (= h)).
Lemma hexists_named_eq : ∀ H,
H = (\∃ h, \[H h] \* (= h)).
Proof using. (* FILL IN HERE *) Admitted.
☐
H = (\∃ h, \[H h] \* (= h)).
Proof using. (* FILL IN HERE *) Admitted.
☐
The xsimpl Tactic
- extract pure facts and existential quantifiers from the LHS;
- instantial existential quantifiers from the RHS, using either Coq unification variables or user-provided hints (details are explained further on);
- cancel out predicates that occur on both the LHS and RHS; certain Coq unification variables may be instantiated during that process.
xsimpl Extracts Pure Facts and Quantifiers in LHS
Lemma xsimpl_demo_lhs_hpure : ∀ H1 H2 H3 H4 (n:int),
H1 \* H2 \* \[n > 0] \* H3 ==> H4.
Proof using.
intros. xsimpl. intros Hn.
Abort.
H1 \* H2 \* \[n > 0] \* H3 ==> H4.
Proof using.
intros. xsimpl. intros Hn.
Abort.
In case the LHS includes a contradiction, such as the pure fact False, the
goal gets solved immediately by xsimpl.
Lemma xsimpl_demo_lhs_hpure : ∀ H1 H2 H3 H4,
H1 \* H2 \* \[False] \* H3 ==> H4.
Proof using.
intros. xsimpl.
Qed.
H1 \* H2 \* \[False] \* H3 ==> H4.
Proof using.
intros. xsimpl.
Qed.
The xsimpl tactic also extracts existential quantifiers from the LHS. It
turns them into universally quantified variables outside of the entailment
relation.
Lemma xsimpl_demo_lhs_hexists : ∀ H1 H2 H3 H4 (p:loc),
H1 \* \∃ (n:int), (p ~~> n \* H2) \* H3 ==> H4.
Proof using.
intros. xsimpl. intros n.
Abort.
H1 \* \∃ (n:int), (p ~~> n \* H2) \* H3 ==> H4.
Proof using.
intros. xsimpl. intros n.
Abort.
A single call to xsimpl extracts all the pure facts and quantifiers from
the LHS.
Lemma xsimpl_demo_lhs_several : ∀ H1 H2 H3 H4 (p q:loc),
H1 \* \∃ (n:int), (p ~~> n \* \[n > 0] \* H2) \* \[p ≠ q] \* H3 ==> H4.
Proof using.
intros. xsimpl. intros n Hn Hp.
Abort.
H1 \* \∃ (n:int), (p ~~> n \* \[n > 0] \* H2) \* \[p ≠ q] \* H3 ==> H4.
Proof using.
intros. xsimpl. intros n Hn Hp.
Abort.
xsimpl Cancels Out Heap Predicates from LHS and RHS
Lemma xsimpl_demo_cancel_one : ∀ H1 H2 H3 H4 H5 H6 H7,
H1 \* H2 \* H3 \* H4 ==> H5 \* H6 \* H2 \* H7.
Proof using.
intros. xsimpl.
Abort.
H1 \* H2 \* H3 \* H4 ==> H5 \* H6 \* H2 \* H7.
Proof using.
intros. xsimpl.
Abort.
xsimpl actually cancels out all the heap predicates that it can spot
appearing on both sides. In the example below, H2, H3, and H4 are
canceled out.
Lemma xsimpl_demo_cancel_many : ∀ H1 H2 H3 H4 H5,
H1 \* H2 \* H3 \* H4 ==> H4 \* H3 \* H5 \* H2.
Proof using.
intros. xsimpl.
Abort.
H1 \* H2 \* H3 \* H4 ==> H4 \* H3 \* H5 \* H2.
Proof using.
intros. xsimpl.
Abort.
If all the pieces of heap predicate get canceled out, the remaining proof
obligation is \[] ==> \[]. In this case, xsimpl automatically solves the
goal by invoking the reflexivity of entailment.
Lemma xsimpl_demo_cancel_all : ∀ H1 H2 H3 H4,
H1 \* H2 \* H3 \* H4 ==> H4 \* H3 \* H1 \* H2.
Proof using.
intros. xsimpl.
Qed.
H1 \* H2 \* H3 \* H4 ==> H4 \* H3 \* H1 \* H2.
Proof using.
intros. xsimpl.
Qed.
xsimpl Instantiates Pure Facts and Quantifiers in the RHS
Lemma xsimpl_demo_rhs_hpure : ∀ H1 H2 H3 (n:int),
H1 ==> H2 \* \[n > 0] \* H3.
Proof using.
intros. xsimpl.
Abort.
H1 ==> H2 \* \[n > 0] \* H3.
Proof using.
intros. xsimpl.
Abort.
When it encounters an existential quantifier in the RHS, the xsimpl tactic
introduces a unification variable denoted by a question mark, that is, an
"evar", in Coq terminology. Here, xsimpl turns \∃ n, .. p ~~> n ..
into .. p ~~> ?Goal .., where ?Goal is the evar.
Lemma xsimpl_demo_rhs_hexists : ∀ H1 H2 H3 H4 (p:loc),
H1 ==> H2 \* \∃ (n:int), (p ~~> n \* H3) \* H4.
Proof using.
intros. xsimpl.
H1 ==> H2 \* \∃ (n:int), (p ~~> n \* H3) \* H4.
Proof using.
intros. xsimpl.
The output of the command Show Existentials shows Existential 1, named
?Goal, of type int. This "evar" corresponds to the value assigned to the
existentially quantified variable n.
Abort.
The "evar" often gets subsequently instantiated as a result of a
cancellation step. For example, in the example below, xsimpl instantiates
the existentially quantified variable n as ?Goal, then cancels out
p ~~> ?Goal from the LHS against p ~~> 3 on the right-hand-side, thereby
unifying ?Goal with 3. As a result, the "evar" ?Goal is never visible.
Lemma xsimpl_demo_rhs_hexists_unify : ∀ H1 H2 H3 H4 (p:loc),
H1 \* (p ~~> 3) ==> H2 \* \∃ (n:int), (p ~~> n \* H3) \* H4.
Proof using.
intros. xsimpl.
Abort.
H1 \* (p ~~> 3) ==> H2 \* \∃ (n:int), (p ~~> n \* H3) \* H4.
Proof using.
intros. xsimpl.
Abort.
The instantiation of "evars" can only be observed if there is another
occurrence of the same variable in the entailment. In the next example,
which refines the previous one, observe how the assertion n > 0 that
appears in the LHS gets turned into the proof obligation 3 > 0. This
results from n being unified with 3 when p ~~> n is cancelled against
p ~~> 3.
Lemma xsimpl_demo_rhs_hexists_unify_view : ∀ H1 H2 H4 (p:loc),
H1 \* (p ~~> 3) ==> H2 \* \∃ (n:int), (p ~~> n \* \[n > 0]) \* H4.
Proof using.
intros. xsimpl.
Abort.
H1 \* (p ~~> 3) ==> H2 \* \∃ (n:int), (p ~~> n \* \[n > 0]) \* H4.
Proof using.
intros. xsimpl.
Abort.
In practice, in most cases, xsimpl would instantiate existentials on the
left-hand side, then discharge what remains of the entailment. Here are two
typical examples.
Lemma xsimpl_demo_rhs_exists_solved_1 : ∀ (p:loc),
p ~~> 3 ==>
\∃ (n:int), p ~~> n.
Proof using. xsimpl. Qed.
Lemma xsimpl_demo_rhs_exists_solved_2 : ∀ (p q:loc),
p ~~> 3 \* q ~~> 3 ==>
\∃ (n:int), p ~~> n \* q ~~> n.
Proof using. xsimpl. Qed.
p ~~> 3 ==>
\∃ (n:int), p ~~> n.
Proof using. xsimpl. Qed.
Lemma xsimpl_demo_rhs_exists_solved_2 : ∀ (p q:loc),
p ~~> 3 \* q ~~> 3 ==>
\∃ (n:int), p ~~> n \* q ~~> n.
Proof using. xsimpl. Qed.
In certain situations, it may be desirable to provide an explicit value for
instantiating an existential quantifier that occurs in the RHS. The xsimpl
tactic accepts arguments, which will be used to instantiate the existentials
(on a first-match basis). The syntax is xsimpl v1 .. vn.
Lemma xsimpl_demo_rhs_hints : ∀ H1 (p q:loc),
H1 ==> \∃ (n m:int), (p ~~> n \* q ~~> m).
Proof using.
intros. xsimpl 8 9.
Abort.
H1 ==> \∃ (n m:int), (p ~~> n \* q ~~> m).
Proof using.
intros. xsimpl 8 9.
Abort.
If two existential quantifiers quantify variables of the same type, it is
possible to provide a value for only the second quantifier by passing as
first argument to xsimpl the special value __. The following example
shows how, on LHS of the form \∃ n m, ..., the tactic xsimpl __ 9
instantiates m with 9 while leaving n as an unresolved evar.
Lemma xsimpl_demo_rhs_hints_evar : ∀ H1 (p q:loc),
H1 ==> \∃ (n m:int), (p ~~> n \* q ~~> m).
Proof using.
intros. xsimpl __ 9.
Abort.
H1 ==> \∃ (n m:int), (p ~~> n \* q ~~> m).
Proof using.
intros. xsimpl __ 9.
Abort.
xsimpl on Entailments Between Postconditions
Lemma qimpl_example_1 : ∀ (Q1 Q2:val→hprop) (H2 H3:hprop),
Q1 \*+ H2 ===> Q2 \*+ H2 \*+ H3.
Proof using. intros. xsimpl. intros r. Abort.
Q1 \*+ H2 ===> Q2 \*+ H2 \*+ H3.
Proof using. intros. xsimpl. intros r. Abort.
Example: Entailment Proofs using xpull and xsimpl
Lemma xpull_example_1 : ∀ (p:loc),
\∃ (n:int), p ~~> n ==>
\∃ (m:int), p ~~> (m + 1).
Proof using.
intros. xpull.
Abort.
Lemma xpull_example_2 : ∀ (H:hprop),
\[False] ==> H.
Proof using. xpull. Qed.
\∃ (n:int), p ~~> n ==>
\∃ (m:int), p ~~> (m + 1).
Proof using.
intros. xpull.
Abort.
Lemma xpull_example_2 : ∀ (H:hprop),
\[False] ==> H.
Proof using. xpull. Qed.
The next example illustrates an interesting situation where xpull is
required because a plain call to xsimpl leads to an awkward goal. This
examples involves a nontrivial instantiation of an existential quantifier on
the right-hand side of the entailment. However, we cannot provide an
explicit hint to xsimpl before extracting an existential quantifier that
appears on the left-hand side of the entailment. Here is the example.
Lemma xpull_example_3 : ∀ (p:loc),
(\∃ (n:int), p ~~> n) ==>
(\∃ (m:int), p ~~> (m + 1)).
Proof using.
intros.
(* xsimpl. *)
(\∃ (n:int), p ~~> n) ==>
(\∃ (m:int), p ~~> (m + 1)).
Proof using.
intros.
(* xsimpl. *)
Invoking xsimpl here leaves the goal ∀ x, x = ?Goal + 1. This
statement is technically provable, because ?Goal can be instantiated with
x - 1. Yet, discharging such a proof obligation, which features a Coq
meta-variable ?Goal that depends on a bound variable x is rather awkward
and impractical. The proper route to solving this kind of entailment is to first extract the
\∃ n into the context, then use xsimpl (n-1) to provide as hint to
xsimpl that m should be instantiated with n-1.
The xchange Tactic
Lemma xchange_demo_base : ∀ H1 H2 H2' H3 H4,
H2 ==> H2' →
H1 \* H2 \* H3 ==> H4.
Proof using.
introv M. xchange M.
(* Note that freshly produced items appear to the front *)
Abort.
H2 ==> H2' →
H1 \* H2 \* H3 ==> H4.
Proof using.
introv M. xchange M.
(* Note that freshly produced items appear to the front *)
Abort.
The xchange tactic can also take an equality as an argument; xchange M
exploits the left-to-right direction of an equality M, whereas
xchange <- M exploits the right-to-left direction.
Lemma xchange_demo_eq : ∀ H1 H2 H3 H4 H5,
H1 \* H3 = H5 →
H1 \* H2 \* H3 ==> H4.
Proof using.
introv M. xchange M.
xchange <- M.
Abort.
H1 \* H3 = H5 →
H1 \* H2 \* H3 ==> H4.
Proof using.
introv M. xchange M.
xchange <- M.
Abort.
The tactic xchange M will accept a lemma or hypothesis M with universal
quantifiers, as long as its conclusion is an equality or an entailment. In
such case, xchange M instantiates M before attemting to perform a
replacement.
Lemma xchange_demo_inst : ∀ H1 (J J':int→hprop) H3 H4,
(∀ n, J n = J' (n+1)) →
H1 \* J 3 \* H3 ==> H4.
Proof using.
introv M. xchange M.
Abort.
(∀ n, J n = J' (n+1)) →
H1 \* J 3 \* H3 ==> H4.
Proof using.
introv M. xchange M.
Abort.
Identifying True and False Entailments
Module EntailmentQuiz.
Implicit Types p q : loc.
Implicit Types n m : int.
Parameter case_study_1 : ∀ p q,
p ~~> 3 \* q ~~> 4
==> q ~~> 4 \* p ~~> 3.
Parameter case_study_2 : ∀ p q,
p ~~> 3
==> q ~~> 4 \* p ~~> 3.
Parameter case_study_3 : ∀ p q,
q ~~> 4 \* p ~~> 3
==> p ~~> 3.
Parameter case_study_4 : ∀ p q,
\[False] \* p ~~> 3
==> p ~~> 4 \* q ~~> 4.
Parameter case_study_5 : ∀ p q,
p ~~> 3 \* q ~~> 4
==> \[False].
Parameter case_study_6 : ∀ p,
p ~~> 3 \* p ~~> 4
==> \[False].
Parameter case_study_7 : ∀ p,
p ~~> 3 \* p ~~> 3
==> \[False].
Parameter case_study_8 : ∀ p,
p ~~> 3
==> \∃ n, p ~~> n.
Parameter case_study_9 : ∀ p,
∃ n, p ~~> n
==> p ~~> 3.
Parameter case_study_10 : ∀ p,
\∃ n, p ~~> n \* \[n > 0]
==> \∃ n, \[n > 1] \* p ~~> (n-1).
Parameter case_study_11 : ∀ p q,
p ~~> 3 \* q ~~> 3
==> \∃ n, p ~~> n \* q ~~> n.
Parameter case_study_12 : ∀ p n,
p ~~> n \* \[n > 0] \* \[n < 0]
==> p ~~> n \* p ~~> n.
End EntailmentQuiz.
Module EntailmentQuizAnswers.
Implicit Types p q : loc.
Implicit Types n m : int.
Parameter case_study_1 : ∀ p q,
p ~~> 3 \* q ~~> 4
==> q ~~> 4 \* p ~~> 3.
Parameter case_study_2 : ∀ p q,
p ~~> 3
==> q ~~> 4 \* p ~~> 3.
Parameter case_study_3 : ∀ p q,
q ~~> 4 \* p ~~> 3
==> p ~~> 3.
Parameter case_study_4 : ∀ p q,
\[False] \* p ~~> 3
==> p ~~> 4 \* q ~~> 4.
Parameter case_study_5 : ∀ p q,
p ~~> 3 \* q ~~> 4
==> \[False].
Parameter case_study_6 : ∀ p,
p ~~> 3 \* p ~~> 4
==> \[False].
Parameter case_study_7 : ∀ p,
p ~~> 3 \* p ~~> 3
==> \[False].
Parameter case_study_8 : ∀ p,
p ~~> 3
==> \∃ n, p ~~> n.
Parameter case_study_9 : ∀ p,
∃ n, p ~~> n
==> p ~~> 3.
Parameter case_study_10 : ∀ p,
\∃ n, p ~~> n \* \[n > 0]
==> \∃ n, \[n > 1] \* p ~~> (n-1).
Parameter case_study_11 : ∀ p q,
p ~~> 3 \* q ~~> 3
==> \∃ n, p ~~> n \* q ~~> n.
Parameter case_study_12 : ∀ p n,
p ~~> n \* \[n > 0] \* \[n < 0]
==> p ~~> n \* p ~~> n.
End EntailmentQuiz.
Module EntailmentQuizAnswers.
The answers to the quiz are as follows.
1. True, by commutativity.
2. False, because one cell does not entail two cells.
3. False, because two cells do not entail one cell.
4. True, because \False entails anything.
5. False, because a satisfiable heap predicate does not entail \False.
6. True, because a cell cannot be starred with itself.
7. True, because a cell cannot be starred with itself.
8. True, by instantiating n with 3.
9. False, because n could be something else than 3.
10. True, by instantiating n in RHS with n+1 for the n of the LHS.
11. True, by instantiating n with 3.
12. True, because it is equivalent to \[False] ==> \[False].
Proofs for the true results appear below, using the xsimpl tactic.
Implicit Types p q : loc.
Implicit Types n m : int.
Lemma case_study_1 : ∀ p q,
p ~~> 3 \* q ~~> 4
==> q ~~> 4 \* p ~~> 3.
Proof using. xsimpl. Qed.
Lemma case_study_4 : ∀ p q,
\[False] \* p ~~> 3
==> p ~~> 4 \* q ~~> 4.
Proof using. xsimpl. Qed.
Lemma case_study_6 : ∀ p,
p ~~> 3 \* p ~~> 4
==> \[False].
Proof using. intros. xchange (hstar_hsingle_same_loc p). Qed.
Lemma case_study_7 : ∀ p,
p ~~> 3 \* p ~~> 3
==> \[False].
Proof using. intros. xchange (hstar_hsingle_same_loc p). Qed.
Lemma case_study_8 : ∀ p,
p ~~> 3
==> \∃ n, p ~~> n.
Proof using. xsimpl. Qed.
Lemma case_study_10 : ∀ p,
\∃ n, p ~~> n \* \[n > 0]
==> \∃ n, \[n > 1] \* p ~~> (n-1).
Proof using.
intros. xpull. intros n Hn. xsimpl (n+1).
math. math.
Qed.
Lemma case_study_11 : ∀ p q,
p ~~> 3 \* q ~~> 3
==> \∃ n, p ~~> n \* q ~~> n.
Proof using. xsimpl. Qed.
Lemma case_study_12 : ∀ p n,
p ~~> n \* \[n > 0] \* \[n < 0] ==> p ~~> n \* p ~~> n.
Proof using. intros. xsimpl. intros Hn1 Hn2. false. math. Qed.
End EntailmentQuizAnswers.
Implicit Types n m : int.
Lemma case_study_1 : ∀ p q,
p ~~> 3 \* q ~~> 4
==> q ~~> 4 \* p ~~> 3.
Proof using. xsimpl. Qed.
Lemma case_study_4 : ∀ p q,
\[False] \* p ~~> 3
==> p ~~> 4 \* q ~~> 4.
Proof using. xsimpl. Qed.
Lemma case_study_6 : ∀ p,
p ~~> 3 \* p ~~> 4
==> \[False].
Proof using. intros. xchange (hstar_hsingle_same_loc p). Qed.
Lemma case_study_7 : ∀ p,
p ~~> 3 \* p ~~> 3
==> \[False].
Proof using. intros. xchange (hstar_hsingle_same_loc p). Qed.
Lemma case_study_8 : ∀ p,
p ~~> 3
==> \∃ n, p ~~> n.
Proof using. xsimpl. Qed.
Lemma case_study_10 : ∀ p,
\∃ n, p ~~> n \* \[n > 0]
==> \∃ n, \[n > 1] \* p ~~> (n-1).
Proof using.
intros. xpull. intros n Hn. xsimpl (n+1).
math. math.
Qed.
Lemma case_study_11 : ∀ p q,
p ~~> 3 \* q ~~> 3
==> \∃ n, p ~~> n \* q ~~> n.
Proof using. xsimpl. Qed.
Lemma case_study_12 : ∀ p n,
p ~~> n \* \[n > 0] \* \[n < 0] ==> p ~~> n \* p ~~> n.
Proof using. intros. xsimpl. intros Hn1 Hn2. false. math. Qed.
End EntailmentQuizAnswers.
Proving an entailment by hand is generally a tedious task. This is why most
frameworks based on Separation Logic include an automated tactic for
simplifying entailments. In this course, the relevant tactic is named
xsimpl. In order to fully appreciate what a simplification tactic provides
and better understand how it works internally, it is very useful to complete
a few entailment proofs by hand.
Exercise: 3 stars, standard, optional (himpl_example_1)
Prove the example entailment below. Hint: exploit hstar_comm, hstar_assoc, or hstar_comm_assoc which combines the two, and exploit himpl_frame_l or himpl_frame_r to cancel out matching pieces.
Lemma himpl_example_1 : ∀ p1 p2 p3 p4,
p1 ~~> 6 \* p2 ~~> 7 \* p3 ~~> 8 \* p4 ~~> 9
==> p4 ~~> 9 \* p3 ~~> 8 \* p2 ~~> 7 \* p1 ~~> 6.
Proof using. (* FILL IN HERE *) Admitted.
☐
p1 ~~> 6 \* p2 ~~> 7 \* p3 ~~> 8 \* p4 ~~> 9
==> p4 ~~> 9 \* p3 ~~> 8 \* p2 ~~> 7 \* p1 ~~> 6.
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 2 stars, standard, optional (himpl_example_2)
Prove the example entailment below. Hint: use himpl_hstar_hpure_l to extract pure facts, once they appear at the head of the left-hand side of the entailment. For arithmetic inequalities, use the math tactic.
Lemma himpl_example_2 : ∀ p1 p2 p3 n,
p1 ~~> 6 \* \[n > 0] \* p2 ~~> 7 \* \[n < 0]
==> p3 ~~> 8.
Proof using. (* FILL IN HERE *) Admitted.
☐
p1 ~~> 6 \* \[n > 0] \* p2 ~~> 7 \* \[n < 0]
==> p3 ~~> 8.
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 2 stars, standard, optional (himpl_example_3)
Prove the example entailment below. Hint: use himpl_hexists_r, himpl_hexists_l, himpl_hstar_hpure_l and/or himpl_hstar_hpure_r to deal with pure facts and quantifiers. You may find the TLC tactic math_rewrite (n+1-1 = n) helpful here.
Lemma himpl_example_3 : ∀ p,
\∃ n, p ~~> n \* \[n > 0]
==> \∃ n, \[n > 1] \* p ~~> (n-1).
Proof using. (* FILL IN HERE *) Admitted.
☐
\∃ n, p ~~> n \* \[n > 0]
==> \∃ n, \[n > 1] \* p ~~> (n-1).
Proof using. (* FILL IN HERE *) Admitted.
☐
Inside the xchange Tactic
Exercise: 2 stars, standard, especially useful (xchange_lemma)
Prove the following lemma without using xchange.
Lemma xchange_lemma : ∀ H1 H1' H H' H2,
H1 ==> H1' →
H ==> H1 \* H2 →
H1' \* H2 ==> H' →
H ==> H'.
Proof using. (* FILL IN HERE *) Admitted.
☐
H1 ==> H1' →
H ==> H1 \* H2 →
H1' \* H2 ==> H' →
H ==> H'.
Proof using. (* FILL IN HERE *) Admitted.
☐
Proofs of Rules for Entailment
Exercise: 1 star, standard, especially useful (himpl_frame_l)
Prove the frame property for entailment. Hint: unfold the definition of hstar.
Lemma himpl_frame_l : ∀ H2 H1 H1',
H1 ==> H1' →
(H1 \* H2) ==> (H1' \* H2).
Proof using. (* FILL IN HERE *) Admitted.
☐
H1 ==> H1' →
(H1 \* H2) ==> (H1' \* H2).
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 1 star, standard, especially useful (himpl_frame_r)
Prove himpl_frame_r, which is the symmetric of himpl_frame_l.
Lemma himpl_frame_r : ∀ H1 H2 H2',
H2 ==> H2' →
(H1 \* H2) ==> (H1 \* H2').
Proof using. (* FILL IN HERE *) Admitted.
☐
H2 ==> H2' →
(H1 \* H2) ==> (H1 \* H2').
Proof using. (* FILL IN HERE *) Admitted.
☐
Exercise: 1 star, standard, especially useful (himpl_frame_lr)
The monotonicity property of the star operator w.r.t. entailment can also be stated in a symmetric fashion, as shown next. Prove this result. Hint: exploit the transitivity of entailment (himpl_trans) and the asymmetric monotonicity results from the two prior exercises.
Lemma himpl_frame_lr : ∀ H1 H1' H2 H2',
H1 ==> H1' →
H2 ==> H2' →
(H1 \* H2) ==> (H1' \* H2').
Proof using. (* FILL IN HERE *) Admitted.
☐
H1 ==> H1' →
H2 ==> H2' →
(H1 \* H2) ==> (H1' \* H2').
Proof using. (* FILL IN HERE *) Admitted.
☐
(* 2024-11-04 20:38 *)