theory BeispielZahlenweltGesetz
imports BeispielZahlenwelt Simulation Gesetze AllgemeinesGesetz
begin

section\<open>Beispiel: BeispielZahlenwelt aber mit Gesetz (Experimental)\<close>

  (*<*)
  fun delta_zahlenwelt :: \<open>(zahlenwelt, person, int) delta\<close> where
    \<open>delta_zahlenwelt (Handlung (Zahlenwelt vor_besitz) (Zahlenwelt nach_besitz)) =
        Aenderung.delta_num_fun (Handlung vor_besitz nach_besitz)\<close>
  (*>*)

subsection\<open>Setup\<close>
  text\<open>Wir nehmen an unsere handelnde Person ist \<^const>\<open>Alice\<close>.\<close>

  definition \<open>beispiel_case_law_absolut maxime handlungsabsicht \<equiv>
    simulateOne
      (SimConsts
        Alice
        maxime
        (printable_case_law_ableiten_absolut show_zahlenwelt))
      5 handlungsabsicht initialwelt (Gesetz {})\<close>
  definition \<open>beispiel_case_law_relativ maxime handlungsabsicht \<equiv>
    simulateOne
      (SimConsts
        Alice
        maxime
        (case_law_ableiten_relativ delta_zahlenwelt))
      10 handlungsabsicht initialwelt (Gesetz {})\<close>

subsection\<open>Beispiele\<close>
  text\<open>Alice kann beliebig oft 5 Wohlstand für sich selbst erschaffen.
  Das entstehende Gesetz ist nicht sehr gut, da es einfach jedes Mal einen
  Snapshot der Welt aufschreibt und nicht sehr generisch ist.\<close>
  (*check: ist auch eine moralische Handlung*)
  lemma \<open>beispiel_case_law_absolut maxime_zahlenfortschritt (Handlungsabsicht (erschaffen 5))
  =
  Gesetz
  {(\<section> 5,
    Rechtsnorm
     (Tatbestand ([(Alice, 25), (Bob, 10), (Carol, - 3)], [(Alice, 30), (Bob, 10), (Carol, - 3)]))
     (Rechtsfolge Erlaubnis)),
   (\<section> 4,
    Rechtsnorm
     (Tatbestand ([(Alice, 20), (Bob, 10), (Carol, - 3)], [(Alice, 25), (Bob, 10), (Carol, - 3)]))
     (Rechtsfolge Erlaubnis)),
   (\<section> 3,
    Rechtsnorm
     (Tatbestand ([(Alice, 15), (Bob, 10), (Carol, - 3)], [(Alice, 20), (Bob, 10), (Carol, - 3)]))
     (Rechtsfolge Erlaubnis)),
   (\<section> 2,
    Rechtsnorm
     (Tatbestand ([(Alice, 10), (Bob, 10), (Carol, - 3)], [(Alice, 15), (Bob, 10), (Carol, - 3)]))
     (Rechtsfolge Erlaubnis)),
   (\<section> 1,
    Rechtsnorm
     (Tatbestand ([(Alice, 5), (Bob, 10), (Carol, - 3)], [(Alice, 10), (Bob, 10), (Carol, - 3)]))
     (Rechtsfolge Erlaubnis))}
  \<close> by eval

  text\<open>Die gleiche Handlung, wir schreiben aber nur die Änderung der Welt ins Gesetz:\<close>
  lemma \<open>beispiel_case_law_relativ maxime_zahlenfortschritt (Handlungsabsicht (erschaffen 5)) =
    Gesetz
    {(\<section> 1, Rechtsnorm (Tatbestand [Gewinnt Alice 5]) (Rechtsfolge Erlaubnis))}\<close>
    by eval

  (*TODO: Beispiele mit der guten maxime!*)
  lemma \<open>beispiel_case_law_relativ
    (Maxime (\<lambda>(ich::person) h. (\<forall>pX. individueller_fortschritt pX h))) (Handlungsabsicht (erschaffen 5)) =
  Gesetz {(\<section> 1, Rechtsnorm (Tatbestand [Gewinnt Alice 5]) (Rechtsfolge Erlaubnis))}\<close>
    by eval

  text\<open>Nun ist es \<^const>\<open>Alice\<close> verboten Wohlstand für sich selbst zu erzeugen.\<close>
  (*check: ist auch keine moralische Handlung*)
  lemma \<open>beispiel_case_law_relativ
          (Maxime (\<lambda>ich. individueller_strikter_fortschritt ich))
          (Handlungsabsicht (erschaffen 5)) =
    Gesetz {(\<section> 1, Rechtsnorm (Tatbestand [Gewinnt Alice 5]) (Rechtsfolge Verbot))}\<close>
    by eval

  (*check: ist auch eine moralische Handlung*)
  lemma \<open>beispiel_case_law_relativ
          (Maxime (\<lambda>ich. globaler_strikter_fortschritt))
          (Handlungsabsicht (erschaffen 5)) =
    Gesetz {(\<section> 1, Rechtsnorm (Tatbestand [Gewinnt Alice 5]) (Rechtsfolge Erlaubnis))}\<close>
    by eval

  (*check: ist auch keine moralische Handlung*)
  lemma \<open>beispiel_case_law_relativ
          (Maxime (\<lambda>ich. globaler_strikter_fortschritt))
          (Handlungsabsicht (erschaffen 0)) =
    Gesetz {(\<section> 1, Rechtsnorm (Tatbestand []) (Rechtsfolge Verbot))}\<close>
    by eval

  (*check: ist auch keine moralische Handlung*)
  lemma \<open>beispiel_case_law_relativ
          maxime_zahlenfortschritt
          (Handlungsabsicht (erschaffen 0)) =
    Gesetz {(\<section> 1, Rechtsnorm (Tatbestand []) (Rechtsfolge Erlaubnis))}\<close>
    by eval

  (*check: ist auch eine moralische Handlung*)
  lemma\<open>beispiel_case_law_relativ
            (Maxime (\<lambda>ich. globaler_fortschritt))
            (Handlungsabsicht (erschaffen 0))
    =
    Gesetz {(\<section> 1, Rechtsnorm (Tatbestand []) (Rechtsfolge Erlaubnis))}\<close>
    by eval

  (*check: ist auch eine moralische Handlung*)
  lemma\<open>beispiel_case_law_relativ
          (Maxime (\<lambda>ich. globaler_fortschritt))
          (Handlungsabsicht (stehlen_nichtwf 5 Bob))
    =
    Gesetz
    {(\<section> 1, Rechtsnorm (Tatbestand [Gewinnt Alice 5, Verliert Bob 5]) (Rechtsfolge Erlaubnis))}\<close>
    by eval

  text\<open>Stehlen ist verboten:\<close>
  (*check: ist auch keine moralische Handlung*)
  lemma \<open>beispiel_case_law_relativ maxime_zahlenfortschritt (Handlungsabsicht (stehlen_nichtwf 5 Bob)) =
    Gesetz
    {(\<section> 1, Rechtsnorm (Tatbestand [Gewinnt Alice 5, Verliert Bob 5]) (Rechtsfolge Verbot))}\<close>
    by eval

  text\<open>Auch wenn \<^const>\<open>Alice\<close> von sich selbst stehlen möchte ist dies verboten,
  obwohl hier keiner etwas verliert:\<close>
  (*check: ist auch keine moralische Handlung*)
  lemma \<open>beispiel_case_law_relativ maxime_zahlenfortschritt (Handlungsabsicht (stehlen_nichtwf 5 Alice)) =
    Gesetz {(\<section> 1, Rechtsnorm (Tatbestand []) (Rechtsfolge Verbot))}\<close>
    by eval

  text\<open>Der Grund ist, dass \<^const>\<open>Alice\<close> die abstrakte Handlung "Alice wird bestohlen" gar nicht gut
  fände, wenn sie jemand anderes ausführt:\<close>
(*
  lemma \<open>debug_maxime show_zahlenwelt initialwelt
          maxime_zahlenfortschritt (Handlungsabsicht (stehlen_nichtwf 5 Alice)) =
   {VerletzteMaxime (Opfer Alice) (Taeter Bob)
     (Handlung [(Alice, 5), (Bob, 10), (Carol, - 3)] [(Bob, 15), (Carol, - 3)]),
    VerletzteMaxime (Opfer Alice) (Taeter Carol)
     (Handlung [(Alice, 5), (Bob, 10), (Carol, - 3)] [(Bob, 10), (Carol, 2)]),
    VerletzteMaxime (Opfer Alice) (Taeter Eve)
     (Handlung [(Alice, 5), (Bob, 10), (Carol, - 3)] [(Bob, 10), (Carol, - 3), (Eve, 5)])
   }\<close>
    by eval
*)
  text\<open>Leider ist das hier abgeleitete Gesetz sehr fragwürdig:
  \<^term>\<open>Rechtsnorm (Tatbestand []) (Rechtsfolge Verbot)\<close>

  Es besagt, dass Nichtstun verboten ist.\<close>

  text\<open>Indem wir die beiden Handlungen Nichtstun und Selbstbestehlen betrachten,
  können wir sogar ein widersprüchliches Gesetz ableiten:\<close>
  lemma \<open>simulateOne
      (SimConsts
        Alice
        maxime_zahlenfortschritt
        (case_law_ableiten_relativ delta_zahlenwelt))
      20 (Handlungsabsicht (stehlen_nichtwf 5 Alice)) initialwelt
      (beispiel_case_law_relativ maxime_zahlenfortschritt (Handlungsabsicht (erschaffen 0)))
    =
    Gesetz
  {(\<section> 2, Rechtsnorm (Tatbestand []) (Rechtsfolge Verbot)),
   (\<section> 1, Rechtsnorm (Tatbestand []) (Rechtsfolge Erlaubnis))}\<close>
    by eval

  text\<open>Meine persönliche Conclusion: Wir müssen irgendwie die Absicht mit ins Gesetz schreiben.\<close>

  text\<open>Es ist \<^const>\<open>Alice\<close> verboten, etwas zu verschenken:\<close>
  (*Check*)
  lemma\<open>beispiel_case_law_relativ maxime_zahlenfortschritt (Handlungsabsicht (schenken 5 Bob))
    =
    Gesetz
      {(\<section> 1,
        Rechtsnorm (Tatbestand [Verliert Alice 5, Gewinnt Bob 5]) (Rechtsfolge Verbot))}\<close>
    by eval
  text\<open>Der Grund ist, dass \<^const>\<open>Alice\<close> dabei etwas verliert und
  die \<^const>\<open>maxime_zahlenfortschritt\<close> dies nicht Erlaubt.
  Es fehlt eine Möglichkeit zu modellieren, dass \<^const>\<open>Alice\<close> damit einverstanden ist,
  etwas abzugeben.
  Doch wir haben bereits in @{thm stehlen_ist_schenken} gesehen,
  dass \<^const>\<open>stehlen\<close> und \<^const>\<open>schenken\<close> nicht unterscheidbar sind.\<close>

(*TODO: gesetz ableiten aendern, so dass allgemeines gesetz ableiten eine
handlungsabsicht anstatt einer handlung nimmt.
Evtl in neue Datei, damit sich dieses Beipsiel noch gut liesst.*)

  text\<open>Folgende ungültige Maxime würde es erlauben, dass \<^const>\<open>Alice\<close> Leute bestehlen darf:\<close>
  lemma\<open>beispiel_case_law_relativ
            (Maxime (\<lambda>ich. individueller_fortschritt Alice))
            (Handlungsabsicht (stehlen_nichtwf 5 Bob))
    =
    Gesetz
    {(\<section> 1, Rechtsnorm (Tatbestand [Gewinnt Alice 5, Verliert Bob 5]) (Rechtsfolge Erlaubnis))}\<close>
    by eval
end


theory Traceback_Properties
imports Safety_Properties
begin

section \<open>Traceback properties\<close>

text \<open>In this section, we prove various traceback properties,
by essentially giving trace-based justifications of certain
occurring situations that are relevant for access to information:
%
\begin{description}
\item{\bf Being an author. }
If a user is an author of a paper, then either the user has registered the paper in the first
place or, inductively, has been appointed as coauthor by another author.
%
\item{\bf Being a chair. }
If a user is a chair of a conference, then either that user has registered the conference
which has been approved by the superuser or, inductively, that user has been appointed
by an existing chair of that conference.
%
%
\item{\bf Being a PC member. }
If a user is a PC member in a conference, then the user either must have been the original chair or must
have been appointed by a chair.
%
\item{\bf Being a reviewer. }
If a user is a paper's reviewer, then the user must have been appointed by a chair (from
among the PC members who have not declared a conflict with the paper).
%
\item{\bf Having conflict. }
If a user has conflict with a paper, then the user is either an author of the paper or the
conflict has been declared by that user or by a paper's author, in such a way that between
the moment when the conflict has been last declared and the current moment there is no
transition that successfully removes the conflict.
%
\item{\bf Conference reaching a phase. }
If a conference is in a given phase different from ``no phase'', then this has happened as
a consequence of either a conference approval action by the superuser (if the phase is
Setup) or a phase change action by a chair (otherwise).
\end{description}

More details and explanations can be found in \<^cite>\<open>\<open>Section 3.6\<close> in "cocon-JAR2021"\<close>.
\<close>

subsection \<open>Preliminaries\<close>

inductive trace_between :: "state \<Rightarrow> (state,act,out) trans trace \<Rightarrow> state \<Rightarrow> bool" where
  empty[simp]: "trace_between s [] s"
| step: "\<lbrakk>trace_between s tr sh; step sh a = (ou,s')\<rbrakk> \<Longrightarrow> trace_between s (tr@[Trans sh a ou s']) s'"

inductive_simps
  trace_ft_empty[simp]: "trace_between s [] s'" and
  trace_ft_snoc: "trace_between s (tr@[trn]) s'"
thm trace_ft_empty trace_ft_snoc

lemma trace_ft_append: "trace_between s (tr1@tr2) s'
  \<longleftrightarrow> (\<exists>sh. trace_between s tr1 sh \<and> trace_between sh tr2 s')"
  apply (induction tr2 arbitrary: s' rule: rev_induct)
   apply simp
  apply (subst append_assoc[symmetric], subst trace_ft_snoc)
  apply (auto simp: trace_ft_snoc)
  done

lemma trace_ft_Cons: "trace_between s (trn#tr) s'
  \<longleftrightarrow> (\<exists>sh ou a. trn = Trans s a ou sh \<and> step s a = (ou,sh) \<and> trace_between sh tr s')"
  apply (subst trace_ft_append[where ?tr1.0 = "[trn]", simplified])
  apply (subst trace_ft_snoc[where tr = "[]", simplified])
  by auto

lemmas trace_ft_simps = trace_ft_empty trace_ft_snoc trace_ft_Cons trace_ft_append

inductive trace_to :: " (state,act,out) trans trace \<Rightarrow> state \<Rightarrow> bool" where
  empty: "trace_to [] istate"
| step: "\<lbrakk>trace_to tr s; step s a = (ou,s')\<rbrakk> \<Longrightarrow> trace_to (tr@[Trans s a ou s']) s'"

lemma trace_to_ft: "trace_to tr s \<longleftrightarrow> trace_between istate tr s"
proof (rule,goal_cases)
  case 1 thus ?case
    by induction (auto intro: trace_between.intros)
next
  case 2
  moreover
  {fix s' assume "trace_between s' tr s" hence "s' = istate \<longrightarrow> trace_to tr s"
   by induction (auto intro: trace_to.intros)
  }
  ultimately show ?case by auto
qed

inductive_simps trace_to_empty[simp]: "trace_to [] s"

lemma trace_to_reach: assumes "trace_to tr s" shows "reach s"
  using assms apply induction
   apply (rule reach.intros)
  by (metis reach_step snd_conv)

lemma reach_to_trace: assumes "reach s" obtains tr where "trace_to tr s"
  using assms apply (induction rule: reach_step_induct)
   apply (auto intro: trace_to.intros) []
  by (metis surjective_pairing trace_to.step)

lemma reach_trace_to_conv: "reach s \<longleftrightarrow> (\<exists>tr. trace_to tr s)"
  by (blast intro: trace_to_reach elim: reach_to_trace)

thm trace_to.induct[no_vars]

lemma trace_to_induct[case_names empty step, induct set]:
  "\<lbrakk>trace_to x1 x2; P [] istate;
  \<And>tr s a ou s'.
    \<lbrakk>trace_to tr s; P tr s; reach s; reach s'; step s a = (ou, s')\<rbrakk>
    \<Longrightarrow> P (tr ## Trans s a ou s') s'\<rbrakk>
  \<Longrightarrow> P x1 x2"
  apply (erule trace_to.induct)
   apply simp
  apply (frule trace_to_reach)
  using reach_PairI by blast

subsection \<open>Authorship\<close>

text \<open>
  Only the creator of a paper, and users explicitly added by other authors,
  are authors of a paper.
\<close>

inductive isAut' :: "(state,act,out) trans trace \<Rightarrow> confID \<Rightarrow> userID \<Rightarrow> paperID \<Rightarrow> bool" where
  creator: "\<lbrakk> trn = Trans _ (Cact (cPaper cid uid _ pid _ _)) outOK _ \<rbrakk>
    \<Longrightarrow> isAut' (tr@[trn]) cid uid pid"
  (* "The creator of a paper is an author"  *)
| co_author: "\<lbrakk>
  isAut' tr cid uid' pid;
  trn = Trans _ (Cact (cAuthor cid uid' _ pid uid)) outOK _ \<rbrakk>
  \<Longrightarrow> isAut' (tr@[trn]) cid uid pid"
  (* "An author can add any other user as a coauthor" *)
| irrelevant: "isAut' tr cid uid' pid \<Longrightarrow> isAut' (tr@[_]) cid uid' pid"

lemma justify_author:
  assumes "trace_to tr s"
  assumes "isAut s cid uid pid"
  shows "isAut' tr cid uid pid"
  using assms
proof (induction arbitrary: uid)
  case (empty s) thus ?case
    by (auto simp add: istate_def)
next
  case (step tr s a ou s')
  show ?case
  proof (cases "isAut s cid uid pid")
    case True with step.IH show ?thesis by (blast intro: isAut'.intros)
  next
    case False
    with step.hyps step.prems obtain
      pass s1 s2 uid' where
      "a=Cact (cPaper cid uid pass pid s1 s2)
      \<or> (a=Cact (cAuthor cid uid' pass pid uid) \<and> isAut s cid uid' pid)"
      and [simp]: "ou=outOK"
      apply (cases a)
        subgoal for x1 apply (cases x1, auto simp add: c_defs) [] .
        subgoal for x2 apply (cases x2, auto simp add: u_defs) [] .
        subgoal for x3 apply (cases x3, auto simp add: uu_defs) [] .
        by simp_all
    thus ?thesis using step.IH
      apply (elim disjE)
      apply (rule isAut'.creator, auto) []
      apply (rule isAut'.co_author, auto) []
      done
  qed
qed

lemma author_justify:
  assumes "trace_to tr s"
  assumes "isAut' tr cid uid pid"
  shows "isAut s cid uid pid"
  using assms
proof (induction arbitrary: uid)
  case (empty s) thus ?case
    by (auto simp add: istate_def elim: isAut'.cases)
next
  case (step tr s a ou s')
  from step.prems
  show ?case
  proof (cases)
    case (creator _ _ pass s1 s2)
    hence [simp]: "a=Cact (cPaper cid uid pass pid s1 s2)" "ou=outOK" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: c_defs)
  next
    case (co_author _ uid' _ _ pass)
    hence [simp]: "a=Cact (cAuthor cid uid' pass pid uid)" "ou=outOK" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: c_defs)
  next
    case (irrelevant) with step.IH have AUT: "isAut s cid uid pid" by simp

    note roles_confIDs[OF \<open>reach s\<close> AUT]
    with AUT \<open>step s a = (ou, s')\<close> show ?thesis
      apply (cases a)
      subgoal for x1 apply (cases x1, auto simp: c_defs) [] .
      subgoal for x2 apply (cases x2, auto simp: u_defs) [] .
      subgoal for x3 apply (cases x3, auto simp: uu_defs) [] .
      by simp_all
  qed
qed

theorem isAut_eq: "trace_to tr s \<Longrightarrow> isAut s cid uid pid \<longleftrightarrow> isAut' tr cid uid pid"
  (* "Trace-based equivalent of authorship" *)
  using justify_author author_justify
  by (blast)

subsection \<open>Becoming a Conference Chair\<close>

inductive isChair' :: "(state,act,out) trans trace \<Rightarrow> confID \<Rightarrow> userID \<Rightarrow> bool" where
  creator: "\<lbrakk> trn=Trans _ (Cact (cConf cid uid _ _ _)) outOK _ \<rbrakk>
    \<Longrightarrow> isChair' (tr@[trn]) cid uid"
| add_chair: "\<lbrakk> isChair' tr cid uid'; trn = Trans _ (Cact (cChair cid uid' _ uid)) outOK _ \<rbrakk>
  \<Longrightarrow> isChair' (tr@[trn]) cid uid"
| irrelevant: "\<lbrakk>isChair' tr cid uid\<rbrakk> \<Longrightarrow> isChair' (tr@[_]) cid uid"

lemma justify_chair:
  assumes "trace_to tr s"
  assumes "isChair s cid uid"
  shows "isChair' tr cid uid"
  using assms
proof (induction arbitrary: uid)
  case (empty s) thus ?case
    by (auto simp add: istate_def)
next
  case (step tr s a ou s')
  show ?case
  proof (cases "isChair s cid uid")
    case True with step.IH show ?thesis by (blast intro: isChair'.intros)
  next
    case False
    term cConf
    with step.hyps step.prems obtain
      pass s1 s2 uid' where
      "a=Cact (cConf cid uid pass s1 s2)
      \<or> (a=Cact (cChair cid uid' pass uid) \<and> isChair s cid uid')"
      and [simp]: "ou=outOK"
      apply (cases a)
      subgoal for x1 apply (cases x1, auto simp add: c_defs) [] .
      subgoal for x2 apply (cases x2, auto simp add: u_defs) [] .
      subgoal for x3 apply (cases x3, auto simp add: uu_defs) [] .
      by simp_all
    thus ?thesis using step.IH
      apply (elim disjE)
      apply (rule isChair'.creator, auto) []
      apply (rule isChair'.add_chair, auto) []
      done
  qed
qed

lemma chair_justify:
  assumes "trace_to tr s"
  assumes "isChair' tr cid uid"
  shows "isChair s cid uid"
  using assms
proof (induction arbitrary: uid)
  case (empty s) thus ?case
    by (auto simp add: istate_def elim: isChair'.cases)
next
  case (step tr s a ou s')
  from step.prems
  show ?case
  proof (cases)
    case (creator _ _ pass s1 s2)
    hence [simp]: "a=Cact (cConf cid uid pass s1 s2)" "ou=outOK" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: c_defs)
  next
    case (add_chair _ uid' _ _ pass)
    hence [simp]: "a=Cact (cChair cid uid' pass uid)" "ou=outOK" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: c_defs)
  next
    case (irrelevant) with step.IH have CH: "isChair s cid uid" by simp

    from CH \<open>step s a = (ou, s')\<close> show ?thesis
      apply (cases a)
      subgoal for x1 apply (cases x1, auto simp: c_defs) [] .
      subgoal for x2 apply (cases x2, auto simp: u_defs) [] .
      subgoal for x3 apply (cases x3, auto simp: uu_defs) [] .
      by simp_all
  qed
qed

theorem isChair_eq: "trace_to tr s \<Longrightarrow> isChair s cid uid = isChair' tr cid uid"
  (* "Trace-based equivalent of being a chair" *)
  using justify_chair chair_justify
  by (blast)

subsection \<open>Committee Membership\<close>

inductive isPC' :: "(state,act,out) trans trace \<Rightarrow> confID \<Rightarrow> userID \<Rightarrow> bool" where
  chair: "isChair' tr cid uid \<Longrightarrow> isPC' tr cid uid"
| add_com: "\<lbrakk> isChair' tr cid uid'; trn = Trans _ (Cact (cPC cid uid' _ uid)) outOK _ \<rbrakk>
  \<Longrightarrow> isPC' (tr@[trn]) cid uid"
| irrelevant: "\<lbrakk>isPC' tr cid uid\<rbrakk> \<Longrightarrow> isPC' (tr@[_]) cid uid"

lemma justify_com:
  assumes "trace_to tr s"
  assumes "isPC s cid uid"
  shows "isPC' tr cid uid"
  using assms
proof (induction arbitrary: uid)
  case (empty s) thus ?case
    by (auto simp add: istate_def)
next
  case (step tr s a ou s')

  show ?case
  proof (cases "isPC s cid uid")
    case True with step.IH show ?thesis by (blast intro: isPC'.irrelevant)
  next
    case False note noPC = this
    show ?thesis proof (cases "isChair s' cid uid")
      case True thus ?thesis
        by (metis chair justify_chair step.hyps(1) step.hyps(4) trace_to.step)
    next
      case False note noChair=this
      from noPC noChair step.hyps step.prems obtain
        pass uid' where "(a=Cact (cPC cid uid' pass uid))"
        and "isChair s cid uid'"
        and [simp]: "ou=outOK"
        apply (cases a)
        subgoal for x1 apply (cases x1, auto simp add: c_defs) [] .
        subgoal for x2 apply (cases x2, auto simp add: u_defs) [] .
        subgoal for x3 apply (cases x3, auto simp add: uu_defs) [] .
        by simp_all
      thus ?thesis
        apply -
        apply (rule isPC'.add_com, auto simp: isChair_eq[OF \<open>trace_to tr s\<close>]) []
        done
    qed
  qed
qed

lemma com_justify:
  assumes "trace_to tr s"
  assumes "isPC' tr cid uid"
  shows "isPC s cid uid"
  using assms
proof (induction arbitrary: uid)
  case (empty s) thus ?case
    by (auto simp add: istate_def elim!: isPC'.cases isChair'.cases)
next
  case (step tr s a ou s')
  from step.prems
  show ?case
  proof (cases)
    case chair thus ?thesis
      by (metis isChair_eq isChair_isPC step.hyps(1) step.hyps(3) step.hyps(4) trace_to.step)
  next
    case (add_com _ uid' _ _ pass)
    hence [simp]: "a=Cact (cPC cid uid' pass uid)" "ou=outOK" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: c_defs)
  next
    case (irrelevant) with step.IH have COM: "isPC s cid uid" by simp

    from COM \<open>step s a = (ou, s')\<close> show ?thesis
      apply (cases a)
      subgoal for x1 apply (cases x1, auto simp: c_defs) [] .
      subgoal for x2 apply (cases x2, auto simp: u_defs) [] .
      subgoal for x3 apply (cases x3, auto simp: uu_defs) [] .
      by simp_all
  qed
qed

theorem isPC_eq: "trace_to tr s \<Longrightarrow> isPC s cid uid = isPC' tr cid uid"
  (* "Trace-based equivalent of committee membership" *)
  using justify_com com_justify
  by (blast)

subsection \<open>Being a Reviewer\<close>

inductive isRev' :: "(state,act,out) trans trace \<Rightarrow> confID \<Rightarrow> userID \<Rightarrow> paperID \<Rightarrow> bool" where
  add_rev: "\<lbrakk> isChair' tr cid uid'; trn = Trans _ (Cact (cReview cid uid' _ pid uid)) outOK _ \<rbrakk>
  \<Longrightarrow> isRev' (tr@[trn]) cid uid pid"
| irrelevant: "\<lbrakk>isRev' tr cid uid pid\<rbrakk> \<Longrightarrow> isRev' (tr@[_]) cid uid pid"

lemma justify_rev:
  assumes "trace_to tr s"
  assumes "isRev s cid uid pid"
  shows "isRev' tr cid uid pid"
  using assms
proof (induction)
  case empty thus ?case
    by (auto simp add: istate_def isRev_def)
next
  case (step tr s a ou s')

  show ?case
  proof (cases "isRev s cid uid pid")
    case True with step.IH show ?thesis by (blast intro: isRev'.irrelevant)
  next
    case False note noRev = this
    with step.hyps step.prems obtain
      pass uid' where "(a=Cact (cReview cid uid' pass pid uid))"
      and "isChair s cid uid'"
      and [simp]: "ou=outOK"
      apply (cases a)
      subgoal for x1 apply (cases x1, auto simp add: c_defs isRev_def) [] .
      subgoal for x2 apply (cases x2, auto simp add: u_defs isRev_def) [] .
      subgoal for x3 apply (cases x3, auto simp add: uu_defs isRev_def) [] .
      by simp_all
    thus ?thesis
      apply -
      apply (rule isRev'.add_rev, auto simp: isChair_eq[OF \<open>trace_to tr s\<close>]) []
      done
  qed
qed

lemma rev_justify:
  assumes "trace_to tr s"
  assumes "isRev' tr cid uid pid"
  shows "isRev s cid uid pid"
  using assms
proof (induction arbitrary: uid)
  case (empty s) thus ?case
    by (auto simp add: istate_def elim!: isRev'.cases)
next
  case (step tr s a ou s')
  from step.prems
  show ?case
  proof (cases)
    case (add_rev _ uid' _ _ pass)
    hence [simp]: "a=Cact (cReview cid uid' pass pid uid)" "ou=outOK" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: c_defs isRev_def)
  next
    case (irrelevant) with step.IH have REV: "isRev s cid uid pid" by simp

    note roles_confIDs[OF step.hyps(2)]
    with REV \<open>step s a = (ou, s')\<close> show ?thesis
      apply (cases a)
      subgoal for x1 apply (cases x1, auto simp: c_defs isRev_def) [] .
      subgoal for x2 apply (cases x2, auto simp: u_defs isRev_def) [] .
      subgoal for x3 apply (cases x3, auto simp: uu_defs isRev_def) [] .
      by simp_all
  qed
qed

theorem isRev_eq: "trace_to tr s \<Longrightarrow> isRev s cid uid pid = isRev' tr cid uid pid"
  (* "Trace-based equivalent of being a reviewer" *)
  using justify_rev rev_justify
  by (blast)

subsection "Conflicts"

fun irrev_conflict :: "userID \<Rightarrow> paperID \<Rightarrow> (state,act,out) trans \<Rightarrow> bool"
 (* "Transitions causing irrevokable conflicts" *)
where
  "irrev_conflict uid pid (Trans _ (Cact (cPaper _ uid' _ pid' _ _)) outOK _)
    \<longleftrightarrow> uid'=uid \<and> pid'=pid"
| "irrev_conflict uid pid (Trans _ (Cact (cAuthor _ _ _ pid' uid')) outOK _)
    \<longleftrightarrow> uid'=uid \<and> pid'=pid"
| "irrev_conflict uid pid _ \<longleftrightarrow> False"

fun set_conflict :: "userID \<Rightarrow> paperID \<Rightarrow> (state,act,out) trans \<Rightarrow> bool"
  (* "Transitions setting conflict state, can be revoked by later reset-actions" *)
  where
  "set_conflict uid pid (Trans _ (Cact (cConflict _ _ _ pid' uid')) outOK _)
    \<longleftrightarrow> uid'=uid \<and> pid'=pid"
| "set_conflict uid pid (Trans _ (Uact (uPref _ uid' _ pid' Conflict)) outOK _)
    \<longleftrightarrow> uid'=uid \<and> pid'=pid"
| "set_conflict _ _ _ \<longleftrightarrow> False"

fun reset_conflict :: "userID \<Rightarrow> paperID \<Rightarrow> (state,act,out)trans \<Rightarrow> bool"
  (* "Transitions re-setting conflict state, can be revoked by later set-actions" *)
  where
  "reset_conflict uid pid (Trans _ (Uact (uPref _ uid' _ pid' pr)) outOK _)
    \<longleftrightarrow> uid'=uid \<and> pid'=pid \<and> pr\<noteq>Conflict"
| "reset_conflict _ _ _ \<longleftrightarrow> False"

definition conflict_trace :: "userID \<Rightarrow> paperID \<Rightarrow> (state,act,out) trans trace \<Rightarrow> bool"
  (* "Trace that causes a conflict: It contains either an irrevokable conflict action,
    or the last action concerning conflicts was set-conflict" *)
  where
  "conflict_trace uid pid tr \<equiv>
  (\<exists>trn\<in>set tr. irrev_conflict uid pid trn)
\<or> (\<exists>tr1 trn tr2. tr=tr1@trn#tr2 \<and>
    set_conflict uid pid trn \<and> (\<forall>trn\<in>set tr2. \<not>reset_conflict uid pid trn))"

lemma irrev_conflict_impl_author:
  assumes "trace_to tr s"
  assumes "\<exists>trn\<in>set tr. irrev_conflict uid pid trn"
  shows "\<exists>cid. isAut s cid uid pid"
  using assms
  apply induction
  apply (auto simp add: istate_def) []
  subgoal for _ _ a apply (cases a)
    subgoal for x1 apply (cases x1, auto simp: c_defs, (metis roles_confIDs)+) [] .
    subgoal for x2 apply (cases x2, auto simp: u_defs) [] .
    subgoal for x3 apply (cases x3, auto simp: uu_defs) [] .
    by simp_all
  done

lemma irrev_conflict_impl_conflict:
  assumes "trace_to tr s"
  assumes "\<exists>trn\<in>set tr. irrev_conflict uid pid trn"
  shows "pref s uid pid = Conflict"
  by (metis assms(1) assms(2) irrev_conflict_impl_author
    isAut_pref_Conflict reach_trace_to_conv)

lemma conflict_justify:
  assumes TR: "trace_to tr s"
  assumes "conflict_trace uid pid tr"
  shows "pref s uid pid = Conflict"
  using assms(2)
  unfolding conflict_trace_def
proof (cases rule: disjE[consumes 1, case_names irrev set])
  case irrev thus ?thesis by (simp add: irrev_conflict_impl_conflict[OF TR])
next
  case set
  then obtain tr1 trn tr2 where
    [simp]: "tr = tr1 @ trn # tr2" and
    SET: "set_conflict uid pid trn"
    and NRESET: "\<forall>trn\<in>set tr2. \<not> reset_conflict uid pid trn"
    by blast

  from TR obtain s1 s2 a ou where
    [simp]: "trn = Trans s1 a ou s2" and
    TR1: "trace_to tr1 s1" and
    STEP: "step s1 a = (ou,s2)" and
    TR2: "trace_between s2 tr2 s"
    by (fastforce simp add: trace_to_ft trace_ft_simps)

  from STEP SET have "pref s2 uid pid = Conflict"
    apply (cases a)
      subgoal for x1 apply (cases x1, auto simp: c_defs) [] .
      subgoal for x2 apply (cases x2, auto simp: u_defs) []
        subgoal for _ x65 apply (cases x65, auto) [] .
        subgoal for _ _ _ x65 apply (cases x65, auto) [] .
        subgoal for _ _ _ x65 apply (cases x65, auto) [] . .
      by simp_all

  with TR2 NRESET show ?thesis
    apply induction
    subgoal by simp
    subgoal for _ _ _ a apply (cases a)
      subgoal for x1 apply (cases x1, auto simp: c_defs) [] .
      subgoal for x2 apply (cases x2, auto simp: u_defs) [] .
      subgoal for x3 apply (cases x3, auto simp: uu_defs) [] .
      by simp_all
    done
qed

lemma justify_conflict:
  assumes TR: "trace_to tr s"
  assumes "pref s uid pid = Conflict"
  shows "conflict_trace uid pid tr"
  using assms
proof induction
  case empty thus ?case by (auto simp add: istate_def)
next
  case (step tr s a ou s')

  let ?trn = "Trans s a ou s'"

  show ?case proof (cases "pref s uid pid = Conflict")
    case False
    with step.prems \<open>step s a = (ou, s')\<close>
    have "irrev_conflict uid pid ?trn \<or> set_conflict uid pid ?trn"
      apply (cases a)
      subgoal for x1 apply (cases x1, auto simp: c_defs) [] .
      subgoal for x2 apply (cases x2, auto simp: u_defs) [] .
      subgoal for x3 apply (cases x3, auto simp: uu_defs) [] .
      by simp_all
    thus ?thesis
      unfolding conflict_trace_def by fastforce
  next
    case True with step.IH have CT: "conflict_trace uid pid tr" .

    from step.prems \<open>step s a = (ou, s')\<close> have "\<not>reset_conflict uid pid ?trn"
      apply (cases a)
      subgoal by simp
      subgoal for x2 by (cases x2, auto simp: u_defs)
      by simp_all

    thus ?thesis using CT
      unfolding conflict_trace_def
      apply clarsimp
      by (metis rotate1.simps(2) set_ConsD set_rotate1)

  qed
qed

theorem conflict_eq:
  assumes "trace_to tr s"
  shows "pref s uid pid = Conflict \<longleftrightarrow> conflict_trace uid pid tr"
  using assms conflict_justify justify_conflict by auto

subsection \<open>Conference Phases\<close>

fun is_uPhase where
  "is_uPhase cid (Trans _ (Uact (uConfA cid' _ _)) outOK _) \<longleftrightarrow> cid'=cid"
| "is_uPhase cid (Trans _ (Uact (uPhase cid' _ _ _)) outOK _) \<longleftrightarrow> cid'=cid"
| "is_uPhase _ _ \<longleftrightarrow> False"

inductive phase' :: "(state,act,out) trans trace \<Rightarrow> confID \<Rightarrow> nat \<Rightarrow> bool" where
  initial: "phase' [] cid noPH"
| approve: "\<lbrakk>phase' tr cid noPH; trn=Trans s (Uact (uConfA cid (voronkov s) _)) outOK _ \<rbrakk>
  \<Longrightarrow> phase' (tr@[trn]) cid setPH"
| advance: "\<lbrakk>trn = (Trans _ (Uact (uPhase cid uid _ ph)) outOK _); isChair' tr cid uid\<rbrakk>
  \<Longrightarrow> phase' (tr@[trn]) cid ph"
| irrelevant: "\<lbrakk>phase' tr cid ph; \<not>is_uPhase cid trn \<rbrakk> \<Longrightarrow> phase' (tr@[trn]) cid ph"

lemma justify_phase:
  assumes "trace_to tr s"
  assumes "phase s cid = ph"
  shows "phase' tr cid ph"
  using assms
proof (induction arbitrary: ph)
  case (empty s) thus ?case
    by (auto simp add: istate_def phase'.initial)
next
  case (step tr s a ou s')
  thus ?case
    apply (cases a)
    subgoal for x1 apply (cases x1, auto simp: c_defs intro: phase'.advance phase'.irrelevant) [] .
    subgoal for x2 apply (cases x2,
      auto
        simp: u_defs isChair_eq
        intro: phase'.advance phase'.irrelevant phase'.approve,
      (fastforce intro: phase'.approve phase'.irrelevant phase'.advance)+
    ) [] .

    subgoal for x3 apply (cases x3, auto simp: uu_defs intro: phase'.irrelevant) [] .
    by (auto intro: phase'.advance phase'.irrelevant)
qed

lemma phase_justify:
  assumes "trace_to tr s"
  assumes "phase' tr cid ph"
  shows "phase s cid = ph"
  using assms
proof (induction arbitrary: ph)
  case (empty s) thus ?case
    by (auto simp add: istate_def elim: phase'.cases)
next
  case (step tr s a ou s')
  from step.prems
  show ?case
  proof (cases)
    case (approve _ _ _ pass _)
    hence [simp]: "a=Uact (uConfA cid (voronkov s) pass)" "ou=outOK" "ph=setPH" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: u_defs)
  next
    case (advance _ _ uid pass _ _)
    hence [simp]: "a=Uact (uPhase cid uid pass ph)" "ou=outOK" by simp_all
    from step.hyps show ?thesis
      by (auto simp add: u_defs)
  next
    case (irrelevant) with step.IH have PH: "phase s cid = ph" "\<not> is_uPhase cid (Trans s a ou s')"
      by simp_all

    from PH \<open>step s a = (ou, s')\<close> show ?thesis
    apply (cases a)
    subgoal for x1 apply (cases x1, auto simp: c_defs) [] .
    subgoal for x2 apply (cases x2, auto simp: u_defs) [] .
    subgoal for x3 apply (cases x3, auto simp: uu_defs) [] .
    by simp_all
  qed auto
qed

theorem phase_eq:
  assumes "trace_to tr s"
  shows "phase s cid = ph \<longleftrightarrow> phase' tr cid ph"
  using assms phase_justify justify_phase by blast

end


           (*-------------------------------------------*
            |        CSP-Prover on Isabelle2004         |
            |               December 2004               |
            |                   July 2005  (modified)   |
            |              September 2005  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2005         |
            |                October 2005  (modified)   |
            |                  April 2006  (modified)   |
            |                  March 2007  (modified)   |
            |                 August 2007  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2009         |
            |                   June 2009  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory CSP_T_law_dist
imports CSP_T_law_basic CSP_T_law_alpha_par
begin

(*****************************************************************

      distribution over internal choice

         1. (P1 |~| P2) [+] Q
         2. Q [+] (P1 |~| P2)
         3. (P1 |~| P2) |[X]| Q
         4. Q |[X]| (P1 |~| P2)
         5. (P1 |~| P2) -- X
         6. (P1 |~| P2) [[r]]
         7. (P1 |~| P2) ;; Q
         8. (P1 |~| P2) |. n
         9. !! x:X .. (P1 |~| P2)

 *****************************************************************)

(*********************************************************
                dist law for Ext_choice (l)
 *********************************************************)

lemma cspT_Ext_choice_dist_l:
  "(P1 |~| P2) [+] Q =T[M,M]
   (P1 [+] Q) |~| (P2 [+] Q)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces, fast)+
done

(*********************************************************
                dist law for Ext_choice (r)
 *********************************************************)

lemma cspT_Ext_choice_dist_r:
  "P [+] (Q1 |~| Q2) =T[M,M]
   (P [+] Q1) |~| (P [+] Q2)"
apply (rule cspT_rw_left)
apply (rule cspT_commut)
apply (rule cspT_rw_left)
apply (rule cspT_Ext_choice_dist_l)
apply (rule cspT_decompo)
apply (rule cspT_commut)+
done

(*********************************************************
                dist law for Parallel (l)
 *********************************************************)

lemma cspT_Parallel_dist_l:
  "(P1 |~| P2) |[X]| Q =T[M,M]
   (P1 |[X]| Q) |~| (P2 |[X]| Q)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces, fast)+
done

(*********************************************************
                dist law for Parallel (r)
 *********************************************************)

lemma cspT_Parallel_dist_r:
  "P |[X]| (Q1 |~| Q2) =T[M,M]
   (P |[X]| Q1) |~| (P |[X]| Q2)"
apply (rule cspT_rw_left)
apply (rule cspT_commut)
apply (rule cspT_rw_left)
apply (rule cspT_Parallel_dist_l)
apply (rule cspT_decompo)
apply (rule cspT_commut)+
done

(*********************************************************
                dist law for Hiding
 *********************************************************)

lemma cspT_Hiding_dist:
  "(P1 |~| P2) -- X =T[M,M]
   (P1 -- X) |~| (P2 -- X)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces, fast)+
done

(*********************************************************
               dist law for Renaming
 *********************************************************)

lemma cspT_Renaming_dist:
  "(P1 |~| P2) [[r]] =T[M,M]
   (P1 [[r]]) |~| (P2 [[r]])"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces, fast)+
done

(*********************************************************
         dist law for Sequential composition
 *********************************************************)

lemma cspT_Seq_compo_dist:
  "(P1 |~| P2) ;; Q =T[M,M]
   (P1 ;; Q) |~| (P2 ;; Q)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces, fast)+
done

(*********************************************************
               dist law for Depth_rest
 *********************************************************)

lemma cspT_Depth_rest_dist:
  "(P1 |~| P2) |. n =T[M,M]
   (P1 |. n) |~| (P2 |. n)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces)
apply (rule, simp add: in_traces)
apply (force)
done

(*********************************************************
               dist law for Rep_int_choice
 *********************************************************)

lemma cspT_Rep_int_choice_sum_dist:
  "!! c:C .. (Pf c |~| Qf c) =T[M,M] (!! c:C .. Pf c) |~| (!! c:C .. Qf c)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces, fast)+
done

lemma cspT_Rep_int_choice_nat_dist:
  "!nat n:N .. (Pf n |~| Qf n) =T[M,M] (!nat n:N .. Pf n) |~| (!nat n:N .. Qf n)"
by (simp add: Rep_int_choice_ss_def cspT_Rep_int_choice_sum_dist)

lemma cspT_Rep_int_choice_set_dist:
  "!set X:Xs .. (Pf X |~| Qf X) =T[M,M] (!set X:Xs .. Pf X) |~| (!set X:Xs .. Qf X)"
by (simp add: Rep_int_choice_ss_def cspT_Rep_int_choice_sum_dist)

lemma cspT_Rep_int_choice_com_dist:
  "! a:X .. (Pf a |~| Qf a) =T[M,M] (! a:X .. Pf a) |~| (! a:X .. Qf a)"
by (simp add: Rep_int_choice_com_def cspT_Rep_int_choice_set_dist)

lemma cspT_Rep_int_choice_f_dist:
  "inj f ==>
   !<f> a:X .. (Pf a |~| Qf a) =T[M,M] (!<f> a:X .. Pf a) |~| (!<f> a:X .. Qf a)"
by (simp add: Rep_int_choice_f_def cspT_Rep_int_choice_com_dist)

lemmas cspT_Rep_int_choice_dist =
       cspT_Rep_int_choice_sum_dist
       cspT_Rep_int_choice_nat_dist
       cspT_Rep_int_choice_set_dist
       cspT_Rep_int_choice_com_dist
       cspT_Rep_int_choice_f_dist

(*********************************************************
                     dist laws
 *********************************************************)

lemmas cspT_dist = cspT_Ext_choice_dist_l cspT_Ext_choice_dist_r
                   cspT_Parallel_dist_l   cspT_Parallel_dist_r
                   cspT_Hiding_dist       cspT_Renaming_dist
                   cspT_Seq_compo_dist    cspT_Depth_rest_dist
                   cspT_Rep_int_choice_dist

(*****************************************************************

      distribution over replicated internal choice

         1. (!! :C .. Pf) [+] Q
         2. Q [+] (!! :C .. Pf)
         3. (!! :C .. Pf) |[X]| Q
         4. Q |[X]| (!! :C .. Pf)
         5. (!! :C .. Pf) -- X
         6. (!! :C .. Pf) [[r]]
         7. (!! :C .. Pf) |. n

 *****************************************************************)

(*********************************************************
                Rep_dist law for Ext_choice (l)
 *********************************************************)

lemma cspT_Ext_choice_Dist_sum_l_nonempty:
  "sumset C ~= {} ==> (!! :C .. Pf) [+] Q =T[M,M]
                      !! c:C .. (Pf c [+] Q)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
apply (rule, simp add: in_traces, fast)+
done

(*** Dist ***)

lemma cspT_Ext_choice_Dist_sum_l:
  "(!! :C .. Pf) [+] Q =T[M,M]
   IF (sumset C={}) THEN (DIV [+] Q) ELSE (!! c:C .. (Pf c [+] Q))"
apply (case_tac "sumset C={}")
apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_decompo)
apply (rule cspT_Rep_int_choice_empty)
apply (simp_all)

apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_Ext_choice_Dist_sum_l_nonempty)
apply (simp)
done

(*********************************************************
                Dist_sum law for Ext_choice (r)
 *********************************************************)

lemma cspT_Ext_choice_Dist_sum_r_nonempty:
  "sumset C ~= {} ==> P [+] (!! :C .. Qf) =T[M,M]
               !! c:C .. (P [+] Qf c)"
apply (rule cspT_rw_left)
apply (rule cspT_commut)
apply (rule cspT_rw_left)
apply (rule cspT_Ext_choice_Dist_sum_l_nonempty, simp)
apply (rule cspT_decompo, simp)
apply (rule cspT_commut)
done

(*** Dist ***)

lemma cspT_Ext_choice_Dist_sum_r:
  "P [+] (!! :C .. Qf) =T[M,M]
   IF (sumset C={}) THEN (P [+] DIV) ELSE (!! c:C .. (P [+] Qf c))"
apply (case_tac "sumset C={}")
apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_decompo)
apply (simp)
apply (simp add: cspT_Rep_int_choice_empty)

apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_Ext_choice_Dist_sum_r_nonempty)
apply (simp)
done

(*********************************************************
                Dist_sum law for Parallel (l)
 *********************************************************)

lemma cspT_Parallel_Dist_sum_l_nonempty:
  "sumset C ~= {} ==>
     (!! :C .. Pf) |[X]| Q =T[M,M]
     !! c:C .. (Pf c |[X]| Q)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE bexE)
  apply (subgoal_tac "EX c. c: sumset C")
  apply (elim exE)
  apply (rule disjI2)
  apply (rule_tac x="c" in bexI)
  apply (simp)
  apply (rule_tac x="<>" in exI)
  apply (rule_tac x="ta" in exI)
  apply (simp)
  apply (simp)
  apply (fast)
  (* *)
  apply (rule disjI2)
  apply (rule_tac x="c" in bexI)
  apply (fast)
  apply (simp)

 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE bexE)
  apply (rule_tac x="<>" in exI)
  apply (rule_tac x="<>" in exI)
  apply (simp)
  apply (fast)
done

(*** Dist ***)

lemma cspT_Parallel_Dist_sum_l:
  "(!! :C .. Pf) |[X]| Q =T[M,M]
   IF (sumset C={}) THEN (DIV |[X]| Q) ELSE (!! c:C .. (Pf c |[X]| Q))"
apply (case_tac "sumset C={}")
apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_decompo)
apply (simp)
apply (simp add: cspT_Rep_int_choice_empty)
apply (simp)

apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_Parallel_Dist_sum_l_nonempty)
apply (simp)
done

(*********************************************************
                Dist_sum law for Parallel (r)
 *********************************************************)

lemma cspT_Parallel_Dist_sum_r_nonempty:
  "sumset C ~= {} ==>
     P |[X]| (!! :C .. Qf) =T[M,M]
     !! c:C .. (P |[X]| Qf c)"
apply (rule cspT_rw_left)
apply (rule cspT_commut)
apply (rule cspT_rw_left)
apply (rule cspT_Parallel_Dist_sum_l_nonempty, simp)
apply (rule cspT_decompo, simp)
apply (rule cspT_commut)
done

(*** Dist ***)

lemma cspT_Parallel_Dist_sum_r:
  "P |[X]| (!! :C .. Qf) =T[M,M]
   IF (sumset C={}) THEN (P |[X]| DIV) ELSE (!! c:C .. (P |[X]| Qf c))"
apply (case_tac "sumset C={}")
apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_decompo)
apply (simp)
apply (simp)
apply (simp add: cspT_Rep_int_choice_empty)

apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_Parallel_Dist_sum_r_nonempty)
apply (simp)
done

(*********************************************************
                Dist_sum law for Hiding
 *********************************************************)

lemma cspT_Hiding_Dist_sum:
  "(!! :C .. Pf) -- X =T[M,M]
   !! c:C .. (Pf c -- X)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE, simp, fast)

 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (rule_tac x="<>" in exI, simp)
 apply (rule_tac x="s" in exI, fast)
done

(*********************************************************
                Dist_sum law for Renaming
 *********************************************************)

lemma cspT_Renaming_Dist_sum:
  "(!! :C .. Pf) [[r]] =T[M,M]
   !! c:C .. (Pf c [[r]])"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE, simp, fast)
 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE, simp, fast)
done

(*********************************************************
          Dist_sum law for Sequential composition
 *********************************************************)

lemma cspT_Seq_compo_Dist_sum:
  "(!! :C .. Pf) ;; Q =T[M,M]
   !! c:C .. (Pf c ;; Q)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp)
 apply (fast)
 apply (force)
 apply (rule disjI2)
 apply (rule_tac x="c" in bexI)
 apply (force)
 apply (simp)

 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (rule disjI1)
 apply (rule_tac x="<>" in exI, simp)
 apply (fast)
 apply (fast)
done

(*********************************************************
                Dist_sum law for Depth_rest
 *********************************************************)

lemma cspT_Depth_rest_Dist_sum:
  "(!! :C .. Pf) |. m =T[M,M]
   !! c:C .. (Pf c |. m)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

 apply (rule, simp add: in_traces)
 apply (rule, simp add: in_traces)
 apply (force)
done

(*********************************************************
                     Dist_sum laws
 *********************************************************)

lemmas cspT_Dist_sum = cspT_Ext_choice_Dist_sum_l cspT_Ext_choice_Dist_sum_r
                        cspT_Parallel_Dist_sum_l   cspT_Parallel_Dist_sum_r
                        cspT_Hiding_Dist_sum       cspT_Renaming_Dist_sum
                        cspT_Seq_compo_Dist_sum    cspT_Depth_rest_Dist_sum

lemmas cspT_Dist_sum_nonempty =
       cspT_Ext_choice_Dist_sum_l_nonempty cspT_Ext_choice_Dist_sum_r_nonempty
       cspT_Parallel_Dist_sum_l_nonempty   cspT_Parallel_Dist_sum_r_nonempty
       cspT_Hiding_Dist_sum       cspT_Renaming_Dist_sum
       cspT_Seq_compo_Dist_sum    cspT_Depth_rest_Dist_sum

(*****************************************************************

      distribution over replicated internal choice

         1. (!nat :C .. Pf) [+] Q
         2. Q [+] (!nat :C .. Pf)
         3. (!nat :C .. Pf) |[X]| Q
         4. Q |[X]| (!nat :C .. Pf)
         5. (!nat :C .. Pf) -- X
         6. (!nat :C .. Pf) [[r]]
         7. (!nat :C .. Pf) |. n

 *****************************************************************)

(*********************************************************
                Rep_dist law for Ext_choice (l)
 *********************************************************)

lemma cspT_Ext_choice_Dist_nat_l_nonempty:
  "N ~= {} ==> (!nat :N .. Pf) [+] Q =T[M,M]
               !nat n:N .. (Pf n [+] Q)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Ext_choice_Dist_nat_l:
  "(!nat :N .. Pf) [+] Q =T[M,M]
   IF (N={}) THEN (DIV [+] Q) ELSE (!nat n:N .. (Pf n [+] Q))"
apply (simp add: Rep_int_choice_ss_def)
apply (rule cspT_rw_left)
apply (rule cspT_Dist_sum)
apply (simp)
done

(*********************************************************
                Dist_nat law for Ext_choice (r)
 *********************************************************)

lemma cspT_Ext_choice_Dist_nat_r_nonempty:
  "N ~= {} ==> P [+] (!nat :N .. Qf) =T[M,M]
               !nat n:N .. (P [+] Qf n)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Ext_choice_Dist_nat_r:
  "P [+] (!nat :N .. Qf) =T[M,M]
   IF (N={}) THEN (P [+] DIV) ELSE (!nat n:N .. (P [+] Qf n))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Dist_sum, simp)

(*********************************************************
                Dist_nat law for Parallel (l)
 *********************************************************)

lemma cspT_Parallel_Dist_nat_l_nonempty:
  "N ~= {} ==>
     (!nat :N .. Pf) |[X]| Q =T[M,M]
     !nat n:N .. (Pf n |[X]| Q)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Parallel_Dist_nat_l:
  "(!nat :N .. Pf) |[X]| Q =T[M,M]
   IF (N={}) THEN (DIV |[X]| Q) ELSE (!nat n:N .. (Pf n |[X]| Q))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Dist_sum, simp)

(*********************************************************
                Dist_nat law for Parallel (r)
 *********************************************************)

lemma cspT_Parallel_Dist_nat_r_nonempty:
  "N ~= {} ==>
     P |[X]| (!nat :N .. Qf) =T[M,M]
     !nat n:N .. (P |[X]| Qf n)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Parallel_Dist_nat_r:
  "P |[X]| (!nat :N .. Qf) =T[M,M]
   IF (N={}) THEN (P |[X]| DIV) ELSE (!nat n:N .. (P |[X]| Qf n))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Dist_sum, simp)

(*********************************************************
                Dist_nat law for Hiding
 *********************************************************)

lemma cspT_Hiding_Dist_nat:
  "(!nat :N .. Pf) -- X =T[M,M]
   !nat n:N .. (Pf n -- X)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
                Dist_nat law for Renaming
 *********************************************************)

lemma cspT_Renaming_Dist_nat:
  "(!nat :N .. Pf) [[r]] =T[M,M]
   !nat n:N .. (Pf n [[r]])"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
          Dist_nat law for Sequential composition
 *********************************************************)

lemma cspT_Seq_compo_Dist_nat:
  "(!nat :N .. Pf) ;; Q =T[M,M]
   !nat n:N .. (Pf n ;; Q)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
                Dist_nat law for Depth_rest
 *********************************************************)

lemma cspT_Depth_rest_Dist_nat:
  "(!nat :N .. Pf) |. m =T[M,M]
   !nat n:N .. (Pf n |. m)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
                     Dist_nat laws
 *********************************************************)

lemmas cspT_Dist_nat = cspT_Ext_choice_Dist_nat_l cspT_Ext_choice_Dist_nat_r
                        cspT_Parallel_Dist_nat_l   cspT_Parallel_Dist_nat_r
                        cspT_Hiding_Dist_nat       cspT_Renaming_Dist_nat
                        cspT_Seq_compo_Dist_nat    cspT_Depth_rest_Dist_nat

lemmas cspT_Dist_nat_nonempty =
       cspT_Ext_choice_Dist_nat_l_nonempty cspT_Ext_choice_Dist_nat_r_nonempty
       cspT_Parallel_Dist_nat_l_nonempty   cspT_Parallel_Dist_nat_r_nonempty
       cspT_Hiding_Dist_nat       cspT_Renaming_Dist_nat
       cspT_Seq_compo_Dist_nat    cspT_Depth_rest_Dist_nat

(*****************************************************************

      distribution over replicated internal choice

         1. (!set :C .. Pf) [+] Q
         2. Q [+] (!set :C .. Pf)
         3. (!set :C .. Pf) |[X]| Q
         4. Q |[X]| (!set :C .. Pf)
         5. (!set :C .. Pf) -- X
         6. (!set :C .. Pf) [[r]]
         7. (!set :C .. Pf) |. n

 *****************************************************************)

(*********************************************************
                Rep_dist law for Ext_choice (l)
 *********************************************************)

lemma cspT_Ext_choice_Dist_set_l_nonempty:
  "Xs ~= {} ==> (!set :Xs .. Pf) [+] Q =T[M,M]
               !set X:Xs .. (Pf X [+] Q)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Ext_choice_Dist_set_l:
  "(!set :Xs .. Pf) [+] Q =T[M,M]
   IF (Xs={}) THEN (DIV [+] Q) ELSE (!set X:Xs .. (Pf X [+] Q))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Dist_sum, simp)

(*********************************************************
                Dist_set law for Ext_choice (r)
 *********************************************************)

lemma cspT_Ext_choice_Dist_set_r_nonempty:
  "Xs ~= {} ==> P [+] (!set :Xs .. Qf) =T[M,M]
               !set X:Xs .. (P [+] Qf X)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Ext_choice_Dist_set_r:
  "P [+] (!set :Xs .. Qf) =T[M,M]
   IF (Xs={}) THEN (P [+] DIV) ELSE (!set X:Xs .. (P [+] Qf X))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Dist_sum, simp)

(*********************************************************
                Dist_set law for Parallel (l)
 *********************************************************)

lemma cspT_Parallel_Dist_set_l_nonempty:
  "Xs ~= {} ==>
     (!set :Xs .. Pf) |[Y]| Q =T[M,M]
     !set X:Xs .. (Pf X |[Y]| Q)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Parallel_Dist_set_l:
  "(!set :Xs .. Pf) |[Y]| Q =T[M,M]
   IF (Xs={}) THEN (DIV |[Y]| Q) ELSE (!set X:Xs .. (Pf X |[Y]| Q))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Dist_sum, simp)

(*********************************************************
                Dist_set law for Parallel (r)
 *********************************************************)

lemma cspT_Parallel_Dist_set_r_nonempty:
  "Xs ~= {} ==>
     P |[Y]| (!set :Xs .. Qf) =T[M,M]
     !set X:Xs .. (P |[Y]| Qf X)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum_nonempty)

(*** Dist ***)

lemma cspT_Parallel_Dist_set_r:
  "P |[Y]| (!set :Xs .. Qf) =T[M,M]
   IF (Xs={}) THEN (P |[Y]| DIV) ELSE (!set X:Xs .. (P |[Y]| Qf X))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Dist_sum, simp)

(*********************************************************
                Dist_set law for Hiding
 *********************************************************)

lemma cspT_Hiding_Dist_set:
  "(!set :Xs .. Pf) -- Y =T[M,M]
   !set X:Xs .. (Pf X -- Y)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
                Dist_set law for Renaming
 *********************************************************)

lemma cspT_Renaming_Dist_set:
  "(!set :Xs .. Pf) [[r]] =T[M,M]
   !set X:Xs .. (Pf X [[r]])"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
          Dist_set law for Sequential composition
 *********************************************************)

lemma cspT_Seq_compo_Dist_set:
  "(!set :Xs .. Pf) ;; Q =T[M,M]
   !set X:Xs .. (Pf X ;; Q)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
                Dist_set law for Depth_rest
 *********************************************************)

lemma cspT_Depth_rest_Dist_set:
  "(!set :Xs .. Pf) |. m =T[M,M]
   !set X:Xs .. (Pf X |. m)"
by (simp add: Rep_int_choice_ss_def cspT_Dist_sum)

(*********************************************************
                     Dist_set laws
 *********************************************************)

lemmas cspT_Dist_set = cspT_Ext_choice_Dist_set_l cspT_Ext_choice_Dist_set_r
                        cspT_Parallel_Dist_set_l   cspT_Parallel_Dist_set_r
                        cspT_Hiding_Dist_set       cspT_Renaming_Dist_set
                        cspT_Seq_compo_Dist_set    cspT_Depth_rest_Dist_set

lemmas cspT_Dist_set_nonempty =
       cspT_Ext_choice_Dist_set_l_nonempty cspT_Ext_choice_Dist_set_r_nonempty
       cspT_Parallel_Dist_set_l_nonempty   cspT_Parallel_Dist_set_r_nonempty
       cspT_Hiding_Dist_set       cspT_Renaming_Dist_set
       cspT_Seq_compo_Dist_set    cspT_Depth_rest_Dist_set

(*****************************************************************

      for convenience

         1. (! :X .. Pf) [+] Q
         2. Q [+] (! :X .. Pf)
         3. (! :X .. Pf) |[X]| Q
         4. Q |[X]| (! :X .. Pf)
         5. (! :X .. Pf) -- X
         6. (! :X .. Pf) [[r]]
         7. (! :X .. Pf) |. n

 *****************************************************************)

(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Ext_choice_Dist_com_l_nonempty:
  "X ~= {}
   ==> (! :X .. Pf) [+] Q =T[M,M] ! x:X .. (Pf x [+] Q)"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

lemma cspT_Ext_choice_Dist_com_r_nonempty:
  "X ~= {}
   ==> P [+] (! :X .. Qf) =T[M,M] ! x:X .. (P [+] Qf x)"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

lemma cspT_Parallel_Dist_com_l_nonempty:
  "Y ~= {}
   ==> (! :Y .. Pf) |[X]| Q =T[M,M] ! x:Y .. (Pf x |[X]| Q)"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

lemma cspT_Parallel_Dist_com_r_nonempty:
  "Y ~= {}
   ==> P |[X]| (! :Y .. Qf) =T[M,M] ! x:Y .. (P |[X]| Qf x)"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

lemma cspT_Ext_choice_Dist_com_l:
  "(! :X .. Pf) [+] Q =T[M,M]
   IF (X ={}) THEN (DIV [+] Q) ELSE (! x:X .. (Pf x [+] Q))"
apply (simp add: Rep_int_choice_com_def)
by (rule cspT_rw_left, rule cspT_Dist_set, simp)

lemma cspT_Ext_choice_Dist_com_r:
  "P [+] (! :X .. Qf) =T[M,M]
   IF (X ={}) THEN (P [+] DIV) ELSE (! x:X .. (P [+] Qf x))"
apply (simp add: Rep_int_choice_com_def)
by (rule cspT_rw_left, rule cspT_Dist_set, simp)

lemma cspT_Parallel_Dist_com_l:
  "(! :Y .. Pf) |[X]| Q =T[M,M]
   IF (Y ={}) THEN (DIV |[X]| Q) ELSE (! x:Y .. (Pf x |[X]| Q))"
apply (simp add: Rep_int_choice_com_def)
by (rule cspT_rw_left, rule cspT_Dist_set, simp)

lemma cspT_Parallel_Dist_com_r:
  "P |[X]| (! :Y .. Qf) =T[M,M]
   IF (Y ={}) THEN (P |[X]| DIV) ELSE (! x:Y .. (P |[X]| Qf x))"
apply (simp add: Rep_int_choice_com_def)
by (rule cspT_rw_left, rule cspT_Dist_set, simp)

lemma cspT_Hiding_Dist_com:
  "(! :Y .. Pf) -- X =T[M,M] ! x:Y .. (Pf x -- X)"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

lemma cspT_Renaming_Dist_com:
  "(! :X .. Pf) [[r]] =T[M,M] ! x:X .. (Pf x [[r]])"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

lemma cspT_Seq_compo_Dist_com:
  "(! :X .. Pf) ;; Q =T[M,M] ! x:X .. (Pf x ;; Q)"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

lemma cspT_Depth_rest_Dist_com:
  "(! :X .. Pf) |. n =T[M,M] ! x:X .. (Pf x |. n)"
by (simp add: Rep_int_choice_com_def cspT_Dist_set_nonempty)

(*********************************************************
                     Dist laws
 *********************************************************)

lemmas cspT_Dist_com = cspT_Ext_choice_Dist_com_l cspT_Ext_choice_Dist_com_r
                           cspT_Parallel_Dist_com_l   cspT_Parallel_Dist_com_r
                           cspT_Hiding_Dist_com       cspT_Renaming_Dist_com
                           cspT_Seq_compo_Dist_com    cspT_Depth_rest_Dist_com

lemmas cspT_Dist_com_nonempty =
       cspT_Ext_choice_Dist_com_l_nonempty cspT_Ext_choice_Dist_com_r_nonempty
       cspT_Parallel_Dist_com_l_nonempty   cspT_Parallel_Dist_com_r_nonempty
       cspT_Hiding_Dist_com       cspT_Renaming_Dist_com
       cspT_Seq_compo_Dist_com    cspT_Depth_rest_Dist_com

(*****************************************************************

      for convenience

         1. (!<f> :X .. Pf) [+] Q
         2. Q [+] (!<f> :X .. Pf)
         3. (!<f> :X .. Pf) |[X]| Q
         4. Q |[X]| (!<f> :X .. Pf)
         5. (!<f> :X .. Pf) -- X
         6. (!<f> :X .. Pf) [[r]]
         7. (!<f> :X .. Pf) |. n

 *****************************************************************)

(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Ext_choice_Dist_f_l_nonempty:
  "[| inj f ; X ~= {} |]
   ==> (!<f> :X .. Pf) [+] Q =T[M,M] !<f> x:X .. (Pf x [+] Q)"
by (simp add: Rep_int_choice_f_def cspT_Dist_com_nonempty)

lemma cspT_Ext_choice_Dist_f_r_nonempty:
  "[| inj f ; X ~= {} |]
   ==> P [+] (!<f> :X .. Qf) =T[M,M] !<f> x:X .. (P [+] Qf x)"
by (simp add: Rep_int_choice_f_def cspT_Dist_com_nonempty)

lemma cspT_Parallel_Dist_f_l_nonempty:
  "[| inj f ; Y ~= {} |]
   ==> (!<f> :Y .. Pf) |[X]| Q =T[M,M] !<f> x:Y .. (Pf x |[X]| Q)"
by (simp add: Rep_int_choice_f_def cspT_Dist_com_nonempty)

lemma cspT_Parallel_Dist_f_r_nonempty:
  "[| inj f ; Y ~= {} |]
   ==> P |[X]| (!<f> :Y .. Qf) =T[M,M] !<f> x:Y .. (P |[X]| Qf x)"
by (simp add: Rep_int_choice_f_def cspT_Dist_com_nonempty)

lemma cspT_Ext_choice_Dist_f_l:
  "(!<f> :X .. Pf) [+] Q =T[M,M]
   IF (X ={}) THEN (DIV [+] Q) ELSE (!<f> x:X .. (Pf x [+] Q))"
apply (simp add: Rep_int_choice_f_def)
by (rule cspT_rw_left, rule cspT_Dist_com, simp)

lemma cspT_Ext_choice_Dist_f_r:
  "P [+] (!<f> :X .. Qf) =T[M,M]
   IF (X ={}) THEN (P [+] DIV) ELSE (!<f> x:X .. (P [+] Qf x))"
apply (simp add: Rep_int_choice_f_def)
by (rule cspT_rw_left, rule cspT_Dist_com, simp)

lemma cspT_Parallel_Dist_f_l:
  "(!<f> :Y .. Pf) |[X]| Q =T[M,M]
   IF (Y ={}) THEN (DIV |[X]| Q) ELSE (!<f> x:Y .. (Pf x |[X]| Q))"
apply (simp add: Rep_int_choice_f_def)
by (rule cspT_rw_left, rule cspT_Dist_com, simp)

lemma cspT_Parallel_Dist_f_r:
  "P |[X]| (!<f> :Y .. Qf) =T[M,M]
   IF (Y ={}) THEN (P |[X]| DIV) ELSE (!<f> x:Y .. (P |[X]| Qf x))"
apply (simp add: Rep_int_choice_f_def)
by (rule cspT_rw_left, rule cspT_Dist_com, simp)

lemma cspT_Hiding_Dist_f:
  "(!<f> :Y .. Pf) -- X =T[M,M] !<f> x:Y .. (Pf x -- X)"
by (simp add: Rep_int_choice_f_def cspT_Dist_com)

lemma cspT_Renaming_Dist_f:
  "(!<f> :X .. Pf) [[r]] =T[M,M] !<f> x:X .. (Pf x [[r]])"
by (simp add: Rep_int_choice_f_def cspT_Dist_com)

lemma cspT_Seq_compo_Dist_f:
  "(!<f> :X .. Pf) ;; Q =T[M,M] !<f> x:X .. (Pf x ;; Q)"
by (simp add: Rep_int_choice_f_def cspT_Dist_com)

lemma cspT_Depth_rest_Dist_f:
  "(!<f> :X .. Pf) |. n =T[M,M] !<f> x:X .. (Pf x |. n)"
by (simp add: Rep_int_choice_f_def cspT_Dist_com)

(*********************************************************
                     Dist laws
 *********************************************************)

lemmas cspT_Dist_f = cspT_Ext_choice_Dist_f_l cspT_Ext_choice_Dist_f_r
                           cspT_Parallel_Dist_f_l   cspT_Parallel_Dist_f_r
                           cspT_Hiding_Dist_f       cspT_Renaming_Dist_f
                           cspT_Seq_compo_Dist_f    cspT_Depth_rest_Dist_f

lemmas cspT_Dist_f_nonempty =
       cspT_Ext_choice_Dist_f_l_nonempty cspT_Ext_choice_Dist_f_r_nonempty
       cspT_Parallel_Dist_f_l_nonempty   cspT_Parallel_Dist_f_r_nonempty
       cspT_Hiding_Dist_f       cspT_Renaming_Dist_f
       cspT_Seq_compo_Dist_f    cspT_Depth_rest_Dist_f

(*** all rules ***)

lemmas cspT_Dist = cspT_Dist_sum
                   cspT_Dist_nat cspT_Dist_set cspT_Dist_com cspT_Dist_f

lemmas cspT_Dist_nonempty = cspT_Dist_sum_nonempty
                            cspT_Dist_nat_nonempty
                            cspT_Dist_set_nonempty
                            cspT_Dist_com_nonempty
                            cspT_Dist_f_nonempty

(*****************************************************************

      additional distribution over replicated internal choice

         1. (!! :X .. (a -> P))
         2. (!! :Y .. (? :X -> P))

 *****************************************************************)

(*********************************************************
              Dist law for Act_prefix
 *********************************************************)

lemma cspT_Act_prefix_Dist_sum:
  "sumset C ~= {} ==>
   a -> (!! :C .. Pf) =T[M,M] !! c:C .. (a -> Pf c)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)
 apply (force)
 apply (force)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)
 apply (force)
done

(*********************************************************
              Dist_nat law for Ext_pre_choice
 *********************************************************)

lemma cspT_Ext_pre_choice_Dist_sum:
  "sumset C ~= {} ==>
   ? x:X -> (!! c:C .. (Pf c) x) =T[M,M] !! c:C .. (? :X -> (Pf c))"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)
 apply (force)
 apply (force)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)
 apply (force)
done

(*****************************************************************
                     for convenienve
 *****************************************************************)

(* nat *)

lemma cspT_Act_prefix_Dist_nat:
  "N ~= {} ==>
   a -> (!nat :N .. Pf) =T[M,M] !nat n:N .. (a -> Pf n)"
by (simp add: Rep_int_choice_ss_def cspT_Act_prefix_Dist_sum)

lemma cspT_Ext_pre_choice_Dist_nat:
  "N ~= {} ==>
   ? x:X -> (!nat n:N .. (Pf n) x) =T[M,M] !nat n:N .. (? :X -> (Pf n))"
by (simp add: Rep_int_choice_ss_def cspT_Ext_pre_choice_Dist_sum)

(* set *)

lemma cspT_Act_prefix_Dist_set:
  "Xs ~= {} ==>
   a -> (!set :Xs .. Pf) =T[M,M] !set X:Xs .. (a -> Pf X)"
by (simp add: Rep_int_choice_ss_def cspT_Act_prefix_Dist_sum)

lemma cspT_Ext_pre_choice_Dist_set:
  "Ys ~= {} ==>
   ? x:X -> (!set Y:Ys .. (Pf Y) x) =T[M,M] !set Y:Ys .. (? :X -> (Pf Y))"
by (simp add: Rep_int_choice_ss_def cspT_Ext_pre_choice_Dist_sum)

(* com *)

lemma cspT_Act_prefix_Dist_com:
  "X ~= {} ==>
   a -> (! :X .. Pf) =T[M,M] ! x:X .. (a -> Pf x)"
by (simp add: Rep_int_choice_com_def cspT_Act_prefix_Dist_set)

lemma cspT_Ext_pre_choice_Dist_com:
  "Y ~= {} ==>
   ? x:X -> (! y:Y .. (Pf y) x) =T[M,M] ! y:Y .. (? :X -> (Pf y))"
by (simp add: Rep_int_choice_com_def cspT_Ext_pre_choice_Dist_set)

(* f *)

lemma cspT_Act_prefix_Dist_f:
  "X ~= {} ==>
   a -> (!<f> :X .. Pf) =T[M,M] !<f> x:X .. (a -> Pf x)"
by (simp add: Rep_int_choice_f_def cspT_Act_prefix_Dist_com)

lemma cspT_Ext_pre_choice_Dist_f:
  "Y ~= {} ==>
   ? x:X -> (!<f> y:Y .. (Pf y) x) =T[M,M] !<f> y:Y .. (? :X -> (Pf y))"
by (simp add: Rep_int_choice_f_def cspT_Ext_pre_choice_Dist_com)

(*** arias ***)

lemmas cspT_Act_prefix_Dist
     = cspT_Act_prefix_Dist_sum
       cspT_Act_prefix_Dist_nat
       cspT_Act_prefix_Dist_set
       cspT_Act_prefix_Dist_com
       cspT_Act_prefix_Dist_f

lemmas cspT_Ext_pre_choice_Dist
     = cspT_Ext_pre_choice_Dist_sum
       cspT_Ext_pre_choice_Dist_nat
       cspT_Ext_pre_choice_Dist_set
       cspT_Ext_pre_choice_Dist_com
       cspT_Ext_pre_choice_Dist_f

(*****************************************************************
      distribution over external choice
         1. (P1 [+] P2) [[r]]
         2. (P1 [+] P2) |. n
 *****************************************************************)

(*********************
     [[r]]-[+]-dist
 *********************)

lemma cspT_Renaming_Ext_dist:
  "(P1 [+] P2) [[r]] =T[M,M]
   (P1 [[r]]) [+] (P2 [[r]])"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (force)

(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (force)
done

(*********************
     |.-[+]-dist
 *********************)

lemma cspT_Depth_rest_Ext_dist:
  "(P1 [+] P2) |. n =T[M,M]
   (P1 |. n) [+] (P2 |. n)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule)
 apply (simp add: in_traces)

(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (force)
done

lemmas cspT_Ext_dist = cspT_Renaming_Ext_dist cspT_Depth_rest_Ext_dist

(*---------------------------------------------------------*
 |                   complex distribution                  |
 *---------------------------------------------------------*)

(*********************
     !!-input-!set
 *********************)

lemma cspT_Rep_int_choice_sum_input_set:
  "(!! c:C .. (? :(Yf c) -> Rff c))
   =T[M,M]
   (!set Y : {(Yf c)|c. c: sumset C} ..
      (? a : Y -> (!! c:{c:C. a : Yf c}s .. Rff c a)))"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)
  apply (force)

(* <= *)
 apply (rule, simp add: in_traces)
 apply (elim disjE conjE exE)
 apply (simp_all)
 apply (fast)
 apply (force)
done

lemma cspT_Rep_int_choice_nat_input_set:
  "(!nat n:N .. (? :(Yf n) -> Rff n))
   =T[M,M]
   (!set Y : {(Yf n)|n. n:N} .. (? a : Y -> (!nat n:{n:N. a : Yf n} .. Rff n a)))"
apply (simp add: Rep_int_choice_ss_def)
apply (rule cspT_rw_left)
apply (rule cspT_Rep_int_choice_sum_input_set)
apply (simp add: Rep_int_choice_ss_def)
apply (rule cspT_decompo)
apply (auto)
apply (rule_tac x="type2 n" in exI)
by (auto)

lemma cspT_Rep_int_choice_set_input_set:
  "(!set X:Xs .. (? :(Yf X) -> Rff X))
   =T[M,M]
   (!set Y : {(Yf X)|X. X:Xs} .. (? a : Y -> (!set X:{X:Xs. a : Yf X} .. Rff X a)))"
apply (simp add: Rep_int_choice_ss_def)
apply (rule cspT_rw_left)
apply (rule cspT_Rep_int_choice_sum_input_set)
apply (simp add: Rep_int_choice_ss_def)
apply (rule cspT_decompo)
apply (auto)
apply (rule_tac x="type1 X" in exI)
by (auto)

lemmas cspT_Rep_int_choice_input_set =
       cspT_Rep_int_choice_sum_input_set
       cspT_Rep_int_choice_nat_input_set
       cspT_Rep_int_choice_set_input_set

(*-------------------------------*
          !!-[+]-Dist
 *-------------------------------*)

lemma cspT_Rep_int_choice_Ext_Dist_sum:
  "ALL c:sumset C. (Qf c = SKIP | Qf c = DIV) ==>
   (!! c:C .. (Pf c [+] Qf c)) =T[M,M]
   ((!! :C .. Pf) [+] (!! :C .. Qf))"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim conjE exE bexE disjE)
 apply (simp_all)
 apply (force)
 apply (drule_tac x="c" in bspec)
 apply (simp)
 apply (erule disjE)
 apply (simp_all add: in_traces)
 apply (erule disjE)
 apply (simp_all)
 apply (rule disjI2)
 apply (rule_tac x="c" in bexI)
 apply (simp_all add: in_traces)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim conjE exE bexE disjE)
 apply (simp_all)
 apply (fast)
 apply (fast)
done

lemma cspT_Rep_int_choice_Ext_Dist_nat:
  "ALL n:N. (Qf n = SKIP | Qf n = DIV) ==>
   (!nat n:N .. (Pf n [+] Qf n)) =T[M,M]
   ((!nat :N .. Pf) [+] (!nat :N .. Qf))"
apply (simp add: Rep_int_choice_ss_def)
apply (rule cspT_Rep_int_choice_Ext_Dist_sum)
by (auto)

lemma cspT_Rep_int_choice_Ext_Dist_set:
  "ALL X:Xs. (Qf X = SKIP | Qf X = DIV) ==>
   (!set X:Xs .. (Pf X [+] Qf X)) =T[M,M]
   ((!set :Xs .. Pf) [+] (!set :Xs .. Qf))"
apply (simp add: Rep_int_choice_ss_def)
apply (rule cspT_Rep_int_choice_Ext_Dist_sum)
by (auto)

lemma cspT_Rep_int_choice_Ext_Dist_com:
  "ALL a:X. (Qf a = SKIP | Qf a = DIV) ==>
   (! a:X .. (Pf a [+] Qf a)) =T[M,M]
   ((! :X .. Pf) [+] (! :X .. Qf))"
apply (simp add: Rep_int_choice_com_def)
apply (rule cspT_Rep_int_choice_Ext_Dist_set)
by (auto)

lemma cspT_Rep_int_choice_Ext_Dist_f:
  "[| inj f ; ALL a:X. (Qf a = SKIP | Qf a = DIV) |] ==>
   (!<f> a:X .. (Pf a [+] Qf a)) =T[M,M]
   ((!<f> :X .. Pf) [+] (!<f> :X .. Qf))"
apply (simp add: Rep_int_choice_f_def)
apply (rule cspT_Rep_int_choice_Ext_Dist_com)
by (auto)

lemmas cspT_Rep_int_choice_Ext_Dist =
       cspT_Rep_int_choice_Ext_Dist_sum
       cspT_Rep_int_choice_Ext_Dist_nat
       cspT_Rep_int_choice_Ext_Dist_set
       cspT_Rep_int_choice_Ext_Dist_com
       cspT_Rep_int_choice_Ext_Dist_f

(*-------------------------------*
          !!-input-Dist
 *-------------------------------*)

lemma cspT_Rep_int_choice_input:
  "!set X:Xs .. (? :X -> Pf) =T[M,M] (? :(Union Xs) -> Pf)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule, simp add: in_traces)
 apply (force)

(* <= *)
 apply (rule, simp add: in_traces)
 apply (force)
done

lemma cspT_Rep_int_choice_input_Dist:
  "(!set X:Xs .. (? :X -> Pf)) [+] Q =T[M,M] (? :(Union Xs) -> Pf) [+] Q"
apply (rule cspT_decompo)
apply (rule cspT_Rep_int_choice_input)
apply (rule cspT_reflex)
done

(* =================================================== *
 |             addition for CSP-Prover 5               |
 * =================================================== *)

(* --------------------------------------------------- *
     distribution hiding over sequential composition
 * --------------------------------------------------- *)

(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Seq_compo_hide_dist:
  "(P ;; Q) -- X =T[M,M] (P -- X) ;; (Q -- X)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim conjE exE disjE)
 apply (simp_all)

  (* 1 *)
 apply (rule disjI1)
 apply (rule_tac x="sa --tr X" in exI)
 apply (simp add: rmTick_hide)
 apply (rule_tac x="sa" in exI)
 apply (simp)

  (* 2 *)
 apply (rule disjI2)
 apply (rule_tac x="sa --tr X" in exI)
 apply (rule_tac x="ta --tr X" in exI)
 apply (simp)
 apply (rule conjI)
  apply (rule_tac x="sa ^^^ <Tick>" in exI)
  apply (simp)
  apply (rule_tac x="ta" in exI)
  apply (simp)

(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE)
  (* 1 *)
  apply (insert trace_last_noTick_or_Tick)
  apply (drule_tac x="sa" in spec)
  apply (elim disjE conjE exE)
   apply (simp)
   apply (rule_tac x="sa" in exI)
   apply (simp)
   apply (rule disjI1)
   apply (rule_tac x="sa" in exI)
   apply (simp)

   apply (simp)
   apply (rule_tac x="sb" in exI)
   apply (simp)
   apply (rule disjI1)
   apply (rule_tac x="sb ^^^ <Tick>" in exI)
   apply (simp)

 (* 2 *)
  apply (drule_tac x="sa" in spec)
  apply (elim disjE conjE exE)
   apply (simp)
   apply (subgoal_tac "noTick(sa --tr X)")
   apply (rotate_tac 2)
   apply (drule sym)
   apply (simp del: hide_tr_noTick)
   apply (simp)

   apply (simp)
   apply (rule_tac x="sc ^^^ sb" in exI)
   apply (simp)
   apply (rule disjI2)
   apply (rule_tac x="sc" in exI)
   apply (rule_tac x="sb" in exI)
   apply (simp)
done

(* --------------------------------------------------- *
         distribution hiding over interleaving
 * --------------------------------------------------- *)

(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Interleave_hide_dist:
  "(P ||| Q) -- X =T[M,M] (P -- X) ||| (Q -- X)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim conjE exE disjE)
 apply (simp_all)
 apply (rule_tac x="sa --tr X" in exI)
 apply (rule_tac x="ta --tr X" in exI)
 apply (simp add: interleave_of_hide_tr_ex)
 apply (force)

(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE)

 apply (simp add: interleave_of_hide_tr_ex)
 apply (elim conjE exE)
 apply (simp)
 apply (rule_tac x="v" in exI)
 apply (simp)
 apply (force)
done

(* --------------------------------------------------- *
    distribution renaming over sequential composition
 * --------------------------------------------------- *)

(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Seq_compo_renaming_dist:
  "(P ;; Q) [[r]] =T[M,M] (P [[r]]) ;; (Q [[r]])"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim conjE exE disjE)
 apply (simp_all)

  (* 1 *)
  apply (rule disjI1)
  apply (rule_tac x="t" in exI)
  apply (subgoal_tac "noTick t")
  apply (simp)
  apply (rule_tac x="rmTick sa" in exI)
  apply (simp)
  apply (rule memT_prefix_closed)
  apply (simp)
  apply (simp)
  apply (rule ren_tr_noTick_left)
  apply (simp)
  apply (simp)

  (* 2 *)
  apply (rule disjI2)
  apply (simp add: ren_tr_appt_decompo_left)
  apply (elim conjE exE)

  apply (simp)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="t2" in exI)
  apply (simp)
  apply (rule conjI)

   apply (rule_tac x="sa ^^^ <Tick>" in exI)
   apply (simp add: ren_tr_noTick_left)

   apply (simp add: ren_tr_noTick_left)
   apply (rule_tac x="ta" in exI)
   apply (simp)

(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE)
  (* 1 *)
  apply (insert trace_last_noTick_or_Tick)
  apply (drule_tac x="s" in spec)
  apply (elim disjE conjE exE)
   apply (simp)
   apply (rule_tac x="sa" in exI)
   apply (simp)
   apply (rule disjI1)
   apply (rule_tac x="sa" in exI)
   apply (simp)
   apply (simp add: ren_tr_noTick_right)

   apply (simp)
   apply (simp add: ren_tr_appt_decompo_right)
   apply (elim conjE exE)
   apply (simp)
   apply (rule_tac x="s1" in exI)
   apply (simp)
   apply (rule disjI1)
   apply (rule_tac x="s1 ^^^ <Tick>" in exI)
   apply (simp)

 (* 2 *)
  apply (simp)
  apply (simp add: ren_tr_appt_decompo_right)
  apply (elim conjE exE)
  apply (simp)
  apply (rule_tac x="s1 ^^^ sb" in exI)
  apply (rule conjI)

   apply (force)
   apply (force)
done

(* --------------------------------------------------- *
         distribution renaming over interleaving
 * --------------------------------------------------- *)
(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Interleave_renaming_dist:
  "(P ||| Q) [[r]] =T[M,M] (P [[r]]) ||| (Q [[r]])"
apply (simp add: cspT_semantics)
apply (rule order_antisym)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim conjE exE disjE)
 apply (insert interleave_of_ren_tr_only_if_all)
 apply (drule_tac x="s" in spec)
 apply (drule_tac x="r" in spec)
 apply (drule_tac x="t" in spec)
 apply (drule_tac x="sa" in spec)
 apply (drule_tac x="ta" in spec)
 apply (force)

(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim conjE exE disjE)
 apply (erule rem_asmE)
 apply (insert interleave_of_ren_tr_if_all)
 apply (drule_tac x="t" in spec)
 apply (drule_tac x="r" in spec)
 apply (drule_tac x="sa" in spec)
 apply (drule_tac x="sb" in spec)
 apply (drule_tac x="s" in spec)
 apply (drule_tac x="ta" in spec)
 apply (force)
done

(* --------------------------------------------------- *
     distribution internal choice over prefix
 * --------------------------------------------------- *)

(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Act_prefix_dist:
  "a -> (P |~| Q) =T[M,M] (a -> P) |~| (a -> Q)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)
done

lemma cspT_Int_choice_Act_prefix_delay:
  "(a -> P) |~| (a -> Q) =T[M,M] a -> (P |~| Q)"
apply (rule cspT_sym)
apply (simp add: cspT_Act_prefix_dist)
done

lemma cspT_Int_choice_Act_prefix_delay_eq:
  "a = b ==> (a -> P) |~| (b -> Q) =T[M,M] a -> (P |~| Q)"
apply (simp add: cspT_Int_choice_Act_prefix_delay)
done

(* --------------------------------------------------- *
     distribution internal choice over prefix choice
 * --------------------------------------------------- *)

(*------------------*
 |      csp law     |
 *------------------*)

lemma cspT_Ext_pre_choice_dist:
  "? x:X -> (Pf x |~| Qf x) =T[M,M] (? x:X -> Pf x) |~| (? x:X -> Qf x)"
apply (simp add: cspT_semantics)
apply (rule order_antisym)
(* <= *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)

(* => *)
 apply (rule)
 apply (simp add: in_traces)
 apply (elim disjE conjE exE bexE)
 apply (simp_all)
done

lemma cspT_Int_choice_Ext_pre_choice_delay:
  "(? x:X -> Pf x) |~| (? x:X -> Qf x)  =T[M,M] ? x:X -> (Pf x |~| Qf x)"
apply (rule cspT_sym)
apply (simp add: cspT_Ext_pre_choice_dist)
done

lemma cspT_Int_choice_Ext_pre_choice_delay_eq:
  "X = Y ==>
  (? x:X -> Pf x) |~| (? x:Y -> Qf x)
  =T[M,M] ? x:X -> (Pf x |~| Qf x)"
apply (simp add: cspT_Int_choice_Ext_pre_choice_delay)
done

(*  replicated internal choice *)

lemma cspT_Act_prefix_delay_sum:
  "!! c:C .. (a -> Pf c) =T[M,M]
   IF (sumset C = {}) THEN DIV ELSE (a -> (!! c:C .. (Pf c)))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "sumset C = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Act_prefix_Dist)
done

lemma cspT_Ext_pre_choice_delay_sum:
  "!! c:C .. (? :X -> (Pf c)) =T[M,M]
   IF (sumset C = {}) THEN DIV ELSE (? x:X -> (!! c:C .. (Pf c) x))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "sumset C = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Ext_pre_choice_Dist)
done

lemma cspT_Act_prefix_delay_nat:
  "!nat n:N .. (a -> Pf n) =T[M,M]
   IF (N = {}) THEN DIV ELSE (a -> (!nat n:N .. (Pf n)))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "N = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Act_prefix_Dist)
done

lemma cspT_Ext_pre_choice_delay_nat:
  "!nat n:N .. (? :X -> (Pf n)) =T[M,M]
   IF (N = {}) THEN DIV ELSE (? x:X -> (!nat n:N .. (Pf n) x))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "N = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Ext_pre_choice_Dist)
done

lemma cspT_Act_prefix_delay_set:
  "!set X:Xs .. (a -> Pf X) =T[M,M]
   IF (Xs = {}) THEN DIV ELSE (a -> (!set X:Xs .. (Pf X)))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "Xs = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Act_prefix_Dist)
done

lemma cspT_Ext_pre_choice_delay_set:
  "!set Y:Xs .. (? :X -> (Pf Y)) =T[M,M]
   IF (Xs = {}) THEN DIV ELSE (? x:X -> (!set Y:Xs .. (Pf Y) x))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "Xs = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Ext_pre_choice_Dist)
done

lemma cspT_Act_prefix_delay_com:
  "! x:X .. (a -> Pf x) =T[M,M]
   IF (X = {}) THEN DIV ELSE (a -> (! :X .. Pf))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "X = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Act_prefix_Dist)
done

lemma cspT_Ext_pre_choice_delay_com:
  "! y:Y .. (? :X -> (Pf y)) =T[M,M]
   IF (Y = {}) THEN DIV ELSE (? x:X -> (! y:Y .. (Pf y) x))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "Y = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Ext_pre_choice_Dist)
done

lemma cspT_Act_prefix_delay_f:
  "inj f ==>
   !<f> x:X .. (a -> Pf x) =T[M,M]
   IF (X = {}) THEN DIV ELSE (a -> (!<f> :X .. Pf))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "X = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Act_prefix_Dist)
done

lemma cspT_Ext_pre_choice_delay_f:
  "inj f ==>
   !<f> y:Y .. (? :X -> (Pf y)) =T[M,M]
   IF (Y = {}) THEN DIV ELSE (? x:X -> (!<f> y:Y .. (Pf y) x))"
apply (rule cspT_rw_right)
apply (rule cspT_IF_split)
apply (case_tac "Y = {}")
apply (simp add: cspT_Rep_int_choice_DIV)
apply (simp)
apply (rule cspT_sym)
apply (simp add: cspT_Ext_pre_choice_Dist)
done

lemmas cspT_choice_delay =
       cspT_Int_choice_Act_prefix_delay
       cspT_Int_choice_Ext_pre_choice_delay
       cspT_Act_prefix_delay_sum
       cspT_Ext_pre_choice_delay_sum
       cspT_Act_prefix_delay_nat
       cspT_Ext_pre_choice_delay_nat
       cspT_Act_prefix_delay_set
       cspT_Ext_pre_choice_delay_set
       cspT_Act_prefix_delay_com
       cspT_Ext_pre_choice_delay_com
       cspT_Act_prefix_delay_f
       cspT_Ext_pre_choice_delay_f

lemmas cspT_choice_delay_eq =
       cspT_Int_choice_Act_prefix_delay_eq
       cspT_Int_choice_Ext_pre_choice_delay_eq

(*********************************************************
                       P |[X,Y]| Q
 *********************************************************)

(* ---------- *
    |~| left
 * ---------- *)

lemma cspT_Alpha_Parallel_dist_l:
  "(P1 |~| P2) |[X,Y]| Q =T[M,M]
   (P1 |[X,Y]| Q) |~| (P2 |[X,Y]| Q)"
apply (simp add: Alpha_parallel_def)

apply (rule cspT_rw_left)
apply (rule cspT_decompo)
apply (simp)
apply (rule cspT_dist)
apply (rule cspT_reflex)
apply (rule cspT_rw_left)
apply (rule cspT_dist)
apply (simp)
done

(* ---------- *
    |~| right
 * ---------- *)
lemma cspT_Alpha_Parallel_dist_r:
  "P |[X,Y]| (Q1 |~| Q2) =T[M,M]
   (P |[X,Y]| Q1) |~| (P |[X,Y]| Q2)"
apply (simp add: Alpha_parallel_def)

apply (rule cspT_rw_left)
apply (rule cspT_decompo)
apply (simp)
apply (rule cspT_reflex)
apply (rule cspT_dist)
apply (rule cspT_rw_left)
apply (rule cspT_dist)
apply (simp)
done

(* ---------- *
    !! left
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_sum_l_nonempty:
  "sumset C ~= {} ==>
     (!! :C .. Pf) |[X,Y]| Q =T[M,M]
     !! c:C .. (Pf c |[X,Y]| Q)"
apply (simp add: Alpha_parallel_def)

apply (rule cspT_rw_left)
apply (rule cspT_decompo)
apply (simp)
apply (rule cspT_Parallel_Dist_sum_l_nonempty)
apply (simp)
apply (rule cspT_reflex)
apply (rule cspT_rw_left)
apply (rule cspT_Parallel_Dist_sum_l_nonempty)
apply (simp)
apply (simp)
done

lemma cspT_Alpha_Parallel_Dist_sum_l:
  "(!! :C .. Pf) |[X,Y]| Q =T[M,M]
   IF (sumset C={}) THEN (DIV |[X,Y]| Q) ELSE (!! c:C .. (Pf c |[X,Y]| Q))"
apply (case_tac "sumset C={}")
apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_decompo_Alpha_parallel)
apply (simp)+
apply (simp add: cspT_Rep_int_choice_empty)
apply (simp)

apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_Alpha_Parallel_Dist_sum_l_nonempty)
apply (simp)
done

(* ---------- *
    !! right
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_sum_r_nonempty:
  "sumset C ~= {} ==>
     P |[X,Y]| (!! :C .. Qf) =T[M,M]
     !! c:C .. (P |[X,Y]| Qf c)"
apply (rule cspT_rw_left)
apply (rule cspT_Alpha_parallel_commut)
apply (rule cspT_rw_left)
apply (rule cspT_Alpha_Parallel_Dist_sum_l_nonempty, simp)
apply (rule cspT_decompo, simp)
apply (rule cspT_Alpha_parallel_commut)
done

lemma cspT_Alpha_Parallel_Dist_sum_r:
  "P |[X,Y]| (!! :C .. Qf) =T[M,M]
   IF (sumset C={}) THEN (P |[X,Y]| DIV) ELSE (!! c:C .. (P |[X,Y]| Qf c))"
apply (case_tac "sumset C={}")
apply (simp)
apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_decompo_Alpha_parallel)
apply (simp)+
apply (simp add: cspT_Rep_int_choice_empty)
apply (simp)

apply (rule cspT_rw_right)
apply (rule cspT_IF)
apply (rule cspT_Alpha_Parallel_Dist_sum_r_nonempty)
apply (simp)
done

(* ---------- *
   !nat left
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_nat_l_nonempty:
  "N ~= {} ==>
     (!nat :N .. Pf) |[X,Y]| Q =T[M,M]
     !nat n:N .. (Pf n |[X,Y]| Q)"
by (simp add: Rep_int_choice_ss_def cspT_Alpha_Parallel_Dist_sum_l_nonempty)

(*** Dist ***)

lemma cspT_Alpha_Parallel_Dist_nat_l:
  "(!nat :N .. Pf) |[X,Y]| Q =T[M,M]
   IF (N={}) THEN (DIV |[X,Y]| Q) ELSE (!nat n:N .. (Pf n |[X,Y]| Q))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_sum_l, simp)

(* ---------- *
   !nat right
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_nat_r_nonempty:
  "N ~= {} ==>
     P |[X,Y]| (!nat :N .. Qf) =T[M,M]
     !nat n:N .. (P |[X,Y]| Qf n)"
by (simp add: Rep_int_choice_ss_def cspT_Alpha_Parallel_Dist_sum_r_nonempty)

(*** Dist ***)

lemma cspT_Alpha_Parallel_Dist_nat_r:
  "P |[X,Y]| (!nat :N .. Qf) =T[M,M]
   IF (N={}) THEN (P |[X,Y]| DIV) ELSE (!nat n:N .. (P |[X,Y]| Qf n))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_sum_r, simp)

(* ---------- *
   !set left
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_set_l_nonempty:
  "Xs ~= {} ==>
     (!set :Xs .. Pf) |[Y,Z]| Q =T[M,M]
     !set X:Xs .. (Pf X |[Y,Z]| Q)"
by (simp add: Rep_int_choice_ss_def cspT_Alpha_Parallel_Dist_sum_l_nonempty)

(*** Dist ***)

lemma cspT_Alpha_Parallel_Dist_set_l:
  "(!set :Xs .. Pf) |[Y,Z]| Q =T[M,M]
   IF (Xs={}) THEN (DIV |[Y,Z]| Q) ELSE (!set X:Xs .. (Pf X |[Y,Z]| Q))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_sum_l, simp)

(* ---------- *
   !set right
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_set_r_nonempty:
  "Xs ~= {} ==>
     P |[Y,Z]| (!set :Xs .. Qf) =T[M,M]
     !set X:Xs .. (P |[Y,Z]| Qf X)"
by (simp add: Rep_int_choice_ss_def cspT_Alpha_Parallel_Dist_sum_r_nonempty)

(*** Dist ***)

lemma cspT_Alpha_Parallel_Dist_set_r:
  "P |[Y,Z]| (!set :Xs .. Qf) =T[M,M]
   IF (Xs={}) THEN (P |[Y,Z]| DIV) ELSE (!set X:Xs .. (P |[Y,Z]| Qf X))"
apply (simp add: Rep_int_choice_ss_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_sum_r, simp)

(* ---------- *
     ! left
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_com_l_nonempty:
  "A ~= {}
   ==> (! :A .. Pf) |[X,Y]| Q =T[M,M] ! x:A .. (Pf x |[X,Y]| Q)"
by (simp add: Rep_int_choice_com_def cspT_Alpha_Parallel_Dist_set_l_nonempty)

lemma cspT_Alpha_Parallel_Dist_com_l:
  "(! :A .. Pf) |[X,Y]| Q =T[M,M]
   IF (A ={}) THEN (DIV |[X,Y]| Q) ELSE (! x:A .. (Pf x |[X,Y]| Q))"
apply (simp add: Rep_int_choice_com_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_set_l, simp)

(* ---------- *
     ! right
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_com_r_nonempty:
  "A ~= {}
   ==> P |[X,Y]| (! :A .. Qf) =T[M,M] ! x:A .. (P |[X,Y]| Qf x)"
by (simp add: Rep_int_choice_com_def cspT_Alpha_Parallel_Dist_set_r_nonempty)

lemma cspT_Alpha_Parallel_Dist_com_r:
  "P |[X,Y]| (! :A .. Qf) =T[M,M]
   IF (A ={}) THEN (P |[X,Y]| DIV) ELSE (! x:A .. (P |[X,Y]| Qf x))"
apply (simp add: Rep_int_choice_com_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_set_r, simp)

(* ---------- *
   !<f> left
 * ---------- *)

lemma cspT_Alpha_Parallel_Dist_f_l_nonempty:
  "[| inj f ; A ~= {} |]
   ==> (!<f> :A .. Pf) |[X,Y]| Q =T[M,M] !<f> x:A .. (Pf x |[X,Y]| Q)"
by (simp add: Rep_int_choice_f_def cspT_Alpha_Parallel_Dist_com_l_nonempty)

lemma cspT_Alpha_Parallel_Dist_f_l:
  "(!<f> :A .. Pf) |[X,Y]| Q =T[M,M]
   IF (A ={}) THEN (DIV |[X,Y]| Q) ELSE (!<f> x:A .. (Pf x |[X,Y]| Q))"
apply (simp add: Rep_int_choice_f_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_com_l, simp)

lemma cspT_Alpha_Parallel_Dist_f_r_nonempty:
  "[| inj f ; A ~= {} |]
   ==> P |[X,Y]| (!<f> :A .. Qf) =T[M,M] !<f> x:A .. (P |[X,Y]| Qf x)"
by (simp add: Rep_int_choice_f_def cspT_Alpha_Parallel_Dist_com_r_nonempty)

lemma cspT_Alpha_Parallel_Dist_f_r:
  "P |[X,Y]| (!<f> :A .. Qf) =T[M,M]
   IF (A ={}) THEN (P |[X,Y]| DIV) ELSE (!<f> x:A .. (P |[X,Y]| Qf x))"
apply (simp add: Rep_int_choice_f_def)
by (rule cspT_rw_left, rule cspT_Alpha_Parallel_Dist_com_r, simp)

lemmas cspT_dist_Alpha_Parallel =
       cspT_Alpha_Parallel_dist_l
       cspT_Alpha_Parallel_dist_r

lemmas cspT_Dist_Alpha_Parallel =
      cspT_Alpha_Parallel_Dist_sum_l
      cspT_Alpha_Parallel_Dist_sum_r
      cspT_Alpha_Parallel_Dist_nat_l
      cspT_Alpha_Parallel_Dist_nat_r
      cspT_Alpha_Parallel_Dist_set_l
      cspT_Alpha_Parallel_Dist_set_r
      cspT_Alpha_Parallel_Dist_com_l
      cspT_Alpha_Parallel_Dist_com_r
      cspT_Alpha_Parallel_Dist_f_l
      cspT_Alpha_Parallel_Dist_f_r

lemmas cspT_Dist_Alpha_Parallel_nonempty =
      cspT_Alpha_Parallel_Dist_sum_l_nonempty
      cspT_Alpha_Parallel_Dist_sum_r_nonempty
      cspT_Alpha_Parallel_Dist_nat_l_nonempty
      cspT_Alpha_Parallel_Dist_nat_r_nonempty
      cspT_Alpha_Parallel_Dist_set_l_nonempty
      cspT_Alpha_Parallel_Dist_set_r_nonempty
      cspT_Alpha_Parallel_Dist_com_l_nonempty
      cspT_Alpha_Parallel_Dist_com_r_nonempty
      cspT_Alpha_Parallel_Dist_f_l_nonempty
      cspT_Alpha_Parallel_Dist_f_r_nonempty

(****************** to add them again ******************)

end