(*<*) theory LTL imports
CIMP_pred
Infinite_Sequences begin
(*>*) section‹ Linear Temporal Logic \label{sec:ltl}›
text‹
talk about liveness we need to consider infinitary behaviour on
. Traditionally future-time linear temporal logic (LTL) is used to do cite‹"MannaPnueli:1991" and "OwickiLamport:1982"›.
following is a straightforward shallow embedding of the
-traditional anchored semantics of LTL cite‹"MannaPnueli:1988"›. Some of it is adapted
the sophisticated TLA development in the AFP due to 🍋‹"TLA-AFP"›.
🍋‹"Lamport:2002"›, include the
operator, which is convenient for stating rules. Sometimes it allows us to
the system, i.e. to state rules as temporally valid
LTL-valid) rather than just temporally program valid (LTL-cimp-), in Jackson's terminology.
›
definition state_prop :: "('a ==> bool) ==> 'a seq_pred" (‹⌈_⌉›) where "⌈P⌉ = (λσ. P (σ 0))"
definition"next" :: "'a seq_pred ==> 'a seq_pred" (‹◯_› [80] 80) where "(◯P) = (λσ. P (σ |s 1))"
definition always :: "'a seq_pred ==> 'a seq_pred" (‹◻_› [80] 80) where "(◻P) = (λσ. ∀i. P (σ |s i))"
definition until :: "'a seq_pred ==> 'a seq_pred ==> 'a seq_pred" (infixr‹U›30) where(* FIXME priority, binds tighter than \<^bold>\<longrightarrow> *) "(P U Q) = (λσ. ∃i. Q (σ |s i) ∧ (∀k<i. P (σ |s k)))"
definition eventually :: "'a seq_pred ==> 'a seq_pred" (‹♢_› [80] 80) where(* FIXME priority, consider making an abbreviation *) "(♢P) = (⟨True⟩U P)"
definition release :: "'a seq_pred ==> 'a seq_pred ==> 'a seq_pred" (infixr‹R›30) where(* FIXME priority, dual of Until *) "(P R Q) = (\<not>(\<not>P U\<not>Q))"
definition unless :: "'a seq_pred ==> 'a seq_pred ==> 'a seq_pred" (infixr‹W›30) where(* FIXME priority, aka weak until *) "(P W Q) = ((P U Q) \<or> ◻P)"
abbreviation (input)
pred_always_imp_syn :: "'a seq_pred ==> 'a seq_pred ==> 'a seq_pred" (infixr‹\↪›25) where "P \<hookrightarrow> Q ≡◻(P \<longrightarrow> Q)"
lemma necessitation: "(∧s. P s) ==> (◻P) σ" "(∧s. P s) ==> (♢P) σ" "(∧s. P s) ==> (P W Q) σ" "(∧s. Q s) ==> (P U Q) σ" unfoldingdefsby auto
lemma cong: "(∧s. P s = P' s) ==>⌈P⌉ = ⌈P'⌉" "(∧σ. P σ = P' σ) ==> (◻P) = (◻P')" "(∧σ. P σ = P' σ) ==> (♢P) = (♢P')" "(∧σ. P σ = P' σ) ==> (◯P) = (◯P')" "[∧σ. P σ = P' σ; ∧σ. Q σ = Q' σ]==> (P U Q) = (P' U Q')" "[∧σ. P σ = P' σ; ∧σ. Q σ = Q' σ]==> (P W Q) = (P' W Q')" unfoldingdefsby auto
lemma until_imp_eventually: "((P U Q) \<longrightarrow> ♢Q) σ" unfoldingdefsby auto
lemma until_until_disj: assumes"(P U Q U R) σ" shows"((P \<or> Q) U R) σ" using assms unfoldingdefs apply clarsimp apply (metis (full_types) add_diff_inverse_nat nat_add_left_cancel_less) done
lemma unless_unless_disj: assumes"(P W Q W R) σ" shows"((P \<or> Q) W R) σ" using assms unfoldingdefs apply auto apply (metis add.commute add_diff_inverse_nat leI less_diff_conv2) apply (metis add_diff_inverse_nat) done
lemma until_conj_distrib: "((P \<and> Q) U R) = ((P U R) \<and> (Q U R))" unfoldingdefs apply (auto simp: fun_eq_iff) apply (metis dual_order.strict_trans nat_neq_iff) done
lemma until_disj_distrib: "(P U (Q \<or> R)) = ((P U Q) \<or> (P U R))" unfoldingdefsby (auto simp: fun_eq_iff)
lemma leads_to_leads_to_viaE: shows"((P \<hookrightarrow> P U Q) \<longrightarrow> P \<leadsto> Q) σ" unfoldingdefsby clarsimp blast
lemma leads_to_via_concl_weaken: assumes"(R \<hookrightarrow> R') σ" assumes"(P \<hookrightarrow> Q U R) σ" shows"(P \<hookrightarrow> Q U R') σ" using assms unfolding LTL.defsby force
lemma leads_to_via_trans: assumes"(A \<hookrightarrow> B U C) σ" assumes"(C \<hookrightarrow> D U E) σ" shows"(A \<hookrightarrow> (B \<or> D) U E) σ" proof(rule alwaysI, rule impI) fix i assume"A (σ |s i)"with assms show"((B \<or> D) U E) (σ |s i)" apply - apply (erule alwaysE[where i=i]) apply clarsimp apply (erule untilE) apply clarsimp (* suffix *) apply (drule (1) always_imp_mp_suffix) apply (erule untilE) apply clarsimp (* suffix *) apply (rule_tac i="ia + iaa"in untilI; simp add: ac_simps) apply (metis (full_types) add.assoc leI le_Suc_ex nat_add_left_cancel_less) (* arithmetic *) done qed
lemma leads_to_via_disj: ― ‹ useful for case distinctions › assumes"(P \<hookrightarrow> Q U R) σ" assumes"(P' \<hookrightarrow> Q' U R) σ" shows"(P \<or> P' \<hookrightarrow> (Q \<or> Q') U R) σ" using assms unfoldingdefsby (auto 100)
lemma leads_to_via_disj': ― ‹ more like a chaining rule › assumes"(A \<hookrightarrow> B U C) σ" assumes"(C \<hookrightarrow> D U E) σ" shows"(A \<or> C \<hookrightarrow> (B \<or> D) U E) σ" proof(rule alwaysI, rule impI, erule disjE) fix i assume"A (σ |s i)"with assms show"((B \<or> D) U E) (σ |s i)" apply - apply (erule alwaysE[where i=i]) apply clarsimp apply (erule untilE) apply clarsimp (* suffix *) apply (drule (1) always_imp_mp_suffix) apply (erule untilE) apply clarsimp (* suffix *) apply (rule_tac i="ia + iaa"in untilI; simp add: ac_simps) apply (metis (full_types) add.assoc leI le_Suc_ex nat_add_left_cancel_less) (* arithmetic *) done next fix i assume"C (σ |s i)"with assms(2) show"((B \<or> D) U E) (σ |s i)" apply - apply (erule alwaysE[where i=i]) apply (simp add: mono) done qed
lemma leads_to_via_stable_augmentation: assumes stable: "(P \<and> Q \<hookrightarrow> ◯Q) σ" assumes U: "(A \<hookrightarrow> P U C) σ" shows"((A \<and> Q) \<hookrightarrow> P U (C \<and> Q)) σ" proof(intro alwaysI impI, elim conjE) fix i assume AP: "A (σ |s i)""Q (σ |s i)" have"Q (σ |s (j + i))"if"Q (σ |s i)"and"∀k<j. P (σ |s (k + i))"for j using that stable by (induct j; force simp: defs) with U AP show"(P U (λσ. C σ ∧ Q σ)) (σ |s i)" unfoldingdefsby clarsimp (metis (full_types) add.commute) qed
lemma leads_to_via_wf: assumes"wf R" assumes indhyp: "∧t. (A \<and> ⌈δ =⟨t⟩⌉\<hookrightarrow> B U (A \<and> ⌈δ \<otimes> ⟨t⟩\<in> ⟨R⟩⌉\<or> C)) σ" shows"(A \<hookrightarrow> B U C) σ" proof(intro alwaysI impI) fix i assume"A (σ |s i)"with‹wf R›show"(B U C) (σ |s i)" proof(induct "δ (σ i)" arbitrary: i) case (less i) with indhyp[where t="δ (σ i)"] show ?case apply - apply (drule alwaysD[where i=i]) apply clarsimp apply (erule untilE) apply (rename_tac j) apply (erule disjE; clarsimp) apply (drule_tac x="i + j"in meta_spec; clarsimp) apply (erule untilE; clarsimp) apply (rename_tac j k) apply (rule_tac i="j + k"in untilI) apply (simp add: add.assoc) apply clarsimp apply (metis add.assoc add.commute add_diff_inverse_nat less_diff_conv2 not_le) apply auto done qed qed
text‹
well-founded response rule due to 🍋‹‹Fig~1.23: \texttt{WELL} (well-founded response)› in"MannaPnueli:2010"›,
to an arbitrary set of assertions and sequence predicates.
▪ ‹W1› generalised to be contingent.
▪ ‹W2› is a well-founded set of assertions that by ‹W1› includes ‹P›
›
(* FIXME: Does \<open>Is\<close> need to be consistent? *) lemma leads_to_wf: fixesIs :: "('a seq_pred × ('a ==> 'b)) set" assumes"wf (R :: 'b rel)" assumes W1: "(◻(\<exists>φ. ⌈⟨φ∈fst ` Is⟩⌉\<and> (P \<longrightarrow> φ))) σ" assumes W2: "∀(φ, δ)∈Is. ∃(φ', δ')∈insert (Q, δ0) Is. ∀t. (φ \<and> ⌈δ =⟨t⟩⌉\<leadsto> φ' \<and> ⌈δ' \<otimes> ⟨t⟩\<in> ⟨R⟩⌉) σ" shows"(P \<leadsto> Q) σ" proof - have"(φ \<and> ⌈δ =⟨t⟩⌉\<leadsto> Q) σ"if"(φ, δ) ∈ Is"for φ δ t using‹wf R› that W2 apply (induct t arbitrary: φ δ) unfolding LTL.defs split_def apply clarsimp apply (metis (no_types, opaque_lifting) ab_semigroup_add_class.add_ac(1) fst_eqD snd_conv surjective_pairing) done with W1 show ?thesis apply - apply (rule alwaysI) apply clarsimp apply (erule_tac i=i in alwaysE) apply clarsimp using alwaysD suffix_state_prop apply blast done qed
subsection‹Fairness›
text‹
few renderings of weak fairness. 🍋‹"vanGlabbeekHofner:2019"› call this
response to insistence" as a generalisation of weak fairness.
›
definition weakly_fair :: "'a seq_pred ==> 'a seq_pred ==> 'a seq_pred"where "weakly_fair enabled taken = (◻enabled \<hookrightarrow> ♢taken)"
lemma weakly_fair_def2: shows"weakly_fair enabled taken = ◻(\<not>◻(enabled \<and> \<not>taken))" unfolding weakly_fair_def by (metis (full_types) always_conj_distrib norm(18))
unfoldingdefs(* True, but can we get there deductively? *) apply auto apply (metis (full_types) add.left_commute semiring_normalization_rules(25)) done
lemma weakly_fair_def4: shows"weakly_fair enabled taken = ◻♢(enabled \<longrightarrow> taken)" using weakly_fair_def2 by force
lemma mp_weakly_fair: assumes"weakly_fair enabled taken σ" assumes"(◻enabled) σ" shows"(♢taken) σ" using assms unfolding weakly_fair_def using always_imp_mp by blast
lemma strongly_fair_imp_weakly_fair: assumes"strongly_fair enabled taken σ" shows"weakly_fair enabled taken σ" using assms unfolding strongly_fair_def3 weakly_fair_def3 by (simp add: eventually_always_imp_always_eventually)
lemma always_enabled_weakly_fair_strongly_fair: assumes"(◻enabled) σ" shows"weakly_fair enabled taken σ = strongly_fair enabled taken σ" using assms by (metis strongly_fair_def3 strongly_fair_imp_weakly_fair unfold(2) weakly_fair_def3)
subsection‹Safety and liveness \label{sec:ltl-safety-liveness}›
text‹
🍋‹"Sistla:1994"› shows some characterisations
LTL formulas in terms of safety and liveness. Note his @{term
(U)"} is actually @{term "(W)"}.
lemma safety_unless: assumes"safety P" assumes"safety Q" shows"safety (P W Q)" proof(rule safetyI2) fix σ assume X: "∃β. (P W Q) (stake i σ @- β)"for i thenshow"(P W Q) σ" proof(cases "∀i j. ∃β. P (σ(i → j) @- β)") case True with‹safety P›have"∀i. P (σ |s i)"unfolding safety_def2 by blast thenshow ?thesis by (blast intro: unless_alwaysI) next case False thenobtain k k' where"∀β. ¬ P (σ(k → k') @- β)"by clarsimp thenhave"∀i u. k + k' ≤ i ⟶¬P ((stake i σ @- u) |s k)" by (metis add.commute diff_add stake_shift_stake_shift stake_suffix_drop suffix_shift) thenhave"∀i u. k + k' ≤ i ∧ (P W Q) (stake i σ @- u) ⟶ (∃m≤k. Q ((stake i σ @- u) |s m) ∧ (∀p<m. P ((stake i σ @- u) |s p)))" unfoldingdefsusing leI by blast thenhave"∀i u. k + k' ≤ i ∧ (P W Q) (stake i σ @- u) ⟶ (∃m≤k. Q (σ(m → i - m) @- u)∧ (∀p<m. P (σ(p → i - p) @- u)))" by (metis stake_suffix add_leE nat_less_le order_trans) thenhave"∀i. ∃n≥i. ∃m≤k. ∃u. Q (σ(m → n - m) @- u) ∧ (∀p<m. P (σ(p → n - p) @- u))" using X by (metis add.commute le_add1) thenhave"∃m≤k. ∀i. ∃n≥i. ∃u. Q (σ(m → n - m) @- u) ∧ (∀p<m. P (σ(p → n - p) @- u))" by (simp add: always_eventually_pigeonhole) with‹safety P›‹safety Q›show"(P W Q) σ" unfoldingdefsby (metis Nat.le_diff_conv2 add_leE safety_always_eventually) qed qed
lemma safety_always: assumes"safety P" shows"safety (◻P)" using assms by (metis norm(20) safety_def safety_unless)
lemma absolute_liveness_eventually: shows"absolute_liveness P ⟷ (∃σ. P σ) ∧ P = ♢P" unfolding absolute_liveness_def defs by (metis cancel_comm_monoid_add_class.diff_cancel drop_eq_Nil order_refl shift.simps(1) stake_suffix_id suffix_shift suffix_zero)
lemma stable_always: shows"stable P ⟷ (∃σ. P σ) ∧ P = ◻P" unfolding stable_def defsby (metis suffix_zero)
(* FIXME Sistla's examples of stable properties are boring and follow directly from this lemma.
FIXME the fairness "type of formulas" follow from the above and the fairness def. *)
text‹
show that @{const ‹weakly_fair›} is a @{const ‹fairness›} property requires some constraints on ‹enabled› and ‹taken›:
▪ it is reasonable to assume they are state formulas
▪ ‹taken› must be satisfiable
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.