Theory Non_Deterministic_CSP_Distributivity
chapter‹Algebraic Rules of CSP›
section‹ The Non-Deterministic Distributivity ›
theory Non_Deterministic_CSP_Distributivity
imports Constant_Processes Deterministic_Choice Non_Deterministic_Choice
Global_Non_Deterministic_Choice Sliding_Choice
Multi_Deterministic_Prefix_Choice Multi_Non_Deterministic_Prefix_Choice
Sequential_Composition Synchronization_Product Hiding Renaming
begin
text ‹CSP operators are distributive over non deterministic choice.›
subsection ‹Global Distributivity›
lemma Mndetprefix_distrib_GlobalNdet :
‹B ≠ {} ⟹ (⊓a ∈ A → ⊓b ∈ B. P a b) = ⊓b ∈ B. ⊓a ∈ A → P a b›
by (simp add: Mndetprefix_GlobalNdet GlobalNdet_sets_commute[of A] write0_GlobalNdet)
lemma Det_distrib_GlobalNdet_left :
‹P □ (⊓a∈A. Q a) = (if A = {} then P else ⊓a∈A. P □ Q a)›
by (auto simp add: Process_eq_spec Det_projs GlobalNdet_projs
intro: is_processT8 is_processT6_TR_notin)
corollary Det_distrib_GlobalNdet_right :
‹(⊓a∈A. P a) □ Q = (if A = {} then Q else ⊓a∈A. P a □ Q)›
by (simp add: Det_commute Det_distrib_GlobalNdet_left)
lemma Sliding_distrib_GlobalNdet_left :
‹P ⊳ (⊓a∈A. Q a) = (if A = {} then P ⊓ STOP else ⊓a∈A. P ⊳ Q a)›
by (auto simp add: Process_eq_spec GlobalNdet_projs
Sliding_projs Ndet_projs STOP_projs)
lemma Sliding_distrib_GlobalNdet_right :
‹(⊓a∈A. P a) ⊳ Q = (if A = {} then Q else ⊓a∈A. P a ⊳ Q)›
by (auto simp add: Process_eq_spec GlobalNdet_projs Sliding_projs)
lemma Sync_distrib_GlobalNdet_left :
‹P ⟦S⟧ (⊓ a∈A. Q a) = (if A = {} then P ⟦S⟧ STOP else ⊓ a∈A. (P ⟦S⟧ Q a))›
proof (split if_split, intro conjI impI)
show ‹A = {} ⟹ P ⟦S⟧ (⊓ a∈A. Q a) = P ⟦S⟧ STOP›
by (simp add: GlobalNdet.abs_eq STOP.abs_eq)
next
show ‹A ≠ {} ⟹ P ⟦S⟧ (⊓ a∈A. Q a) = ⊓ a∈A. (P ⟦S⟧ Q a)›
by (simp add: Process_eq_spec Sync_projs F_GlobalNdet D_GlobalNdet T_GlobalNdet)
(safe; simp; use front_tickFree_Nil in blast)
qed
corollary Sync_distrib_GlobalNdet_right :
‹(⊓ a∈A. P a) ⟦S⟧ Q = (if A = {} then STOP ⟦S⟧ Q else ⊓ a∈A. (P a ⟦S⟧ Q))›
by (simp add: Sync_commute Sync_distrib_GlobalNdet_left)
lemmas Inter_distrib_GlobalNdet_left = Sync_distrib_GlobalNdet_left[where S = ‹{}›]
and Par_distrib_GlobalNdet_left = Sync_distrib_GlobalNdet_left[where S = UNIV]
and Inter_distrib_GlobalNdet_right = Sync_distrib_GlobalNdet_right[where S = ‹{}›]
and Par_distrib_GlobalNdet_right = Sync_distrib_GlobalNdet_right[where S = UNIV]
lemma Seq_distrib_GlobalNdet_left :
‹P ❙; ⊓ a∈A. Q a = (if A = {} then P ❙; STOP else ⊓ a∈A. (P ❙; Q a))›
by (simp add: Process_eq_spec GlobalNdet_projs STOP_projs Seq_projs) blast
lemma Seq_distrib_GlobalNdet_right : ‹(⊓ a∈A. P a) ❙; Q = ⊓ a∈A. (P a ❙; Q)›
by (simp add: Process_eq_spec GlobalNdet_projs STOP_projs Seq_projs)
(safe; simp; blast)
lemma Renaming_distrib_GlobalNdet : ‹Renaming (⊓ a∈A. P a) f g = ⊓ a∈A. Renaming (P a) f g›
by (simp add: Process_eq_spec Renaming_projs GlobalNdet_projs)
(safe; simp; blast)
text ‹The \<^const>‹Hiding› operator does not distribute the \<^const>‹GlobalNdet› in general.
We give a finite version derived from the binary version below.›
subsection ‹Binary Distributivity›
lemma Mndetprefix_distrib_Ndet :
‹(⊓a ∈ A → P a ⊓ Q a) = (⊓a ∈ A → P a) ⊓ (⊓a ∈ A → Q a)›
by (simp add: Process_eq_spec Mndetprefix_projs Ndet_projs, safe) auto
lemma Det_distrib_Ndet_left : ‹P □ Q ⊓ R = (P □ Q) ⊓ (P □ R)›
by (auto simp add: Process_eq_spec Det_projs Ndet_projs)
corollary Det_distrib_Ndet_right : ‹P ⊓ Q □ R = (P □ R) ⊓ (Q □ R)›
by (simp add: Det_commute Det_distrib_Ndet_left)
lemma Ndet_distrib_Det_left : ‹P ⊓ (Q □ R) = P ⊓ Q □ P ⊓ R›
by (auto simp add: Process_eq_spec Det_projs Ndet_projs
is_processT8 is_processT6_TR_notin)
corollary Ndet_distrib_Det_right : ‹(P □ Q) ⊓ R = P ⊓ R □ Q ⊓ R›
by (simp add: Ndet_commute Ndet_distrib_Det_left)
lemma Sliding_distrib_Ndet_left : ‹P ⊳ (Q ⊓ R) = (P ⊳ Q) ⊓ (P ⊳ R)›
and Sliding_distrib_Ndet_right : ‹(P ⊓ Q) ⊳ R = (P ⊳ R) ⊓ (Q ⊳ R)›
by (auto simp add: Process_eq_spec Ndet_projs Sliding_projs)
lemma Sync_distrib_Ndet_left : ‹M ⟦S⟧ P ⊓ Q = (M ⟦S⟧ P) ⊓ (M ⟦S⟧ Q)›
by (auto simp: Process_eq_spec, simp_all add: Sync_projs Ndet_projs) blast+
corollary Sync_distrib_Ndet_right : ‹P ⊓ Q ⟦S⟧ M = (P ⟦S⟧ M) ⊓ (Q ⟦S⟧ M)›
by (metis Sync_commute Sync_distrib_Ndet_left)
lemma Seq_distrib_Ndet_left : ‹P ❙; Q ⊓ R = (P ❙; Q) ⊓ (P ❙; R)›
by (fact Seq_distrib_GlobalNdet_left[of P ‹{0 :: nat, 1}›
‹λn. if n = 0 then Q else if n = 1 then R else undefined›,
simplified GlobalNdet_distrib_unit_bis, simplified])
lemma Seq_distrib_Ndet_right : ‹P ⊓ Q ❙; R = (P ❙; R) ⊓ (Q ❙; R)›
by (fact Seq_distrib_GlobalNdet_right[of ‹{0 :: nat, 1}›
‹λn. if n = 0 then P else if n = 1 then Q else undefined› R,
simplified GlobalNdet_distrib_unit_bis, simplified])
lemma Renaming_distrib_Ndet : ‹Renaming (P ⊓ Q) f g = Renaming P f g ⊓ Renaming Q f g›
by (fact Renaming_distrib_GlobalNdet[of ‹{0 :: nat, 1}›
‹λn. if n = 0 then P else if n = 1 then Q else undefined›,
simplified GlobalNdet_distrib_unit_bis, simplified])
lemma Hiding_distrib_Ndet : ‹P ⊓ Q \ S = (P \ S) ⊓ (Q \ S)›
proof (subst Process_eq_spec_optimized, safe)
fix s assume ‹s ∈ 𝒟 (P ⊓ Q \ S)›
then obtain t u
where * : ‹front_tickFree u› ‹tickFree t› ‹s = trace_hide t (ev ` S) @ u›
‹t ∈ 𝒟 (P ⊓ Q) ∨ (∃f. isInfHiddenRun f (P ⊓ Q) S ∧ t ∈ range f)›
unfolding D_Hiding by blast
from "*"(4) show ‹s ∈ 𝒟 ((P \ S) ⊓ (Q \ S))›
proof (elim disjE exE)
from "*"(1, 2) show ‹t ∈ 𝒟 (P ⊓ Q) ⟹ s ∈ 𝒟 ((P \ S) ⊓ (Q \ S))›
unfolding D_Ndet D_Hiding "*"(3) by blast
next
fix f assume ‹isInfHiddenRun f (P ⊓ Q) S ∧ t ∈ range f›
hence ‹isInfHiddenRun f P S ∨ isInfHiddenRun f Q S›
by (simp add: T_Ndet) (meson is_processT3_TR linorder_le_cases strict_mono_less_eq)
with "*"(1, 2) ‹isInfHiddenRun f (P ⊓ Q) S ∧ t ∈ range f›
show ‹s ∈ 𝒟 ((P \ S) ⊓ (Q \ S))› unfolding D_Ndet D_Hiding "*"(3) by blast
qed
next
show ‹s ∈ 𝒟 ((P \ S) ⊓ (Q \ S)) ⟹ s ∈ 𝒟 (P ⊓ Q \ S)› for s
unfolding Ndet_projs D_Hiding by blast
next
assume same_div : ‹𝒟 (P ⊓ Q \ S) = 𝒟 ((P \ S) ⊓ (Q \ S))›
fix s X assume ‹(s, X) ∈ ℱ (P ⊓ Q \ S)›
then consider ‹s ∈ 𝒟 (P ⊓ Q \ S)›
| t where ‹s = trace_hide t (ev ` S)› ‹(t, X ∪ ev ` S) ∈ ℱ (P ⊓ Q)›
by (simp add: F_Hiding D_Hiding) blast
thus ‹(s, X) ∈ ℱ ((P \ S) ⊓ (Q \ S))›
proof cases
from same_div D_F show ‹s ∈ 𝒟 (P ⊓ Q \ S) ⟹ (s, X) ∈ ℱ ((P \ S) ⊓ (Q \ S))› by blast
next
show ‹s = trace_hide t (ev ` S) ⟹ (t, X ∪ ev ` S) ∈ ℱ (P ⊓ Q)
⟹ (s, X) ∈ ℱ ((P \ S) ⊓ (Q \ S))› for t
by (auto simp add: F_Ndet F_Hiding)
qed
next
show ‹(s, X) ∈ ℱ ((P \ S) ⊓ (Q \ S)) ⟹ (s, X) ∈ ℱ (P ⊓ Q \ S)› for s X
unfolding Ndet_projs F_Hiding by blast
qed
lemma Hiding_distrib_finite_GlobalNdet :
‹finite A ⟹ (⊓a ∈ A. P a) \ S = ⊓a ∈ A. (P a \ S)›
proof (induct A rule: finite_induct)
show ‹(⊓a ∈ {}. P a) \ S = ⊓a ∈ {}. (P a \ S)›
by (auto simp add: Process_eq_spec GlobalNdet_projs
Hiding_seqRun_projs seqRun_def)
next
fix A a assume ‹finite A› ‹a ∉ A› and hyp : ‹(⊓a ∈ A. P a) \ S = ⊓a ∈ A. (P a \ S)›
show ‹(⊓a ∈ insert a A. P a) \ S = ⊓a ∈ insert a A. (P a \ S)› (is ‹?lhs = ?rhs›)
proof (cases ‹A = {}›)
show ‹A = {} ⟹ ?lhs = ?rhs› by simp
next
assume ‹A ≠ {}›
have ‹?lhs = P a ⊓ (⊓a ∈ A. P a) \ S›
by (simp add: GlobalNdet_distrib_unit ‹A ≠ {}› ‹a ∉ A›)
also have ‹… = (P a \ S) ⊓ ((⊓a ∈ A. P a) \ S)› by (simp add: Hiding_distrib_Ndet)
also have ‹… = (P a \ S) ⊓ (⊓a ∈ A. (P a \ S))› by (simp add: hyp)
also have ‹… = ?rhs› by (simp add: GlobalNdet_distrib_unit_bis ‹A ≠ {}› ‹a ∉ A›)
finally show ‹?lhs = ?rhs› .
qed
qed
text ‹For the \<^const>‹Mprefix› operator, we obviously do not have a
conventional distributivity: \<^term>‹(⊓)› becomes \<^term>‹(□)›.›
lemma Mprefix_distrib_Ndet :
‹(□a ∈ A → P ⊓ Q) = (□a ∈ A → P) □ (□a ∈ A → Q)› (is ‹?lhs = ?rhs›)
proof (subst Process_eq_spec, safe)
show ‹s ∈ 𝒟 ?lhs ⟹ s ∈ 𝒟 ?rhs›
and ‹s ∈ 𝒟 ?rhs ⟹ s ∈ 𝒟 ?lhs› for s
by (auto simp add: D_Det D_Ndet D_Mprefix)
next
show ‹(s, X) ∈ ℱ ?lhs ⟹ (s, X) ∈ ℱ ?rhs› for s X
by (cases s) (auto simp add: F_Mprefix F_Det F_Ndet)
next
show ‹(s, X) ∈ ℱ ?rhs ⟹ (s, X) ∈ ℱ ?lhs› for s X
by (auto simp add: F_Mprefix F_Det F_Ndet)
qed
end