Theory Atomic
theory Atomic
imports
"ConcurrentHOL.ConcurrentHOL"
begin
section‹ Atomic sections \label{sec:atomic} ›
text‹
By restricting the environment to stuttering steps we can consider arbitrary processes to be atomic,
i.e., free of interference.
›
setup ‹Sign.mandatory_path "spec"›
definition atomic :: "'a ⇒ ('a, 's, 'v) spec ⇒ ('a, 's, 'v) spec" where
"atomic a P = P ⊓ spec.rel ({a} × UNIV)"
setup ‹Sign.mandatory_path "idle"›
lemma atomic_le_conv[spec.idle_le]:
shows "spec.idle ≤ spec.atomic a P ⟷ spec.idle ≤ P"
by (simp add: spec.atomic_def spec.idle.rel_le)
setup ‹Sign.parent_path›
setup ‹Sign.mandatory_path "term"›
setup ‹Sign.mandatory_path "none"›
lemma atomic:
shows "spec.term.none (spec.atomic a P) = spec.atomic a (spec.term.none P)"
by (simp add: spec.atomic_def spec.term.none.inf spec.term.none.inf_rel)
setup ‹Sign.parent_path›
setup ‹Sign.mandatory_path "all"›
lemma atomic:
shows "spec.term.all (spec.atomic a P) = spec.atomic a (spec.term.all P)"
by (simp add: spec.atomic_def spec.term.all.inf spec.term.all.rel)
setup ‹Sign.parent_path›
setup ‹Sign.parent_path›
setup ‹Sign.mandatory_path "atomic"›
lemma bot[simp]:
shows "spec.atomic a ⊥ = ⊥"
by (simp add: spec.atomic_def)
lemma top[simp]:
shows "spec.atomic a ⊤ = spec.rel ({a} × UNIV)"
by (simp add: spec.atomic_def)
lemma contractive:
shows "spec.atomic a P ≤ P"
by (simp add: spec.atomic_def)
lemma idempotent[simp]:
shows "spec.atomic a (spec.atomic a P) = spec.atomic a P"
by (simp add: spec.atomic_def)
lemma monotone:
shows "mono (spec.atomic a)"
by (simp add: spec.atomic_def monoI le_infI1)
lemmas strengthen[strg] = st_monotone[OF spec.atomic.monotone]
lemmas mono = monotoneD[OF spec.atomic.monotone]
lemmas mono2mono[cont_intro, partial_function_mono]
= monotone2monotone[OF spec.atomic.monotone, simplified, of orda P for orda P]
lemma Sup:
shows "spec.atomic a (⨆X) = ⨆(spec.atomic a ` X)"
by (simp add: spec.atomic_def ac_simps heyting.inf_Sup_distrib)
lemmas sup = spec.atomic.Sup[where X="{P, Q}" for P Q, simplified]
lemma mcont2mcont[cont_intro]:
assumes "mcont luba orda Sup (≤) P"
shows "mcont luba orda Sup (≤) (λx. spec.atomic a (P x))"
by (simp add: spec.atomic_def assms)
lemma Inf_not_empty:
assumes "X ≠ {}"
shows "spec.atomic a (⨅X) = ⨅(spec.atomic a ` X)"
using assms by (simp add: spec.atomic_def INF_inf_const2)
lemmas inf = spec.atomic.Inf_not_empty[where X="{P, Q}" for P Q, simplified]
lemma idle:
shows "spec.atomic a spec.idle = spec.idle"
by (simp add: spec.atomic_def inf.absorb1 spec.idle.rel_le)
lemma action:
shows "spec.atomic a (spec.action F) = spec.action (F ∩ UNIV × ({a} × UNIV ∪ UNIV × Id))"
by (simp add: spec.atomic_def spec.action.inf_rel_reflcl)
lemma return:
shows "spec.atomic a (spec.return v) = spec.return v"
by (simp add: spec.return_def spec.atomic.action Times_Int_Times)
lemma bind:
shows "spec.atomic a (f ⤜ g) = spec.atomic a f ⤜ (λv. spec.atomic a (g v))"
by (simp add: spec.atomic_def spec.bind.inf_rel ac_simps)
lemma map_le:
fixes af :: "'a ⇒ 'b"
shows "spec.map af sf vf (spec.atomic a P) ≤ spec.atomic (af a) (spec.map af sf vf P)"
by (auto simp: spec.atomic_def spec.map.inf_rel
intro!: spec.map.mono inf.mono order.refl spec.rel.mono)
lemma invmap:
fixes af :: "'a ⇒ 'b"
shows "spec.atomic a (spec.invmap af sf vf P) ≤ spec.invmap af sf vf (spec.atomic (af a) P)"
by (auto simp: spec.atomic_def spec.invmap.inf spec.invmap.rel
intro!: le_infI2 spec.rel.mono)
lemma rel:
shows "spec.atomic a (spec.rel r) = spec.rel (r ∩ {a} × UNIV)"
by (simp add: spec.atomic_def flip: spec.rel.inf)
lemma interference:
shows "spec.atomic (proc a) (spec.rel ({env} × UNIV)) = spec.rel {}"
by (simp add: spec.atomic.rel flip: Times_Int_distrib1)
setup ‹Sign.mandatory_path "cam"›
lemma cl:
shows "spec.atomic (proc a) (spec.cam.cl ({env} × UNIV) P) = spec.atomic (proc a) P"
by (simp add: spec.cam.cl_def spec.atomic.sup spec.atomic.bind spec.atomic.interference
spec.rel.empty spec.term.none.bind spec.term.none.Sup spec.term.none.return
image_image spec.bind.botR spec.bind.idleR sup_iff_le
flip: spec.term.none.atomic spec.term.all.atomic)
setup ‹Sign.parent_path›
setup ‹Sign.mandatory_path "interference"›
lemma cl:
shows "spec.atomic (proc a) (spec.interference.cl ({env} × UNIV) P) = spec.return () ⪢ spec.atomic (proc a) P"
by (simp add: spec.interference.cl_def UNIV_unit spec.atomic.bind spec.atomic.interference
spec.rel.empty spec.atomic.cam.cl spec.bind.return spec.atomic.return)
setup ‹Sign.parent_path›
setup ‹Sign.parent_path›
setup ‹Sign.parent_path›
setup ‹Sign.mandatory_path "prog"›
lift_definition atomic :: "('s, 'v) prog ⇒ ('s, 'v) prog" is
"λP. spec.interference.cl ({env} × UNIV) (spec.atomic self P)" ..
setup ‹Sign.mandatory_path "atomic"›
lemma bot[simp]:
shows "prog.atomic ⊥ = ⊥"
by transfer
(simp add: spec.interference.cl.bot spec.atomic.interference spec.interference.cl.rel
flip: spec.term.none.atomic spec.term.none.interference.cl)
lemma contractive:
shows "prog.atomic P ≤ P"
by transfer (simp add: spec.atomic.contractive spec.interference.least)
lemma idempotent[simp]:
shows "prog.atomic (prog.atomic P) = prog.atomic P"
by transfer (metis spec.atomic.idempotent spec.atomic.interference.cl spec.interference.closed_conv)
lemma monotone:
shows "mono prog.atomic"
by (rule monoI) (transfer; simp add: spec.atomic.mono spec.interference.mono_cl)
lemmas strengthen[strg] = st_monotone[OF prog.atomic.monotone]
lemmas mono = monotoneD[OF prog.atomic.monotone]
lemmas mono2mono[cont_intro, partial_function_mono] = monotone2monotone[OF prog.atomic.monotone, simplified, of orda P for orda P]
lemma Sup:
shows "prog.atomic (⨆X) = ⨆(prog.atomic ` X)"
by transfer
(simp add: spec.atomic.Sup spec.atomic.sup spec.interference.cl_Sup spec.interference.cl_sup
image_image spec.interference.cl.bot spec.atomic.interference spec.interference.cl.rel
flip: spec.term.none.atomic spec.term.none.interference.cl)
lemmas sup = prog.atomic.Sup[where X="{P, Q}" for P Q, simplified]
lemma mcont:
shows "mcont Sup (≤) Sup (≤) prog.atomic"
by (simp add: mcontI contI prog.atomic.Sup)
lemmas mcont2mcont[cont_intro] = mcont2mcont[OF prog.atomic.mcont, of luba orda P for luba orda P]
lemma Inf_le:
shows "prog.atomic (⨅X) ≤ ⨅(prog.atomic ` X)"
by transfer (simp add: Inf_lower le_INF_iff spec.atomic.mono spec.interference.mono_cl)
lemmas inf_le = prog.atomic.Inf_le[where X="{P, Q}" for P Q, simplified]
lemma action:
shows "prog.atomic (prog.action F) = prog.action F"
by transfer
(simp add: spec.atomic.interference.cl spec.atomic.action spec.bind.returnL spec.idle.action_le;
rule arg_cong; blast)
lemma return:
shows "prog.atomic (prog.return v) = prog.return v"
by (simp add: prog.return_def prog.atomic.action)
lemma bind_le:
shows "prog.atomic (f ⤜ g) ≤ prog.atomic f ⤜ (λv. prog.atomic (g v))"
by transfer
(simp add: spec.atomic.bind spec.bind.mono
spec.interference.closed.bind spec.interference.expansive spec.interference.least)
setup ‹Sign.parent_path›
setup ‹Sign.mandatory_path "p2s"›
lemmas atomic = prog.atomic.rep_eq
setup ‹Sign.parent_path›
setup ‹Sign.parent_path›
subsection‹ Inhabitation ›
setup ‹Sign.mandatory_path "inhabits.spec"›
lemma atomic:
assumes "P -s, xs→ P'"
assumes "trace.steps' s xs ⊆ {a} × UNIV"
shows "spec.atomic a P -s, xs→ spec.atomic a P'"
unfolding spec.atomic_def by (rule inhabits.inf[OF assms(1) inhabits.spec.rel.rel[OF assms(2)]])
lemma atomic_term:
assumes "P -s, xs→ spec.return v"
assumes "trace.steps' s xs ⊆ {a} × UNIV"
shows "spec.atomic a P -s, xs→ spec.return v"
by (rule inhabits.spec.atomic[where P'="spec.return v", simplified spec.atomic.return, OF assms])
lemma atomic_diverge:
assumes "P -s, xs→ ⊥"
assumes "trace.steps' s xs ⊆ {a} × UNIV"
shows "spec.atomic a P -s, xs→ ⊥"
by (rule inhabits.spec.atomic[where P'="⊥", simplified spec.atomic.bot, OF assms])
setup ‹Sign.parent_path›
setup ‹Sign.mandatory_path "inhabits.prog"›
lemma atomic_term:
assumes "prog.p2s P -s, xs→ spec.return v"
assumes "trace.steps' s xs ⊆ {self} × UNIV"
shows "prog.p2s (prog.atomic P) -s, xs→ spec.return v"
unfolding prog.p2s.atomic
by (rule inhabits.mono[OF spec.interference.expansive order.refl
inhabits.spec.atomic_term[OF assms]])
lemma atomic_diverge:
assumes "prog.p2s P -s, xs→ ⊥"
assumes "trace.steps' s xs ⊆ {self} × UNIV"
shows "prog.p2s (prog.atomic P) -s, xs→ ⊥"
unfolding prog.p2s.atomic
by (rule inhabits.mono[OF spec.interference.expansive order.refl
inhabits.spec.atomic_diverge[OF assms]])
setup ‹Sign.parent_path›
subsection‹ Assume/guarantee ›
setup ‹Sign.mandatory_path "ag.prog"›
lemma atomic:
assumes "prog.p2s c ≤ ⦃P⦄, Id ⊢ G, ⦃Q⦄"
assumes P: "stable A P"
assumes Q: "⋀v. stable A (Q v)"
shows "prog.p2s (prog.atomic c) ≤ ⦃P⦄, A ⊢ G, ⦃Q⦄"
apply (subst ag.assm_heyting[where A=A and r=A, simplified, symmetric])
apply (simp add: prog.p2s.atomic)
apply (strengthen ord_to_strengthen[OF assms(1)])
apply (simp add: spec.atomic_def heyting ac_simps spec.interference.cl.inf_rel inf_sup_distrib Times_Int_Times
flip: spec.rel.inf)
using assms
apply (force intro: order.trans[OF _ spec.interference.cl_ag_le[where A=A and r=A, simplified]]
spec.interference.cl.mono[OF order.refl] ag.pre_a
simp add: heyting[symmetric] ag.assm_heyting[where r="{}", simplified])
done
setup ‹Sign.parent_path›
end