Library Merge

Require Export BranchingOrder.

Merging of two behaviours


Section SP_Merge.

Open Scope SP.

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.

Lemma merge_unique : forall B1 B2 B B',
  B1 [V] B2 == B -> B1 [V] B2 == B' -> B = B'.

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.

Lemma MB_merge : forall B1 B2, B1 [>>] B2 <-> B1 [V] B2 == B1.

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.

Lemma merge_assoc : forall B1 B2 B3 B12 B23 B,
  B1 [V] B2 == B12 -> B12 [V] B3 == B -> B2 [V] B3 == B23 -> B1 [V] B23 == B.

End SP_Merge.

Notation "B1 [V] B2 == B" := (merge B1 B2 B) (at level 20).