Theory ProcessCalculi

(* Kirstin Peters, TU Berlin, 2015 *)

theory ProcessCalculi
  imports Relations
begin

section ‹Process Calculi›

text ‹A process calculus is given by a set of process terms (syntax) and a relation on terms
      (semantics). We consider reduction as well as labelled variants of the semantics.›

subsection ‹Reduction Semantics›

text ‹A set of process terms and a relation on pairs of terms (called reduction semantics) define
      a process calculus.›

record 'proc processCalculus =
  Reductions :: "'proc  'proc  bool"

text ‹A pair of the reduction relation is called a (reduction) step.›

abbreviation step :: "'proc  'proc processCalculus  'proc  bool"
  (‹_ _ _› [70, 70, 70] 80) where
  "P Cal Q  Reductions Cal P Q"

text ‹We use * to indicate the reflexive and transitive closure of the reduction relation.›

primrec nSteps :: "'proc  'proc processCalculus  nat  'proc  bool"
  (‹_ __ _› [70, 70, 70, 70] 80) where
  "P Cal0Q     = (P = Q)"
| "P CalSuc nQ = (P'. P CalnP'  P' Cal Q)"

definition steps :: "'proc  'proc processCalculus  'proc  bool"
  (‹_ _* _› [70, 70, 70] 80) where
  "P Cal* Q  n. P CalnQ"

text ‹A process is divergent, if it can perform an infinite sequence of steps.›

definition divergent :: "'proc  'proc processCalculus  bool"  (‹_ _ω [70, 70] 80) where
  "P (Cal)ω  P'. P Cal* P'  (P''. P' Cal P'')"

text ‹Each term can perform an (empty) sequence of steps to itself.›

lemma steps_refl:
  fixes Cal :: "'proc processCalculus"
    and P   :: "'proc"
  shows "P Cal* P"
proof -
  have "P Cal0P"
    by simp
  hence "n. P CalnP"
    by blast
  thus "P Cal* P"
    by (simp add: steps_def)
qed

text ‹A single step is a sequence of steps of length one.›

lemma step_to_steps:
  fixes Cal  :: "'proc processCalculus"
    and P P' :: "'proc"
  assumes step: "P Cal P'"
  shows "P Cal* P'"
proof -
  from step have "P Cal1P'"
    by simp
  thus ?thesis
    unfolding steps_def
    by blast
qed

text ‹If there is a sequence of steps from P to Q and from Q to R, then there is also a sequence
      of steps from P to R.›

lemma nSteps_add:
  fixes Cal   :: "'proc processCalculus"
    and n1 n2 :: "nat"
  shows "P Q R. P Caln1Q  Q Caln2R  P Cal(n1 + n2)R"
proof (induct n2, simp)
  case (Suc n)
  assume IH: "P Q R. P Caln1Q  Q CalnR  P Cal(n1 + n)R"
  show ?case
  proof clarify
    fix P Q R
    assume "Q CalSuc nR"
    from this obtain Q' where A1: "Q CalnQ'" and A2: "Q' Cal R"
      by auto
    assume "P Caln1Q"
    with A1 IH have "P Cal(n1 + n)Q'"
      by blast
    with A2 show "P Cal(n1 + Suc n)R"
      by auto
  qed
qed

lemma steps_add:
  fixes Cal   :: "'proc processCalculus"
    and P Q R :: "'proc"
  assumes A1: "P Cal* Q"
      and A2: "Q Cal* R"
  shows "P Cal* R"
proof -
  from A1 obtain n1 where "P Caln1Q"
    by (auto simp add: steps_def)
  moreover from A2 obtain n2 where "Q Caln2R"
    by (auto simp add: steps_def)
  ultimately have "P Cal(n1 + n2)R"
    using nSteps_add[where Cal="Cal"]
    by blast
  thus "P Cal* R"
    by (simp add: steps_def, blast)
qed

subsubsection ‹Observables or Barbs›

text ‹We assume a predicate that tests terms for some kind of observables. At this point we do not
      limit or restrict the kind of observables used for a calculus nor the method to check them.›

record ('proc, 'barbs) calculusWithBarbs =
  Calculus :: "'proc processCalculus"
  HasBarb  :: "'proc  'barbs  bool" (‹__› [70, 70] 80)

abbreviation hasBarb :: "'proc  ('proc, 'barbs) calculusWithBarbs  'barbs  bool"
  (‹_↓<_>_› [70, 70, 70] 80) where
  "P↓<CWB>a  HasBarb CWB P a"

text ‹A term reaches a barb if it can evolve to a term that has this barb.›

abbreviation reachesBarb :: "'proc  ('proc, 'barbs) calculusWithBarbs  'barbs  bool"
  (‹_⇓<_>_› [70, 70, 70] 80) where
  "P⇓<CWB>a  P'. P (Calculus CWB)* P'  P'↓<CWB>a"

text ‹A relation R preserves barbs if whenever (P, Q) in R and P has a barb then also Q has this
      barb.›

abbreviation rel_preserves_barb_set
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool" where
  "rel_preserves_barb_set Rel CWB Barbs 
   rel_preserves_binary_pred Rel (λP a. a  Barbs  P↓<CWB>a)"

abbreviation rel_preserves_barbs
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool" where
  "rel_preserves_barbs Rel CWB  rel_preserves_binary_pred Rel (HasBarb CWB)"

lemma preservation_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_preserves_barbs Rel CWB = (Barbs. rel_preserves_barb_set Rel CWB Barbs)"
  by blast

text ‹A relation R reflects barbs if whenever (P, Q) in R and Q has a barb then also P has this
      barb.›

abbreviation rel_reflects_barb_set
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool" where
  "rel_reflects_barb_set Rel CWB Barbs 
   rel_reflects_binary_pred Rel (λP a. a  Barbs  P↓<CWB>a)"

abbreviation rel_reflects_barbs
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool" where
  "rel_reflects_barbs Rel CWB  rel_reflects_binary_pred Rel (HasBarb CWB)"

lemma reflection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_reflects_barbs Rel CWB = (Barbs. rel_reflects_barb_set Rel CWB Barbs)"
  by blast

text ‹A relation respects barbs if it preserves and reflects barbs.›

abbreviation rel_respects_barb_set
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool" where
  "rel_respects_barb_set Rel CWB Barbs 
   rel_preserves_barb_set Rel CWB Barbs  rel_reflects_barb_set Rel CWB Barbs"

abbreviation rel_respects_barbs
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool" where
  "rel_respects_barbs Rel CWB  rel_preserves_barbs Rel CWB  rel_reflects_barbs Rel CWB"

lemma respection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_respects_barbs Rel CWB = (Barbs. rel_respects_barb_set Rel CWB Barbs)"
  by blast

text ‹If a relation preserves barbs then so does its reflexive or/and transitive closure.›

lemma preservation_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes preservation: "rel_preserves_barbs Rel CWB"
  shows "rel_preserves_barbs (Rel=) CWB"
    and "rel_preserves_barbs (Rel+) CWB"
    and "rel_preserves_barbs (Rel*) CWB"
  using preservation
        preservation_of_binary_predicates_and_closures[where Rel="Rel" and Pred="HasBarb CWB"]
  by blast+

text ‹If a relation reflects barbs then so does its reflexive or/and transitive closure.›

lemma reflection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes reflection: "rel_reflects_barbs Rel CWB"
  shows "rel_reflects_barbs (Rel=) CWB"
    and "rel_reflects_barbs (Rel+) CWB"
    and "rel_reflects_barbs (Rel*) CWB"
  using reflection
        reflection_of_binary_predicates_and_closures[where Rel="Rel" and Pred="HasBarb CWB"]
  by blast+

text ‹If a relation respects barbs then so does its reflexive, symmetric, or/and transitive
      closure.›

lemma respection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes respection: "rel_respects_barbs Rel CWB"
  shows "rel_respects_barbs (Rel=) CWB"
    and "rel_respects_barbs (symcl Rel) CWB"
    and "rel_respects_barbs (Rel+) CWB"
    and "rel_respects_barbs (symcl (Rel=)) CWB"
    and "rel_respects_barbs (Rel*) CWB"
    and "rel_respects_barbs ((symcl (Rel=))+) CWB"
proof -
  from respection show "rel_respects_barbs (Rel=) CWB"
    using respection_of_binary_predicates_and_closures(1)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (symcl Rel) CWB"
    using respection_of_binary_predicates_and_closures(2)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (Rel+) CWB"
    using respection_of_binary_predicates_and_closures(3)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (symcl (Rel=)) CWB"
    using respection_of_binary_predicates_and_closures(4)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs (Rel*) CWB"
    using respection_of_binary_predicates_and_closures(5)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
next
  from respection show "rel_respects_barbs ((symcl (Rel=))+) CWB"
    using respection_of_binary_predicates_and_closures(6)[where Rel="Rel" and Pred="HasBarb CWB"]
    by blast
qed

text ‹A relation R weakly preserves barbs if it preserves reachability of barbs, i.e., if (P, Q)
      in R and P reaches a barb then also Q has to reach this barb.›

abbreviation rel_weakly_preserves_barb_set
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool" where
  "rel_weakly_preserves_barb_set Rel CWB Barbs 
   rel_preserves_binary_pred Rel (λP a. a  Barbs  P⇓<CWB>a)"

abbreviation rel_weakly_preserves_barbs
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool" where
  "rel_weakly_preserves_barbs Rel CWB  rel_preserves_binary_pred Rel (λP a. P⇓<CWB>a)"

lemma weak_preservation_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_weakly_preserves_barbs Rel CWB =
         (Barbs. rel_weakly_preserves_barb_set Rel CWB Barbs)"
  by blast

text ‹A relation R weakly reflects barbs if it reflects reachability of barbs, i.e., if (P, Q) in
      R and Q reaches a barb then also P has to reach this barb.›

abbreviation rel_weakly_reflects_barb_set
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool" where
  "rel_weakly_reflects_barb_set Rel CWB Barbs 
   rel_reflects_binary_pred Rel (λP a. a  Barbs  P⇓<CWB>a)"

abbreviation rel_weakly_reflects_barbs
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool" where
  "rel_weakly_reflects_barbs Rel CWB  rel_reflects_binary_pred Rel (λP a. P⇓<CWB>a)"

lemma weak_reflection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_weakly_reflects_barbs Rel CWB = (Barbs. rel_weakly_reflects_barb_set Rel CWB Barbs)"
  by blast

text ‹A relation weakly respects barbs if it weakly preserves and weakly reflects barbs.›

abbreviation rel_weakly_respects_barb_set
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  'barbs set  bool" where
  "rel_weakly_respects_barb_set Rel CWB Barbs 
   rel_weakly_preserves_barb_set Rel CWB Barbs  rel_weakly_reflects_barb_set Rel CWB Barbs"

abbreviation rel_weakly_respects_barbs
  :: "('proc × 'proc) set  ('proc, 'barbs) calculusWithBarbs  bool" where
  "rel_weakly_respects_barbs Rel CWB 
   rel_weakly_preserves_barbs Rel CWB  rel_weakly_reflects_barbs Rel CWB"

lemma weak_respection_of_barbs_and_set_of_barbs:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  shows "rel_weakly_respects_barbs Rel CWB = (Barbs. rel_weakly_respects_barb_set Rel CWB Barbs)"
  by blast

text ‹If a relation weakly preserves barbs then so does its reflexive or/and transitive closure.›

lemma weak_preservation_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes preservation: "rel_weakly_preserves_barbs Rel CWB"
  shows "rel_weakly_preserves_barbs (Rel=) CWB"
    and "rel_weakly_preserves_barbs (Rel+) CWB"
    and "rel_weakly_preserves_barbs (Rel*) CWB"
  using preservation preservation_of_binary_predicates_and_closures[where Rel="Rel"
        and Pred="λP a. P⇓<CWB>a"]
  by blast+

text ‹If a relation weakly reflects barbs then so does its reflexive or/and transitive closure.›

lemma weak_reflection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes reflection: "rel_weakly_reflects_barbs Rel CWB"
  shows "rel_weakly_reflects_barbs (Rel=) CWB"
    and "rel_weakly_reflects_barbs (Rel+) CWB"
    and "rel_weakly_reflects_barbs (Rel*) CWB"
  using reflection reflection_of_binary_predicates_and_closures[where Rel="Rel"
        and Pred="λP a. P⇓<CWB>a"]
  by blast+

text ‹If a relation weakly respects barbs then so does its reflexive, symmetric, or/and
      transitive closure.›

lemma weak_respection_of_barbs_and_closures:
  fixes Rel :: "('proc × 'proc) set"
    and CWB :: "('proc, 'barbs) calculusWithBarbs"
  assumes respection: "rel_weakly_respects_barbs Rel CWB"
  shows "rel_weakly_respects_barbs (Rel=) CWB"
    and "rel_weakly_respects_barbs (symcl Rel) CWB"
    and "rel_weakly_respects_barbs (Rel+) CWB"
    and "rel_weakly_respects_barbs (symcl (Rel=)) CWB"
    and "rel_weakly_respects_barbs (Rel*) CWB"
    and "rel_weakly_respects_barbs ((symcl (Rel=))+) CWB"
proof -
  from respection show "rel_weakly_respects_barbs (Rel=) CWB"
    using respection_of_binary_predicates_and_closures(1)[where Rel="Rel"
          and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (symcl Rel) CWB"
    using respection_of_binary_predicates_and_closures(2)[where Rel="Rel"
          and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (Rel+) CWB"
    using respection_of_binary_predicates_and_closures(3)[where Rel="Rel"
          and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (symcl (Rel=)) CWB"
    using respection_of_binary_predicates_and_closures(4)[where Rel="Rel"
          and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs (Rel*) CWB"
    using respection_of_binary_predicates_and_closures(5)[where Rel="Rel"
          and Pred="λP a. P⇓<CWB>a"]
    by blast
next
  from respection show "rel_weakly_respects_barbs ((symcl (Rel=))+) CWB"
    using respection_of_binary_predicates_and_closures(6)[where Rel="Rel"
          and Pred="λP a. P⇓<CWB>a"]
    by blast
qed

(* Kirstin Peters, University of Augsburg, 2026 *)

subsection ‹Labelled Semantics›

text ‹Alternatively, a process calculus is defined by a set of process terms and a relation on a
      term, a label, and a term (called labelled semantics). Moreover, we assume that in this case
      there exists a special label to denote an internal action.›

record ('proc, 'lab) labelledProcessCalculus =
  LabelledSemantics :: "'proc  'lab  'proc  bool"
  InternalAction    :: "'lab"

text ‹A triple of the labelled semantics is called a labelled step. To avoid confusion we disable
      some syntactic sugar for Limes in Topological Spaces.›

no_notation Topological_Spaces.LIM ((‹notation=‹infix LIM››(_)/ (_)/ (_)) [60, 0, 60] 60)

abbreviation labelledStep
  :: "'proc  'lab  ('proc, 'lab) labelledProcessCalculus  'proc  bool"
  (‹_ __ _› [70, 70, 70, 70] 80) where
  "P αCal Q  LabelledSemantics Cal P α Q"

text ‹The internal action is denoted by tau, where we add the respective calculus, since different
      calculi may have a different internal action label.›

abbreviation internal :: "('proc, 'lab) labelledProcessCalculus  'lab"  (τ-_› [70] 90) where
  "τ-Cal  InternalAction Cal"

text ‹A weak internal step is the reflexive and transitive closure of a labelled step on the
      internal action label.›

inductive weakTauStep :: "'proc  ('proc, 'lab) labelledProcessCalculus  'proc  bool"
  (‹_ _* _› [70, 70, 70] 80) where
  WTS_refl:  "P Cal* P"
| WTS_trans: "P Cal* Q; Q τ-CalCal R  P Cal* R"

lemma weakTauStep_decompose:
  fixes P Q :: "'proc"
    and Cal :: "('proc, 'lab) labelledProcessCalculus"
  assumes "P Cal* Q"
  shows "P = Q  (R. P Cal* R  R τ-CalCal Q)"
  using assms
  by (induct, auto)

lemma weakTauSteps_trans:
  fixes P Q R :: "'proc"
    and Cal   :: "('proc, 'lab) labelledProcessCalculus"
  assumes "P Cal* Q"
      and "Q Cal* R"
    shows "P Cal* R"
  using assms(2) assms(1)
proof induct
  case (WTS_refl Q Cal)
  assume "P Cal* Q"
  thus "P Cal* Q" .
next
  case (WTS_trans Q Cal S R)
  assume "P Cal* Q  P Cal* S" and "P Cal* Q"
  hence "P Cal* S"
    by simp
  moreover assume "S τ-CalCal R"
  ultimately show "P Cal* R"
    using weakTauStep.WTS_trans[of P Cal S R]
    by simp
qed

text ‹A weak labelled step is a labelled step surrounded by an arbitrary number of steps on the
      internal action.›

definition weakLabelledActionStep
  :: "'proc  'lab  ('proc, 'lab) labelledProcessCalculus  'proc  bool"
  (‹_ __* _› [70, 70, 70, 70] 80) where
  "P αCal* Q  α  τ-Cal  (R S. P Cal* R  R αCal S  S Cal* Q)"

definition weakLabelledStep
  :: "'proc  'lab  ('proc, 'lab) labelledProcessCalculus  'proc  bool"
  (‹_ ─⁀__* _› [70, 70, 70, 70] 80) where
  "P ─⁀αCal* Q  if α = τ-Cal then P Cal* Q else P αCal* Q"

text ‹A weak labelled step can be extended by any number of internal steps.›

lemma weakLabelledActionStep_extend_by_internal:
  fixes P P' P'' :: "'proc"
    and α        :: "'lab"
    and Cal      :: "('proc, 'lab) labelledProcessCalculus"
  assumes action:   "P αCal* P'"
      and internal: "P' Cal* P''"
    shows "P αCal* P''"
proof -
  from action obtain R S where A1: "α  τ-Cal" and A2: "P Cal* R" and A3: "R αCal S"
                           and A4: "S Cal* P'"
    unfolding weakLabelledActionStep_def
    by blast
  from internal A4 have "S Cal* P''"
    using weakTauSteps_trans[of S Cal P' P'']
    by simp
  with A1 A2 A3 show "P αCal* P''"
    unfolding weakLabelledActionStep_def
    by blast
qed

lemma weakLabelledActionStep_preceeded_by_internal:
  fixes P P' P'' :: "'proc"
    and α        :: "'lab"
    and Cal      :: "('proc, 'lab) labelledProcessCalculus"
  assumes internal: "P Cal* P'"
      and action:   "P' αCal* P''"
    shows "P αCal* P''"
proof -
  from action obtain R S where A1: "α  τ-Cal" and A2: "P' Cal* R" and A3: "R αCal S"
                           and A4: "S Cal* P''"
    unfolding weakLabelledActionStep_def
    by blast
  from internal A2 have "P Cal* R"
    using weakTauSteps_trans[of P Cal P' R]
    by simp
  with A1 A3 A4 show "P αCal* P''"
    unfolding weakLabelledActionStep_def
    by blast
qed

lemma weakLabelledStep_extend_by_internal:
  fixes P P' P'' :: "'proc"
    and α        :: "'lab"
    and Cal      :: "('proc, 'lab) labelledProcessCalculus"
  assumes action:   "P ─⁀αCal* P'"
      and internal: "P' Cal* P''"
    shows "P ─⁀αCal* P''"
  unfolding weakLabelledStep_def
proof auto
  assume "α = τ-Cal"
  with action have "P Cal* P'"
    unfolding weakLabelledStep_def
    by simp
  with internal show "P Cal* P''"
    using weakTauSteps_trans[of P Cal P' P'']
    by simp
next
  assume "α  τ-Cal"
  with action have "P αCal* P'"
    unfolding weakLabelledStep_def
    by simp
  with internal show "P αCal* P''"
    using weakLabelledActionStep_extend_by_internal[of P α Cal P' P'']
    by simp
qed

lemma weakLabelledStep_preceeded_by_internal:
  fixes P P' P'' :: "'proc"
    and α        :: "'lab"
    and Cal      :: "('proc, 'lab) labelledProcessCalculus"
  assumes internal: "P Cal* P'"
      and action:   "P' ─⁀αCal* P''"
    shows "P ─⁀αCal* P''"
  unfolding weakLabelledStep_def
proof auto
  assume "α = τ-Cal"
  with action have "P' Cal* P''"
    unfolding weakLabelledStep_def
    by simp
  with internal show "P Cal* P''"
    using weakTauSteps_trans[of P Cal P' P'']
    by simp
next
  assume "α  τ-Cal"
  with action have "P' αCal* P''"
    unfolding weakLabelledStep_def
    by simp
  with internal show "P αCal* P''"
    using weakLabelledActionStep_preceeded_by_internal[of P Cal P' α P'']
    by simp
qed

text ‹A sequence of weak labelled steps is called a weak labelled sequence. Note that for each
      internal action in the sequence an arbitrary number of internal steps can be performed even 0
      and similarly for each other label. Also note that we deliberately do not forbid internal
      labels in the considered word.›

inductive weakLabelledSequence
  :: "'proc  'lab list  ('proc, 'lab) labelledProcessCalculus  'proc  bool"
  (‹_ ─⌢__* _› [70, 70, 70, 70] 80) where
  WLS_Nil:  "P Cal* P'  P ─⌢[]Cal* P'"
| WLS_Cons: "P ─⌢wCal* P'; P' ─⁀αCal* P''  P ─⌢(w@[α])Cal* P''"

lemma internal_weakLabelledSequence:
  fixes P P' :: "'proc"
    and Cal  :: "('proc, 'lab) labelledProcessCalculus"
  assumes "P ─⌢[]Cal* P'"
  shows "P Cal * P'"
proof -
  define w where def_w: "w = ([]::'lab list)"
  with assms have "P ─⌢wCal* P'"
    by simp
  from this def_w show "P Cal * P'"
    by (induct, simp_all)
qed

text ‹A weak labelled sequence can be extended by any number of internal steps.›

lemma weakLabelledSequence_extend_by_internal:
  fixes P P' P'' :: "'proc"
    and w        :: "'lab list"
    and Cal      :: "('proc, 'lab) labelledProcessCalculus"
  assumes word:     "P ─⌢wCal* P'"
      and internal: "P' Cal* P''"
    shows "P ─⌢wCal* P''"
  using assms
proof (induct arbitrary: P'')
  case (WLS_Nil P Cal P')
  assume "P Cal* P'" and "P' Cal* P''"
  hence "P Cal* P''"
    using weakTauSteps_trans[of P Cal P' P'']
    by simp
  thus "P ─⌢[]Cal* P''"
    using weakLabelledSequence.WLS_Nil[of P Cal P'']
    by simp
next
  case (WLS_Cons P w Cal P' α R)
  assume "P ─⌢wCal* P'"
  moreover assume "P' ─⁀αCal* R" and "R Cal* P''"
  hence "P' ─⁀αCal* P''"
    using weakLabelledStep_extend_by_internal[of P' α Cal R P'']
    by simp
  ultimately show "P ─⌢(w@[α])Cal* P''"
    using weakLabelledSequence.WLS_Cons[of P w Cal P' α P'']
    by simp
qed

lemma weakLabelledSequence_preceeded_by_internal:
  fixes P P' P'' :: "'proc"
    and w        :: "'lab list"
    and Cal      :: "('proc, 'lab) labelledProcessCalculus"
  assumes internal: "P Cal* P'"
      and word:     "P' ─⌢wCal* P''"
    shows "P ─⌢wCal* P''"
  using word internal
proof (induct)
  case (WLS_Nil P' Cal P'')
  assume "P Cal* P'" and "P' Cal* P''"
  hence "P Cal* P''"
    using weakTauSteps_trans[of P Cal P' P'']
    by simp
  thus "P ─⌢[]Cal* P''"
    using weakLabelledSequence.WLS_Nil[of P Cal P'']
    by simp
next
  case (WLS_Cons P' w Cal P'' α P''')
  assume "P Cal* P'  P ─⌢wCal* P''" and "P Cal* P'"
  hence "P ─⌢wCal* P''"
    by simp
  moreover assume "P'' ─⁀αCal* P'''"
  ultimately show "P ─⌢(w@[α])Cal* P'''"
    using weakLabelledSequence.WLS_Cons[of P w Cal P'' α P''']
    by simp
qed

lemma weakLabelledSequence_single:
  fixes P P' :: "'proc"
    and α    :: "'lab"
    and Cal  :: "('proc, 'lab) labelledProcessCalculus"
  assumes step: "P ─⁀αCal* P'"
  shows "P ─⌢[α]Cal* P'"
proof -
  have "P Cal* P"
    using WTS_refl[of P Cal]
    by simp
  hence "P ─⌢[]Cal* P"
    using WLS_Nil[of P Cal P]
    by simp
  with step show "P ─⌢[α]Cal* P'"
    using WLS_Cons[of P "[]" Cal P α P']
    by simp
qed

lemma weakLabelledSequence_decompose:
  fixes P P' :: "'proc"
    and w    :: "'lab list"
    and Cal  :: "('proc, 'lab) labelledProcessCalculus"
  assumes step: "P ─⌢wCal* P'"
  shows "w = []  P Cal* P'"
    and "w  []  w' α P''. w = w'@[α]  P ─⌢w'Cal* P''  P'' ─⁀αCal* P'"
  using step
proof induct
  case (WLS_Nil P Cal P')
  {
    assume "P Cal* P'"
    thus "P Cal* P'" .
  next
    assume "[]  []"
    hence False
      by simp
    thus "w' α P''. [] = w'@[α]  P ─⌢w'Cal* P''  P'' ─⁀αCal* P'"
      by simp
  }
next
  case (WLS_Cons P w Cal P' α P'')
  {
    assume "w@[α] = []"
    hence False
      by simp
    thus "P Cal* P''"
      by simp
  next
    assume "P ─⌢wCal* P'" and "P' ─⁀αCal* P''"
    thus "w' α' P'''. w@[α] = w'@[α']  P ─⌢w'Cal* P'''  P''' ─⁀α'Cal* P''"
      by blast
  }
qed

lemma weakLabelledSequence_single_rev:
  fixes P P' :: "'proc"
    and α    :: "'lab"
    and Cal  :: "('proc, 'lab) labelledProcessCalculus"
  assumes step: "P ─⌢[α]Cal* P'"
  shows "P ─⁀αCal* P'"
proof -
  from step obtain P'' where A1: "P ─⌢[]Cal* P''" and A2: "P'' ─⁀αCal* P'"
    using weakLabelledSequence_decompose(2)[of P "[α]" Cal P']
    by auto
  from A1 have "P Cal* P''"
    using weakLabelledSequence_decompose(1)[of P "[]" Cal P'']
    by simp
  with A2 show "P ─⁀αCal* P'"
    using weakLabelledStep_preceeded_by_internal[of P Cal P'' α P']
    by simp
qed

text ‹A process is divergent, if it can perform an infinite sequence of internal steps.›

definition divergentLS
  :: "'proc  ('proc, 'lab) labelledProcessCalculus  bool" (‹_ _ω [70, 70] 80) where
  "P (Cal)ω  P'. P Cal* P'  (P''. P' τ-CalCal P'')"

end