Library CC
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).
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.
Inductive Choreography : Type :=
| Interaction : Eta -> Ann -> Choreography -> Choreography
| Cond : Pid -> BExpr -> Choreography -> Choreography -> Choreography
| Call : RecVar -> Choreography
| RT_Call : RecVar -> (list Pid) -> Choreography -> Choreography
| End : Choreography
.
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.
Definition Choreography_WF (C:Choreography) : Prop :=
no_self_comm C /\ no_empty_ann C.
Lemma Choreography_WF_dec : forall C, {Choreography_WF C} + {~Choreography_WF C}.
Lemma Choreography_WF_no_self_comm : forall C, Choreography_WF C -> no_self_comm C.
Lemma Choreography_WF_no_empty_ann : forall C, Choreography_WF C -> no_empty_ann C.
Inversion results.
Lemma Choreography_WF_eta : forall ann eta C,
Choreography_WF (eta @ ann;;C) -> Choreography_WF C.
Lemma Choreography_WF_Then : forall p b C1 C2,
Choreography_WF (If p ?? b Then C1 Else C2) -> Choreography_WF C1.
Lemma Choreography_WF_Else : forall p b C1 C2,
Choreography_WF (If p ?? b Then C1 Else C2) -> Choreography_WF C2.
Lemma Choreography_WF_Call_1 : forall X ps C,
Choreography_WF (RT_Call X ps C) -> Choreography_WF C.
Lemma Choreography_WF_Call_2 : forall X p ps C,
Choreography_WF (RT_Call X ps C) -> [#] ps > 1 ->
Choreography_WF (RT_Call X (ps [\] p) C).
A program is well-formed if there is a finite set of procedures Xs such that:
We first define the free procedure names in a choreography.
- 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
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.
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.
Lemma Program_WF_Main_change : forall D C C',
Choreography_WF C' -> consistent (Names D) C' ->
Program_WF (D,C) -> Program_WF (D,C').
Lemma Program_WF_eta : forall D C ann eta,
Program_WF (D,eta @ ann;;C) -> Program_WF (D,C).
Lemma Program_WF_Then : forall D p b C1 C2,
Program_WF (D,If p ?? b Then C1 Else C2) -> Program_WF (D,C1).
Lemma Program_WF_Else : forall D p b C1 C2,
Program_WF (D,If p ?? b Then C1 Else C2) -> Program_WF (D,C2).
Lemma Program_WF_Call : forall D X ps C,
Program_WF (D,RT_Call X ps C) -> Program_WF (D,C).
End Syntactic_Properties.
The next definition and lemmas extend some lemmas in module
Transitions to communication actions, which are specific to
CC.
Definition disjoint_eta_rl (eta:Eta) (t:RichLabel Pid Value Var RecVar) : Prop :=
match eta with
| p # _ --> q $ _ => disjoint_p_rl p t /\ disjoint_p_rl q t
| p --> q [_] => disjoint_p_rl p t /\ disjoint_p_rl q t
end.
Lemma disjoint_Sel_Sel : forall p q l p' q' l',
disjoint_eta_rl (p --> q[l]) (RL_Sel p' q' l') ->
disjoint (p::q::nil) (p'::q'::nil).
Lemma disjoint_Com_Com : forall p q e x p' q' v x',
disjoint_eta_rl (p#e --> q$x) (RL_Com p' v q' x') ->
disjoint (p::q::nil) (p'::q'::nil).
Lemma disjoint_Com_Sel : forall p q e x p' q' l,
disjoint_eta_rl (p#e --> q$x) (RL_Sel p' q' l) ->
disjoint (p::q::nil) (p'::q'::nil).
Lemma disjoint_Sel_Com : forall p q l p' v q' x,
disjoint_eta_rl (p --> q[l]) (RL_Com p' x q' v) ->
disjoint (p::q::nil) (p'::q'::nil).
Lemma disjoint_eta_rl_eq : forall eta t t', Forget t = Forget t' ->
disjoint_eta_rl eta t -> disjoint_eta_rl eta t'.
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.
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.
Lemma CCC_To_eq : forall D C s1 tl C' s2 s1' s2', s1 [==] s1' -> s2 [==] s2' ->
<<C,s1>> --[tl,D]--> <<C',s2>> -> <<C,s1'>> --[tl,D]--> <<C',s2'>>.
Lemma CCP_To_eq : forall P s1 tl P' s2 s1' s2', s1 [==] s1' -> s2 [==] s2' ->
(P,s1) --[tl]--> (P',s2) -> (P,s1') --[tl]--> (P',s2').
Lemma CCP_ToStar_eq : forall P s1 tl P' s2 s1' s2', s1 [==] s1' -> s2 [==] s2' ->
(P,s1) --[tl]-->* (P',s2) -> (P,s1') --[tl]-->* (P',s2').
Lemma CCT_Trans : forall c tl c' tl' c'',
c --[tl]-->* c' -> c' --[tl']-->* c'' -> c --[tl++tl']-->* c''.
Determining the state from the label.
Lemma CCC_To_Com_state : forall D C s p v q x C' s',
<<C,s>> --[RL_Com p v q x,D]--> <<C',s'>> -> s' [==] (s[[q,x => v]]).
Lemma CCC_To_Sel_state : forall D C s p v l C' s',
<<C,s>> --[RL_Sel p v l,D]--> <<C',s'>> -> s [==] s'.
Lemma CCC_To_Cond_state : forall D C s p C' s',
<<C,s>> --[RL_Cond p,D]--> <<C',s'>> -> s [==] s'.
Lemma CCC_To_Call_state : forall D C s p X C' s',
<<C,s>> --[RL_Call X p,D]--> <<C',s'>> -> s [==] s'.
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.
Lemma CCP_To_consistent : forall P s l P' s',
Program_WF P -> (P,s) --[l]--> (P',s') -> consistent (Vars P') (Main P').
Lemma CCP_To_Program_WF : forall P s l P' s',
Program_WF P -> (P,s) --[l]--> (P',s') -> Program_WF P'.
Lemma CCP_ToStar_Program_WF : forall P s l P' s',
Program_WF P -> (P,s) --[l]-->* (P',s') -> Program_WF P'.
Lemma CCP_ToStar_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).
The set of procedure definitions never changes.
Lemma CCP_To_Defs_stable : forall D D' C C' tl s s',
(D,C,s) --[tl]--> (D',C',s') -> D = D'.
Lemma CCP_ToStar_Defs_stable : forall D D' C C' tl s s',
(D,C,s) --[tl]-->* (D',C',s') -> D = D'.
Reductions are also preserved under equivalence of the set of definitions.
Lemma CCC_To_Defs_eq : forall D D' C s tl C' s',
(forall X, D X = D' X) ->
<<C,s>> --[tl,D]--> <<C',s'>> -> <<C,s>> --[tl,D']--> <<C',s'>>.
Lemma CCP_To_Defs_eq : forall P s tl P' s' D,
(forall X, Procedures P X = D X) ->
(P,s) --[tl]--> (P',s') -> (D,Main P,s) --[tl]--> (D,Main P',s').
Lemma CCP_ToStar_Defs_eq : forall P s tl P' s' D,
(forall X, Procedures P X = D X) ->
(P,s) --[tl]-->* (P',s') -> (D,Main P,s) --[tl]-->* (D,Main P',s').
Some more specific properties.
Lemma CCC_To_Com_neq : forall D C s p v q x C' s', Choreography_WF C ->
<<C,s>> --[RL_Com p v q x,D]--> <<C',s'>> -> p <> q.
Lemma CCC_To_Sel_neq : forall D C s p q l C' s', Choreography_WF C ->
<<C,s>> --[RL_Sel p q l,D]--> <<C',s'>> -> p <> q.
Lemma CCP_ToStar_End : forall P s P' s' tl,
(P,s) --[ tl ]-->* (P',s') -> Main P = End -> tl = nil /\ s [==] s'.
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.
Lemma used_procedures_C_mon : forall C Xs Ys, set_incl Xs Ys ->
used_procedures_C C Xs -> used_procedures_C C Ys.
Lemma used_procedures_C_Free : forall C Xs, used_procedures_C C Xs ->
forall X, X_Free X C -> In X Xs.
Given an adequate set of procedures, we can decide program well-formedness.
Definition used_procedures (P:Program) (Xs:list RecVar) :=
used_procedures_C (Main P) Xs /\
forall X, (In X Xs -> used_procedures_C (Procs P X) Xs)
/\ (~In X Xs -> Procs P X = End /\ Vars P X <> nil).
Lemma used_procedures_Main : forall P Xs,
used_procedures P Xs -> used_procedures_C (Main P) Xs.
Lemma used_procedures_Procs : forall P Xs, used_procedures P Xs ->
forall X, In X Xs -> used_procedures_C (Procs P X) Xs.
Lemma used_procedures_End : forall P Xs, used_procedures P Xs ->
forall X, ~In X Xs -> Procs P X = End.
Lemma used_procedures_Vars : forall P Xs, used_procedures P Xs ->
forall X, ~In X Xs -> Vars P X <> nil.
Lemma Program_WF_dec : forall P Xs, used_procedures P Xs ->
{Program_WF P} + {~Program_WF P}.
Lemma CCP_To_used_procedures : forall P s l P' s' Xs, used_procedures P Xs ->
(P,s) --[l]--> (P',s') -> used_procedures P' Xs.
Lemma CCC_To_Xs : forall D C s p X C' s' Xs, used_procedures_C C Xs ->
<<C,s>> --[RL_Call X p,D]--> <<C',s'>> -> In X Xs.
Reductions and state.
Hypothesis D : DefSet.
Lemma CCC_To_disjoint_eval : forall C s tl s' p e C', disjoint_p_rl p tl ->
<<C,s>> --[tl,D]--> <<C',s'>> -> eval_on_state Ev e s p = eval_on_state Ev e s' p.
Lemma CCC_To_disjoint_beval : forall C s tl s' p b C', disjoint_p_rl p tl ->
<<C,s>> --[tl,D]--> <<C',s'>> -> eval_on_state BEv b s p = eval_on_state BEv b s' p.
Lemma CCC_To_disjoint_update : forall C s tl s' p x v C', disjoint_p_rl p tl ->
<<C,s>> --[tl,D]--> <<C',s'>> ->
<<C,s[[p,x => v]]>> --[tl,D]--> <<C',s'[[p,x => v]]>>.
Determinism of reductions given the label.
Lemma CCC_To_deterministic_1 : forall C C1 C2 tl s s1 s2,
<<C,s>> --[tl,D]--> <<C1,s1>> -> <<C,s>> --[tl,D]--> <<C2,s2>> -> C1 = C2.
Lemma CCC_To_deterministic_2 : forall C C1 C2 tl s s1 s2,
<<C,s>> --[tl,D]--> <<C1,s1>> -> <<C,s>> --[tl,D]--> <<C2,s2>> -> s1 [==] s2.
Lemma CCC_To_deterministic : forall C C1 C2 tl1 tl2 s s1 s2,
<<C,s>> --[tl1,D]--> <<C1,s1>> -> <<C,s>> --[tl2,D]--> <<C2,s2>> ->
tl1 = tl2 -> C1 = C2 /\ s1 [==] s2.
<<C,s>> --[tl,D]--> <<C1,s1>> -> <<C,s>> --[tl,D]--> <<C2,s2>> -> C1 = C2.
Lemma CCC_To_deterministic_2 : forall C C1 C2 tl s s1 s2,
<<C,s>> --[tl,D]--> <<C1,s1>> -> <<C,s>> --[tl,D]--> <<C2,s2>> -> s1 [==] s2.
Lemma CCC_To_deterministic : forall C C1 C2 tl1 tl2 s s1 s2,
<<C,s>> --[tl1,D]--> <<C1,s1>> -> <<C,s>> --[tl2,D]--> <<C2,s2>> ->
tl1 = tl2 -> C1 = C2 /\ s1 [==] s2.
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.
Lemma CCC_To_rl_implies_state : forall C1 s tl C1' s1 C2 C2' s2,
<<C1,s>> --[tl,D]--> <<C1',s1>> -> <<C2,s>> --[tl,D]--> <<C2',s2>> -> s1 [==] s2.
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.
Section Confluence.
Lemma diamond_Chor : forall D C s tl1 tl2 C1 C2 s1 s2,
<<C,s>> --[tl1,D]--> <<C1,s1>> -> <<C,s>> --[tl2,D]--> <<C2,s2>> -> tl1 <> tl2 ->
exists C' s', <<C1,s1>> --[tl2,D]--> <<C',s'>> /\ <<C2,s2>> --[tl1,D]--> <<C',s'>>.
Lemma diamond_1 : forall c tl1 tl2 c1 c2, c --[ tl1 ]--> c1 -> c --[ tl2 ]--> c2 ->
tl1 <> tl2 -> exists c', c1 --[ tl2 ]--> c' /\ c2 --[ tl1 ]--> c'.
Lemma diamond_2 : forall c tl1 tl2 c1 c2, c --[ tl1 ]--> c1 -> c --[ tl2 ]--> c2 ->
{fst c1 = fst c2 /\ snd c1 [==] snd c2}
+ {exists c', c1 --[ tl2 ]--> c' /\ c2 --[ tl1 ]--> c'}.
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.