Library SP

Require Export Common.
Require Export CC.

Local Open Scope nat_scope.

Preamble: a lot of things just as in CC.

Section SPBase.

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 Store := (State Pid Var Value).

Syntax of processes


Section Syntax.

Behaviours

Induction principles on behaviours.

Fixpoint depth (B:Behaviour) : nat :=
match B with
 | Send p e _ B' => 1 + depth B'
 | Recv p x _ B' => 1 + depth B'
 | Sel p l _ B' => 1 + depth B'
 | Branching p mB mB' =>
             1 + (match mB with None => 0 | Some (_,B) => depth B end)
               + (match mB' with None => 0 | Some (_,B) => depth B end)
 | Cond b B1 B2 => 1 + Nat.max (depth B1) (depth B2)
 | Call X => 1
 | End => 1
end.

Theorem Behaviour_ind' :
  forall P:Behaviour -> Prop,
    P End ->
    (forall p e a B, P B -> P (Send p e a B)) ->
    (forall p v a B, P B -> P (Recv p v a B)) ->
    (forall p l a B, P B -> P (Sel p l a B)) ->
    (forall p, P (Branching p None None)) ->
    (forall p a Bl, P Bl -> P (Branching p (Some (a,Bl)) None)) ->
    (forall p a Br, P Br -> P (Branching p None (Some (a,Br)))) ->
    (forall p a Bl a' Br, P Bl -> P Br ->
            P (Branching p (Some (a,Bl)) (Some (a',Br)))) ->
    (forall b B1 B2, P B1 -> P B2 -> P (Cond b B1 B2)) ->
    (forall X, P (Call X)) ->
    forall B, P B.

Theorem Behaviour_rec' :
  forall P:Behaviour -> Type,
    P End ->
    (forall p e a B, P B -> P (Send p e a B)) ->
    (forall p v a B, P B -> P (Recv p v a B)) ->
    (forall p l a B, P B -> P (Sel p l a B)) ->
    (forall p, P (Branching p None None)) ->
    (forall p a Bl, P Bl -> P (Branching p (Some (a,Bl)) None)) ->
    (forall p a Br, P Br -> P (Branching p None (Some (a,Br)))) ->
    (forall p a Bl a' Br, P Bl -> P Br ->
            P (Branching p (Some (a,Bl)) (Some (a',Br)))) ->
    (forall b B1 B2, P B1 -> P B2 -> P (Cond b B1 B2)) ->
    (forall X, P (Call X)) ->
    forall B, P B.

Local Ltac dec_eq t t' H H' :=
  case (eq_dec t t'); [intro H; rewrite <- H | right; intro; inversion H'; auto].

Equality of behaviours is decidable.

Networks

Networks are maps from process names to behaviours.

Definition Network := Pid -> Behaviour.

A lot of definitions are parameterised on process lists, for decidability.

Definition within_ps (ps:list Pid) (N:Network) :=
  forall p, ~In p ps -> N p = End.

Lemma within_ps_cons : forall ps N, within_ps ps N ->
  forall p, within_ps (p::ps) N.

Lemma within_ps_rev : forall ps N, within_ps ps N ->
  forall p, N p <> End -> In p ps.

Definition finite_support (N:Network) := exists ps, within_ps ps N.

Network equality


Definition Network_eq (N N':Network) : Prop := forall p, N p = N' p.

Network equality is an equivalence relation, as expected.
Programs in SP are pairs, like choreography programs in CC.

Definition DefSetB := RecVar -> Behaviour.

Definition Program : Type := DefSetB * Network.

Definition Procs : Program -> DefSetB := fst.
Definition Net : Program -> Network := snd.

Lemma SP_eta : forall P, P = (Procs P,Net P).

Syntactic constructors for building networks as lists

Definition EmptyNet : Network := fun _ => End.

Definition Process (p:Pid) (B:Behaviour) : Network :=
  fun p' => if (eq_dec p' p) then B else End.

Definition Par (N N':Network) :=
  fun p => if (Behaviour_eq_End_dec (N p)) then N' p else N p.

Definition Network_rm (N:Network) (p:Pid) :=
  fun r => if (eq_dec r p) then End else N r.


Definition Network_rm_ps (N:Network) (ps:list Pid) :=
  fun r => if (in_dec (@eq_dec Pid) r ps) then End else N r.

Definition Network_res_ps (N:Network) (ps:list Pid) :=
  fun r => if (in_dec (@eq_dec Pid) r ps) then N r else End.

End Syntax.

Add Parametric Relation : Network Network_eq
  reflexivity proved by Network_eq_refl
  symmetry proved by Network_eq_sym
  transitivity proved by Network_eq_trans
  as Network_eq_rel.

Pretty-printing rules. For some reason | only works if it is given an invalid level.

Delimit Scope SP_scope with SP.


Notation "p ! e @! a ; B" := (Send p e a B)
  (at level 60, e at level 9, right associativity) : SP_scope.
Notation "p ? xx @? a ; B" := (Recv p xx a B)
  (at level 60) : SP_scope.
Notation "p (+) l @+ a ; B" := (Sel p l a B)
  (at level 60, l at level 9) : SP_scope.
Notation "p '&' B1 '//' B2" := (Branching p B1 B2)
  (at level 60, no associativity) : SP_scope.
Notation "'If' e 'Then' B1 'Else' B2" := (Cond e B1 B2)
  (at level 60) : SP_scope.
Notation "'bnil'" := (End) : SP_scope.
Notation "'nnil'" := (EmptyNet) : SP_scope.

Notation "N | N'" := (Par N N') (at level 201, right associativity) : SP_scope.
Notation "p [ B ]" := (Process p B) (at level 40, no associativity) : SP_scope.
Notation "N '\' p" := (Network_rm N p) (at level 40, no associativity) : SP_scope.
Notation "N (==) N'" := (Network_eq N N') (at level 80) : SP_scope.

Open Scope SP_scope.


Syntactic properties

A bunch of useful properties about networks.

Lemma EmptyNet_within_ps : forall ps, within_ps ps EmptyNet.

Lemma EmptyNet_finite_supp : finite_support EmptyNet.

Lemma Process_refl : forall p B, (p[B]) p = B.

Lemma Process_out : forall p B p', p <> p' -> (p[B]) p' = End.

Lemma Par_proj1 : forall N N' p, N p <> End -> (N | N') p = N p.

Lemma Par_proj2 : forall N N' p, N p = End -> (N | N') p = N' p.

Lemma Par_proj1' : forall N N' p, N' p = End -> (N | N') p = N p.

Lemma Par_assoc : forall N N' N'', (N | (N' | N'')) (==) ((N | N') | N'').

Useful results for networks with two processes.

Lemma Par_fst : forall p Bp q Bq, p <> q -> (p[Bp] | q[Bq]) p = Bp.

Lemma Par_snd : forall p Bp q Bq, p <> q -> (p[Bp] | q[Bq]) q = Bq.

Lemmas about subterms.

Lemma Send_neq_cont : forall p e a B, p ! e @! a; B <> B.

Lemma Recv_neq_cont : forall p x a B, p ? x @? a; B <> B.

Lemma Sel_neq_cont : forall p l a B, p (+) l @+ a; B <> B.

Lemma Branching_l_neq_cont : forall p a Bl Br, Branching p (Some (a,Bl)) Br <> Bl.

Lemma Branching_r_neq_cont : forall p a Bl Br, Branching p Bl (Some (a,Br)) <> Br.

Lemma Then_neq_cont : forall b B1 B2, If b Then B1 Else B2 <> B1.

Lemma Else_neq_cont : forall b B1 B2, If b Then B1 Else B2 <> B2.

If two networks do not share any running processes, then their parallel composition is symmetric.

Definition Network_disjoint (N N':Network) :=
  forall p, N p = End \/ N' p = End.

Lemma Network_disjoint_sym : forall N N',
  Network_disjoint N N' -> Network_disjoint N' N.

Lemma Par_comm : forall N N', Network_disjoint N N' -> (N | N') (==) (N' | N).

Lemma Par_eq : forall N1 N2 N1' N2',
  N1 (==) N1' -> N2 (==) N2' -> (N1 | N2) (==) (N1' | N2').

Properties of removal.

Lemma Network_rm_In : forall N p, (N \ p) p = End.

Lemma Network_rm_out : forall N p p', p <> p' -> (N \ p) p' = N p'.

Lemma Network_rm_add : forall N p, N (==) (N \ p | p[N p]).

Lemma Network_rm_within_ps : forall N p ps,
  within_ps (p::ps) N -> within_ps ps (N \ p).

Lemma Network_rm_add_2_p : forall N p q Bp Bq, p <> q ->
  (N \ p \ q | p[Bp] | q[Bq]) p = Bp.

Lemma Network_rm_add_2_q : forall N p q Bp Bq, p <> q ->
  (N \ p \ q | p[Bp] | q[Bq]) q = Bq.

Lemma Network_rm_add_2_out : forall N p q r Bp Bq,
  p <> r -> q <> r -> (N \ p \ q | p[Bp] | q[Bq]) r = N r.

Lemma Network_rm_eq : forall N N', N (==) N' -> forall p, N \ p (==) N' \ p.

Lemma Network_rm_res_ps :
  forall N ps, N (==) (Network_rm_ps N ps | Network_res_ps N ps).

Rewriting of networks.
For a simpler formulation of the next lemmas.

Definition disj_3 (p q r:Pid) := p <> q /\ p <> r /\ q <> r.
Definition disj_4 (p q r s:Pid) :=
  p <> q /\ p <> r /\ p <> s /\ q <> r /\ q <> s /\ r <> s.

Local Ltac elim_3 H Hpq Hpr Hqr := destruct H as [Hpq [Hpr Hqr] ].
Local Ltac elim_4 H Hpq Hpr Hps Hqr Hqs Hrs :=
  destruct H as [Hpq [Hpr [Hps [Hqr [Hqs Hrs] ] ] ] ].

Lemma Network_eq_cross' : forall N N1 N2 p q r Bp Bq Br, disj_3 p q r ->
  N1 (==) (N \ p \ q | p[Bp] | q[Bq]) -> N2 (==) (N \ r | r[Br]) ->
  (N2 \ p \ q | p[Bp] | q[Bq]) (==) (N1 \ r | r[Br]).

Lemma Network_eq_cross : forall N N1 N2 p q r s Bp Bq Br Bs, disj_4 p q r s ->
  N1 (==) (N \ p \ q | p[Bp] | q[Bq]) -> N2 (==) (N \ r \ s | r[Br] | s[Bs]) ->
  (N2 \ p \ q | p[Bp] | q[Bq]) (==) (N1 \ r \ s | r[Br] | s[Bs]).

Lemma Network_eq_within_ps_dec : forall ps N N',
  within_ps ps N -> within_ps ps N' -> { N (==) N' }+{~ (N (==) N') }.

Well-formedness

Not used too much, since this is guaranteed by EPP.

Fixpoint Behaviour_WF (p:Pid) (B:Behaviour) : Prop :=
match B with
| q ! _ @! _ ; B' => p <> q /\ Behaviour_WF p B'
| q ? _ @? _ ; B' => p <> q /\ Behaviour_WF p B'
| q (+) l @+ _; B' => p <> q /\ Behaviour_WF p B'
| q & B1 // B2 => p <> q
      /\ (match B1 with None => True | Some (_,B) => Behaviour_WF p B end)
      /\ (match B2 with None => True | Some (_,B) => Behaviour_WF p B end)
| (If e Then B1 Else B2) => Behaviour_WF p B1 /\ Behaviour_WF p B2
| Call _ => True
| End => True
end.

Lemma Behaviour_WF_dec : forall p B, {Behaviour_WF p B} + {~Behaviour_WF p B}.

Definition Network_WF (N:Network) : Prop := forall p, Behaviour_WF p (N p).

Lemma Network_WF_dec : forall ps N, within_ps ps N ->
  {Network_WF N} + {~Network_WF N}.

Lemma Par_WF : forall N N', Network_WF N -> Network_WF N' -> Network_WF (N | N').

Lemma WF_Par1 : forall N N', Network_WF (N | N') -> Network_WF N.

Lemma WF_Par2 : forall N N', Network_disjoint N N' ->
  Network_WF (N | N') -> Network_WF N'.

Lemma Network_WF_par : forall N N', Network_disjoint N N' ->
  Network_WF (N | N') -> Network_WF N /\ Network_WF N'.

Lemma Network_WF_comm : forall N N', Network_disjoint N N' ->
  Network_WF (N | N') -> Network_WF (N' | N).

Program_WF doesn't make sense, because procedures don't know the processes that will execute them, so we do not know what to pass to Behaviour_WF. But: program with WF network reduces to program with WF network is an interesting property that is guaranteed by EPP.

Semantics of SP


Section Semantics.

Same strategy as for CC.

Inductive SP_To (D : DefSetB) :
  Network -> Store -> (RichLabel Pid Value Var RecVar) -> Network -> Store -> Prop :=
 | S_Com N p e a B q x a' B' N' s s' :
    N p = (q ! e @!a ; B) -> N q = (p ? x @? a'; B') ->
    let v := (eval_on_state Ev e s p) in
    N' (==) (N \ p \ q | p[B] | q[B']) -> s' [==] (s[[q,x => v]]) ->
    SP_To D N s (RL_Com p v q x) N' s'
 | S_LSel N p a B q a' Bl Br N' s s' :
    N p = (q (+) left @+ a ; B) -> N q = (p & Some (a',Bl) // Br) ->
    N' (==) (N \ p \ q | p[B] | q[Bl]) -> s [==] s' ->
    SP_To D N s (RL_Sel p q left) N' s'
 | S_RSel N p a B q a' Bl Br N' s s' :
    N p = (q (+) right @+ a ; B) -> N q = (p & Bl // Some (a',Br)) ->
    N' (==) (N \ p \ q | p[B] | q[Br]) -> s [==] s' ->
    SP_To D N s (RL_Sel p q right) N' s'
 | S_Then N p b B1 B2 N' s s' :
    N p = (If b Then B1 Else B2) ->
    eval_on_state BEv b s p = true ->
    N' (==) (N \ p | p[B1]) -> s [==] s' ->
    SP_To D N s (RL_Cond p) N' s'
 | S_Else N p b B1 B2 N' s s' :
    N p = (If b Then B1 Else B2) ->
    eval_on_state BEv b s p = false ->
    N' (==) (N \ p | p[B2]) -> s [==] s' ->
    SP_To D N s (RL_Cond p) N' s'
 | S_Call N p X N' s s' :
    N p = Call X ->
    N' (==) (N \ p | p[D X]) -> s [==] s' ->
    SP_To D N s (RL_Call X p) N' s'.

Notation "<< N , s >> --[ tl , D ]--> << N' , s' >>" :=
  (SP_To D N s tl N' s') (at level 100) : SP_scope.

Default reductions.

Lemma S_Com' : forall D N p e a B q x a' B' s,
  N p = (q ! e @! a ; B) -> N q = (p ? x @? a' ; B') ->
  let v := (eval_on_state Ev e s p) in
  <<N,s>> --[RL_Com p v q x,D]--> <<N \ p \ q | p[B] | q[B'],s[[q,x => v]]>>.

Lemma S_LSel' : forall D N p a B q a' Bl Br s,
  N p = (q (+) left @+ a ; B) -> N q = (p & Some (a',Bl) // Br) ->
  <<N,s>> --[RL_Sel p q left,D]--> <<N \ p \ q | p[B] | q[Bl],s>>.

Lemma S_RSel' : forall D N p a B q a' Bl Br s,
  N p = (q (+) right @+ a ; B) -> N q = (p & Bl // Some (a',Br)) ->
  <<N,s>> --[RL_Sel p q right,D]--> <<N \ p \ q | p[B] | q[Br], s>>.

Lemma S_Then' : forall D N p b B1 B2 s,
  N p = (If b Then B1 Else B2) -> eval_on_state BEv b s p = true ->
  <<N,s>> --[RL_Cond p,D]--> <<N \ p | p[B1],s>>.

Lemma S_Else' : forall D N p b B1 B2 s,
  N p = (If b Then B1 Else B2) -> eval_on_state BEv b s p = false ->
  <<N,s>> --[RL_Cond p,D]--> <<N \ p | p[B2],s>>.

Lemma S_Call' : forall D N p X s, N p = Call X ->
  <<N,s>> --[RL_Call X p,D]--> <<N \ p | p[D X],s>>.

Definition Configuration : Type := Program * Store.

Inductive SPP_To :
  Configuration -> (TransitionLabel Pid Value) -> Configuration -> Prop :=
 | SPP_Base D N s t N' s' : SP_To D N s t N' s' ->
     SPP_To (D,N,s) (forget t) (D,N',s').

Inductive SPP_ToStar :
  Configuration -> list (TransitionLabel Pid Value) -> Configuration -> Prop :=
 | SPT_Base P s s' : s [==] s' -> SPP_ToStar (P,s) nil (P,s')
 | SPT_Step c1 t c2 l c3 : SPP_To c1 t c2 ->
                           SPP_ToStar c2 l c3 -> SPP_ToStar c1 (t::l) c3
.

Lemma SPT_Refl : forall c, SPP_ToStar c nil c.

End Semantics.


Notation "<< N , s >> --[ tl , D ]--> << N' , s' >>" :=
  (SP_To D N s tl N' s') (at level 100) : SP_scope.
Notation "C --[ l ]--> C'" := (SPP_To C l C')
  (at level 50, left associativity) : SP_scope.
Notation "C --[ ls ]-->* C'" := (SPP_ToStar C ls C')
  (at level 50, left associativity) : SP_scope.

Results on determinism of the semantics.

These results are named consistently with CC.

Section Determinism.

Reductions are preserved by state equivalence...
...by network equivalence...
... and by extensionally equal sets of procedure definitions.

Lemma SP_To_Defs_wd : forall D D', (forall X, D X = D' X) ->
  forall N s tl N' s',
  <<N,s>> --[tl,D]--> <<N',s'>> -> <<N,s>> --[tl,D']--> <<N',s'>>.

The set of procedure definitions never changes.
Reductions and state.
Determinism of reductions given the label.

Lemma SP_To_deterministic_1 : forall N N1 N2 tl s s1 s2,
  <<N,s>> --[tl,D]--> <<N1,s1>> -> <<N,s>> --[tl,D]--> <<N2,s2>> -> N1 (==) N2.

Lemma SP_To_deterministic_2 : forall N N1 N2 tl s s1 s2,
  <<N,s>> --[tl,D]--> <<N1,s1>> -> <<N,s>> --[tl,D]--> <<N2,s2>> -> s1 [==] s2.

Lemma SP_To_deterministic : forall N N1 N2 tl1 tl2 s s1 s2,
  <<N,s>> --[tl1,D]--> <<N1,s1>> -> <<N,s>> --[tl2,D]--> <<N2,s2>> ->
  tl1 = tl2 -> (N1 (==) N2) /\ s1 [==] s2.


Ltac diff_assert p q H1 H2 H3 := assert (p <> q) as H1;
  [intro H1; rewrite H1, H2 in H3; inversion H3 | idtac].

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

The label alone determines the resulting state.

Confluence

Useful generalizations

Lemma SPP_To_deterministic_1 : forall P s tl P' s' P'' s'',
  (P,s) --[tl]--> (P',s') -> (P,s) --[tl]--> (P'',s'') ->
  Net P' (==) Net P''.

Lemma SPP_To_deterministic_2 : forall P s tl P' s' P'' s'',
  (P,s) --[tl]--> (P',s') -> (P,s) --[tl]--> (P'',s'') -> s' [==] s''.

Lemma SPP_To_deterministic : forall P s tl P' s' P'' s'',
  (P,s) --[tl]--> (P',s') -> (P,s) --[tl]--> (P'',s'') ->
  (Net P' (==) Net P'') /\ Procs P' = Procs P'' /\ s' [==] s''.

Lemma SPP_ToStar_deterministic_1 : forall P s tl P' s' P'' s'',
  (P,s) --[tl]-->* (P',s') -> (P,s) --[tl]-->* (P'',s'')
  -> Net P' (==) Net P''.

End SPBase.

Delimit Scope SP_scope with SP.


Notation "p ! e @! a ; B" := (Send _ p e a B)
  (at level 60, e at level 9, right associativity) : SP_scope.
Notation "p ? xx @? a ; B" := (Recv _ p xx a B)
  (at level 60, right associativity) : SP_scope.
Notation "p (+) l @+ a ; B" := (Sel _ p l a B)
  (at level 49, l at level 9, right associativity) : SP_scope.
Notation "p '&' B1 '//' B2" := (Branching _ p B1 B2)
  (at level 60, no associativity) : SP_scope.
Notation "'If' e 'Then' B1 'Else' B2" := (Cond _ e B1 B2)
  (at level 60) : SP_scope.
Notation "'bnil'" := (End _) : SP_scope.
Notation "'nnil'" := (EmptyNet _) : SP_scope.

Notation "<< N , s >> --[ tl , D ]--> << N' , s' >>" :=
  (SP_To _ D N s tl N' s') (at level 100) : SP_scope.
Notation "C --[ l ]--> C'" := (SPP_To _ C l C')
  (at level 50, left associativity) : SP_scope.
Notation "C --[ ls ]-->* C'" := (SPP_ToStar _ C ls C')
  (at level 50, left associativity) : SP_scope.

Notation "N | N'" := (Par _ N N') (at level 202, right associativity) : SP_scope.
Notation "p [ B ]" := (Process _ p B) (at level 201, no associativity) : SP_scope.
Notation "N \ p" := (Network_rm _ N p) (at level 50, no associativity) : SP_scope.
Notation "N (==) N'" := (Network_eq _ N N') (at level 80) : SP_scope.


Tactics for proofs by induction.

Ltac BInduction B := induction B using Behaviour_ind'.
Ltac BDInduction B B' := induction B using Behaviour_ind'; induction B' using Behaviour_ind'.

Ltac elim_as mB p := case mB; try induction p.
Ltac opt_elim b p := case_eq b; repeat induction p.

Tactics for network equality.

Ltac NEQr := apply Network_eq_refl.
Ltac NEQs := apply Network_eq_sym; auto.
Ltac NEQt N := apply Network_eq_trans with N; auto.