Theory SM.SM_POR
theory SM_POR
imports SM_Sticky
begin
context transition_system_concurrent begin
lemma pac_en_blocked':
assumes A: "s ∈ nodes" "path w s" "pac p ∩ {a. en a s} ∩ set w = {}"
assumes IS: "⋀s' a. ⟦pac p ∩ {a. en a s} = pac p ∩ {a. en a s'};
psen p s = psen p s'; en a s'; a∉pac p ⟧ ⟹
pac p ∩ {b. en b (ex a s')} = pac p ∩ {a. en a s'} ∧ psen p (ex a s') = psen p s'"
shows "pac p ∩ set w = {}"
proof (rule words_fin_blocked[OF _ A(2,3)])
fix w
assume "path w s" "pac p ∩ set w = {}"
hence "pac p ∩ {a. en a s} = pac p ∩ {a. en a (target w s)} ∧ psen p s = psen p (fold ex w s)"
proof (induction w rule: rev_induct)
case (snoc a w)
from snoc have
"pac p ∩ {a. en a s} = pac p ∩ {a. en a (target w s)}"
"psen p s = psen p (fold ex w s)"
by auto
with IS[OF this] snoc.prems show ?case by auto
qed simp
thus "pac p ∩ {a. en a (target w s)} ⊆ pac p ∩ {a. en a s}" by blast
qed
end
context cprog begin
definition is_ample_static :: "cmdc ⇒ bool" where
"is_ample_static c ≡ ∀a c'. cfgc c a c' ⟶
read_globals a = {} ∧ write_globals a = {}"
end
context visible_prog
begin
lemma None_ga_en_conv[simp]:
"None∈ga_en gc ⟷ ga_en gc = {None}"
by (auto simp: ga_en_def stutter_extend_en_def)
lemma genabled_no_global_read_indep_other_pids:
assumes "read_globals a = {}"
assumes "pid'≠pid"
shows "(pid,c,a, c')∈ga_gen (ga_gex (pid',cac') gc)
⟷ (pid,c,a, c')∈ga_gen gc"
using assms
apply (auto
simp: ga_gen_def ga_gex_def ex_pres_en
split: prod.splits)
done
end
definition pid_pac :: "pid ⇒ global_action option set" where
"pid_pac pid ≡ Collect (λSome (pid',_) ⇒ pid'=pid | None ⇒ True)"
lemma pid_pac_None[simp]: "None ∈ pid_pac pid"
by (auto simp: pid_pac_def)
context visible_prog
begin
definition pid_procs :: "pid_global_config ⇒ pid set" where
"pid_procs gc ≡ {0..<length (pid_global_config.processes gc)}"
definition pid_psen :: "pid ⇒ pid_global_config ⇒ global_action option set"
where "pid_psen pid gc ≡ insert None
(Some`{(pid,c,a,c') | c a c'. c = cmd_of_pid gc pid ∧ cfgc c a c'})"
sublocale jsys: transition_system_concurrent
ga_ex "λ a p. a ∈ ga_en p" "λ p. p = pid_init_gc"
pid_procs pid_pac pid_psen
apply unfold_locales
apply (auto simp: pid_procs_def) []
apply (auto
simp: pid_pac_def pid_psen_def ga_en_def ga_gen_def
simp: stutter_extend_en_def
split: option.splits
) []
apply (auto
simp: pid_pac_def pid_psen_def ga_en_def ga_gen_def
simp: stutter_extend_en_def ga_ex_def ga_gex_def
split: option.splits if_split_asm prod.splits
) []
done
end
locale ample_prog = sticky_prog +
fixes ga_ample :: "pid_global_config ⇒ global_action option set"
assumes ga_ample_approx:
"⟦gc ∈ (g_E ga_automaton)⇧* `` g_V0 ga_automaton; ga_ample gc ≠ ga_en gc⟧ ⟹
ga_ample gc ∩ sticky_ga = {}
∧ ga_ample gc ≠ {}
∧ (∃pid.
ga_ample gc = ga_en gc ∩ pid_pac pid
∧ is_ample_static (cmd_of_pid gc pid))"
begin
lemma pid_enabled_ample:
assumes REACH[simp, intro!]: "gc ∈ ga.E⇧* `` ga.V0"
shows "jsys.ample_set gc (ga_ample gc)"
proof (cases "ga_ample gc = ga_en gc")
case True thus ?thesis using jsys.ample_en by auto
next
case False
from ga_ample_approx[OF REACH False] obtain pid where
AMPLE_SS: "ga_ample gc ⊆ ga_en gc"
and NE: "ga_ample gc ≠ {}"
and NS: "ga_ample gc ∩ sticky_ga = {}"
and AMPLE_FMT: "ga_ample gc = pid_pac pid ∩ ga_en gc"
and A_STATIC: "is_ample_static (cmd_of_pid gc pid)"
by blast
hence aux1: "ga_ample gc = ga_ample gc ∩ ga_en gc" by blast
from False NE AMPLE_SS have NN: "None ∉ ga_en gc" by auto
from A_STATIC have LOC: "
⋀c a c'. Some (pid, c,a,c') ∈ pid_psen pid gc
⟹ read_globals a = {} ∧ write_globals a = {}"
unfolding is_ample_static_def pid_psen_def
by auto
from A_STATIC have LOC': "
⋀c a c'. Some (pid, c,a,c') ∈ pid_pac pid ∩ ga_en gc
⟹ read_globals a = {} ∧ write_globals a = {}"
unfolding is_ample_static_def pid_pac_def ga_en_def
by (auto split: prod.splits simp: ga_gen_def)
from reachable_alt[symmetric] REACH
have REACH': "gc ∈ jsys.nodes" by simp
have INV':
"⋀c a c'. Some (pid,c,a,c')∈ga_en gc
⟹ Some (pid,c,a,c') ∉ jsys.visible"
using NS sticky_ga_approx_visible
apply (clarsimp simp: AMPLE_FMT pid_pac_def split: option.splits)
apply blast
done
{
fix ga gc'
assume en_eq: "pid_pac pid ∩ ga_en gc = pid_pac pid ∩ ga_en gc'"
assume psen_eq: "pid_psen pid gc = pid_psen pid gc'"
assume ga_en: "ga ∈ ga_en gc'"
assume ga_not_pid: "ga ∉ pid_pac pid"
from en_eq NN have [simp]: "None ∉ ga_en gc'"
using pid_pac_None
by blast
with ga_en have "ga≠None" by metis
then obtain pid' c a c' where [simp]: "ga = Some (pid',c,a,c')"
by (cases ga) auto
from ga_not_pid have [simp]: "pid'≠pid" by (auto simp: pid_pac_def)
have [simp]: "⋀cac. Some (pid,cac) ∈ ga_en gc'
⟷ Some (pid,cac) ∈ ga_en gc"
using en_eq unfolding pid_pac_def
by (auto split: option.splits)
hence pid_gen_gc'_gc: "⋀cac. (pid,cac) ∈ ga_gen gc'
⟷ (pid,cac) ∈ ga_gen gc"
unfolding ga_en_def
by simp
have "cmd_of_pid (ga_gex (pid', c, a, c') gc') pid
= cmd_of_pid gc' pid"
by (auto simp: ga_gex_def split: prod.splits)
hence G1: "pid_psen pid (ga_ex ga gc') = pid_psen pid gc'"
by (auto simp: pid_psen_def ga_gex_def ga_ex_def
split: prod.splits)
have pid_ge_ex_invar: "⋀cac.
(pid,cac)∈ga_gen (ga_ex (Some (pid', c, a, c')) gc') ⟷
(pid,cac)∈ga_gen gc'"
apply (clarsimp simp: ga_en_def ga_ex_def)
proof
fix c'' a'' c'''
assume A: "(pid, c'', a'', c''') ∈ ga_gen (ga_gex (pid', c, a, c') gc')"
hence "Some (pid, c'', a'', c''') ∈ pid_psen pid (ga_gex (pid', c, a, c') gc')"
by (auto simp: pid_psen_def ga_gen_def)
hence "Some (pid, c'', a'', c''') ∈ pid_psen pid gc" using G1 psen_eq
by (simp add: ga_ex_def)
from LOC[OF this]
have "read_globals a'' = {}" by simp
from genabled_no_global_read_indep_other_pids[OF this ‹pid'≠pid›] A
show "((pid, c'', a'', c''') ∈ ga_gen gc')" ..
next
fix c'' a'' c'''
assume A: "((pid, c'', a'', c''') ∈ ga_gen gc')"
hence "Some (pid, c'', a'', c''') ∈ pid_psen pid gc'"
by (auto simp: pid_psen_def ga_gen_def)
hence "Some (pid, c'', a'', c''') ∈ pid_psen pid gc" using psen_eq
by (simp)
from LOC[OF this] have "read_globals a'' = {}" by simp
from genabled_no_global_read_indep_other_pids[OF this ‹pid'≠pid›] A
show "(pid, c'', a'', c''') ∈ ga_gen (ga_gex (pid', c, a, c') gc')" ..
qed
have [simp]:
"ga_gen (ga_ex (Some (pid', c, a, c')) gc') ≠ {}"
"ga_gen gc' ≠ {}"
proof -
from NN NE obtain cac2 where "Some (pid,cac2) ∈ ga_en gc"
unfolding AMPLE_FMT
apply (clarsimp simp: ex_in_conv[symmetric])
using NN
apply (auto simp: pid_pac_def split: option.splits)
done
hence "(pid,cac2) ∈ ga_gen gc" by (auto simp: ga_en_def)
hence 1: "(pid,cac2) ∈ ga_gen gc'"
by (simp add: pid_gen_gc'_gc)
thus "ga_gen gc' ≠ {}" by blast
from 1 have "(pid,cac2) ∈ ga_gen (ga_ex (Some (pid', c, a, c')) gc')"
by (simp add: pid_ge_ex_invar pid_gen_gc'_gc)
thus "ga_gen (ga_ex (Some (pid', c, a, c')) gc') ≠ {}" by blast
qed
have G2: "pid_pac pid ∩ ga_en (ga_ex ga gc') =
pid_pac pid ∩ ga_en gc'"
apply (auto simp: pid_pac_def split: option.splits)
apply (auto simp add: ga_en_def stutter_extend_en_def
pid_ge_ex_invar
split: if_split_asm) [2]
done
note G1 G2
} note aux=this
show ?thesis
apply (subst AMPLE_FMT)
apply (rule jsys.restrict_ample_set[unfolded Collect_mem_eq])
apply (simp add: reachable_alt del: ga_automaton_simps)
using NE AMPLE_FMT apply blast
using NS AMPLE_FMT apply blast
apply safe []
apply (rename_tac ga1 ga2)
apply (case_tac "(ga1,ga2)" rule: ind.cases)
using NN apply (simp_all) [4]
apply (simp_all add: pid_pac_def LOC' INV') []
apply (rule jsys.pac_en_blocked'[OF REACH'])
unfolding Collect_mem_eq
apply assumption+
apply (rule conjI)
apply (rule aux, assumption+)
apply (rule aux, assumption+)
done
qed
sublocale jsys: ample_abstract
ga_ex "λ a p. a ∈ ga_en p" "λ p. p = pid_init_gc"
pid_interp_gc ind "jsys.scut¯¯" "λ a p. a ∈ ga_ample p"
apply unfold_locales
unfolding Collect_mem_eq
apply (rule pid_enabled_ample)
apply (simp add: reachable_alt)
done
definition "ample_rel ≡ rel_of_enex (ga_ample, ga_ex)"
definition "ample_succ ≡ succ_of_enex (ga_ample, ga_ex)"
definition reduced_automaton
where "reduced_automaton =
⦇ g_V = UNIV, g_E = ample_rel, g_V0 = {pid_init_gc}, sa_L = pid_interp_gc ⦈"
lemma reduced_automaton_simps[simp]:
"g_V reduced_automaton = UNIV"
"g_E reduced_automaton = ample_rel"
"g_V0 reduced_automaton = {pid_init_gc}"
"sa_L reduced_automaton = pid_interp_gc"
unfolding reduced_automaton_def by auto
sublocale ample: sa reduced_automaton by unfold_locales auto
lemma jsys_R_lang_eq: "snth ` jsys.R.language = Collect ample.accept"
apply (subst system_complete_language_eq_lsystem_accept)
using ample.sa_axioms
unfolding reduced_automaton_def ample_rel_def
apply simp
apply (auto simp: ample_rel_def sngp_sym_conv)
done
lemma ample_accept_subset: "ample.accept w ⟹ lv.sa.accept w"
proof -
assume "ample.accept w"
hence "w ∈ snth ` jsys.R.language" by (simp add: jsys_R_lang_eq)
hence "w ∈ snth ` jsys.language" using jsys.reduction_language_subset by auto
with jsys_lang_eq show "lv.sa.accept w" by auto
qed
lemma ample_accept_stuttering:
assumes A: "lv.sa.accept w"
obtains w' where "w≈w'" "ample.accept w'"
proof -
from A have "w ∈ snth ` jsys.language" by (simp add: jsys_lang_eq)
then obtain w' where "w ≈ w'" "w' ∈ snth ` jsys.R.language"
by (auto elim!: jsys.reduction_language_stuttering)
hence "ample.accept w'" by (simp add: jsys_R_lang_eq)
thus ?thesis using ‹w≈w'› by (blast intro: that)
qed
end
end