Theory Labeled_Transition_Systems
section ‹Labeled Transition Systems›
theory Labeled_Transition_Systems
imports
Main
begin
subsection ‹Labeled Transition Systems›
text ‹A locale for Labeled Transition Systems,
parameterized over action type ‹'a› and state type ‹'s›.
›
locale lts =
fixes step :: ‹'s ⇒ 'a ⇒ 's ⇒ bool›
(‹_ ⟼_ _› [70, 70, 70] 80)
begin
text ‹Example definitions for derivatives and deadlock.›
abbreviation derivatives :: ‹'s ⇒ 'a ⇒ 's set›
where ‹derivatives p α ≡ {p'. p ⟼α p'}›
abbreviation deadlocked :: ‹'s ⇒ bool›
where ‹deadlocked s ≡ ∀α. derivatives s α = {}›
definition image_finite :: ‹bool›
where ‹image_finite ≡ (∀ p α. finite (derivatives p α))›
subsection ‹Paths and Traces›
text ‹Step sequences as inductive definition›
text ‹Teaching Hint: Inductive definitions!›
inductive step_sequence :: ‹'s ⇒ 'a list ⇒ 's ⇒ bool›
("_ ⟼$ _ _" [70, 70, 70] 80)
where
srefl: ‹p ⟼$ [] p› |
sstep: ‹p ⟼$ (a#tr) p''› if ‹∃p'. p ⟼ a p' ∧ p' ⟼$ tr p''›
text ‹Traces as enabled step sequences›
abbreviation traces :: ‹'s ⇒ 'a list set›
where ‹traces p ≡ {tr. ∃p'. p ⟼$ tr p'}›
lemma empty_trace_trivial:
fixes p
shows ‹[] ∈ traces p›
using step_sequence.srefl by blast
inductive path :: ‹'s list ⇒ bool›
where
init: ‹path [p]› |
step: ‹path (p # (p' # pp))› if ‹∃α. p ⟼ α p' ∧ path (p' # pp)›
lemma no_empty_paths:
assumes ‹path []›
shows ‹False›
using assms path.cases by blast
lemma path_implies_trace:
assumes ‹path pp›
shows ‹∃tr. (hd pp) ⟼$ tr (last pp)›
using assms
proof induct
case (init p)
then show ?case using step_sequence.srefl by force
next
case (step p p' pp)
then show ?case by (metis last_ConsR list.distinct(1) list.sel(1) step_sequence.simps)
qed
lemma trace_implies_path:
assumes ‹p ⟼$ tr p'›
shows ‹∃pp. path pp ∧ hd pp = p ∧ last pp = p'›
using assms
proof induct
case (srefl p)
then show ?case using path.init by fastforce
next
case (sstep p a tr p'')
then show ?case by (metis last.simps list.collapse list.sel(1) no_empty_paths path.step)
qed
end
subsection ‹Transition Systems with Internal Behavior›
locale lts_tau =
lts step
for
step :: ‹'s ⇒ 'a ⇒ 's ⇒ bool› (‹_ ⟼_ _› [70, 70, 70] 80) +
fixes
τ :: 'a
begin
text ‹Define silent-reachability ‹↠› and prove its transitivity›
inductive silent_reachable :: ‹'s ⇒ 's ⇒ bool› (infix ‹↠› 80) where
refl: ‹p ↠ p› |
step: ‹p ↠ p''› if ‹p ⟼ τ p'› and ‹p' ↠ p''›
thm silent_reachable.induct
lemma silent_reachable_compose:
fixes
p p' p''
assumes
‹p ↠ p'›
‹p' ↠ p''›
shows
‹p ↠ p''›
using assms
proof induct
fix p
assume ‹p ↠ p''›
thus ‹p ↠ p''› .
next
fix p p' p'''
assume ‹p ⟼τ p'› ‹p''' ↠ p'' ⟹ p' ↠ p''› ‹p''' ↠ p''›
from this(2,3) have ‹p' ↠ p''› .
with silent_reachable.step ‹p ⟼τ p'› show ‹p ↠ p''› .
qed
lemma silent_reachable_preorder:
‹reflp (↠)›
‹transp (↠)›
using silent_reachable.refl silent_reachable_compose
unfolding reflp_def transp_def by blast+
text ‹A weak step ‹↠⟼› is ‹⟼› wrapped in ‹↠› (or just ‹↠› for ‹τ›)›
definition weak_step (‹_ ↠⟼ _ _› [70,70,70] 80) where
‹p ↠⟼ α p''' ≡
if α = τ then p ↠ p''' else
(∃p' p''. p ↠ p' ∧ p' ⟼ α p'' ∧ p'' ↠ p''')›
text ‹weak step sequence ‹↠⟼$› and traces analogous to strong steps.›
inductive weak_step_sequence :: ‹'s ⇒ 'a list ⇒ 's ⇒ bool›
("_ ↠⟼$ _ _" [70, 70, 70] 80)
where
internal: ‹p ↠⟼$ [] p'› if ‹p ↠ p'› |
step: ‹p ↠⟼$ (α#tr) p''› if ‹∃p'. p ↠⟼ α p' ∧ p' ↠⟼$ tr p''›
abbreviation weak_traces :: ‹'s ⇒ 'a list set›
where ‹weak_traces p ≡ {tr. ∃p'. p ↠⟼$ tr p'}›
lemma empty_weak_trace_trivial:
fixes p
shows ‹[] ∈ weak_traces p›
using weak_step_sequence.internal silent_reachable.refl by blast
lemma weak_seq_tau_transparent:
assumes ‹p ↠⟼$ tr p'›
shows ‹p ↠⟼$ (filter (λα. α ≠ τ) tr) p'›
using assms
proof (induct tr arbitrary: p p')
case Nil
then show ?case by simp
next
case (Cons α tr p p'')
from this(2) obtain p' where step1: ‹p ↠⟼ α p'› ‹p' ↠⟼$ tr p''›
using weak_step_sequence.cases by force
then have step2: ‹p' ↠⟼$ (filter (λα. α ≠ τ) tr) p''› using Cons(1) by blast
show ?case
proof (cases ‹α ≠ τ›)
case True
then show ?thesis using step1(1) step2
using weak_step_sequence.step by fastforce
next
case False
hence ‹α = τ› by blast
hence ‹p ↠ p'› using step1(1) unfolding weak_step_def by auto
hence ‹p ↠⟼$ tr p''› using step1(2) weak_step_def silent_reachable_compose
by (smt (verit, best)
weak_step_sequence.internal weak_step_sequence.cases weak_step_sequence.step)
hence ‹p ↠⟼$ (filter (λα. α ≠ τ) tr) p''› using Cons.hyps by blast
then show ?thesis using ‹α = τ› by auto
qed
qed
end
end