Library CC

Require Export Basic.
Require Export Common.

The general type of Core Choreographies

This type is parameterized over sets of process identifiers, values, expressions and recursion variables. A lot of stuff is common with SP, and was defined already in Common.

Record Signature :=
  { pid : DecType;
    var : DecType;
    value : DecType;
    expr : DecType;
    bexpr : DecType;
    recvar : DecType;
    ann : DecType;
    ev : @Eval expr var value value;
    bev : @Eval bexpr var value Bool}.

Notation "X [\] x" := (set_remove' (@eq_dec (pid _)) x X) (at level 50).
Notation "[#] X" := (set_size (@eq_dec (pid _)) X) (at level 40).
Notation "X [U] Y" := (set_union (@eq_dec (pid _)) X Y) (at level 50).
Notation "X [C] Y" := (@set_incl (pid _) X Y) (at level 40).

Ltac sup := rewrite set_union_iff; auto.

Section CCBase.

Variable Sig : Signature.

Notation Pid := (pid Sig).
Notation Var := (var Sig).
Notation Value := (value Sig).
Notation Expr := (expr Sig).
Notation BExpr := (bexpr Sig).
Notation RecVar := (recvar Sig).
Notation Ann := (ann Sig).
Notation Ev := (ev Sig).
Notation BEv := (bev Sig).

Notation PSt := (LState Value Var).
Notation Store := (State Pid Var Value).
Notation Forget := (@forget Pid Value Var RecVar).

Syntax of Core Choreographies.


Section Syntax.

Communication actions.

Inductive Eta : Type :=
 | Com : Pid -> Expr -> Pid -> Var -> Eta
 | Sel : Pid -> Pid -> Label -> Eta
.

Lemma eta_eq_dec : forall (eta eta':Eta), { eta = eta' } + { eta <> eta' }.

Choreographies.
A program is a pair containing all procedure definitions and the main choreography.
Procedure definitions are functions from a variable number of processes to choreographies, without free process names. We model this as a function returning a pair (list Pid)*Choreography, with the proviso that all processes occurring in the choreography must be included in the list of processes.

Definition DefSet := RecVar -> (list Pid)*Choreography.

Definition Program : Type := DefSet * Choreography.

Definition Procedures : Program -> DefSet := (@fst _ _).
Definition Main : Program -> Choreography := (@snd _ _ ).

Definition Vars := fun P X => fst (Procedures P X).
Definition Procs := fun P X => snd (Procedures P X).

Definition Names (D:DefSet) := fun X => fst (D X).

End Syntax.

Pretty-printing rules for choreographies.

Delimit Scope CC_scope with CC.


Notation "p # e --> q $ x" := (Com p e q x)
          (at level 50, e at level 9) : CC_scope.
Notation "p --> q [ l ]" := (Sel p q l)
          (at level 50) : CC_scope.
Notation "eta '@' ann ';;' C" := (Interaction eta ann C)
          (at level 60, right associativity) : CC_scope.
Notation "'If' p '??' b 'Then' C1 'Else' C2" := (Cond p b C1 C2)
          (at level 60) : CC_scope.

Open Scope CC_scope.

Syntactic properties of choreographies and programs.

Section Syntactic_Properties.

Lemma chor_eq_dec : forall (C C':Choreography), { C = C' } + { C <> C' }.

Initial choreographies do not contain runtime terms - these are the choreographies that programmers should write.

Fixpoint initial (C:Choreography) : Prop :=
match C with
| Interaction _ _ C' => initial C'
| Cond _ _ C1 C2 => initial C1 /\ initial C2
| Call _ => True
| RT_Call _ _ _ => False
| End => True
end.

Lemma initial_dec : forall C, {initial C} + {~initial C}.

No process attempts to communicate with itself.

Fixpoint no_self_comm (C:Choreography) : Prop :=
match C with
| Interaction eta _ C' => match eta with
                          | Com p _ q _ => p <> q
                          | Sel p q _ => p <> q
                          end /\ no_self_comm C'
| Cond _ _ C1 C2 => no_self_comm C1 /\ no_self_comm C2
| Call _ => True
| RT_Call _ _ C' => no_self_comm C'
| End => True
end.

Lemma no_self_comm_dec : forall C, {no_self_comm C} + {~no_self_comm C}.

There are no procedure calls with empty annotations.

Fixpoint no_empty_ann (C:Choreography) : Prop :=
match C with
| Interaction eta _ C' => no_empty_ann C'
| Cond _ _ C1 C2 => no_empty_ann C1 /\ no_empty_ann C2
| Call _ => True
| RT_Call _ l C' => l <> nil /\ no_empty_ann C'
| End => True
end.

Lemma no_empty_ann_dec : forall C, {no_empty_ann C} + {~no_empty_ann C}.

Lemma initial_no_empty_ann : forall C, initial C -> no_empty_ann C.

A choreography is well-formed if:
  • it does not contain self-communications;
  • annotations of runtime terms are not empty.
Inversion results.
A program is well-formed if there is a finite set of procedures Xs such that:
  • main is well-formed
  • all procedures are initial and well-formed
  • runtime terms in main are consistent with procedure annotations
  • procedure annotations are globally consistent
We first define the free procedure names in a choreography.

Definition set_union_rv := set_union (@eq_dec RecVar).

Fixpoint Free_RecVar (C:Choreography) : list RecVar :=
match C with
| Interaction _ _ C' => Free_RecVar C'
| Cond _ _ C1 C2 => set_union_rv (Free_RecVar C1) (Free_RecVar C2)
| Call Y => (Y::nil)
| RT_Call Y _ C' => set_union_rv (Y::nil) (Free_RecVar C')
| End => nil
end.

Definition X_Free (X:RecVar) (C:Choreography) : Prop := In X (Free_RecVar C).

Lemma X_Free_dec : forall X C, {X_Free X C} + {~X_Free X C}.

Inversion results for bound variables.

Lemma X_Free_Eta : forall X ann eta C, X_Free X (eta @ ann;;C) -> X_Free X C.

Lemma X_Free_Cond : forall X p b C1 C2,
  X_Free X (If p ?? b Then C1 Else C2) -> {X_Free X C1} + {X_Free X C2}.

Lemma Not_X_Free_Eta : forall X ann eta C, ~X_Free X (eta @ ann;;C) -> ~X_Free X C.

Lemma Not_X_Free_Then : forall X p b C1 C2,
  ~X_Free X (If p ?? b Then C1 Else C2) -> ~X_Free X C1.

Lemma Not_X_Free_Else : forall X p b C1 C2,
  ~X_Free X (If p ?? b Then C1 Else C2) -> ~X_Free X C2.

Consistent annotations.

Fixpoint consistent (Xs:RecVar -> list Pid) (C:Choreography) : Prop :=
match C with
| Interaction _ _ C' => consistent Xs C'
| Cond _ _ C1 C2 => consistent Xs C1 /\ consistent Xs C2
| Call X => True
| RT_Call X l C' => l [C] Xs X /\ consistent Xs C'
| End => True
end.

Lemma consistent_dec : forall Xs C, {consistent Xs C} + {~consistent Xs C}.

Lemma initial_consistent : forall C, initial C -> forall Xs, consistent Xs C.

The set of process names in a choreography.

Definition eta_pn (e:Eta) : list Pid :=
match e with
| Com p _ q _ => (p::q::nil)
| Sel p q _ => (p::q::nil)
end.

Fixpoint CCC_pn (C:Choreography) (Pids:RecVar -> list Pid) : list Pid :=
match C with
| Interaction eta _ C' => (eta_pn eta [U] CCC_pn C' Pids)
| Cond p _ C1 C2 => ((p::nil) [U] CCC_pn C1 Pids [U] CCC_pn C2 Pids)
| Call X => Pids X
| RT_Call _ l C' => l [U] CCC_pn C' Pids
| End => nil
end.

Lemma CCC_pn_mon : forall X Y, (forall Z p, In p (X Z) -> In p (Y Z)) ->
  forall C p, In p (CCC_pn C X) -> In p (CCC_pn C Y).

For well-formed programs, these are all relevant processes.

Definition CCP_pn (P:Program) := CCC_pn (Main P) (Vars P).

A program is well-annotated if every process used by a procedure is in its annotation.

Definition well_ann (P:Program) (X:RecVar) : Prop :=
  Vars P X <> nil /\ CCC_pn (Procs P X) (Vars P) [C] Vars P X.

Lemma well_ann_Main_change : forall D C C' X, well_ann (D,C) X -> well_ann (D,C') X.

Finally, well-formedness.

Definition Program_WF (P:Program) : Prop :=
  Choreography_WF (Main P) /\ consistent (Vars P) (Main P) /\
  forall X, no_self_comm (Procs P X) /\ initial (Procs P X) /\ well_ann P X.

Lemma Program_WF_Proc : forall P, Program_WF P ->
  forall X, Choreography_WF (Procs P X).

Lemma Program_WF_Main : forall P, Program_WF P -> Choreography_WF (Main P).

Lemma Program_WF_consistent : forall P, Program_WF P ->
  consistent (Vars P) (Main P).

Lemma Program_WF_initial_Proc : forall P, Program_WF P ->
  forall X, initial (Procs P X).

Lemma Program_WF_well_ann : forall P, Program_WF P ->
  forall X, well_ann P X.

Lemma Program_WF_Vars_incl : forall P, Program_WF P ->
  forall X, CCC_pn (Procs P X) (Vars P) [C] Vars P X.

Lemma Program_WF_Vars : forall P, Program_WF P ->
  forall X, Vars P X <> nil.

Inversion results.

Semantics of CC.

The next definition and lemmas extend some lemmas in module Transitions to communication actions, which are specific to CC.
One-step and multi-step reduction. Multi-step reduction is simply a reflexive and transitive closure.

Inductive CCC_To (D : DefSet) :
  Choreography -> Store -> (RichLabel Pid Value Var RecVar)
               -> Choreography -> Store -> Prop :=
 | C_Com p e q x a C s s' : let v := eval_on_state Ev e s p in
        s' [==] (s[[q,x => v]]) ->
        CCC_To D (p#e --> q$x @ a ;; C) s (RL_Com p v q x) C s'
 | C_Sel p q l a C s s': s [==] s' ->
        CCC_To D (p --> q [l] @ a ;; C) s (RL_Sel p q l) C s'
 | C_Then p b C1 C2 s s': s [==] s' ->
        eval_on_state BEv b s p = true ->
        CCC_To D (If p ?? b Then C1 Else C2) s (RL_Cond p) C1 s'
 | C_Else p b C1 C2 s s': s [==] s' ->
        eval_on_state BEv b s p = false ->
        CCC_To D (If p ?? b Then C1 Else C2) s (RL_Cond p) C2 s'
 | C_Delay_Eta eta ann C C' s s' t: disjoint_eta_rl eta t ->
        CCC_To D C s t C' s' ->
        CCC_To D (eta @ ann;; C) s t (eta @ ann;; C') s'
 | C_Delay_Cond p b C1 C2 C1' C2' s s' t: disjoint_p_rl p t ->
        CCC_To D C1 s t C1' s' ->
        CCC_To D C2 s t C2' s' ->
        CCC_To D (If p ?? b Then C1 Else C2) s t
                    (If p ?? b Then C1' Else C2') s'
 | C_Delay_Call ps X C C' s s' t:
        disjoint_ps_rl ps t -> CCC_To D C s t C' s' ->
        CCC_To D (RT_Call X ps C) s t (RT_Call X ps C') s'
 | C_Call_Local p X s s': s [==] s' ->
        [#] (fst (D X)) = 1 -> In p (fst (D X)) ->
        CCC_To D (Call X) s (RL_Call X p) (snd (D X)) s'
 | C_Call_Start p X s s': s [==] s' ->
        [#] (fst (D X)) > 1 -> In p (fst (D X)) ->
        CCC_To D (Call X) s (RL_Call X p)
                 (RT_Call X (fst (D X) [\] p) (snd (D X))) s'
 | C_Call_Enter p ps X C s s': s [==] s' ->
        [#] ps > 1 -> In p ps ->
        CCC_To D (RT_Call X ps C) s (RL_Call X p)
                 (RT_Call X (ps [\] p) C) s'
 | C_Call_Finish p ps X C s s': s [==] s' ->
        [#] ps = 1 -> In p ps ->
        CCC_To D (RT_Call X ps C) s (RL_Call X p) C s'
.

Notation "<< C , s >> --[ rl , D ]--> << C' , s' >>" :=
  (CCC_To D C s rl C' s') (at level 100).

Useful for inferring a transition automatically.

Lemma C_Com' : forall D p e q x a C s, let v := (eval_on_state Ev e s p) in
        <<p#e --> q$x @ a;; C,s>> --[RL_Com p v q x,D]--> <<C,s[[q,x => v]]>>.

Lemma C_Sel' : forall D p q l a C s,
        <<p --> q[l] @ a;; C,s>> --[RL_Sel p q l,D]--> <<C,s>>.

Lemma C_Then' : forall D p b C1 C2 s, eval_on_state BEv b s p = true ->
        <<If p ?? b Then C1 Else C2,s>> --[RL_Cond p,D]--> <<C1,s>>.

Lemma C_Else' : forall D p b C1 C2 s, eval_on_state BEv b s p = false ->
        <<If p ?? b Then C1 Else C2,s>> --[RL_Cond p,D]--> <<C2,s>>.

Lemma C_Call_Local' : forall D p X s, [#] (fst (D X)) = 1 -> In p (fst (D X)) ->
        <<Call X,s>> --[RL_Call X p,D]--> <<snd (D X),s>>.

Lemma C_Call_Start' : forall D p X s, [#] (fst (D X)) > 1 -> In p (fst (D X)) ->
        <<Call X,s>> --[RL_Call X p,D]-->
               <<RT_Call X (fst (D X) [\] p) (snd (D X)),s>>.

Lemma C_Call_Enter' : forall D p ps X C s, [#] ps > 1 -> In p ps ->
        <<RT_Call X ps C,s>> --[RL_Call X p,D]--> <<RT_Call X (ps [\] p) C,s>>.

Lemma C_Call_Finish' : forall D p ps X C s, [#] ps = 1 -> In p ps ->
        <<RT_Call X ps C,s>> --[RL_Call X p,D]--> <<C,s>>.

Definition Configuration : Type := Program * Store.

Inductive CCP_To : Configuration -> TransitionLabel _ _ -> Configuration -> Prop :=
 | CCP_Base D C s t C' s' : <<C,s>> --[t,D]--> <<C',s'>> ->
     CCP_To (D,C,s) (forget t) (D,C',s').

Inductive CCP_ToStar :
  Configuration -> list (TransitionLabel _ _) -> Configuration -> Prop :=
 | CCT_Base P s s' : s [==] s' -> CCP_ToStar (P,s) nil (P,s')
 | CCT_Step c1 t c2 l c3 : CCP_To c1 t c2 ->
                           CCP_ToStar c2 l c3 -> CCP_ToStar c1 (t::l) c3
.

Lemma CCT_Refl : forall c, CCP_ToStar c nil c.

End Semantics_Definitions.

Notations for reductions.

Notation "<< C , s >> --[ rl , D ]--> << C' , s' >>" :=
        (CCC_To D C s rl C' s') (at level 100) : CC_scope.
Notation "c --[ tl ]--> c'" := (CCP_To c tl c') (at level 50) : CC_scope.
Notation "c --[ ts ]-->* c'" := (CCP_ToStar c ts c') (at level 50) : CC_scope.

Section Sanity_Checks.

Example Com_reduction : forall P p e q x a C s,
  (P,p#e --> q$x @ a;; C,s) --[TL_Com p (eval_on_state Ev e s p) q]-->
        (P,C,s[[q,x => eval_on_state Ev e s p]]).

Example Sel_reduction : forall P p q l a C s,
  (P,p --> q[l] @ a;; C,s) --[TL_Sel p q l]--> (P,C,s).

End Sanity_Checks.

Main properties of the semantics


Section Properties.

Useful rules for reducing procedure calls.

Lemma RT_Call_reduce : forall ps, (ps <> nil) ->
  exists tl, forall D X C s, (D,RT_Call X ps C,s) --[tl]-->* (D,C,s).

Lemma Call_reduce : forall (D:DefSet) X, (fst (D X) <> nil) ->
  exists tl, forall s, (D,Call X,s) --[tl]-->* (D,snd (D X),s).

Transitions are preserved by state equivalence.
Determining the state from the label.
Transitions do not add new processes.

Lemma CCC_To_pn : forall D C s tl C' s', <<C,s>> --[tl,D]--> <<C',s'>> ->
  forall p, In p (RL_pn _ _ _ _ tl) -> In p (CCC_pn C (Names D)).

Lemma CCP_To_pn : forall P s tl P' s', (P,s) --[tl]--> (P',s') ->
  forall p, In p (TL_pn _ _ tl) -> In p (CCP_pn P).

Lemma CCC_To_pn' : forall D C s tl C' s', <<C,s>> --[tl,D]--> <<C',s'>> ->
  forall p, In p (CCC_pn C' (Names D)) ->
    In p (CCC_pn C (Names D))
     \/ exists X, (In p (CCC_pn (snd (D X)) (Names D)) /\ X_Free X C).

Lemma CCP_To_pn' : forall P s tl P' s', Program_WF P -> (P,s) --[tl]--> (P',s') ->
  forall p, In p (CCP_pn P') -> In p (CCP_pn P).

Reductions preserve well-formedness.
The set of procedure definitions never changes.
Reductions are also preserved under equivalence of the set of definitions.
Some more specific properties.
Deadlock-freedom by design.

Theorem progress : forall P, Main P <> End -> Program_WF P ->
  forall s, exists tl c', (P,s) --[tl]--> c'.

Theorem deadlock_freedom : forall P, Program_WF P ->
  forall s ts c', (P,s) --[ts]-->* c' ->
  {Main (fst c') = End} + {exists tl c'', c' --[tl]--> c''}.

End Properties.

Decidability results

In practice, programs are finite - so in particular they can only use a finite number of procedures. This has some implications for decidability and computability.

Fixpoint used_procedures_C (C:Choreography) (Xs:list RecVar) : Prop :=
match C with
| Interaction _ _ C' => used_procedures_C C' Xs
| Cond _ _ C1 C2 => used_procedures_C C1 Xs /\ used_procedures_C C2 Xs
| Call X => In X Xs
| RT_Call X _ C' => In X Xs /\ used_procedures_C C' Xs
| End => True
end.

We cannot compute the set of used procedures (it may be infinite), but we can check it.
Monotonicity and minimum requirements.
Given an adequate set of procedures, we can decide program well-formedness.

Results on determinism of the semantics.


Section Uniqueness.

Reductions and state.
Determinism of reductions given the label.
Conversely: the result choreography determines the transition label and resulting state.

Lemma CCC_To_eta_reduction : forall ann eta C s1 s2 tl,
  <<eta @ ann;;C,s1>> --[tl,D]--> <<C,s2>> ->
  (forall p e q x, eta = (p#e --> q$x) -> tl = RL_Com p (eval_on_state Ev e s1 p) q x)
  /\ (forall p q l, eta = (p --> q[l]) -> tl = RL_Sel p q l).

Lemma CCC_To_Then_reduction : forall p b C1 C2 s1 s2 tl,
  <<If p ?? b Then C1 Else C2,s1>> --[tl,D]--> <<C1,s2>> -> tl = RL_Cond p.

Lemma CCC_To_Else_reduction : forall p b C1 C2 s1 s2 tl,
  <<If p ?? b Then C1 Else C2,s1>> --[tl,D]--> <<C2,s2>> -> tl = RL_Cond p.

Lemma CCC_To_Call_reduction_1 : forall p X s1 s2 tl,
  initial (snd (D X)) -> In p (fst (D X)) ->
  <<Call X,s1>> --[tl,D]--> <<snd (D X),s2>> -> tl = RL_Call X p.

Lemma CCC_To_Call_reduction_2 : forall p X s1 s2 tl,
  initial (snd (D X)) -> In p (fst (D X)) ->
  <<Call X,s1>> --[tl,D]--> <<RT_Call X (fst (D X)[\]p) (snd (D X)),s2>> ->
  tl = RL_Call X p.

Lemma CCC_To_Call_reduction_3 : forall C p ps X s1 s2 tl, In p ps ->
  <<RT_Call X ps C,s1>> --[tl,D]--> <<RT_Call X (ps[\]p) C,s2>> ->
  tl = RL_Call X p.

Fixpoint C_size (C:Choreography) :=
match C with
| Eta@_;; C' => S (C_size C')
| Cond _ _ C1 C2 => S (C_size C1 + C_size C2)
| RT_Call _ _ C' => S (C_size C')
| _ => 0
end.

Fixpoint subterm (C1 C2:Choreography) : Prop :=
match C2 with
| Eta@_;;C' => C1 = C' \/ subterm C1 C'
| Cond _ _ C1' C2' => C1 = C1' \/ C1 = C2' \/ subterm C1 C1' \/ subterm C1 C2'
| RT_Call _ _ C' => C1 = C' \/ subterm C1 C'
| _ => False
end.

Lemma subterm_size : forall C C', subterm C C' -> C_size C < C_size C'.

Lemma subterm_not_equal : forall C C', subterm C C' -> C <> C'.

Lemma CCC_To_Call_reduction_4 : forall C p ps X s1 s2 tl,
  In p ps -> <<RT_Call X ps C,s1>> --[tl,D]--> <<C,s2>> -> tl = RL_Call X p.

Lemma CCC_To_deterministic_3 : forall C C' tl1 tl2 s s1 s2,
  <<C,s>> --[tl1,D]--> <<C',s1>> -> <<C,s>> --[tl2,D]-->
  <<C',s2>> -> tl1 = tl2.

Lemma CCC_To_deterministic_4 : forall C C' tl1 tl2 s s1 s2,
  <<C,s>> --[tl1,D]--> <<C',s1>> -> <<C,s>> --[tl2,D]--> <<C',s2>> -> s1 [==] s2.

The label alone determines the resulting state.
Currently not used, but might prove useful.

Lemma RL_Com_reduce_eq : forall D p C v v' q q' x x' s C' s' C'' s'',
  <<C,s>> --[RL_Com p v q x,D]--> <<C',s'>> ->
  <<C,s>> --[RL_Com p v' q' x',D]--> <<C'',s''>> -> v = v' /\ q = q' /\ x = x'.

Lemma TL_Com_reduce_eq : forall D p C v v' q q' s C' s' C'' s'',
  (D,C,s) --[TL_Com p v q]--> (D,C',s') ->
  (D,C,s) --[TL_Com p v' q']--> (D,C'',s'') -> v = v' /\ q = q'.

Lemma RL_Com_reduce_neq : forall D p p' C v v' q q' x x' s C' s' C'' s'',
  <<C,s>> --[RL_Com p v q x,D]--> <<C',s'>> ->
  <<C,s>> --[RL_Com p' v' q' x',D]--> <<C'',s''>> -> p <> p' -> q <> q'.

Lemma TL_Com_reduce_neq : forall D p p' C v v' q q' s C' s' C'' s'',
  (D,C,s) --[TL_Com p v q]--> (D,C',s') ->
  (D,C,s) --[TL_Com p' v' q']--> (D,C'',s'') -> p <> p' -> q <> q'.

Lemma RL_Sel_reduce_eq : forall D p C q q' l l' s C' s' C'' s'',
  <<C,s>> --[RL_Sel p q l,D]--> <<C',s'>> ->
  <<C,s>> --[RL_Sel p q' l',D]--> <<C'',s''>> -> q = q' /\ l = l'.

Lemma TL_Sel_reduce_eq : forall D p C q q' l l' s C' s' C'' s'',
  (D,C,s) --[TL_Sel p q l]--> (D,C',s') ->
  (D,C,s) --[TL_Sel p q' l']--> (D,C'',s'') -> q = q' /\ l = l'.

Lemma RL_Sel_reduce_neq : forall D p p' C q q' l l' s C' s' C'' s'',
  <<C,s>> --[RL_Sel p q l,D]--> <<C',s'>> ->
  <<C,s>> --[RL_Sel p' q' l',D]--> <<C'',s''>> -> p <> p' -> q <> q'.

Lemma TL_Sel_reduce_neq : forall D p p' C q q' l l' s C' s' C'' s'',
  (D,C,s) --[TL_Sel p q l]--> (D,C', s') ->
  (D,C,s) --[TL_Sel p' q' l']--> (D,C'', s'') -> p <> p' -> q <> q'.

End Uniqueness.

Confluence of CC

In this one we unfold the configuration because of the equivalence. Furthermore, we use logical disjunction - the labels are too weak...

Lemma diamond_3a : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]--> (P2,s2) ->
  (exists tl' s1', (P2,s2) --[ tl' ]-->* (P1,s1')
                 /\ s1 [==] s1' /\ Permutation tl1 (tl2::tl'))
  \/ (exists P' s', (P1,s1) --[ tl2 ]--> (P',s') /\ (P2,s2) --[ tl1 ]-->* (P',s')).

Lemma diamond_3 : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]--> (P2,s2) ->
  (exists tl' s1', (P2,s2) --[ tl' ]-->* (P1,s1') /\ s1 [==] s1')
  \/ (exists P' s', (P1,s1) --[ tl2 ]--> (P',s') /\ (P2,s2) --[ tl1 ]-->* (P',s')).

Lemma diamond_4' : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]-->* (P2,s2) ->
  (exists P' tl1' tl2' s1' s2' n,
    (P1,s1) --[ tl1' ]-->* (P',s1') /\ (P2,s2) --[ tl2' ]-->* (P',s2')
    /\ s1' [==] s2' /\ Permutation (tl1 ++ tl1') (tl2 ++ tl2')
    /\ length tl1 = length tl2' + n /\ length tl2 = length tl1' + n).

Lemma diamond_4a : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]-->* (P2,s2) ->
  (exists P' tl1' tl2' s1' s2',
    (P1,s1) --[ tl1' ]-->* (P',s1') /\ (P2,s2) --[ tl2' ]-->* (P',s2')
    /\ s1' [==] s2' /\ length tl1 + length tl1' = length tl2 + length tl2').

Lemma diamond_4b : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]-->* (P2,s2) ->
  (exists P' tl1' tl2' s1' s2',
    (P1,s1) --[ tl1' ]-->* (P',s1') /\ (P2,s2) --[ tl2' ]-->* (P',s2')
    /\ s1' [==] s2' /\ Permutation (tl1 ++ tl1') (tl2 ++ tl2')
    /\ length tl1' <= length tl2 /\ length tl2' <= length tl1).

Lemma diamond_4 : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]-->* (P2,s2) ->
  (exists P' tl1' tl2' s1' s2', (P1,s1) --[ tl1' ]-->* (P',s1')
                             /\ (P2,s2) --[ tl2' ]-->* (P',s2') /\ s1' [==] s2').

Useful particular cases.

Lemma diamond_5a : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]-->* (P2,s2) -> Main P2 = End ->
  (exists tl1' s1', (P1,s1) --[ tl1' ]-->* (P2,s1')
                  /\ s1' [==] s2 /\ length tl1 + length tl1' = length tl2).

Lemma diamond_5 : forall P s tl1 tl2 P1 s1 P2 s2,
  (P,s) --[ tl1 ]-->* (P1,s1) -> (P,s) --[ tl2 ]-->* (P2,s2) -> Main P2 = End ->
  (exists tl1' s1', (P1,s1) --[ tl1' ]-->* (P2,s1') /\ s1' [==] s2).

Lemma termination_unique : forall c tl1 c1 tl2 c2,
  c --[tl1]-->* c1 -> c --[tl2]-->* c2 ->
  Main (fst c1) = End -> Main (fst c2) = End -> snd c1 [==] snd c2.

End Confluence.

End CCBase.

Delimit Scope CC_scope with CC.


Notation "p # e --> q $ x" := (Com _ p e q x) (at level 50, e at level 9) : CC_scope.
Notation "p --> q [ l ]" := (Sel _ p q l) (at level 50) : CC_scope.
Notation "eta '@' ann ';;' C" := (Interaction _ eta ann C) (at level 60, right associativity) : CC_scope.
Notation "'If' p '??' b 'Then' C1 'Else' C2" := (Cond _ p b C1 C2) (at level 60) : CC_scope.
Notation "<< C , s >> --[ rl , D ]--> << C' , s' >>" := (CCC_To _ D C s rl C' s') (at level 100) : CC_scope.
Notation "c --[ tl ]--> c'" := (CCP_To _ c tl c') (at level 50, left associativity) : CC_scope.
Notation "c --[ ts ]-->* c'" := (CCP_ToStar _ c ts c') (at level 50, left associativity) : CC_scope.