Theory Labeled_Transition_Systems

(* License: LGPL *)

section ‹Labeled Transition Systems›

theory Labeled_Transition_Systems
  imports Main
begin

subsection ‹Base LTS›

text ‹
  The locale LTS› represents a labeled transition system consisting of a set of states $\mathcal{P}$, a set of actions $\Sigma$, and a transition relation $\mapsto \subseteq \mathcal{P}\times\Sigma\times\mathcal{P}$.
  We formalize the sets of states and actions by the type variables 's› and 'a›. An LTS is then determined by the transition relation step›.
›

locale lts =
  fixes step :: 's  'a  's  bool (‹_  _ _› [70,70,70] 80)
begin

text ‹One may lift termstep to sets of states, written as P ↦S α Q›.›
abbreviation step_setp (‹_ ↦S _ _› [70,70,70] 80) where
  P ↦S α Q  (q  Q. p  P. p  α q)  (p  P. q. p  α q  q  Q)

text ‹The set of α›-derivatives for a set of states P›.›
definition step_set :: 's set  'a  's set where
  step_set P α  { q . p  P. p  α q }

text ‹The set of possible α›-steps for a set of states P› is an instance of termstep lifted to sets of steps.›
lemma step_set_is_step_set: P ↦S α (step_set P α)
  using step_set_def by force

text ‹The lifted termstep_setp (P ↦S α Q›) is therefore this set Q›.›
lemma step_set_eq:
  assumes P ↦S α Q
  shows Q = step_set P α
  using assms step_set_is_step_set by fastforce

end ― ‹of locale lts›

subsection ‹Labeled Transition Systems with Silent Steps›

text ‹
  We formalize labeled transition systems with silent steps as an extension of ordinary labeled transition systems with a fixed internal action τ›.
›

locale lts_tau =
  lts step
    for step :: 's  'a  's  bool (‹_  _ _› [70,70,70] 80) +
    fixes τ :: 'a
begin

text ‹
  The paper citebj2023silentStepSpectroscopyArxiv introduces a transition $p \xrightarrow{(\alpha)}p'$ if $p \xrightarrow{\alpha} p'$, or if $\alpha = \tau$ and $p = p'$.
  We define termsoft_step analogously and provide the notation p ↦a α p'›.
›
abbreviation soft_step (‹_ ↦a _ _› [70,70,70] 80) where
  p ↦a α q  p α q  (α = τ  p = q)

inductive silent_reachable :: 's  's  bool  (infix  80)
  where
    refl: p  p |
    step: p  p'' if p  τ p' and p'  p''

text ‹If p'› is silent-reachable from p› and there is a τ›-transition from p'› to p''› then p''› is silent reachable from p›.›
lemma silent_reachable_append_τ: p  p'  p'  τ p''  p  p''
proof (induct rule: silent_reachable.induct)
  case (refl p)
  then show ?case using silent_reachable.intros by blast
next
  case (step p p' p'')
  then show ?case using silent_reachable.intros by blast
qed

text ‹The relation termsilent_reachable is transitive.›
lemma silent_reachable_trans:
  assumes
    p  p'
    p'  p''
  shows
    p  p''
using assms silent_reachable.intros(2)
  by (induct, blast+)

text ‹The relation silent_reachable_loopless› is a variation of termsilent_reachable that does not use self-loops.›
inductive silent_reachable_loopless :: 's  's  bool  (infix ↠L 80)
  where
    p ↠L p |
    p ↠L p'' if p  τ p' and p' ↠L p'' and p  p'

text ‹If a state p'› is termsilent_reachable from p› it is also termsilent_reachable_loopless.›
lemma silent_reachable_impl_loopless:
  assumes p  p'
  shows p ↠L p'
  using assms
proof(induct rule: silent_reachable.induct)
  case (refl p)
  thus ?case by (rule silent_reachable_loopless.intros(1))
next
  case (step p p' p'')
  thus ?case proof(cases p = p')
    case True
    thus ?thesis using step.hyps(3) by auto
  next
    case False
    thus ?thesis using step.hyps silent_reachable_loopless.intros(2) by blast
  qed
qed

lemma tau_chain_reachabilty:
  assumes i < length pp - 1.  pp!i  τ pp!(Suc i)
  shows j < length pp. i  j. pp!i  pp!j
proof safe
  fix j i
  assume j < length pp i  j
  thus pp!i  pp!j
  proof (induct j)
    case 0
    then show ?case
      using silent_reachable.refl by blast
  next
    case (Suc j)
    then show ?case
    proof (induct i)
      case 0
      then show ?case using assms silent_reachable_append_τ
        by (metis Suc_lessD Suc_lessE bot_nat_0.extremum diff_Suc_1)
    next
      case (Suc i)
      then show ?case using silent_reachable.refl assms silent_reachable_append_τ
        by (metis Suc_lessD Suc_lessE  diff_Suc_1 le_SucE)
    qed
  qed
qed

text ‹A state p› can reach p'› weakly by performing an α›-transition, possibly proceeded and followed by any number of τ›-transitions.›
definition weak_step (‹_ ↠↦↠ _ _› [70, 70, 70] 80) where
  p  ↠↦↠ α p'  if α = τ
                    then p  p'
                    else p1 p2. p  p1  p1  α p2  p2  p'

lemma silent_prepend_weak_step: p  p'  p' ↠↦↠ α p''  p ↠↦↠ α p''
  unfolding weak_step_def using silent_reachable_trans[of p p'] by fastforce

text ‹A sequence of termweak_steps from one state p› to another p'›.›
inductive weak_step_sequence :: 's  'a list  's  bool (‹_ ↠↦↠$ _ _› [70,70,70] 80) where
  p ↠↦↠$ [] p' if p  p' |
  p ↠↦↠$ (α#rt) p'' if p ↠↦↠ α p' p' ↠↦↠$ rt p''

lemma weak_step_sequence_trans:
  assumes p ↠↦↠$ tr_1 p' and p' ↠↦↠$ tr_2 p''
  shows p ↠↦↠$ (tr_1 @ tr_2) p''
  using assms weak_step_sequence.intros(2)
proof induct
  case (1 p p')
  then show ?case
    by (metis weak_step_sequence.simps append_Nil silent_prepend_weak_step silent_reachable_trans)
next
  case (2 p α p' rt p'')
  then show ?case by fastforce
qed

text ‹The weak traces of a state are all possible sequences of weak transitions that can be performed.›
abbreviation weak_traces :: 's  'a list set
  where weak_traces p  {tr. p'. p ↠↦↠$ tr p'}

text ‹The empty trace is in termweak_traces for all states.›
lemma empty_trace_allways_weak_trace:
  shows []  weak_traces p
  using silent_reachable.intros(1) weak_step_sequence.intros(1) by fastforce

text τ› can be prepended to any weak trace.›
lemma prepend_τ_weak_trace:
  assumes tr  weak_traces p
  shows (τ # tr)  weak_traces p
  using assms silent_reachable.intros(1) mem_Collect_eq
    weak_step_sequence.intros(2) weak_step_def by fastforce

lemma silent_prepend_weak_traces:
  assumes
    p  p'
    tr  weak_traces p'
  shows
    tr  weak_traces p
  using assms
proof -
  assume p  p'
     and tr  weak_traces p'
  hence p''. p' ↠↦↠$ tr p'' by auto
  then obtain p'' where p' ↠↦↠$ tr p'' by auto
  from p' ↠↦↠$ tr p''
    and p  p'
  have p ↠↦↠$ tr p''
    by (metis append_self_conv2 weak_step_sequence.intros(1) weak_step_sequence_trans)
  hence p''. p ↠↦↠$ tr p'' by auto
  then show tr  weak_traces p
    by blast
qed

text ‹If there is an α›-transition from p› to p'›, and p'› has a weak trace tr›, then the sequence (α # tr)› is a valid (weak) trace of p›.›
lemma step_prepend_weak_traces:
  assumes
    p  α p'
    tr  weak_traces p'
  shows
    (α # tr)  weak_traces p
  using assms
proof -
  from tr  weak_traces p'
  have p''. p' ↠↦↠$ tr p'' by auto
  then obtain p'' where p' ↠↦↠$ tr p'' by auto
  with p  α p'
  have p ↠↦↠$ (α # tr) p''
    by (metis lts_tau.silent_reachable.intros(1) lts_tau.silent_reachable_append_τ
        lts_tau.weak_step_def lts_tau.weak_step_sequence.intros(2))
  then have p''. p ↠↦↠$ (α # tr) p'' by auto
  then show (α # tr)  weak_traces p by auto
qed

text ‹A state is weakly trace pre-ordered to another other, weakly_trace_preordered›
denoted by ≲WT› if all its traces can also be observed from the second process.›
definition weakly_trace_preordered (infix ≲WT 60) where
  p ≲WT q  weak_traces p  weak_traces q

definition weakly_trace_equivalent (infix ≃WT 60) where
  p ≃WT q  p ≲WT q  q ≲WT p

text ‹Just like termstep_setp, one can lift termsilent_reachable to sets of states.›
abbreviation silent_reachable_setp (infix ↠S 80) where
  P ↠S P'  ((p'  P'. p  P. p  p')  (p  P. p'. p  p'  p'  P'))

definition silent_reachable_set :: 's set  's set where
  silent_reachable_set P  { q . p  P. p  q }

lemma sreachable_set_is_sreachable: P ↠S (silent_reachable_set P)
  using silent_reachable_set_def by auto

lemma sreachable_set_eq:
  assumes P ↠S Q
  shows Q = silent_reachable_set P
  using sreachable_set_is_sreachable assms by fastforce

text ‹We likewise lift termsoft_step to sets of states.›
abbreviation soft_step_setp (‹_ ↦aS _ _› [70,70,70] 80) where
  P ↦aS α Q  (q  Q. p  P. p ↦a α q)  (p  P. q. p ↦a α q  q  Q)

definition soft_step_set :: 's set  'a  's set where
  soft_step_set P α  { q . p  P. p ↦a α q }

lemma soft_step_set_is_soft_step_set:
  P ↦aS α (soft_step_set P α)
  using soft_step_set_def by auto

lemma exactly_one_soft_step_set:
  ∃!Q. P ↦aS α Q
proof -
  from soft_step_set_is_soft_step_set
  have P ↦aS α (soft_step_set P α)
    and Q. P ↦aS α Q  Q = (soft_step_set P α)
    by fastforce+
  show ∃!Q. P ↦aS α Q
  proof
    from P ↦aS α (soft_step_set P α)
    show P ↦aS α (soft_step_set P α) .
  next
    from Q. P ↦aS α Q  Q = (soft_step_set P α)
    show Q. P ↦aS α Q  Q = (soft_step_set P α) .
  qed
qed

lemma soft_step_set_eq:
  assumes P ↦aS α Q
  shows Q = soft_step_set P α
  using exactly_one_soft_step_set soft_step_set_is_soft_step_set assms
  by fastforce

text ‹A state is stable if it cannot make any further internal steps.›
abbreviation stable_state p  p'. ¬(p  τ p')

lemma stable_state_stable:
  assumes stable_state p p  p'
  shows p = p'
  using assms(2,1) by (cases, blast+)

definition stability_respecting :: ('s  's  bool)  bool where
  stability_respecting R   p q. R p q  stable_state p 
    (q'. q  q'  R p q'  stable_state q')

end ― ‹of locale lts_tau›

end