(*>*) section‹ A Temporal Logic of Safety (TLS) \label{sec:tls} ›
text‹
model systems with finite and infinite sequences of states, closed
stuttering following 🍋‹"Lamport:1994"›. This theory relates
safety logic of \S\ref{sec:safety_logic} to the powerset
quotiented by stuttering) representing properties of these sequences
see \S\ref{sec:tls-safety}). Most of this story is standard but the
of finite sequences does have some impact.
:
▪ historical motivations for future-time linear temporal logic (LTL): 🍋‹"MannaPnueli:1991" and "OwickiLamport:1982"›.
▪ a discussion on the merits of proving liveness: 🪙‹https://cs.nyu.edu/acsys/beyond-safety/liveness.htm›
:
▪ Lamport (and Abadi et al) treat infinite stuttering as termination
▪ 🍋‹‹p189› in "Lamport:1999"›: ``we can represent a terminating execution of any system by an
infinite behavior that ends with a sequence of nothing but stuttering steps. We have no need of
finite behaviors (finite sequences of states), so we consider only infinite ones.''
▪ this conflates divergence with termination
▪ we separate those concepts here so we can support sequential composition
▪ the traditional account of liveness properties breaks down (see \S\ref{sec:safety_closure})
corecursive collapse :: "'s ==> ('a × 's, 'v) tllist ==> ('a × 's, 'v) tllist"where "collapse s xs = (if snd ` tset xs ⊆ {s} then trailing (undefined, s) xs else if snd (thd xs) = s then collapse s (ttl xs) else TCons (thd xs) (collapse (snd (thd xs)) (ttl xs)))" proof - have"(LEAST i. s ≠ snd (tnth (ttl xs) i)) < (LEAST i. s ≠ snd (tnth xs i))" if *: "¬ snd ` tset xs ⊆ {s}" and **: "snd (thd xs) = s" for s and xs :: "('a × 's, 'v) tllist" proof - from * obtain a s' where"(a, s') ∈ tset xs"and"s ≠ s'"by fastforce thenobtain i where"snd (tnth xs i) ≠ s" by (atomize_elim, induct rule: tset_induct) (auto intro: exI[of _ 0] exI[of _ "Suc i"for i]) with * ** have"(LEAST i. s ≠ snd (tnth xs i)) = Suc (LEAST i. s ≠ snd (tnth xs (Suc i)))" by (cases xs) (simp_all add: Least_Suc[where n=i]) with * show"(LEAST i. s ≠ snd (tnth (ttl xs) i)) < (LEAST i. s ≠ snd (tnth xs i))" by (cases xs) simp_all qed thenshow ?thesis by (relation "measure (λ(s, xs). LEAST i. s ≠ snd (tnth xs i))"; simp) qed
setup‹Sign.mandatory_path "tmap"›
lemma trailing: shows"tmap sf vf (trailing s xs) = trailing (sf s) (tmap sf vf xs)" by (simp add: trailing_def tmap_trepeat)
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "tlength"›
lemma trailing: shows"tlength (trailing s xs) ≤ tlength xs" by (fastforce simp: trailing_def dest: not_lfinite_llength)
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "trailing"›
lemma simps[simp]: shows TNil: "trailing s (TNil b) = TNil b" and TCons: "trailing s (TCons x xs) = trailing s xs" and ttl: "ttl (trailing s xs) = trailing s xs" and idempotent: "trailing s (trailing s xs) = trailing s xs" and tset_finite: "tset (trailing s xs) = (if tfinite xs then {} else {s})" and trepeat: "trailing s (trepeat s) = trepeat s" by (simp_all add: trailing_def)
lemma eq_TNil_conv: shows"trailing s xs = TNil b ⟷ tfinite xs ∧ terminal xs = b" and"TNil b = trailing s xs ⟷ tfinite xs ∧ terminal xs = b" and"is_TNil (trailing s xs) ⟷ tfinite xs" by (auto simp: trailing_def dest: is_TNil_tfinite)
lemma eq_TCons_conv: shows"trailing s xs = TCons y ys ⟷¬tfinite xs ∧ TCons y ys = trepeat s" and"TCons y ys = trailing s xs ⟷¬tfinite xs ∧ TCons y ys = trepeat s" by (auto simp: trailing_def)
lemma tmap: shows"trailing s (tmap sf vf xs) = tmap id vf (trailing s xs)" by (simp add: trailing_def tmap_trepeat)
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "collapse"›
lemma unique: assumes"∧s xs. f s xs = (if snd ` tset xs ⊆ {s} then trailing (undefined, s) xs else if snd (thd xs) = s then f s (ttl xs) else TCons (thd xs) (f (snd (thd xs)) (ttl xs)))" shows"f = collapse" proof(intro ext) show"f s xs = collapse s xs"for s xs proof(coinduction arbitrary: s xs) case (Eq_tllist s xs) show ?case apply (induct arg≡"(s, xs)" arbitrary: s xs rule: collapse.inner_induct) apply (subst (123) assms) apply (subst (123) collapse.code) apply simp apply (subst (123) assms) apply (subst (123) collapse.code) apply simp apply (metis assms collapse.code) done qed qed
lemma collapse: shows"collapse s (collapse s xs) = collapse s xs" proof - have"(λs xs. collapse s (collapse s xs)) = collapse" apply (rule collapse.unique) apply (subst (123) collapse.code) apply auto done thenshow ?thesis by (fastforce simp: fun_eq_iff) qed
lemma simps[simp]: shows TNil: "collapse s (TNil b) = TNil b" and TCons: "collapse s (TCons x xs) = (if snd x = s then collapse s xs else TCons x (collapse (snd x) xs))" and trailing: "collapse s (trailing (undefined, s) xs) = trailing (undefined, s) xs" by (simp_all add: collapse.code trailing_def)
lemma tshift_stuttering: assumes"snd ` set xs ⊆ {s}" shows"collapse s (tshift xs ys) = collapse s ys" using assms by (induct xs) simp_all
lemma infinite_trailing: assumes"¬tfinite xs" assumes"snd ` tset xs ⊆ {s'}" shows"collapse s xs = (if s = s' then trepeat (undefined, s') else TCons (thd xs) (trepeat (undefined, s')))" using assms by (cases xs) (simp_all add: assms collapse.code trailing_def)
lemma eq_TNil_conv: shows"collapse s xs = TNil b ⟷ tfinite xs ∧ snd ` tset xs ⊆ {s} ∧ terminal xs = b" (is"?lhs ⟷ ?rhs") and"TNil b = collapse s xs ⟷ tfinite xs ∧ snd ` tset xs ⊆ {s} ∧ terminal xs = b"(is"?thesis1") proof - show"?lhs ⟷ ?rhs" proof(rule iffI) show"?lhs ==> ?rhs" proof(induct arg≡"(s, xs)" arbitrary: s xs rule: collapse.inner_induct[case_names step]) case (step s xs) thenshow ?case by (cases xs; clarsimp split: if_splits)
(subst (asm) collapse.code; clarsimp simp: trailing.eq_TNil_conv split: if_splits) qed show"?rhs ==> ?lhs" by (simp add: conj_explode) (induct arbitrary: s rule: tfinite_induct; simp) qed thenshow ?thesis1 by (rule eq_commute_conv) qed
lemma eq_TConsE: assumes"collapse s xs = TCons y ys" obtains
(trailing_stuttering) "¬ tfinite xs" and"snd ` tset xs = {s}" and"TCons y ys = trepeat (undefined, s)"
| (step) us ys' where"xs = tshift us (TCons y ys')" and"snd ` set us ⊆ {s}" and"snd y ≠ s" and"collapse (snd y) ys' = ys" apply atomize_elim using assms proof(induct arg≡"(s, xs)" arbitrary: s xs rule: collapse.inner_induct[case_names step]) case (step s xs) show ?case proof(cases xs) case (TNil v) with step.prems show ?thesis by simp next case (TCons x xs') show ?thesis proof(cases "snd ` tset xs' ⊆ {snd x}") case True with TCons trans[OF collapse.code[symmetric] step.prems] show ?thesis by (force simp: trailing.eq_TCons_conv tshift_eq_TCons_conv split: if_split_asm) next case False with TCons trans[OF collapse.code[symmetric] step.prems] step.hyps[OF refl] show ?thesis by (cases x, cases y)
(simp add: trailing.eq_TCons_conv tshift_eq_TCons_conv trepeat_eq_TCons_conv
eq_snd_iff exI[where x="[]"]
split: if_split_asm; safe; force dest!: spec[where x="(fst x, s) # us"for us]) qed qed qed
lemma eq_TCons_conv: shows"collapse s xs = TCons y ys ⟷ (¬tfinite xs ∧ snd ` tset xs = {s} ∧ TCons y ys = trepeat (undefined, s)) ∨ (∃xs' ys'. xs = tshift xs' (TCons y ys') ∧ snd ` set xs' ⊆ {s} ∧ snd y ≠ s ∧ collapse (snd y) ys' = ys)" (is"?lhs ⟷ ?rhs") and"TCons y ys = collapse s xs ⟷ (¬tfinite xs ∧ snd ` tset xs = {s} ∧ TCons y ys = trepeat (undefined, s)) ∨ (∃xs' ys'. xs = tshift xs' (TCons y ys') ∧ snd ` set xs' ⊆ {s} ∧ snd y ≠ s ∧ collapse (snd y) ys' = ys)" (is ?thesis1) proof - show"?lhs ⟷ ?rhs" by (auto elim: collapse.eq_TConsE simp: collapse.tshift_stuttering collapse.infinite_trailing) thenshow ?thesis1 by (rule eq_commute_conv) qed
lemma tfinite: shows"tfinite (collapse s xs) ⟷ tfinite xs" (is"?lhs ⟷ ?rhs") proof(rule iffI) show ?lhs if ?rhs using that by (induct arbitrary: s rule: tfinite_induct) simp_all show ?rhs if ?lhs using that by (induct "collapse s xs" arbitrary: s xs rule: tfinite_induct)
(auto simp: collapse.eq_TNil_conv collapse.eq_TCons_conv trepeat_eq_TCons_conv) qed
lemma tfinite_conv: assumes"collapse s xs = collapse s' xs'" shows"tfinite xs ⟷ tfinite xs'" by (metis assms collapse.tfinite)
lemma terminal: shows"terminal (collapse s xs) = terminal xs" proof(cases "tfinite xs") case True thenobtain i where"tlength xs ≤ enat i" using llength_eq_infty_conv_lfinite by fastforce thenshow ?thesis proof(induct i arbitrary: s xs) case (Suc i s xs) thenshow ?case by (cases xs) (simp_all flip: eSuc_enat) qed (clarsimp simp: enat_0 tlength_0_conv) qed (simp add: collapse.tfinite terminal_tinfinite)
lemma tlength: shows"tlength (collapse s xs) ≤ tlength xs" proof(cases "tfinite xs") case True thenshow ?thesis by (induct arbitrary: s rule: tfinite_induct) (auto intro: order.trans[OF _ ile_eSuc]) next case False thenshow ?thesis by (fastforce dest: not_lfinite_llength) qed
lemma tset_memberD: assumes"(a, s') ∈ tset (collapse s xs)" shows"s' ∈ snd ` tset xs" using assms by (induct "collapse s xs" arbitrary: s xs rule: tset_induct)
(auto simp: collapse.eq_TCons_conv trepeat_eq_TCons_conv tset_tshift image_Un)
lemma tset_memberD2: assumes"(a, s') ∈ tset xs" shows"s = s' ∨ s' ∈ snd ` tset (collapse s xs)" using assms by (induct xs arbitrary: a s rule: tset_induct; simp; fast)
lemma tshift: shows"collapse s (tshift xs ys) = tshift (trace.natural' s xs) (collapse (trace.final' s xs) ys)" by (induct xs arbitrary: s) simp_all
lemma trepeat: shows"collapse s (trepeat (a, s)) = trepeat (undefined, s)" by (subst collapse.code) (simp add: trailing_def)
lemma eq_trepeat_conv: shows"trepeat (undefined, s) = collapse s xs ⟷¬tfinite xs ∧ snd ` tset xs = {s}" (is"?thesis1") and"collapse s xs = trepeat (undefined, s) ⟷¬tfinite xs ∧ snd ` tset xs = {s}" (is"?thesis2") proof - show ?thesis1 by (rule iffI,
(subst (asm) trepeat_unfold, simp add: collapse.eq_TCons_conv),
simp add: collapse.infinite_trailing) thenshow ?thesis2 by (rule eq_commute_conv) qed
lemma treplicate: shows"collapse s (treplicate i (a, s) v) = TNil v" by (subst collapse.code) (simp add: trailing.eq_TNil_conv split: nat.split)
lemma eq_tshift_conv: shows"collapse s xs = tshift ys zs ⟷ (∃xs' xs'' ys'. tshift xs' xs'' = xs ∧ trace.natural' s xs' @ ys' = ys ∧ ((¬tfinite xs'' ∧ snd ` tset xs'' = {trace.final' s xs'} ∧ tshift ys' zs = trepeat (undefined, trace.final' s xs')) ∨ (ys' = [] ∧ collapse (trace.final' s xs') xs'' = zs)))" (is"?lhs ⟷ ?rhs") and"tshift ys zs = collapse s xs ⟷ (∃xs' xs'' ys'. tshift xs' xs'' = xs ∧ trace.natural' s xs' @ ys' = ys ∧ ((¬tfinite xs'' ∧ snd ` tset xs'' = {trace.final' s xs'} ∧ tshift ys' zs = trepeat (undefined, trace.final' s xs')) ∨ (ys' = [] ∧ collapse (trace.final' s xs') xs'' = zs)))" (is ?thesis1) proof - show"?lhs ⟷ ?rhs" proof(rule iffI) show"?lhs ==> ?rhs" proof(induct ys arbitrary: s xs) case Nil thenshow ?case by (simp add: exI[where x="[]"]) next case (Cons y ys s xs) from Cons.prems[simplified] show ?case proof(cases rule: collapse.eq_TConsE) case trailing_stuttering thenshow ?thesis by (simp add: exI[where x="[]"]) next case (step xs' ys') from step(1-3) Cons.hyps[OF step(4)] show ?thesis by (fastforce simp: trace.natural'.append tshift_append
simp flip: trace.natural'.eq_Nil_conv
intro: exI[where x="xs' @ y # ys''"for ys'']) qed qed show"?rhs ==> ?lhs" by (auto simp: collapse.tshift tshift_append collapse.infinite_trailing) qed thenshow ?thesis1 by (rule eq_commute_conv) qed
lemma eq_collapse_ttake_dropn_conv: shows"collapse s xs = collapse s ys ⟷ (∃j. trace.natural' s (fst (ttake i xs)) = trace.natural' s (fst (ttake j ys)) ∧ snd (ttake i xs) = snd (ttake j ys) ∧ collapse (trace.final' s (fst (ttake i xs))) (tdropn i xs) = collapse (trace.final' s (fst (ttake i xs))) (tdropn j ys))" (is"?lhs ⟷ (∃j. ?rhs i j s xs ys)") proof(rule iffI) show"?lhs ==> (∃j. ?rhs i j s xs ys)" proof(induct i arbitrary: s xs ys) case (Suc i s xs ys) show ?case proof(cases xs) case (TNil b) with Suc.prems show ?thesis by (fastforce intro: exI[where x="case tlength ys of ∞==> undefined | enat j ==> Suc j"]
simp: collapse.eq_TNil_conv trace.natural'.eq_Nil_conv
ttake_eq_Some_conv tfinite_tlength_conv tdropn_tlength
dest: in_set_ttakeD) next case (TCons x xs') show ?thesis proof(cases "snd x = s") case True with Suc TCons show ?thesis by simp next case False note Suc.prems TCons False moreoverfrom calculation obtain us ys' where"ys = tshift us (TCons x ys')" and"snd ` set us ⊆ {s}" and"collapse (snd x) ys' = collapse (snd x) xs'" by (auto simp: collapse.eq_TCons_conv trepeat_eq_TCons_conv) moreoverfrom calculation Suc.hyps[of "snd x""xs'""ys'"] obtain j where"?rhs i j (snd x) xs' ys'" by presburger ultimatelyshow ?thesis by (auto simp: ttake_tshift trace.natural'.append tdropn_tshift
simp flip: trace.natural'.eq_Nil_conv
intro: exI[where x="Suc (length us) + j"]) qed qed qed (simp add: exI[where x=0]) show"∃j. ?rhs i j s xs ys ==> ?lhs" by (metis collapse.tshift trace.final'.natural' tshift_fst_ttake_tdropn_id) qed
lemma tshift_tdropn: assumes"trace.natural' s (fst (ttake i xs)) = trace.natural' s ys" shows"collapse s (tshift ys (tdropn i xs)) = collapse s xs" by (metis assms collapse.tshift trace.final'.natural' tshift_fst_ttake_tdropn_id)
lemma map_collapse: shows"collapse (sf s) (tmap (map_prod af sf) vf (collapse s xs)) = collapse (sf s) (tmap (map_prod af sf) vf xs)" (is"?lhs s xs = ?rhs s xs") proof(coinduction arbitrary: s xs) case (Eq_tllist s xs) show ?case proof(intro conjI; (intro impI)?) have *: "sf s' = sf s" if"tfinite xs"and"sf ` snd ` tset (collapse s xs) ⊆ {sf s}"and"(a, s') ∈ tset xs" for a s s' using that by (induct arbitrary: s rule: tfinite_induct; clarsimp split: if_split_asm; metis) show"is_TNil (?lhs s xs) ⟷ is_TNil (?rhs s xs)" by (rule iffI,
fastforce dest!: * simp: collapse.is_TNil_conv collapse.tfinite tllist.set_map snd_image_map_prod,
fastforce dest!: collapse.tset_memberD simp: collapse.is_TNil_conv collapse.tfinite tllist.set_map) show"terminal (?lhs s xs) = terminal (?rhs s xs)" if"is_TNil (?lhs s xs)"and"is_TNil (?rhs s xs)" using that by (simp add: collapse.is_TNil_conv collapse.terminal) assume"¬is_TNil (?lhs s xs)"and"¬is_TNil (?rhs s xs)" thenobtain y ys z zs where l: "?lhs s xs = TCons y ys"and r: "?rhs s xs = TCons z zs" by (simp add: tllist.disc_eq_case(2) split: tllist.split_asm) from l show"thd (?lhs s xs) = thd (?rhs s xs) ∧ (∃s' xs'. ttl (?lhs s xs) = ?lhs s' xs' ∧ ttl (?rhs s xs) = ?rhs s' xs')" proof(cases rule: collapse.eq_TConsE) case trailing_stuttering note left = this from r show ?thesis proof(cases rule: collapse.eq_TConsE) case trailing_stuttering from left(3) trailing_stuttering(3) show ?thesis by (fold l r) (simp; metis) next case (step us zs') from left(2) step(1,3) have False by (clarsimp simp: tset_tshift tset_tmap tmap_eq_tshift_conv TCons_eq_tmap_conv collapse.tshift
split: if_split_asm)
(use step(2) in‹fastforce simp flip: trace.final'.map[where af=af]›) thenshow ?thesis .. qed next case (step us ys') note left = this from r show ?thesis proof(cases rule: collapse.eq_TConsE) case trailing_stuttering have False if"sf s' ≠ sf s" and"(λx. sf (snd x)) ` tset xs = {sf s}" and"(λx. sf (snd x)) ` set us ⊆ {sf s}" and"collapse s xs = tshift us (TCons (a, s') vs)" for a s' us vs using that by (force simp: tset_tshift
dest!: arg_cong[where f="λxs. s' ∈ snd ` tset xs"] collapse.tset_memberD
intro: imageI[where f="λx. sf (snd x)"]) with l left(3) trailing_stuttering(2) have False by (fastforce simp: tset_tmap tmap_eq_tshift_conv TCons_eq_tmap_conv collapse.eq_TCons_conv
trepeat_eq_TCons_conv snd_image_map_prod image_image) thenshow ?thesis .. next case (step vs zs') from left step show ?thesis unfolding l r apply (clarsimp simp: tmap_eq_tshift_conv collapse.tshift TCons_eq_tmap_conv
tmap_tshift trace.natural'.map_natural'[where af=af and sf=sf and s=s]
iffD2[OF trace.natural'.eq_Nil_conv(1)]
dest!: arg_cong[where f="λxs. collapse (sf s) (tmap (map_prod af sf) vf xs)"]
split: if_split_asm) apply (use step(2) in‹fastforce simp flip: trace.final'.map[where af=af]›) apply (metis list.set_map trace.final'.idle trace.final'.map trace.final'.natural') apply metis done qed qed qed qed
lemma takeE: fixes ψ :: "('a, 's, 'v) behavior.t" obtains j where"♮(behavior.take i ψ) = behavior.take j (♮Tψ)" proof atomize_elim have"∃j. trace.natural' s (fst (ttake i xs)) = fst (ttake j (collapse s xs)) ∧ snd (ttake i xs) = snd (ttake j (collapse s xs))" for s and xs :: "('a × 's, 'v) tllist" proof(induct i arbitrary: s xs) case0show ?caseby (fastforce simp: ttake_eq_Nil_conv) next case (Suc i s xs) show ?case proof(cases xs) case (TCons x' xs') with Suc[where s="snd x'"and xs=xs'] show ?thesis by (fastforce intro: exI[where x="Suc j"for j]) qed (simp add: exI[where x=1]) qed thenshow"∃j. ♮ (behavior.take i ψ) = behavior.take j (♮T ψ)" by (simp add: behavior.take_def trace.natural_def split_def) qed
setup‹Sign.parent_path›
subsection‹ The 🪙‹('a, 's, 'v) tls› lattice \label{sec:tls-tls} ›
text‹
is our version of Lamport's TLA lattice which we treat in a ``semantic'' way similarly to 🍋‹"AbadiMerz:1996"›.
:
▪ there is a somewhat natural partial ordering on the ‹tls› lattice induced by the connection with
the ‹spec› lattice (see \S\ref{sec:tls-safety} and \S\ref{sec:safety_closure}) which we do not use
›
typedef ('a, 's, 'v) tls = "behavior.stuttering.closed :: ('a, 's, 'v) behavior.t set set" morphisms unTLS TLS by blast
setup_lifting type_definition_tls
instantiation tls :: (type, type, type) complete_boolean_algebra begin
instance by (standard; transfer;
auto simp: behavior.stuttering.cl_bot
behavior.stuttering.closed_strict_complete_distrib_lattice_axiomI[OF behavior.stuttering.cl_bot])
:
▪ as we lack next/X/‹◯› (due to stuttering closure) we do not have induction for‹U› (until)
▪ 🍋‹"Lamport:1994"› omitted the LTL ``until'' operator from TLA as he considered it too hard to use
▪ As 🍋‹"DeGiacomoVardi:2013"› observe, things get non-standard on finite traces
▪ see \S\ref{sec:safety_closure} for an example
▪ 🍋‹"Maier:2004"› provides an alternative account
›
setup‹Sign.mandatory_path "raw"›
definition state_prop :: "'s pred ==> ('a, 's, 'v) behavior.t set"where "state_prop P = {ψ. P (behavior.init ψ)}"
definition
until :: "('a, 's, 'v) behavior.t set ==> ('a, 's, 'v) behavior.t set ==> ('a, 's, 'v) behavior.t set" where "until P Q = {ψ . ∃i. ∃ψ'∈Q. behavior.dropn i ψ = Some ψ' ∧ (∀j<i. the (behavior.dropn j ψ) ∈ P)}"
definition
eventually :: "('a, 's, 'v) behavior.t set ==> ('a, 's, 'v) behavior.t set" where "eventually P = raw.until UNIV P"
definition
always :: "('a, 's, 'v) behavior.t set ==> ('a, 's, 'v) behavior.t set" where "always P = -raw.eventually (-P)"
abbreviation (input) "unless P Q ≡ raw.until P Q ∪ raw.always P"
lemma untilI: assumes"behavior.dropn i ψ = Some ψ'" assumes"ψ' ∈ Q" assumes"∧j. j < i ==> the (behavior.dropn j ψ) ∈ P" shows"ψ ∈ raw.until P Q" using assms unfolding raw.until_def by blast
lemma eventually_alt_def: shows"raw.eventually P = {ψ . ∃ψ'∈P. ∃i. behavior.dropn i ψ = Some ψ'}" by (auto simp: raw.eventually_def raw.until_def)
lemma always_alt_def: shows"raw.always P = {ψ . ∀i ψ'. behavior.dropn i ψ = Some ψ' ⟶ ψ' ∈ P}" by (auto simp: raw.always_def raw.eventually_alt_def)
lemma alwaysI: assumes"∧i ψ'. behavior.dropn i ψ = Some ψ' ==> ψ' ∈ P" shows"ψ ∈ raw.always P" by (simp add: raw.always_alt_def assms)
lemma alwaysD: assumes"ψ ∈ raw.always P" assumes"behavior.dropn i ψ = Some ψ'" shows"ψ' ∈ P" using assms by (simp add: raw.always_alt_def)
setup‹Sign.mandatory_path "state_prop"›
lemma monotone: shows"mono raw.state_prop" by (fastforce intro: monoI simp: raw.state_prop_def)
lemma base: shows"ψ ∈ Q ==> ψ ∈ raw.until P Q" and"Q ⊆ raw.until P Q" by (force simp: raw.until_def)+
lemma step: assumes"ψ ∈ P" assumes"behavior.tl ψ = Some ψ'" assumes"ψ' ∈ raw.until P Q" shows"ψ ∈ raw.until P Q" proof - from‹ψ' ∈ raw.until P Q› obtain i ψ'' where"ψ'' ∈ Q"and"∀j<i. the (behavior.dropn j ψ') ∈ P"and"behavior.dropn i ψ' = Some ψ''" by (clarsimp simp: raw.until_def) with assms(1,2) show ?thesis by (clarsimp simp: raw.until_def behavior.dropn.Suc less_Suc_eq_0_disj
intro!: exI[where x="Suc i"]) qed
lemma induct[case_names base step, consumes 1, induct set: raw.until]: assumes"ψ ∈ raw.until P Q" assumes base: "∧ψ. ψ ∈ Q ==> R ψ" assumes step: "∧ψ ψ'. [ψ ∈ P; behavior.tl ψ = Some ψ'; ψ' ∈ raw.until P Q; R ψ']==> R ψ" shows"R ψ" proof - from‹ψ ∈ raw.until P Q›obtain ψ' i where"behavior.dropn i ψ = Some ψ'"and"ψ' ∈ Q"and"∀j<i. the (behavior.dropn j ψ) ∈ P" unfolding raw.until_def by blast thenshow ?thesis proof(induct i arbitrary: ψ) case0thenshow ?case by (force intro: base) next case Suc from Suc.prems show ?case by (fastforce intro: step Suc.hyps dest: spec[where x="Suc j"for j]
simp: behavior.dropn.Suc raw.until_def
split: Option.bind_split_asm) qed qed
lemma mono: assumes"P ⊆ P'" assumes"Q ⊆ Q'" shows"raw.until P Q ⊆ raw.until P' Q'" unfolding raw.until_def using assms by blast
lemma botR: shows"raw.until P {} = {}" by (force simp: raw.until_def)
lemma untilR: shows"raw.until P (raw.until P Q) = raw.until P Q" (is"?lhs = ?rhs") proof(rule antisym[OF subsetI]) show"ψ ∈ ?rhs"if"ψ ∈ ?lhs"for ψ using that by induct blast+ show"?rhs ⊆ ?lhs"by blast qed
lemma InfL_not_empty: assumes"X ≠ {}" shows"raw.until (∩X) Q = (∩x∈X. raw.until x Q)" (is"?lhs = ?rhs") proof(rule antisym[OF _ subsetI]) show"?lhs ⊆ ?rhs" by (simp add: INT_greatest Inter_lower raw.until.mono) show"ψ ∈ ?lhs"if"ψ ∈ ?rhs"for ψ proof - from‹X ≠ {}›obtain P where"P ∈ X"by blast with that obtain i ψ' where *: "behavior.dropn i ψ = Some ψ'""ψ' ∈ Q""∀j<i. the (behavior.dropn j ψ) ∈ P" unfolding raw.until_def by blast from this(1,2) obtain k ψ'' where **: "k ≤ i""behavior.dropn k ψ = Some ψ''""ψ'' ∈ Q""∀j<k. the (behavior.dropn j ψ) ∉ Q" using ex_has_least_nat[where k=i and P="λk. k ≤ i ∧ (∀ψ''. behavior.dropn k ψ = Some ψ''⟶ ψ'' ∈ Q)"and m=id] by clarsimp (metis (no_types, lifting) behavior.dropn.shorterD leD nle_le option.sel order.trans) from that * ** show ?thesis by (clarsimp simp: raw.until_def intro!: exI[where x=k])
(metis order.strict_trans1 linorder_not_le option.sel) qed qed
lemma SupR: shows"raw.until P (∪X) = ∪(raw.until P ` X)" unfolding raw.until_def by blast
lemma weakenL: shows"raw.until UNIV P = raw.until (- P) P" (is"?lhs = ?rhs") proof(rule antisym[OF subsetI]) show"ψ ∈ ?rhs"if"ψ ∈ ?lhs"for ψ using that by induct blast+ show"?rhs ⊆ ?lhs"by (simp add: raw.until.mono) qed
lemma implication_ordering_le: ―‹🍋‹‹(16)› in "WarfordVegaStaley:2020"›› shows"raw.until P Q ∩ raw.until (-Q) R ⊆ raw.until P R" by (clarsimp simp: raw.until_def) (metis order.trans linorder_not_le option.sel)
lemma infR_ordering_le: ―‹🍋‹‹(18)› in "WarfordVegaStaley:2020"›› shows"raw.until P (Q ∩ R) ⊆ raw.until (raw.until P Q) R" (is"?lhs⊆ ?rhs") proof(rule subsetI) show"ψ ∈ ?rhs"if"ψ ∈ ?lhs"for ψ using that proof induct case (step ψ ψ') thenshow ?case by - (rule raw.until.step, rule raw.until.step;
blast intro: subsetD[OF raw.until.mono, rotated -1]) qed blast qed
lemma untilL: shows"raw.until (raw.until P Q) Q ⊆ raw.until P Q" (is"?lhs⊆ ?rhs") proof(rule subsetI) show"ψ ∈ ?rhs"if"ψ ∈ ?lhs"for ψ using that by induct auto qed
lemma alwaysR_le: shows"raw.until P (raw.always Q) ⊆ raw.always (raw.until P Q)" (is"?lhs ⊆ ?rhs") proof(rule subsetI) show"ψ ∈ ?rhs"if"ψ ∈ ?lhs"for ψ using that proof induct case (base ψ) thenshow ?caseby (auto simp: raw.always_alt_def) next case (step ψ ψ') show ?case proof(rule raw.alwaysI) fix i ψ'' assume"behavior.dropn i ψ = Some ψ''" with step "behavior.dropn.0"show"ψ'' ∈ raw.until P Q" by (cases i; clarsimp simp: raw.always_alt_def behavior.dropn.Suc; blast) qed qed qed
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "unless"›
lemma neg: shows"- (raw.until P Q ∪ raw.always P) = raw.until (- Q) (- P ∩ - Q)" (is"?lhs = ?rhs") proof(rule antisym[OF subsetI], (unfold Compl_Un Int_iff conj_explode Compl_iff)[1]) fix ψ assume *: "ψ ∉ raw.until P Q" assume"ψ ∉ raw.always P" thenobtain k ψ' where"behavior.dropn k ψ = Some ψ'" and"ψ' ∉ P" by (clarsimp simp: raw.always_alt_def) with ex_has_least_nat[where k=k and P="λi. ∃ψ'. behavior.dropn i ψ = Some ψ' ∧ ψ' ∉ P"andm=id] obtain k ψ' where"behavior.dropn k ψ = Some ψ'" and"ψ' ∉ P" and"∀j<k. the (behavior.dropn j ψ) ∈ P" by clarsimp (metis behavior.dropn.shorterD less_le_not_le option.distinct(1) option.exhaust_sel) with * behavior.dropn.shorterD show"ψ ∈ ?rhs" by (fastforce simp: raw.until_def intro: exI[where x=k]) next show"?rhs ⊆ ?lhs" by (clarsimp simp: raw.always_alt_def raw.until_def subset_iff; metis nat_neq_iff option.sel) qed
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "eventually"›
lemma terminated: shows"raw.eventually raw.terminated = {ψ. tfinite (behavior.rest ψ)}" (is"?lhs = ?rhs") proof(rule antisym[OF _ subsetI]) show"?lhs ⊆ ?rhs" by (clarsimp simp: raw.eventually_alt_def raw.terminated_def behavior.dropn.tfiniteD) show"ψ ∈ ?lhs"if"ψ ∈ ?rhs"for ψ proof - note‹ψ ∈ ?rhs› moreoverfrom calculation obtain i where"tlength (behavior.rest ψ) = enat i" by (clarsimp simp: tfinite_tlength_conv) moreoverfrom calculation obtain ψ' where"behavior.dropn i ψ = Some ψ'" using behavior.dropn.eq_Some_tlength_conv by fastforce moreoverfrom calculation have"behavior.sset ψ' ⊆ {behavior.init ψ'}" by (cases ψ')
(clarsimp dest!: behavior.dropn.eq_Some_tdropnD simp: tdropn_tlength behavior.sset.simps) ultimatelyshow"ψ ∈ ?lhs" by (auto simp: raw.eventually_alt_def raw.terminated_def dest: behavior.dropn.tfiniteD) qed qed
lemma until[intro]: assumes"P ∈ behavior.stuttering.closed" assumes"Q ∈ behavior.stuttering.closed" shows"raw.until P Q ∈ behavior.stuttering.closed" proof - have"ψ2∈ raw.until P Q"if"ψ1∈ raw.until P Q"and"ψ1≃T ψ2"for ψ1 ψ2 using that proof(induct arbitrary: ψ2 rule: raw.until.induct) case (base ψ1 ψ2) with assms(2) show ?case by (blast intro: behavior.stuttering.closed_in) next case (step ψ1 ψ' ψ2) show ?case proof(cases "ψ' ≃T ψ1") case True with‹ψ1≃T ψ2› step.hyps(4) show ?thesis by simp next case False from assms(1) ‹ψ1∈ P›‹ψ1≃T ψ2›have"ψ2∈ P" by (blast intro: behavior.stuttering.closed_in) from False ‹ψ1≃T ψ2›‹behavior.tl ψ1 = Some ψ'› obtain a s0 s1 xs1 xs' ys' where ψ1: "ψ1 = behavior.B s0 (TCons (a, s1) xs1)" and ψ2: "ψ2 = behavior.B s0 (tshift xs' (TCons (a, s1) ys'))" and *: "collapse s0 (TCons (a, s1) xs1) = collapse s0 (tshift xs' (TCons (a, s1) ys'))" "s0≠ s1" and **: "collapse s1 ys' = collapse s1 xs1" and xs': "snd ` set xs' ⊆ {s0}" by (cases ψ1; cases ψ2; cases "behavior.rest ψ1"; simp)
(fastforce simp: behavior.natural_def collapse.eq_TCons_conv trepeat_eq_TCons_conv
split: if_splits) from ψ2‹ψ2∈ P› xs' show ?thesis proof(induct xs' arbitrary: ψ2) case Nil with ψ1 ** step.hyps(2,4) show ?case by (auto simp: behavior.natural_def) next case (Cons x' xs') with behavior.stuttering.closed_in[OF _ _ ‹P ∈ behavior.stuttering.closed›] ψ1 ** step(3) show ?case by (auto simp: behavior.natural_def behavior.split_all) qed qed qed thenshow ?thesis by (fastforce elim: behavior.stuttering.clE) qed
lemma eventually[intro]: assumes"P ∈ behavior.stuttering.closed" shows"raw.eventually P ∈ behavior.stuttering.closed" using assms by (auto simp: raw.eventually_def)
lemma always[intro]: assumes"P ∈ behavior.stuttering.closed" shows"raw.always P ∈ behavior.stuttering.closed" using assms by (auto simp: raw.always_def)
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "tls"›
definition valid :: "('a, 's, 'v) tls ==> bool"where "valid P ⟷ P = ⊤"
lemma trans[trans]: assumes"⊨ P" assumes"P ≤ Q" shows"⊨ Q" using assms by (simp add: tls.valid_def top.extremum_unique)
lemma mp: assumes"⊨ P \<longrightarrow>B Q" assumes"⊨ P" shows"⊨ Q" using assms by (simp add: tls.valid_def)
lemmas rev_mp = tls.valid.mp[rotated]
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "singleton"›
lemma uminus_le_conv[tls.singleton.le_conv]: shows"(•ψ•)T≤ -P ⟷¬(•ψ•)T≤ P" by transfer
(simp add: raw.singleton_def behavior.stuttering.closed_uminus behavior.stuttering.least_conv)
lemma state_prop_le_conv[tls.singleton.le_conv]: shows"(•ψ•)T≤ tls.state_prop P ⟷ P (behavior.init ψ)" by transfer
(simp add: raw.singleton_def behavior.stuttering.least_conv[OF behavior.stuttering.closed.raw.state_prop];
simp add: raw.state_prop_def)
lemma until_le_conv[tls.singleton.le_conv]: fixes P :: "('a, 's, 'v) tls" shows"(•ψ•)T≤ P U Q ⟷ (∃i ψ'. behavior.dropn i ψ = Some ψ' ∧(•ψ'•)T≤ Q ∧ (∀j<i. (•the (behavior.dropn j ψ)•)T≤ P))" (is"?lhs ⟷ ?rhs") proof(rule iffI) show"?lhs ==> ?rhs" proof transfer fix ψ and P Q :: "('a, 's, 'v) behavior.t set" assume *: "P ∈ behavior.stuttering.closed""Q ∈ behavior.stuttering.closed" and"raw.singleton ψ ⊆ raw.until P Q" thenhave"∃i. ∃ψ'∈Q. behavior.dropn i ψ = Some ψ' ∧ (∀j<i. the (behavior.dropn j ψ) ∈P)" by (auto simp: raw.singleton_def raw.until_def) with * show"∃i ψ'. behavior.dropn i ψ = Some ψ' ∧ raw.singleton ψ' ⊆ Q ∧ (∀j<i. raw.singleton (the (behavior.dropn j ψ)) ⊆ P)" by (auto simp: raw.singleton_def behavior.stuttering.least_conv) qed show"?rhs ==> ?lhs" by transfer
(unfold raw.singleton_def;
rule behavior.stuttering.least[OF _ behavior.stuttering.closed.raw.until];
auto 100 intro: iffD2[OF eqset_imp_iff[OF raw.until_def]]) qed
lemma eventually_le_conv[tls.singleton.le_conv]: shows"(•ψ•)T≤♢P ⟷ (∃i ψ'. behavior.dropn i ψ = Some ψ' ∧(•ψ'•)T≤ P)" by (simp add: tls.eventually_def tls.singleton.le_conv)
lemma always_le_conv[tls.singleton.le_conv]: shows"(•ψ•)T≤ tls.always P ⟷ (∀i ψ'. behavior.dropn i ψ = Some ψ' ⟶(•ψ'•)T≤ P)" by (simp add: tls.always_def tls.singleton.le_conv)
setup‹Sign.parent_path›
interpretation until: closure_complete_lattice_distributive_class "tls.until P"for P proof standard show"(x ≤ tls.until P y) = (tls.until P x ≤ tls.until P y)"for x y by transfer
(intro iffD2[OF order_class.order.closure_axioms_alt_def[unfolded closure_axioms_def], rule_format]
conjI allI raw.until.base monoI raw.until.mono order.refl raw.until.untilR, assumption) show"tls.until P (⊔X) ≤⊔(tls.until P ` X) ⊔ tls.until P ⊥"for X by transfer (simp add: raw.until.SupR behavior.stuttering.cl_bot) qed
setup‹Sign.mandatory_path "until"›
lemmas botL = raw.until.botL[transferred] lemmas botR = raw.until.botR[transferred] lemmas topR = tls.until.cl_top lemmas expansiveR = tls.until.expansive[of P Q for P Q]
lemmas weakenL = raw.until.weakenL[transferred]
lemmas mono = raw.until.mono[transferred]
lemma strengthen[strg]: assumes"st_ord F P P'" assumes"st_ord F Q Q'" shows"st_ord F (P U Q) (P' U Q')" using assms by (cases F) (auto simp: tls.until.mono)
lemma SupL_le: shows"(⊔x∈X. x U R) ≤ (⊔X) U R" by (simp add: SupI tls.until.mono)
lemma supL_le: shows"P U R ⊔ Q U R ≤ (P ⊔ Q) U R" by (simp add: tls.until.mono)
lemma SupR: shows"P U (⊔X) = ⊔((U) P ` X)" by (simp add: tls.until.cl_Sup tls.until.botR)
lemmas supR = tls.until.cl_sup
lemmas InfL_not_empty = raw.until.InfL_not_empty[transferred] lemmas infL = tls.until.InfL_not_empty[where X="{P, Q}"for P Q, simplified, of P Q R for P Q R] lemmas InfR_le = tls.until.cl_Inf_le lemmas infR_le = tls.until.cl_inf_le[of P Q R for P Q R]
lemma implication_ordering_le: ―‹🍋‹‹(16)› in "WarfordVegaStaley:2020"›› shows"P U Q ⊓ (-Q) U R ≤ P U R" by transfer (rule raw.until.implication_ordering_le)
lemma supL_ordering_le: ―‹🍋‹‹(17)› in "WarfordVegaStaley:2020"›› shows"P U (Q U R) ≤ (P ⊔ Q) U R" (is"?lhs ≤ ?rhs") proof - have"?rhs = (P ⊔ Q) U ((P ⊔ Q) U R)"by (rule tls.until.idempotent(1)[symmetric]) alsohave"?lhs ≤…"by (blast intro: tls.until.mono le_supI1 le_supI2) finallyshow ?thesis . qed
lemma infR_ordering_le: ―‹🍋‹‹(18)› in "WarfordVegaStaley:2020"›› shows"P U (Q ⊓ R) ≤ (P U Q) U R" by transfer (rule raw.until.infR_ordering_le)
lemma boolean_implication_distrib_le: ―‹🍋‹‹(19)› in "WarfordVegaStaley:2020"›› shows"(P \<longrightarrow>B Q) U R ≤ (P U R) \<longrightarrow>B (Q U R)" by (metis galois.conj_imp.galois order.refl tls.until.infL tls.until.mono)
lemma excluded_middleR: ―‹🍋‹‹(23)› in "WarfordVegaStaley:2020"›› shows"⊨ P U Q ⊔ P U (-Q)" by (simp add: tls.validI tls.until.cl_top flip: tls.until.cl_sup)
lemmas untilR = tls.until.idempotent(1)[of P Q for P Q]
lemma untilL: shows"(P U Q) U Q = P U Q" (is"?lhs = ?rhs") proof(rule antisym) show"?lhs ≤ ?rhs" by transfer (rule raw.until.untilL) show"?rhs ≤ ?lhs" using tls.until.infR_ordering_le[where P=P and Q=Q and R=Q] by simp qed
lemma absorb: shows"P U P = P" by (metis tls.until.botL tls.until.untilL)
lemma absorb_supL: ―‹🍋‹‹(23)› in "WarfordVegaStaley:2020"›› shows"P ⊔ P U Q = P ⊔ Q" by (metis inf_commute inf_sup_absorb le_iff_sup
tls.until.absorb tls.until.cl_sup tls.until.expansive tls.until.infL)
lemma absorb_supR: ―‹🍋‹‹(23)› in "WarfordVegaStaley:2020"›› shows"Q ⊔ P U Q = P U Q" by (simp add: sup.absorb2 tls.until.expansive)
lemma eventually_le: shows"P U Q ≤♢Q" by (simp add: tls.eventually_def tls.until.mono)
lemma absorb_eventually: shows inf_eventually_absorbR: "P U Q ⊓♢Q = P U Q" ―‹🍋‹‹(39)› in "WarfordVegaStaley:2020"›› and sup_eventually_absorbR: "P U Q ⊔♢Q = ♢Q" ―‹🍋‹‹(40)› in "WarfordVegaStaley:2020"›› and eventually_absorbR: "P U♢Q = ♢Q" ―‹🍋‹‹(41)› in "WarfordVegaStaley:2020"›› by (simp_all add: tls.eventually_def sup.absorb2 tls.until.mono
order.eq_iff order.trans[OF tls.until.supL_ordering_le] tls.until.expansiveR
flip: tls.until.infL)
lemma sup_le: ―‹🍋‹‹(28)› in "WarfordVegaStaley:2020"›› shows"P U Q ≤ P ⊔ Q" by (simp add: ac_simps sup.absorb_iff1 tls.until.absorb_supL tls.until.absorb_supR)
lemma ordering: ―‹🍋‹‹(251)› in "WarfordVegaStaley:2020"›› shows"(-P) U Q ⊔ (-Q) U P = ♢(P ⊔ Q)" (is"?lhs = ?rhs") proof - have"?lhs = ⊤U P ⊓ (- Q) U P ⊔⊤U Q ⊓ (- P) U Q" by (simp add: ac_simps inf.absorb2 tls.until.mono) alsohave"… = (- P) U P ⊓ (- Q) U P ⊔ (- Q) U Q ⊓ (- P) U Q" by (simp add: tls.until.weakenL) alsohave"… = (- (P ⊔ Q)) U (P ⊔ Q)" by (simp add: ac_simps tls.until.cl_sup flip: tls.until.infL) alsohave"… = ?rhs" by (simp add: tls.eventually_def tls.until.weakenL) finallyshow ?thesis . qed
lemma neg: ―‹🍋‹‹(170)› in "WarfordVegaStaley:2020"›› shows"-(P W Q) = (-Q) U (-P ⊓ -Q)" by transfer (rule raw.unless.neg)
lemma alwaysR_le: ―‹🍋‹‹(177)› in "WarfordVegaStaley:2020"›› shows"P W◻Q ≤◻(P W Q)" by (simp add: tls.unless_def order.trans[OF tls.until_alwaysR_le] tls.always.mono
order.trans[OF _ tls.always.sup_le])
lemma sup_le: ―‹🍋‹‹(206)› in "WarfordVegaStaley:2020"›› shows"P W Q ≤ P ⊔ Q" by (rule iffD1[OF compl_le_compl_iff]) (simp add: tls.unless.neg tls.until.expansive)
lemma ordering: ―‹🍋‹‹(252)› in "WarfordVegaStaley:2020"›› shows"⊨ (-P) W Q ⊔ (-Q) W P" by (simp add: ac_simps tls.validI tls.unless_def tls.until.ordering tls.eventually.sup flip: tls.eventually.neg)
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "until"›
lemma eq_unless_inf_eventually: shows"P U Q = (P W Q) ⊓♢Q" by transfer (force simp: raw.until_def raw.eventually_def raw.always_alt_def behavior.dropn.shorterD)
lemma always_strengthen_le: ―‹🍋‹‹(83)› in "WarfordVegaStaley:2020"›› shows"◻P ⊓ (Q U R) ≤ (P ⊓ Q) U (P ⊓ R)" by transfer
(clarsimp simp: raw.until_def raw.always_alt_def;
fastforce simp: behavior.dropn.shorterD del: exI intro!: exI)
lemma until_weakI: shows"◻P ⊓♢Q ≤ P U Q" (is"?lhs ≤ ?rhs") ―‹🍋‹‹(84)› in "WarfordVegaStaley:2020"›› by (simp add: tls.eventually_def order.trans[OF tls.until.always_strengthen_le] tls.until.mono)
lemma always_impL: ―‹🍋‹‹(86)› in "WarfordVegaStaley:2020"›› shows"P \<longrightarrow>\<box> P' ⊓ P U Q ≤ P' U Q" (is ?thesis1) and"P U Q ⊓ P \<longrightarrow>\<box> P' ≤ P' U Q" (is ?thesis2) proof - show ?thesis1 by (rule order.trans[OF tls.until.always_strengthen_le])
(simp add: tls.until.mono boolean_implication.shunt1) thenshow ?thesis2 by (simp add: inf_commute) qed
lemma always_impR: ―‹🍋‹‹(85)› in "WarfordVegaStaley:2020"›› shows"Q \<longrightarrow>\<box> Q' ⊓ P U Q ≤ P U Q'" (is ?thesis1) and"P U Q ⊓ Q \<longrightarrow>\<box> Q' ≤ P U Q'" (is ?thesis2) proof - show ?thesis1 by (rule order.trans[OF tls.until.always_strengthen_le])
(simp add: tls.until.mono boolean_implication.shunt1) thenshow ?thesis2 by (simp add: inf_commute) qed
lemma neg: ―‹🍋‹‹(173)› in "WarfordVegaStaley:2020"›› shows"-(P U Q) = (-Q) W (-P ⊓ -Q)" unfolding tls.unless_def by (simp flip: tls.until.eq_unless_inf_eventually tls.unless.neg tls.eventually.neg
boolean_algebra.de_Morgan_conj)
subsubsection‹ Leads-to and leads-to-via \label{sec:TLS_leads-to} ›
text‹
-called 🪙‹response› properties are of the form ‹P \⟶\◻♢Q› (pronounced ``‹P› leads to ‹Q›'', written ‹P \↝ Q›) 🍋‹"MannaPnueli:1991"›. This connective is similar
the ``ensures'' modality of 🍋‹‹\S3.4.4› in "ChandyMisra:1989"›.
🍋‹"Jackson:1998"› used the more general
`‹P› leads to ‹Q› via ‹I›'' form ‹P \⟶\◻ I U Q›
establish liveness properties in a sequential setting.
›
lemma leads_to_refl: shows"⊨ P \<leadsto> P" by (simp add: tls.validI boolean_implication.shunt_top tls.always.top_conv tls.eventually.expansive
top.extremum_unique)
lemma leads_to_leads_to_via: shows"P \<longrightarrow>\<box> Q U R ≤ P \<leadsto> R" by (simp add: boolean_implication.mono tls.always.mono tls.until.eventually_le)
lemma leads_to_trans: shows"P \<leadsto> Q ⊓ Q \<leadsto> R ≤ P \<leadsto> R" (is"?lhs ≤ ?rhs") proof - have"?lhs ≤ P \<leadsto> Q ⊓◻(Q \<leadsto> R)" by (simp add: tls.always.simps) alsohave"…≤ P \<leadsto> Q ⊓♢Q \<leadsto> R" by (meson order.refl inf_mono tls.always.mono tls.always_imp_eventually_generalization) alsohave"…≤ ?rhs" by (simp add: boolean_implication.trans tls.always.mono flip: tls.always.inf) finallyshow ?thesis . qed
lemma leads_to_via_weakenR: shows"Q \<longrightarrow>\<box> Q' ⊓ P \<longrightarrow>\<box> I U Q ≤ P \<longrightarrow>\<box> I U Q'" by transfer
(clarsimp simp: raw.always_alt_def raw.until_def boolean_implication.set_alt_def;
metis behavior.dropn.dropn Option.bind.bind_lunit)
lemma leads_to_via_supL: ―‹ useful for case distinctions › shows"P \<longrightarrow>\<box> I U Q ⊓ P' \<longrightarrow>\<box> I' U Q ≤ P ⊔ P' \<longrightarrow>\<box> (I ⊔ I') U Q" by (simp add: boolean_implication.conv_sup ac_simps le_infI2 le_supI2
monoD[OF tls.always.monotone] tls.until.mono)
lemma leads_to_via_trans: shows"(P \<longrightarrow>\<box> I U Q) ⊓ (Q \<longrightarrow>\<box> I' U R) ≤ P \<longrightarrow>\<box> (I ⊔ I') U R" (is"?lhs ≤ ?rhs") proof - have"?lhs ≤◻(P \<longrightarrow>B I U (I' U R))" by (subst inf.commute) (rule tls.leads_to_via_weakenR) alsohave"…≤ ?rhs" by (strengthen ord_to_strengthen(1)[OF tls.until.supL_ordering_le]) (rule order.refl) finallyshow ?thesis . qed
lemma leads_to_via_disj: ―‹ more like a chaining rule › shows"(P \<longrightarrow>\<box> I U Q) ⊓ (Q \<longrightarrow>\<box> I' U R) ≤ (P ⊔Q \<longrightarrow>\<box> (I ⊔ I') U R)" by (simp add: boolean_implication_def inf.coboundedI2 le_supI2 tls.always.mono tls.until.mono)
subsubsection‹ Fairness\label{sec:tls-fairness} ›
text‹
few renderings of weak fairness. 🍋‹"vanGlabbeekHofner:2019"› call this
`response to insistence'' as a generalisation of weak fairness.
lemma strengthen[strg]: assumes"st_ord (¬F) P P'" assumes"st_ord F Q Q'" shows"st_ord F (tls.weakly_fair P Q) (tls.weakly_fair P' Q')" using assms by (cases F) (auto simp: tls.weakly_fair.mono)
lemma strengthen[strg]: assumes"st_ord (¬F) P P'" assumes"st_ord F Q Q'" shows"st_ord F (tls.strongly_fair P Q) (tls.strongly_fair P' Q')" using assms by (cases F) (auto simp: tls.strongly_fair.mono)
lemma supL: ―‹ does not hold for const‹tls.weakly_fair›› shows"tls.strongly_fair (enabled1 ⊔ enabled2) taken = (tls.strongly_fair enabled1 taken ⊓ tls.strongly_fair enabled2 taken)" by (simp add: boolean_implication.conv_sup sup_inf_distrib2 tls.always.inf tls.always_eventually_sup
tls.strongly_fair_def)
lemma weakly_fair_le: shows"tls.strongly_fair enabled taken ≤ tls.weakly_fair enabled taken" by (simp add: tls.strongly_fair_def3 tls.weakly_fair_def3 boolean_implication.mono
tls.eventually_always_always_eventually_le)
lemma always_enabled_weakly_fair_strongly_fair: shows"◻enabled ≤ tls.weakly_fair enabled taken \<longleftrightarrow>B tls.strongly_fair enabled taken" by (simp add: boolean_eq_def boolean_implication_def)
now carve the safety properties out of the 🍋‹('a, 's, 'v) tls› lattice.
:
▪ 🍋‹‹\S2› in "AlpernSchneider:1985" and "AlpernDemersSchneider:1986" and "Schneider:1987"›
▪ observes that Lamport's earlier definitions do not work without stuttering
▪ provides the now standard definition that works with and without stuttering
▪ 🍋‹‹\S2.2› in "AbadiLamport:1991"›: topological definitions and intuitions
▪ 🍋‹‹\S2.2› in "Sistla:1994"›
go a different way: we establish a Galois connection with 🍋‹('a, 's, 'v) spec›.
:
▪ our safety closure for 🍋‹('a, 's, 'v) tls› introduces infinite sequences to stand for the
prefixes in 🍋‹('a, 's, 'v) spec›
▪ i.e., the non-termination of trace ‹σ› (‹trace.term σ = None›)
is represented by a behavior ending with ‹trace.final σ› infinitely stuttered
▪ 🍋‹‹\S2.1› in "AbadiLamport:1991"› consider these behaviors to represent terminating processes
›
setup‹Sign.mandatory_path "raw"›
definition to_spec :: "('a, 's, 'v) behavior.t set ==> ('a, 's, 'v) trace.t set"where "to_spec T = {behavior.take i ψ |ψ i. ψ ∈ T}"
definition from_spec :: "('a, 's, 'v) trace.t set ==> ('a, 's, 'v) behavior.t set"where "from_spec S = {ψ . ∀i. behavior.take i ψ ∈ S}"
interpretation safety: galois.powerset raw.to_spec raw.from_spec by standard (fastforce simp: raw.to_spec_def raw.from_spec_def)
lemma singleton:
shows "raw.to_spec (TLS.raw.singleton \<omega>)
= (\<Union>i. Safety_Logic.raw.singleton (behavior.take i \<omega>))" (is "?lhs = ?rhs")
proof(rule antisym)
show "?lhs \<subseteq> ?rhs"
by (fastforce simp: TLS.raw.singleton_def raw.to_spec_def
Safety_Logic.raw.singleton_def raw.spec.cl_def
elim: behavior.stuttering.clE behavior.stuttering.equiv.takeE[OF sym]
trace.stuttering.clI[OF _ sym, rotated])
show "?rhs \<subseteq> ?lhs"
by (fastforce simp: Safety_Logic.raw.singleton_def raw.spec.cl_def TLS.raw.singleton_def
raw.to_spec_def trace.less_eq_take_def trace.take.behavior.take
elim: downwards.clE trace.stuttering.clE trace.stuttering.equiv.behavior.takeE)
qed
setup \<open>Sign.parent_path\<close>
setup \<open>Sign.mandatory_path "safety"\<close>
lemma cl_altI:
assumes "\<And>i. \<exists>\<omega>' \<in> P. behavior.take i \<omega> = behavior.take i \<omega>'"
shows "\<omega> \<in> raw.safety.cl P" using assms by (fastforce simp: raw.safety.cl_def raw.from_spec_def raw.to_spec_def)
lemma cl_altE:
assumes "\<omega> \<in> raw.safety.cl P"
obtains \<omega>' where "\<omega>' \<in> P" and "behavior.take i \<omega> = behavior.take i \<omega>'"
proof(atomize_elim, cases "enat i \<le> tlength (behavior.rest \<omega>)") caseTrue with assms show "\<exists>\<omega>'. \<omega>' \<in> P \<and> behavior.take i \<omega> = behavior.take i \<omega>'"
by (clarsimp simp: raw.safety.cl_def raw.from_spec_def raw.to_spec_def)
(metis behavior.take.length behavior.take.sel(3) ttake_eq_None_conv(1)
min.absorb2 min_enat2_conv_enat the_enat.simps)
next caseFalse with assms show "\<exists>\<omega>'. \<omega>' \<in> P \<and> behavior.take i \<omega> = behavior.take i \<omega>'"
by (clarsimp simp: raw.safety.cl_def raw.from_spec_def raw.to_spec_def)
(metis behavior.continue.take_drop_id behavior.take.continue_id leI)
qed
lemma cl_alt_def: \<comment>\<open> \<^citet>\<open>"AlpernDemersSchneider:1986"\<close>: the classical definition: \<open>\<omega>\<close> belongs to the safety closure of \<open>P\<close> if every prefix of \<open>\<omega>\<close> can be extended to a behavior in \<open>P\<close> \<close>
shows "raw.safety.cl P = {\<omega>. \<forall>i. \<exists>\<beta>. behavior.take i \<omega> @-\<^sub>B \<beta> \<in> P}" (is "?lhs = ?rhs")
proof(rule antisym)
show "?lhs \<subseteq> ?rhs"
by clarsimp (metis behavior.continue.take_drop_id raw.safety.cl_altE)
show "?rhs \<subseteq> ?lhs"
proof(clarify intro!: raw.safety.cl_altI)
fix \<omega> i
assume "\<forall>j. \<exists>\<beta>. behavior.take j \<omega> @-\<^sub>B \<beta> \<in> P"
then show "\<exists>\<omega>'\<in>P. behavior.take i \<omega> = behavior.take i \<omega>'"
by (force dest: spec[where x=i]
intro: exI[where x=i] rev_bexI
simp: behavior.take.continue trace.take.behavior.take trace.continue.self_conv
ttake_eq_None_conv length_ttake
split: option.split enat.split)
qed
qed
lemma closed_alt_def: \<comment>\<open> If \<open>\<omega>\<close> is not in \<open>P\<close> then some prefix of \<open>\<omega>\<close> has irretrievably gone wrong \<close>
shows "raw.safety.closed = {P. \<forall>\<omega>. \<omega> \<notin> P \<longrightarrow> (\<exists>i. \<forall>\<beta>. behavior.take i \<omega> @-\<^sub>B \<beta> \<notin> P)}"
unfolding raw.safety.closed_def raw.safety.cl_alt_def by fast
lemma closed_alt_def2: \<comment>\<open> Contraposition gives the customary prefix-closure definition \<close>
shows "raw.safety.closed = {P. \<forall>\<omega>. (\<forall>i. \<exists>\<beta>. behavior.take i \<omega> @-\<^sub>B \<beta> \<in> P) \<longrightarrow> \<omega> \<in> P}"
unfolding raw.safety.closed_alt_def by fast
lemma closedI2:
assumes "\<And>\<omega>. (\<And>i. \<exists>\<beta>. behavior.take i \<omega> @-\<^sub>B \<beta> \<in> P) \<Longrightarrow> \<omega> \<in> P"
shows "P \<in> raw.safety.closed" using assms unfolding raw.safety.closed_alt_def2 by fast
lemma closedE2:
assumes "P \<in> raw.safety.closed"
assumes "\<And>i. \<omega> \<notin> P \<Longrightarrow> \<exists>\<beta>. behavior.take i \<omega> @-\<^sub>B \<beta> \<in> P"
shows "\<omega> \<in> P" using assms unfolding raw.safety.closed_alt_def2 by blast
lemma terminated_iff:
assumes "\<omega> \<in> raw.terminated"
shows "\<omega> \<in> raw.safety.cl P \<longleftrightarrow> \<omega> \<in> P" (is "?lhs \<longleftrightarrow> ?rhs")
proof(rule iffI)
from assms obtain i where "tlength (behavior.rest \<omega>) = enat i"
by (clarsimp simp: raw.terminated_def tfinite_tlength_conv)
then show "?lhs \<Longrightarrow> ?rhs"
by (metis raw.safety.cl_altE[where i="Suc i"]
behavior.continue.take_drop_id behavior.take.continue_id enat_ord_simps(2) lessI)
qed (simp add: raw.safety.expansive')
lemma terminated:
shows "raw.safety.cl raw.terminated = raw.idle \<union> raw.terminated" (is "?lhs = ?rhs")
proof(rule antisym[OF subsetI subsetI])
fix \<omega>
assume "\<omega> \<in> ?lhs"
then have "snd (tnth (behavior.rest \<omega>) i) = behavior.init \<omega>" if"enat i < tlength (behavior.rest \<omega>)" for i using that
by (clarsimp simp: raw.terminated_def behavior.take_def behavior.split_all behavior.sset.simps
split_def
simp del: ttake.simps
elim!: raw.safety.cl_altE[where i="Suc i"])
(metis (no_types, lifting) Suc_ile_eq in_tset_conv_tnth nth_ttake
doubleton_eq_iff insert_image insert_absorb2 lessI subset_singletonD ttake_eq_None_conv(1))
then have "behavior.sset \<omega> \<subseteq> {behavior.init \<omega>}"
by (cases \<omega>) (clarsimp simp: behavior.sset.simps tset_conv_tnth)
then show "\<omega> \<in> ?rhs"
by (simp add: raw.idle_alt_def raw.terminated_def)
next
show "\<omega> \<in> ?lhs"if"\<omega> \<in> ?rhs"for \<omega> using that
proof(cases rule: UnE[consumes 1, case_names idle terminated]) case idle show ?thesis
proof(rule raw.safety.cl_altI)
fix i
let ?\<omega>' = "behavior.take i \<omega> @-\<^sub>B TNil undefined"
from idle have "?\<omega>' \<in> raw.terminated"
by (auto simp: raw.idle_alt_def raw.terminated_def behavior.sset.continue
dest: subsetD[OF behavior.sset.take_le]
split: option.split)
moreover
from idle have "behavior.take i \<omega> = behavior.take i ?\<omega>'"
by (simp add: raw.idle_alt_def behavior.take.continue trace.take.behavior.take
length_ttake tfinite_tlength_conv)
ultimately show "\<exists>\<omega>'\<in>raw.terminated. behavior.take i \<omega> = behavior.take i \<omega>'"
by blast
qed
qed (auto intro: raw.safety.expansive')
qed
lemma le_terminated_bot:
assumes "P \<in> behavior.stuttering.closed"
assumes "raw.safety.cl P \<subseteq> raw.terminated"
shows "P = {}"
proof(rule ccontr)
assume \<open>P \<noteq> {}\<close> then obtain \<omega> where "\<omega> \<in> P" by blast
let ?\<omega>' = "behavior.B (behavior.init \<omega>) (trepeat (undefined, behavior.init \<omega>))"
from \<open>\<omega> \<in> P\<close> have "?\<omega>' \<in> raw.safety.cl P"
by (fastforce intro: exI[where x="behavior.rest \<omega>"]
behavior.stuttering.f_closedI[OF \<open>P \<in> behavior.stuttering.closed\<close>]
simp: raw.safety.cl_alt_def behavior.take.trepeat behavior.continue.simps
behavior.natural.tshift collapse.tshift trace.natural'.replicate
trace.final'.replicate
behavior.stuttering.f_closed[OF \<open>P \<in> behavior.stuttering.closed\<close>]
simp flip: behavior.natural_def)
moreover have "?\<omega>' \<notin> raw.terminated"
by (simp add: raw.terminated_def)
moreover note \<open>raw.safety.cl P \<subseteq> raw.terminated\<close>
ultimately show False by blast
qed
lemma always_le:
shows "raw.safety.cl (raw.always P) \<subseteq> raw.always (raw.safety.cl P)"
unfolding raw.always_alt_def raw.safety.cl_alt_def subset_iff mem_Collect_eq
proof(intro allI impI)
fix \<omega> i \<omega>' j
assume *: "\<forall>i. \<exists>\<beta>. \<forall>k \<omega>'. behavior.dropn k (behavior.take i \<omega> @-\<^sub>B \<beta>) = Some \<omega>' \<longrightarrow> \<omega>' \<in> P" and **: "behavior.dropn i \<omega> = Some \<omega>'"
from spec[where x="i + j", OF *] ** behavior.take.dropn[OF **, where j=j]
show "\<exists>\<beta>. behavior.take j \<omega>' @-\<^sub>B \<beta> \<in> P"
by (clarsimp dest!: spec[where x=i])
(subst (asm) behavior.dropn.continue_shorter;
force simp: length_ttake trace.dropn.behavior.take
dest: behavior.dropn.eq_Some_tlengthD
split: enat.split)
qed
lemma eventually:
assumes "P \<noteq> \<bottom>"
shows "raw.safety.cl (raw.eventually P)
= -raw.eventually raw.terminated \<union> raw.eventually P" (is "?lhs = ?rhs")
proof(rule antisym[OF subsetI iffD2[OF Un_subset_iff, simplified conj_explode, rule_format, OF subsetI]])
show "\<omega> \<in> ?rhs"if"\<omega> \<in> ?lhs"for \<omega>
proof(cases "tlength (behavior.rest \<omega>)") case (enat i) with that show ?thesis
by (fastforce dest: spec[where x="Suc i"]
simp: raw.safety.cl_alt_def raw.terminated_def behavior.take.continue_id)
qed (simp add: raw.eventually.terminated tfinite_tlength_conv)
from assms obtain \<omega>\<^sub>P where "\<omega>\<^sub>P \<in> P" by blast
show "\<omega> \<in> ?lhs"if"\<omega> \<in> -raw.eventually raw.terminated"for \<omega>
proof(intro raw.safety.cl_altI exI bexI)
fix i
let ?\<omega>' = "behavior.take i \<omega> @-\<^sub>B TCons (undefined, behavior.init \<omega>\<^sub>P) (behavior.rest \<omega>\<^sub>P)"
from \<open>\<omega>\<^sub>P \<in> P\<close> \<open>\<omega> \<in> -raw.eventually raw.terminated\<close> show "?\<omega>' \<in> raw.eventually P"
unfolding raw.eventually.terminated
by (auto intro!: exI[where x="Suc i"]
simp: raw.eventually_alt_def tfinite_tlength_conv behavior.dropn.continue
length_ttake ttake_eq_None_conv)
from \<open>\<omega> \<in> -raw.eventually raw.terminated\<close> show "behavior.take i \<omega> = behavior.take i ?\<omega>'"
by (simp add: raw.eventually.terminated behavior.take.continue trace.take.behavior.take
length_ttake tfinite_tlength_conv
split: enat.split)
qed
show "raw.eventually P \<subseteq> ?lhs"
by (fast intro!: order.trans[OF _ raw.safety.expansive])
qed
setup \<open>Sign.parent_path\<close>
setup \<open>Sign.mandatory_path "closed"\<close>
lemma always_eventually:
assumes "P \<in> raw.safety.closed"
assumes "\<forall>i. \<exists>j\<ge>i. \<exists>\<beta>. behavior.take j \<omega> @-\<^sub>B \<beta> \<in> P"
shows "\<omega> \<in> P" using assms(1)
proof(rule raw.safety.closedE2)
fix i
from spec[OF assms(2), where x=i] obtain j \<beta> where "i \<le> j"and"behavior.take j \<omega> @-\<^sub>B \<beta> \<in> P"
by blast
then show "\<exists>\<beta>. behavior.take i \<omega> @-\<^sub>B \<beta> \<in> P"if"\<omega> \<notin> P" using that
by (clarsimp simp: tdropn_tshift2 behavior.continue.tshift2 behavior.continue.take_drop_shorter length_ttake
behavior.continue.term_Some behavior.take.term_Some_conv ttake_eq_Some_conv
split: enat.split split_min
intro!: exI[where x="tdropn i (behavior.rest (behavior.take j \<omega> @-\<^sub>B \<beta>))"])
qed
lemma unless: \<comment>\<open> \<^citet>\<open> \<open>\S3.1\<close> in "Sistla:1994"\<close> -- minimality is irrelevant \<close>
assumes "P \<in> raw.safety.closed"
assumes "Q \<in> raw.safety.closed"
shows "raw.unless P Q \<in> raw.safety.closed"
proof(rule raw.safety.closedI2)
fix \<omega> assume *: "\<exists>\<beta>. behavior.take i \<omega> @-\<^sub>B \<beta> \<in> raw.unless P Q"for i
show "\<omega> \<in> raw.unless P Q"
proof(cases "\<forall>i j \<omega>'. \<exists>\<beta>. behavior.dropn i \<omega> = Some \<omega>' \<longrightarrow> behavior.take j \<omega>' @-\<^sub>B \<beta> \<in> P") caseTrue
with \<open>P \<in> raw.safety.closed\<close> have "behavior.dropn i \<omega> = Some \<omega>' \<longrightarrow> \<omega>' \<in> P"for i \<omega>'
by (blast intro: raw.safety.closedE2)
then show ?thesis
by (simp add: raw.always_alt_def)
next caseFalse
then obtain \<omega>' k l
where **: "behavior.dropn k \<omega> = Some \<omega>'""\<forall>\<beta>. behavior.take l \<omega>' @-\<^sub>B \<beta> \<notin> P"
by clarsimp
{
fix i \<beta>
assume kli: "k + l \<le> i"
moreover
note **
moreover
from kli have "\<exists>j. i - k = l + j" by presburger
moreover
from \<open>behavior.dropn k \<omega> = Some \<omega>'\<close> kli
have ***: "k \<le> length (trace.rest (behavior.take i \<omega>))"
by (fastforce simp: length_ttake split: enat.splits
dest: behavior.dropn.eq_Some_tlengthD)
ultimately have ****: "\<forall>\<omega>''. behavior.dropn k (behavior.take i \<omega> @-\<^sub>B \<beta>) = Some \<omega>'' \<longrightarrow> \<omega>'' \<notin> P"
by (force simp: behavior.dropn.continue_shorter trace.dropn.behavior.take behavior.take.add
simp flip: behavior.continue.tshift2)
{
assume PQ: "behavior.take i \<omega> @-\<^sub>B \<beta> \<in> raw.unless P Q"
from **** PQ obtain m
where "m \<le> k" and"\<forall>\<omega>'. behavior.dropn m (behavior.take i \<omega> @-\<^sub>B \<beta>) = Some \<omega>' \<longrightarrow> \<omega>' \<in> Q" and"\<forall>p<m. (\<forall>\<omega>'. behavior.dropn p (behavior.take i \<omega> @-\<^sub>B \<beta>) = Some \<omega>' \<longrightarrow> \<omega>' \<in> P)"
by (auto60 simp: raw.until_def raw.always_alt_def)
(metis behavior.dropn.shorterD leI nle_le option.sel)
with kli ***
have "(\<exists>m\<le>k. (\<forall>\<omega>'. behavior.dropn m \<omega> = Some \<omega>' \<longrightarrow> behavior.take (i - m) \<omega>' @-\<^sub>B \<beta> \<in> Q)
\<and> (\<forall>p<m. (\<forall>\<omega>'. behavior.dropn p \<omega> = Some \<omega>' \<longrightarrow> behavior.take (i - p) \<omega>' @-\<^sub>B \<beta> \<in> P)))"
by (clarsimp simp: exI[where x=m] behavior.dropn.continue_shorter trace.dropn.behavior.take)
}
}
then have "\<forall>i. \<exists>n\<ge>i. \<exists>m\<le>k. \<exists>\<beta>. (\<forall>\<omega>'. behavior.dropn m \<omega> = Some \<omega>' \<longrightarrow> behavior.take (n - m) \<omega>' @-\<^sub>B \<beta> \<in> Q)
\<and> (\<forall>p<m. \<forall>\<omega>'. behavior.dropn p \<omega> = Some \<omega>' \<longrightarrow> behavior.take (n - p) \<omega>' @-\<^sub>B \<beta> \<in> P)" using * by (metis nle_le)
then obtain m
where "m \<le> k""\<forall>i. \<exists>n\<ge>i. \<exists>\<beta>. (\<forall>\<omega>'. behavior.dropn m \<omega> = Some \<omega>' \<longrightarrow> behavior.take (n - m) \<omega>' @-\<^sub>B \<beta> \<in> Q)
\<and> (\<forall>p<m. \<forall>\<omega>'. behavior.dropn p \<omega> = Some \<omega>' \<longrightarrow> behavior.take (n - p) \<omega>' @-\<^sub>B \<beta> \<in> P)"
by (clarsimp simp: always_eventually_pigeonhole)
with behavior.dropn.shorterD[OF \<open>behavior.dropn k \<omega> = Some \<omega>'\<close> \<open>m \<le> k\<close>]
raw.safety.closed.always_eventually[OF \<open>P \<in> raw.safety.closed\<close>]
raw.safety.closed.always_eventually[OF \<open>Q \<in> raw.safety.closed\<close>]
show "\<omega> \<in> raw.unless P Q"
apply -
apply clarsimp
apply (rule raw.untilI, assumption)
apply (meson add_le_imp_le_diff)
apply (metis add_le_imp_le_diff option.sel behavior.dropn.shorterD[OF _ less_imp_le])
done
qed
qed
lemma from_spec:
shows "raw.from_spec ` trace.stuttering.closed
\<subseteq> (behavior.stuttering.closed :: ('a, 's, 'v) behavior.t set set)"
proof -
have *: "behavior.take i \<omega>\<^sub>2 \<in> P " if"\<omega>\<^sub>1 \<simeq>\<^sub>T \<omega>\<^sub>2"and"\<forall>i. behavior.take i \<omega>\<^sub>1 \<in> P"and"P \<in> trace.stuttering.closed" for \<omega>\<^sub>1 \<omega>\<^sub>2 i and P :: "('a, 's, 'v) trace.t set" using that(2-)
by - (rule behavior.stuttering.equiv.takeE[OF sym[OF \<open>\<omega>\<^sub>1 \<simeq>\<^sub>T \<omega>\<^sub>2\<close>], where i=i];
fastforce intro: trace.stuttering.closed_in)
show ?thesis
by (fastforce simp: raw.from_spec_def elim: behavior.stuttering.clE *)
qed
lemma safety_cl:
assumes "P \<in> behavior.stuttering.closed"
shows "raw.safety.cl P \<in> behavior.stuttering.closed"
unfolding raw.safety.cl_def using assms
by (blast intro: subsetD[OF behavior.stuttering.closed.from_spec]
subsetD[OF trace.stuttering.closed.to_spec])
setup \<open>Sign.parent_path\<close>
setup \<open>Sign.mandatory_path "tls"\<close>
lift_definition to_spec :: "('a, 's, 'v) tls \<Rightarrow> ('a, 's, 'v) spec" is raw.to_spec using raw.spec.closed.to_spec by blast
lift_definition from_spec :: "('a, 's, 'v) spec \<Rightarrow> ('a, 's, 'v) tls" is raw.from_spec
by (meson image_subset_iff behavior.stuttering.closed.from_spec raw.spec.closed.stuttering_closed)
interpretation safety: galois.complete_lattice_class tls.to_spec tls.from_spec
by standard (transfer; simp add: raw.safety.galois)
lemma eventually: \<comment>\<open> all the infinite traces and any finite ones that satisfy \<open>\<diamond>P\<close> \<close>
assumes "P \<noteq> \<bottom>"
shows "tls.safety.cl (\<diamond>P) = -\<diamond>tls.terminated \<squnion> \<diamond>P" using assms by transfer (rule raw.safety.cl.eventually)
lemma terminated_iff:
assumes "\<lblot>\<omega>\<rblot>\<^sub>T \<le> tls.terminated"
shows "\<lblot>\<omega>\<rblot>\<^sub>T \<le> tls.safety.cl P \<longleftrightarrow> \<lblot>\<omega>\<rblot>\<^sub>T \<le> P" (is "?lhs \<longleftrightarrow> ?rhs") using assms
by transfer
(simp add: raw.singleton_def behavior.stuttering.least_conv raw.safety.cl.terminated_iff
behavior.stuttering.closed.safety_cl behavior.stuttering.closed.raw.terminated)
lemma terminated:
shows "tls.safety.cl tls.terminated = tls.idle \<squnion> tls.terminated"
by transfer (simp add: raw.safety.cl.terminated)
lemma not_terminated:
shows "tls.safety.cl (- tls.terminated) = - tls.terminated" (is "?lhs = ?rhs")
proof -
have "?lhs = tls.safety.cl (\<diamond>(- tls.terminated))"
by (simp flip: tls.always.neg tls.terminated.eq_always_terminated)
also have "\<dots> = - \<diamond>tls.terminated \<squnion> \<diamond>(- tls.terminated)"
by (metis tls.safety.cl.eventually tls.terminated.not_top
boolean_algebra.compl_zero boolean_algebra_class.boolean_algebra.double_compl)
also have "\<dots> = ?rhs"
by (simp add: sup.absorb2 tls.eventually.expansive
flip: tls.always.neg tls.terminated.eq_always_terminated)
finally show ?thesis .
qed
lemma le_terminated_conv:
shows "tls.safety.cl P \<le> tls.terminated \<longleftrightarrow> P = \<bottom>" (is "?lhs \<longleftrightarrow> ?rhs")
proof(rule iffI)
show "?lhs \<Longrightarrow> ?rhs"
by transfer (rule raw.safety.cl.le_terminated_bot)
show "?rhs \<Longrightarrow> ?lhs"
by simp
qed
setup \<open>Sign.parent_path\<close>
setup \<open>Sign.mandatory_path "closed"\<close>
lemma transfer[transfer_rule]:
shows "rel_set (pcr_tls (=) (=) (=))
(behavior.stuttering.closed \<inter> raw.safety.closed)
tls.safety.closed" (is "rel_set _ ?lhs ?rhs")
proof(rule rel_setI)
fix X assume "X \<in> ?lhs" then show "\<exists>Y\<in>?rhs. pcr_tls (=) (=) (=) X Y"
by (metis (no_types, opaque_lifting) raw.safety.cl_def raw.safety.closed_conv tls.safety.closed_upper
tls.from_spec.rep_eq TLS_inverse cr_tls_def tls.pcr_cr_eq tls.to_spec.rep_eq Int_iff)
next
fix Y assume "Y \<in> ?rhs" then show "\<exists>X\<in>?lhs. pcr_tls (=) (=) (=) X Y"
by (metis tls.safety.cl_def tls.safety.closed_conv tls.from_spec.rep_eq
tls.pcr_cr_eq cr_tls_def unTLS raw.safety.closed_upper Int_iff)
qed
lemma bot:
shows "\<bottom> \<in> tls.safety.closed"
by (simp add: tls.safety.closed_clI)
definition map :: "('a \<Rightarrow> 'b) \<Rightarrow> ('s \<Rightarrow> 't) \<Rightarrow> ('v \<Rightarrow> 'w) \<Rightarrow> ('a, 's, 'v) tls \<Rightarrow> ('b, 't, 'w) tls" where "map af sf vf P = \<Squnion>(tls.singleton ` behavior.map af sf vf ` {\<sigma>. \<lblot>\<sigma>\<rblot>\<^sub>T \<le> P})"
definition invmap :: "('a \<Rightarrow> 'b) \<Rightarrow> ('s \<Rightarrow> 't) \<Rightarrow> ('v \<Rightarrow> 'w) \<Rightarrow> ('b, 't, 'w) tls \<Rightarrow> ('a, 's, 'v) tls" where "invmap af sf vf P = \<Squnion>(tls.singleton ` behavior.map af sf vf -` {\<sigma>. \<lblot>\<sigma>\<rblot>\<^sub>T \<le> P})"
abbreviation amap ::"('a \<Rightarrow> 'b) \<Rightarrow> ('a, 's, 'v) tls \<Rightarrow> ('b, 's, 'v) tls" where "amap af \<equiv> tls.map af id id"
abbreviation ainvmap ::"('a \<Rightarrow> 'b) \<Rightarrow> ('b, 's, 'v) tls \<Rightarrow> ('a, 's, 'v) tls" where "ainvmap af \<equiv> tls.invmap af id id"
abbreviation smap ::"('s \<Rightarrow> 't) \<Rightarrow> ('a, 's, 'v) tls \<Rightarrow> ('a, 't, 'v) tls" where "smap sf \<equiv> tls.map id sf id"
abbreviation sinvmap ::"('s \<Rightarrow> 't) \<Rightarrow> ('a, 't, 'v) tls \<Rightarrow> ('a, 's, 'v) tls" where "sinvmap sf \<equiv> tls.invmap id sf id"
abbreviation vmap ::"('v \<Rightarrow> 'w) \<Rightarrow> ('a, 's, 'v) tls \<Rightarrow> ('a, 's, 'w) tls" where \<comment>\<open> aka \<open>liftM\<close> \<close> "vmap vf \<equiv> tls.map id id vf"
abbreviation vinvmap ::"('v \<Rightarrow> 'w) \<Rightarrow> ('a, 's, 'w) tls \<Rightarrow> ('a, 's, 'v) tls" where "vinvmap vf \<equiv> tls.invmap id id vf"
interpretation map_invmap: galois.complete_lattice_distributive_class "tls.map af sf vf" "tls.invmap af sf vf"for af sf vf
proof standard
show "tls.map af sf vf P \<le> Q \<longleftrightarrow> P \<le> tls.invmap af sf vf Q" (is "?lhs \<longleftrightarrow> ?rhs") for P Q
proof(rule iffI)
show "?lhs \<Longrightarrow> ?rhs"
by (fastforce simp: tls.map_def tls.invmap_def intro: tls.singleton_le_extI)
show "?rhs \<Longrightarrow> ?lhs"
by (fastforce simp: tls.map_def tls.invmap_def tls.singleton_le_conv
dest: order.trans[of _ P] behavior.stuttering.equiv.map[where af=af and sf=sf and vf=vf]
cong: tls.singleton_cong)
qed
show "tls.invmap af sf vf (\<Squnion>X) \<le> \<Squnion>(tls.invmap af sf vf ` X)"for X
by (fastforce simp: tls.invmap_def)
qed
lemma map_le_conv[tls.singleton.le_conv]:
shows "\<lblot>\<omega>\<rblot>\<^sub>T \<le> tls.map af sf vf P \<longleftrightarrow> (\<exists>\<omega>'. \<lblot>\<omega>'\<rblot>\<^sub>T \<le> P \<and> \<lblot>\<omega>\<rblot>\<^sub>T \<le> \<lblot>behavior.map af sf vf \<omega>'\<rblot>\<^sub>T)"
by (simp add: tls.map_def)
lemma invmap_le_conv[tls.singleton.le_conv]:
shows "\<lblot>\<omega>\<rblot>\<^sub>T \<le> tls.invmap af sf vf P \<longleftrightarrow> \<lblot>behavior.map af sf vf \<omega>\<rblot>\<^sub>T \<le> P"
by (simp add: tls.invmap_def tls.singleton_le_conv)
(metis behavior.natural.map_natural tls.singleton_eq_conv)
lemmas Inf_le = tls.map_invmap.lower_Inf_le \<comment>\<open> Converse does not hold \<close>
lemmas inf_le = tls.map_invmap.lower_inf_le \<comment>\<open> Converse does not hold \<close>
lemma singleton:
shows "tls.map af sf vf \<lblot>\<omega>\<rblot>\<^sub>T = \<lblot>behavior.map af sf vf \<omega>\<rblot>\<^sub>T"
by (auto simp: tls.map_def order.eq_iff tls.singleton_le_conv intro: behavior.stuttering.equiv.map)
lemma id:
shows "tls.map id id id P = P" and"tls.map (\<lambda>x. x) (\<lambda>x. x) (\<lambda>x. x) P = P"
by (simp_all add: tls.map_def flip: id_def)
lemma comp:
shows "tls.map af sf vf \<circ> tls.map ag sg vg = tls.map (af \<circ> ag) (sf \<circ> sg) (vf \<circ> vg)" (is "?lhs = ?rhs") and"tls.map af sf vf (tls.map ag sg vg P) = tls.map (\<lambda>a. af (ag a)) (\<lambda>s. sf (sg s)) (\<lambda>v. vf (vg v)) P" (is ?thesis1)
proof -
have "?lhs P = ?rhs P"for P
by (rule tls.singleton.exhaust[where x=P])
(simp add: tls.map.Sup tls.map.singleton map_prod.comp image_image comp_def)
then show "?lhs = ?rhs"and ?thesis1 by (simp_all add: comp_def)
qed
lemmas map = tls.map.comp
setup \<open>Sign.parent_path\<close>
setup \<open>Sign.mandatory_path "invmap"\<close>
lemmas bot = tls.map_invmap.upper_bot
lemmas top = tls.map_invmap.upper_top
lemma singleton:
shows "tls.invmap af sf vf \<lblot>\<omega>\<rblot>\<^sub>T = \<Squnion>(tls.singleton ` {\<omega>'. \<lblot>behavior.map af sf vf \<omega>'\<rblot>\<^sub>T \<le> \<lblot>\<omega>\<rblot>\<^sub>T})"
by (simp add: tls.invmap_def)
lemma id:
shows "tls.invmap id id id P = P" and"tls.invmap (\<lambda>x. x) (\<lambda>x. x) (\<lambda>x. x) P = P"
unfolding id_def[symmetric] by (metis tls.map.id(1) tls.map_invmap.lower_upper_lower(2))+
lemma comp:
shows "tls.invmap af sf vf (tls.invmap ag sg vg P) = tls.invmap (\<lambda>x. ag (af x)) (\<lambda>s. sg (sf s)) (\<lambda>v. vg (vf v)) P" (is "?lhs P = ?rhs P") and"tls.invmap af sf vf \<circ> tls.invmap ag sg vg = tls.invmap (ag \<circ> af) (sg \<circ> sf) (vg \<circ> vf)" (is ?thesis1)
proof -
show "?lhs P = ?rhs P"for P
by (auto intro: tls.singleton.antisym tls.singleton_le_extI simp: tls.singleton.le_conv)
then show ?thesis1
by (simp add: fun_eq_iff comp_def)
qed
lemma map:
shows "tls.to_spec (tls.map af sf vf P) = spec.map af sf vf (tls.to_spec P)"
by (rule tls.singleton.exhaust[of P])
(simp add: tls.map.Sup tls.map.singleton spec.map.Sup spec.map.singleton image_image
tls.to_spec.singleton tls.to_spec.Sup behavior.take.map)
setup \<open>Sign.parent_path\<close>
setup \<open>Sign.parent_path\<close>
subsection\<open> Abadi's axioms for TLA\label{sec:tls-abadi_axioms} \<close>
text\<open>
The axioms for ``propositional'' TLA due to \<^citet>\<open>"Abadi:1990"\<close> hold in this model.
These are complete for \<^const>\<open>tls.always\<close> and \<^const>\<open>tls.eventually\<close>.
Observations:
\<^item> Abadi says that the temporal system is D aka S4.3Dum; see \<^citet>\<open>\<open>\S8\<close> in "Goldblatt:1992"\<close>
\<^item> the only interesting axiom here is 5: the discrete-time Dummett axiom
\<^item> ``propositional'' means that actions are treated separately; we omit this part as we don't have actions ala TLA
lemma Ax4:
\<comment>\<open> ``a classical way to express that time is linear -- that any two instants in the future are ordered''
\<^citet>\<open>\<open>(254) Lemmon formula\<close> in "WarfordVegaStaley:2020"\<close> \<close>
shows "\<Turnstile> \<box>(\<box>P \<^bold>\<longrightarrow>\<^sub>B Q) \<squnion> \<box>(\<box>Q \<^bold>\<longrightarrow>\<^sub>B P)"
proof -
have "\<Turnstile> (-\<box>P) \<W> \<box>Q \<squnion> (-\<box>Q) \<W> \<box>P" by (rule tls.unless.ordering)
also have "\<dots> \<le> \<box>((-\<box>P) \<W> \<box>Q) \<squnion> \<box>((-\<box>Q) \<W> \<box>P)"
by (metis sup_mono tls.always.idempotent tls.unless.alwaysR_le)
also have "\<dots> \<le> \<box>(-\<box>P \<squnion> Q) \<squnion> \<box>(-\<box>Q \<squnion> P)"
by (strengthen ord_to_strengthen(1)[OF tls.unless.sup_le])
(meson order.refl sup_mono tls.always.contractive tls.always.mono)
also have "\<dots> = \<box>(\<box>P \<^bold>\<longrightarrow>\<^sub>B Q) \<squnion> \<box>(\<box>Q \<^bold>\<longrightarrow>\<^sub>B P)"
by (simp add: boolean_implication.conv_sup)
finally show ?thesis .
qed
lemma Ax5:
\<comment>\<open> ``expresses the discreteness of time''
See also \<^citet>\<open>\<open>\S4.1 ``the Dummett formula''\<close> in "WarfordVegaStaley:2020"\<close>: for them
``next'' encodes discreteness \<close>
fixes P :: "('a, 's, 'v) tls"
shows "\<Turnstile> \<box>(\<box>(P \<^bold>\<longrightarrow>\<^sub>B \<box>P) \<^bold>\<longrightarrow>\<^sub>B P) \<^bold>\<longrightarrow>\<^sub>B \<diamond>\<box>P \<^bold>\<longrightarrow>\<^sub>B P" (is "\<Turnstile> ?goal")
proof -
have raw_Ax5: "raw.always (raw.eventually (P \<inter> raw.eventually (-P)) \<union> P)
\<inter> raw.eventually (raw.always P)
\<subseteq> P" (is "?lhs \<subseteq> ?rhs") for P :: "('a, 's, 'v) behavior.t set"
proof(rule subsetI)
fix \<omega> assume "\<omega> \<in> ?lhs"
from IntD2[OF \<open>\<omega> \<in> ?lhs\<close>]
obtain i
where "\<exists>\<omega>'. behavior.dropn i \<omega> = Some \<omega>' \<and> \<omega>' \<in> raw.always P"
by (force simp: raw.always_alt_def raw.eventually_alt_def)
then obtain i
where i: "\<exists>\<omega>'. behavior.dropn i \<omega> = Some \<omega>' \<and> \<omega>' \<in> raw.always P" and"\<forall>j<i. \<forall>\<omega>'. behavior.dropn j \<omega> = Some \<omega>' \<longrightarrow> \<omega>' \<notin> raw.always P" using ex_has_least_nat[where k=i and P="\<lambda>i. \<exists>\<omega>'. behavior.dropn i \<omega> = Some \<omega>' \<and> \<omega>' \<in> raw.always P"and m=id]
by (auto dest: leD)
have "\<exists>\<omega>'. behavior.dropn (i - j) \<omega> = Some \<omega>' \<and> \<omega>' \<in> raw.always P"for j
proof(induct j) case (Suc j) show ?case
proof(cases "j < i") caseTrue show ?thesis
proof(rule ccontr)
assume "\<nexists>\<omega>'. behavior.dropn (i - Suc j) \<omega> = Some \<omega>' \<and> \<omega>' \<in> raw.always P"
with \<open>\<exists>\<omega>'. behavior.dropn i \<omega> = Some \<omega>' \<and> \<omega>' \<in> raw.always P\<close>
have "\<exists>\<omega>'. behavior.dropn (i - Suc j) \<omega> = Some \<omega>' \<and> \<omega>' \<notin> raw.always P" using behavior.dropn.shorterD[OF _ diff_le_self] by blast
then obtain k where "\<exists>\<omega>'. behavior.dropn (i - Suc j + k) \<omega> = Some \<omega>' \<and> \<omega>' \<notin> P"
by (clarsimp simp: raw.always_alt_def behavior.dropn.add behavior.dropn.Suc) blast
with Suc.hyps \<open>j < i\<close>
have "\<exists>\<omega>'. behavior.dropn (i - Suc j) \<omega> = Some \<omega>' \<and> \<omega>' \<notin> P"
by (fastforce simp: raw.always_alt_def behavior.dropn.add
split: nat_diff_split_asm
dest: spec[where x="k - 1"])
with \<open>j < i\<close> IntD1[OF \<open>\<omega> \<in> ?lhs\<close>]
obtain m n where "\<exists>\<omega>' \<omega>'' \<omega>'''. behavior.dropn (i - Suc j) \<omega> = Some \<omega>' \<and> \<omega>' \<notin> P
\<and> behavior.dropn m \<omega>' = Some \<omega>'' \<and> \<omega>'' \<in> P
\<and> behavior.dropn n \<omega>'' = Some \<omega>''' \<and> \<omega>''' \<notin> P"
by (simp add: raw.always_alt_def raw.eventually_alt_def)
(blast dest: spec[where x="i - Suc j"])
with \<open>j < i\<close> Suc.hyps
show False
by (clarsimp simp: raw.always_alt_def dest!: spec[where x="m + n - 1"] split: nat_diff_split_asm)
(metis behavior.dropn.Suc behavior.dropn.bind_tl_commute behavior.dropn.dropn bind.bind_lunit)
qed
qed (use Suc.hyps in simp)
qed (use i in simp)
from this[of i] show "\<omega> \<in> P"
by (fastforce simp: raw.always_alt_def dest: spec[where x=0])
qed
show ?thesis
proof(rule tls.validI)
have "\<box>(\<diamond>(P \<sqinter> \<diamond>(- P)) \<squnion> P) \<sqinter> \<diamond>\<box>P \<le> P"
by (rule raw_Ax5[transferred])
then have "\<box>(\<diamond>(P \<sqinter> \<diamond>(- P)) \<squnion> P) \<sqinter> \<diamond>\<box>P \<le> P"
by (simp add: boolean_implication.conv_sup tls.always.neg)
then show "\<top> \<le> ?goal"
by - (intro iffD1[OF boolean_implication.shunt1];
simp add: boolean_implication.conv_sup tls.always.neg)
qed
qed
bundle extra_syntax
begin
notation tls.singleton (\<open>\<lblot>_\<rblot>\<^sub>T\<close> [0])
notation tls.from_spec (\<open>\<lparr>_\<rparr>\<close> [0])
end
setup \<open>Sign.parent_path\<close>
(*<*)
end
(*>*)
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.143Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.