Library Merge
Merging is defined inductively as a ternary relation.
Variable Sig : Signature.
Inductive merge : Behaviour Sig -> Behaviour Sig -> Behaviour Sig -> Prop :=
| merge_End : merge (End _) (End _) (End _)
| merge_Send : forall p e a B1 B2 B, merge B1 B2 B ->
merge (p ! e @! a; B1) (p ! e @! a;B2) (p ! e @! a;B)
| merge_Recv : forall p x a B1 B2 B, merge B1 B2 B ->
merge (p ? x @? a;B1) (p ? x @? a;B2) (p ? x @? a;B)
| merge_Sel : forall p l a B1 B2 B, merge B1 B2 B ->
merge (p (+) l @+ a;B1) (p (+) l @+ a;B2) (p (+) l @+ a;B)
| merge_Branching_NNNN : forall p,
merge (p & None // None)
(p & None // None)
(p & None // None)
| merge_Branching_NNNS : forall p aR bR,
merge (p & None // None)
(p & None // Some (aR,bR))
(p & None // Some (aR,bR))
| merge_Branching_NNSN : forall p aL bL,
merge (p & None // None)
(p & Some (aL,bL) // None)
(p & Some (aL,bL) // None)
| merge_Branching_NNSS : forall p aL bL aR bR,
merge (p & None // None)
(p & Some (aL,bL) // Some (aR,bR))
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_NSNN : forall p aR bR,
merge (p & None // Some (aR,bR))
(p & None // None)
(p & None // Some (aR,bR))
| merge_Branching_NSNS : forall p aR bR1 bR2 bR, merge bR1 bR2 bR ->
merge (p & None // Some (aR,bR1))
(p & None // Some (aR,bR2))
(p & None // Some (aR,bR))
| merge_Branching_NSSN : forall p aL bL aR bR,
merge (p & None // Some (aR,bR))
(p & Some (aL,bL) // None)
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_NSSS : forall p aL bL aR bR1 bR2 bR, merge bR1 bR2 bR ->
merge (p & None // Some (aR,bR1))
(p & Some (aL,bL) // Some (aR,bR2))
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_SNNN : forall p aL bL,
merge (p & Some (aL,bL) // None)
(p & None // None)
(p & Some (aL,bL) // None)
| merge_Branching_SNNS : forall p aL bL aR bR,
merge (p & Some (aL,bL) // None)
(p & None // Some (aR,bR))
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_SNSN : forall p aL bL1 bL2 bL, merge bL1 bL2 bL ->
merge (p & Some (aL,bL1) // None)
(p & Some (aL,bL2) // None)
(p & Some (aL,bL) // None)
| merge_Branching_SNSS : forall p aL bL1 bL2 bL aR bR, merge bL1 bL2 bL ->
merge (p & Some (aL,bL1) // None)
(p & Some (aL,bL2) // Some (aR,bR))
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_SSNN : forall p aL bL aR bR,
merge (p & Some (aL,bL) // Some (aR,bR))
(p & None // None)
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_SSNS : forall p aL bL aR bR1 bR2 bR, merge bR1 bR2 bR ->
merge (p & Some (aL,bL) // Some (aR,bR1))
(p & None // Some (aR,bR2))
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_SSSN : forall p aL bL1 bL2 bL aR bR, merge bL1 bL2 bL ->
merge (p & Some (aL,bL1) // Some (aR,bR))
(p & Some (aL,bL2) // None)
(p & Some (aL,bL) // Some (aR,bR))
| merge_Branching_SSSS : forall p aL bL1 bL2 bL aR bR1 bR2 bR,
merge bL1 bL2 bL -> merge bR1 bR2 bR ->
merge (p & Some (aL,bL1) // Some (aR,bR1))
(p & Some (aL,bL2) // Some (aR,bR2))
(p & Some (aL,bL) // Some (aR,bR))
| merge_Cond : forall b Bt1 Be1 Bt2 Be2 Bt Be,
merge Bt1 Bt2 Bt -> merge Be1 Be2 Be ->
merge (If b Then Bt1 Else Be1)
(If b Then Bt2 Else Be2)
(If b Then Bt Else Be)
| merge_Call : forall X, merge (Call _ X) (Call _ X) (Call _ X)
.
Notation "B1 [V] B2 == B" := (merge B1 B2 B) (at level 20).
We start by proving that this relation is functional.
Furthermore, we can decide whether two behaviours are mergeable,
and compute their merge in the affirmative case.
Ltac fail_with H := right; intro H; induction H as [B HB]; inversion HB; auto.
Lemma merge_dec : forall B1 B2,
{ B | B1 [V] B2 == B } + { ~exists B, B1 [V] B2 == B }.
Merge preserves well-formedness.
Lemma merge_WF : forall B1 B2 B p, B1 [V] B2 == B ->
Behaviour_WF _ p B1 -> Behaviour_WF _ p B2 -> Behaviour_WF _ p B.
Relationship with the branching order
We now look into the relationship between merge and more_branches.Lemma larger_is_merge : forall B1 B2, B1 [>>] B2 -> B1 [V] B2 == B1.
Lemma merge_is_larger : forall B1 B2, B1 [V] B2 == B1 -> B1 [>>] B2.
Summary of the previous two lemmas.
Idempotence and commutativity follow directly from the definition.
Lemma merge_idempotent : forall B, B [V] B == B.
Lemma merge_comm : forall B1 B2 B, B1 [V] B2 == B -> B2 [V] B1 == B.
We can now prove that merge is a partial lub.
Lemma merge_is_upper_bound : forall B1 B2 B, B1 [V] B2 == B -> B [>>] B1.
Lemma merge_is_upper_bound' : forall B1 B2 B, B1 [V] B2 == B -> B [>>] B2.
Useful characterization, with dedicated tactics for recurring goals.
Local Ltac mb_trans B B' := apply MB_trans with B;
[idtac | apply merge_is_upper_bound with B']; auto.
Local Ltac mb_trans' B B' := apply MB_trans with B;
[idtac | apply merge_is_upper_bound' with B']; auto.
Local Ltac mb_trans'' B B' := apply MB_trans with B;
[apply merge_is_upper_bound with B' | idtac]; auto.
Local Ltac mb_trans''' B B' := apply MB_trans with B;
[apply merge_is_upper_bound' with B' | idtac]; auto.
Lemma MB_yields_merge : forall B1 B2 B1' B2' B,
B1 [>>] B1' -> B2 [>>] B2' -> B1 [V] B2 == B ->
exists B', B1' [V] B2' == B' /\ B [>>] B'.
Merge is an lub
Lemma MB_has_lub : forall B B1 B2, B [>>] B1 -> B [>>] B2 ->
exists B', B1 [V] B2 == B' /\ B [>>] B'.
Lemma merge_is_lub : forall B B1 B2, B [>>] B1 -> B [>>] B2 ->
forall B', B1 [V] B2 == B' -> B [>>] B'.
Using these results we can prove associativity of merge.