diff --git a/thys/LTL_Master_Theorem/Code_Export.thy b/thys/LTL_Master_Theorem/Code_Export.thy --- a/thys/LTL_Master_Theorem/Code_Export.thy +++ b/thys/LTL_Master_Theorem/Code_Export.thy @@ -1,68 +1,78 @@ (* Author: Benedikt Seidl License: BSD *) section \Code export to Standard ML\ theory Code_Export imports - "LTL_to_DRA/DRA_Implementation" + "LTL_to_DRA/DRA_Instantiation" LTL.Code_Equations "HOL-Library.Code_Target_Numeral" begin subsection \Hashing Sets\ global_interpretation comp_fun_commute "plus o cube o hashcode :: ('a :: hashable) \ hashcode \ hashcode" by unfold_locales (auto simp: cube_def) lemma [code]: "hashcode (set xs) = fold (plus o cube o hashcode) (remdups xs) (uint32_of_nat (length (remdups xs)))" by (simp add: fold_set_fold_remdups length_remdups_card_conv) lemma [code]: "hashcode (abs_ltln\<^sub>P \) = hashcode (min_dnf \)" by simp +lemma min_dnf_rep_abs[simp]: + "min_dnf (Unf (rep_ltln\<^sub>Q (abs_ltln\<^sub>Q \))) = min_dnf (Unf \)" + using Quotient3_ltln\<^sub>Q ltl_prop_equiv_min_dnf ltl_prop_unfold_equiv_def rep_abs_rsp by fastforce + +lemma [code]: + "hashcode (abs_ltln\<^sub>Q \) = hashcode (min_dnf (Unf \))" + by simp + subsection \LTL to DRA\ -export_code ltlc_to_draei checking +declare ltl_to_dra\<^sub>P.af_letter\<^sub>F_lifted_semantics [code] +declare ltl_to_dra\<^sub>P.af_letter\<^sub>G_lifted_semantics [code] +declare ltl_to_dra\<^sub>P.af_letter\<^sub>\_lifted_semantics [code] -declare ltl_to_dra.af_letter\<^sub>F_lifted_semantics [code] -declare ltl_to_dra.af_letter\<^sub>G_lifted_semantics [code] -declare ltl_to_dra.af_letter\<^sub>\_lifted_semantics [code] +declare ltl_to_dra\<^sub>Q.af_letter\<^sub>F_lifted_semantics [code] +declare ltl_to_dra\<^sub>Q.af_letter\<^sub>G_lifted_semantics [code] +declare ltl_to_dra\<^sub>Q.af_letter\<^sub>\_lifted_semantics [code] definition atoms_ltlc_list_literals :: "String.literal ltlc \ String.literal list" where "atoms_ltlc_list_literals = atoms_ltlc_list" -definition ltlc_to_draei_literals :: "String.literal ltlc \ (String.literal set, nat) draei" +definition ltlc_to_draei_literals :: "equiv \ String.literal ltlc \ (String.literal set, nat) draei" where "ltlc_to_draei_literals = ltlc_to_draei" definition sort_transitions :: "(nat \ String.literal set \ nat) list \ (nat \ String.literal set \ nat) list" where "sort_transitions = sort_key fst" -export_code True_ltlc Iff_ltlc ltlc_to_draei_literals +export_code True_ltlc Iff_ltlc ltlc_to_draei_literals Prop PropUnfold alphabetei initialei transitionei conditionei integer_of_nat atoms_ltlc_list_literals sort_transitions set in SML module_name LTL file_prefix LTL_to_DRA subsection \LTL to NBA\ (* TODO *) subsection \LTL to LDBA\ (* TODO *) end diff --git a/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Construction.thy b/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Construction.thy --- a/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Construction.thy +++ b/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Construction.thy @@ -1,436 +1,906 @@ (* Author: Benedikt Seidl License: BSD *) section \Constructing DRAs for LTL Formulas\ theory DRA_Construction imports Transition_Functions "../Quotient_Type" "../Omega_Words_Fun_Stream" + "HOL-Library.Log_Nat" + "../Logical_Characterization/Master_Theorem" + "../Logical_Characterization/Restricted_Master_Theorem" Transition_Systems_and_Automata.DBA_Combine Transition_Systems_and_Automata.DCA_Combine Transition_Systems_and_Automata.DRA_Combine begin \ \We use prefix and suffix on infinite words.\ hide_const Sublist.prefix Sublist.suffix -locale dra_construction = transition_functions eq + quotient eq Rep Abs +locale dra_construction = transition_functions eq normalise + quotient eq Rep Abs for eq :: "'a ltln \ 'a ltln \ bool" (infix "\" 75) and + normalise :: "'a ltln \ 'a ltln" + and Rep :: "'ltlq \ 'a ltln" and Abs :: "'a ltln \ 'ltlq" begin subsection \Lifting Setup\ abbreviation true\<^sub>n_lifted :: "'ltlq" ("\true\<^sub>n") where "\true\<^sub>n \ Abs true\<^sub>n" abbreviation false\<^sub>n_lifted :: "'ltlq" ("\false\<^sub>n") where "\false\<^sub>n \ Abs false\<^sub>n" abbreviation af_letter_lifted :: "'a set \ 'ltlq \ 'ltlq" ("\afletter") where "\afletter \ \ \ Abs (af_letter (Rep \) \)" abbreviation af_lifted :: "'ltlq \ 'a set list \ 'ltlq" ("\af") where "\af \ w \ fold \afletter w \" abbreviation GF_advice_lifted :: "'ltlq \ 'a ltln set \ 'ltlq" ("_\[_]\<^sub>\" [90,60] 89) where "\\[X]\<^sub>\ \ Abs ((Rep \)[X]\<^sub>\)" lemma af_letter_lifted_semantics: "\afletter \ (Abs \) = Abs (af_letter \ \)" by (metis Rep_Abs_eq af_letter_congruent Abs_eq) lemma af_lifted_semantics: "\af (Abs \) w = Abs (af \ w)" by (induction w rule: rev_induct) (auto simp: Abs_eq, insert Rep_Abs_eq af_letter_congruent eq_sym, blast) lemma af_lifted_range: "range (\af (Abs \)) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" using af_lifted_semantics af_nested_prop_atoms by blast definition af_letter\<^sub>F_lifted :: "'a ltln \ 'a set \ 'ltlq \ 'ltlq" ("\afletter\<^sub>F") where "\afletter\<^sub>F \ \ \ \ Abs (af_letter\<^sub>F \ (Rep \) \)" definition af_letter\<^sub>G_lifted :: "'a ltln \ 'a set \ 'ltlq \ 'ltlq" ("\afletter\<^sub>G") where "\afletter\<^sub>G \ \ \ \ Abs (af_letter\<^sub>G \ (Rep \) \)" lemma af_letter\<^sub>F_lifted_semantics: "\afletter\<^sub>F \ \ (Abs \) = Abs (af_letter\<^sub>F \ \ \)" by (metis af_letter\<^sub>F_lifted_def Rep_inverse af_letter\<^sub>F_def af_letter_congruent Abs_eq) lemma af_letter\<^sub>G_lifted_semantics: "\afletter\<^sub>G \ \ (Abs \) = Abs (af_letter\<^sub>G \ \ \)" by (metis af_letter\<^sub>G_lifted_def Rep_inverse af_letter\<^sub>G_def af_letter_congruent Abs_eq) abbreviation af\<^sub>F_lifted :: "'a ltln \ 'ltlq \ 'a set list \ 'ltlq" ("\af\<^sub>F") where "\af\<^sub>F \ \ w \ fold (\afletter\<^sub>F \) w \" abbreviation af\<^sub>G_lifted :: "'a ltln \ 'ltlq \ 'a set list \ 'ltlq" ("\af\<^sub>G") where "\af\<^sub>G \ \ w \ fold (\afletter\<^sub>G \) w \" lemma af\<^sub>F_lifted_semantics: "\af\<^sub>F \ (Abs \) w = Abs (af\<^sub>F \ \ w)" by (induction w rule: rev_induct) (auto simp: af_letter\<^sub>F_lifted_semantics) lemma af\<^sub>G_lifted_semantics: "\af\<^sub>G \ (Abs \) w = Abs (af\<^sub>G \ \ w)" by (induction w rule: rev_induct) (auto simp: af_letter\<^sub>G_lifted_semantics) -lemma af\<^sub>F_lifted_range: - "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ range (\af\<^sub>F \ (Abs \)) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" - using af\<^sub>F_lifted_semantics af\<^sub>F_nested_prop_atoms by blast - -lemma af\<^sub>G_lifted_range: - "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ range (\af\<^sub>G \ (Abs \)) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" - using af\<^sub>G_lifted_semantics af\<^sub>G_nested_prop_atoms by blast - definition af_letter\<^sub>\_lifted :: "'a ltln set \ 'a set \ 'ltlq \ 'ltlq \ 'ltlq \ 'ltlq" ("\afletter\<^sub>\") where "\afletter\<^sub>\ X \ p \ (Abs (fst (af_letter\<^sub>\ X (Rep (fst p), Rep (snd p)) \)), Abs (snd (af_letter\<^sub>\ X (Rep (fst p), Rep (snd p)) \)))" abbreviation af\<^sub>\_lifted :: "'a ltln set \ 'ltlq \ 'ltlq \ 'a set list \ 'ltlq \ 'ltlq" ("\af\<^sub>\") where "\af\<^sub>\ X p w \ fold (\afletter\<^sub>\ X) w p" lemma af_letter\<^sub>\_lifted_semantics: "\afletter\<^sub>\ X \ (Abs x, Abs y) = (Abs (fst (af_letter\<^sub>\ X (x, y) \)), Abs (snd (af_letter\<^sub>\ X (x, y) \)))" by (simp add: af_letter\<^sub>\_def af_letter\<^sub>\_lifted_def) (insert GF_advice_congruent Rep_Abs_eq Rep_inverse af_letter_lifted_semantics eq_trans Abs_eq, blast) lemma af\<^sub>\_lifted_semantics: "\af\<^sub>\ X (Abs \, Abs \) w = (Abs (fst (af\<^sub>\ X (\, \) w)), Abs (snd (af\<^sub>\ X (\, \) w)))" apply (induction w rule: rev_induct) apply (auto simp: af_letter\<^sub>\_lifted_def af_letter\<^sub>\_lifted_semantics af_letter_lifted_semantics) by (metis (no_types, hide_lams) af_letter\<^sub>\_lifted_def af\<^sub>\_fst af_letter\<^sub>\_lifted_semantics eq_fst_iff prod.sel(2)) subsection \Büchi automata for basic languages\ definition \\<^sub>\ :: "'a ltln \ ('a set, 'ltlq) dba" where "\\<^sub>\ \ = dba UNIV (Abs \) \afletter (\\. \ = \true\<^sub>n)" definition \\<^sub>\_GF :: "'a ltln \ ('a set, 'ltlq) dba" where "\\<^sub>\_GF \ = dba UNIV (Abs (F\<^sub>n \)) (\afletter\<^sub>F \) (\\. \ = \true\<^sub>n)" definition \\<^sub>\ :: "'a ltln \ ('a set, 'ltlq) dca" where "\\<^sub>\ \ = dca UNIV (Abs \) \afletter (\\. \ = \false\<^sub>n)" definition \\<^sub>\_FG :: "'a ltln \ ('a set, 'ltlq) dca" where "\\<^sub>\_FG \ = dca UNIV (Abs (G\<^sub>n \)) (\afletter\<^sub>G \) (\\. \ = \false\<^sub>n)" lemma dba_run: "DBA.run (dba UNIV p \ \) (to_stream w) p" unfolding dba.run_alt_def by simp lemma dca_run: "DCA.run (dca UNIV p \ \) (to_stream w) p" unfolding dca.run_alt_def by simp lemma \\<^sub>\_language: "\ \ \LTL \ to_stream w \ DBA.language (\\<^sub>\ \) \ w \\<^sub>n \" proof - assume "\ \ \LTL" then have "w \\<^sub>n \ \ (\n. \k\n. af \ (w[0 \ k]) \ true\<^sub>n)" by (meson af_\LTL af_prefix_true le_cases) also have "\ \ (\n. \k\n. af \ (w[0 \ Suc k]) \ true\<^sub>n)" by (meson af_prefix_true le_SucI order_refl) also have "\ \ infs (\\. \ = \true\<^sub>n) (DBA.trace (\\<^sub>\ \) (to_stream w) (Abs \))" by (simp add: infs_snth \\<^sub>\_def DBA.transition_def af_lifted_semantics Abs_eq[symmetric] af_letter_lifted_semantics) also have "\ \ to_stream w \ DBA.language (\\<^sub>\ \)" unfolding \\<^sub>\_def dba.initial_def dba.accepting_def by (auto simp: dba_run) finally show ?thesis by simp qed lemma \\<^sub>\_GF_language: "\ \ \LTL \ to_stream w \ DBA.language (\\<^sub>\_GF \) \ w \\<^sub>n G\<^sub>n (F\<^sub>n \)" proof - assume "\ \ \LTL" then have "w \\<^sub>n G\<^sub>n (F\<^sub>n \) \ (\n. \k. af (F\<^sub>n \) (w[n \ k]) \\<^sub>L true\<^sub>n)" using ltl_lang_equivalence.af_\LTL_GF by blast also have "\ \ (\n. \k>n. af\<^sub>F \ (F\<^sub>n \) (w[0 \ k]) \ true\<^sub>n)" using af\<^sub>F_semantics_ltr af\<^sub>F_semantics_rtl using \\ \ \LTL\ af_\LTL_GF calculation by blast also have "\ \ (\n. \k\n. af\<^sub>F \ (F\<^sub>n \) (w[0 \ Suc k]) \ true\<^sub>n)" by (metis less_Suc_eq_le less_imp_Suc_add) also have "\ \ infs (\\. \ = \true\<^sub>n) (DBA.trace (\\<^sub>\_GF \) (to_stream w) (Abs (F\<^sub>n \)))" by (simp add: infs_snth \\<^sub>\_GF_def DBA.transition_def af\<^sub>F_lifted_semantics Abs_eq[symmetric] af_letter\<^sub>F_lifted_semantics) also have "\ \ to_stream w \ DBA.language (\\<^sub>\_GF \)" unfolding \\<^sub>\_GF_def dba.initial_def dba.accepting_def by (auto simp: dba_run) finally show ?thesis by simp qed lemma \\<^sub>\_language: "\ \ \LTL \ to_stream w \ DCA.language (\\<^sub>\ \) \ w \\<^sub>n \" proof - assume "\ \ \LTL" then have "w \\<^sub>n \ \ (\n. \k\n. \ af \ (w[0 \ k]) \ false\<^sub>n)" by (meson af_\LTL af_prefix_false le_cases order_refl) also have "\ \ (\n. \k\n. \ af \ (w[0 \ Suc k]) \ false\<^sub>n)" by (meson af_prefix_false le_SucI order_refl) also have "\ \ fins (\\. \ = \false\<^sub>n) (DCA.trace (\\<^sub>\ \) (to_stream w) (Abs \))" by (simp add: infs_snth \\<^sub>\_def DBA.transition_def af_lifted_semantics Abs_eq[symmetric] af_letter_lifted_semantics) also have "\ \ to_stream w \ DCA.language (\\<^sub>\ \)" unfolding \\<^sub>\_def dca.initial_def dca.rejecting_def by (auto simp: dca_run) finally show ?thesis by simp qed lemma \\<^sub>\_FG_language: "\ \ \LTL \ to_stream w \ DCA.language (\\<^sub>\_FG \) \ w \\<^sub>n F\<^sub>n (G\<^sub>n \)" proof - assume "\ \ \LTL" then have "w \\<^sub>n F\<^sub>n (G\<^sub>n \) \ (\k. \j. \ af (G\<^sub>n \) (w[k \ j]) \\<^sub>L false\<^sub>n)" using ltl_lang_equivalence.af_\LTL_FG by blast also have "\ \ (\n. \k>n. \ af\<^sub>G \ (G\<^sub>n \) (w[0 \ k]) \ false\<^sub>n)" using af\<^sub>G_semantics_ltr af\<^sub>G_semantics_rtl using \\ \ \LTL\ af_\LTL_FG calculation by blast also have "\ \ (\n. \k\n. \ af\<^sub>G \ (G\<^sub>n \) (w[0 \ Suc k]) \ false\<^sub>n)" by (metis less_Suc_eq_le less_imp_Suc_add) also have "\ \ fins (\\. \ = \false\<^sub>n) (DCA.trace (\\<^sub>\_FG \) (to_stream w) (Abs (G\<^sub>n \)))" by (simp add: infs_snth \\<^sub>\_FG_def DBA.transition_def af\<^sub>G_lifted_semantics Abs_eq[symmetric] af_letter\<^sub>G_lifted_semantics) also have "\ \ to_stream w \ DCA.language (\\<^sub>\_FG \)" unfolding \\<^sub>\_FG_def dca.initial_def dca.rejecting_def by (auto simp: dca_run) finally show ?thesis by simp qed -lemma \\<^sub>\_nodes: - "DBA.nodes (\\<^sub>\ \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" - unfolding \\<^sub>\_def - using af_lifted_semantics af_nested_prop_atoms by fastforce - -lemma \\<^sub>\_GF_nodes: - "DBA.nodes (\\<^sub>\_GF \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" - unfolding \\<^sub>\_GF_def dba.nodes_alt_def dba.reachable_alt_def - using af\<^sub>F_nested_prop_atoms[of "F\<^sub>n \"] by (auto simp: af\<^sub>F_lifted_semantics) - -lemma \\<^sub>\_nodes: - "DCA.nodes (\\<^sub>\ \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" - unfolding \\<^sub>\_def - using af_lifted_semantics af_nested_prop_atoms by fastforce - -lemma \\<^sub>\_FG_nodes: - "DCA.nodes (\\<^sub>\_FG \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" - unfolding \\<^sub>\_FG_def dca.nodes_alt_def dca.reachable_alt_def - using af\<^sub>G_nested_prop_atoms[of "G\<^sub>n \"] by (auto simp: af\<^sub>G_lifted_semantics) - - - subsection \A DCA checking the GF-advice Function\ definition \ :: "'a ltln \ 'a ltln set \ ('a set, 'ltlq \ 'ltlq) dca" where - "\ \ X = dca UNIV (Abs \, Abs (\[X]\<^sub>\)) (\afletter\<^sub>\ X) (\p. snd p = \false\<^sub>n)" + "\ \ X = dca UNIV (Abs \, Abs ((normalise \)[X]\<^sub>\)) (\afletter\<^sub>\ X) (\p. snd p = \false\<^sub>n)" lemma \_language: "to_stream w \ DCA.language (\ \ X) \ (\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\)" proof - have "(\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\) - \ (\m. \k\m. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n)" + \ (\m. \k\m. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n)" using af\<^sub>\_semantics_ltr af\<^sub>\_semantics_rtl by blast - also have "\ \ fins (\p. snd p = \false\<^sub>n) (DCA.trace (\ \ X) (to_stream w) (Abs \, Abs (\[X]\<^sub>\)))" + also have "\ \ fins (\p. snd p = \false\<^sub>n) (DCA.trace (\ \ X) (to_stream w) (Abs \, Abs ((normalise \)[X]\<^sub>\)))" by(simp add: infs_snth \_def DCA.transition_def af\<^sub>\_lifted_semantics af_letter\<^sub>\_lifted_semantics Abs_eq) also have "\ \ to_stream w \ DCA.language (\ \ X)" by (simp add: \_def dca.initial_def dca.rejecting_def dca.language_def dca_run) finally show ?thesis by blast qed -lemma \_nodes: - "DCA.nodes (\ \ X) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \} \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X}" - unfolding \_def dca.nodes_alt_def dca.reachable_alt_def - apply (auto simp add: af\<^sub>\_lifted_semantics af_letter\<^sub>\_lifted_semantics) - using af\<^sub>\_fst_nested_prop_atoms apply force - using GF_advice_nested_prop_atoms\<^sub>\ af\<^sub>\_snd_nested_prop_atoms dra_construction_axioms by fastforce - - - subsection \A DRA for each combination of sets X and Y\ lemma dba_language: "(\w. to_stream w \ DBA.language \ \ w \\<^sub>n \) \ DBA.language \ = {w. to_omega w \\<^sub>n \}" by (metis (mono_tags, lifting) Collect_cong dba.language_def mem_Collect_eq to_stream_to_omega) lemma dca_language: "(\w. to_stream w \ DCA.language \ \ w \\<^sub>n \) \ DCA.language \ = {w. to_omega w \\<^sub>n \}" by (metis (mono_tags, lifting) Collect_cong dca.language_def mem_Collect_eq to_stream_to_omega) definition \\<^sub>1 :: "'a ltln \ 'a ltln list \ ('a set, 'ltlq \ 'ltlq) dca" where "\\<^sub>1 \ xs = \ \ (set xs)" lemma \\<^sub>1_language: "to_omega ` DCA.language (\\<^sub>1 \ xs) = L\<^sub>1 \ (set xs)" by (simp add: \\<^sub>1_def L\<^sub>1_def set_eq_iff \_language) lemma \\<^sub>1_alphabet: "DCA.alphabet (\\<^sub>1 \ xs) = UNIV" unfolding \\<^sub>1_def \_def by simp definition \\<^sub>2 :: "'a ltln list \ 'a ltln list \ ('a set, 'ltlq list degen) dba" where "\\<^sub>2 xs ys = DBA_Combine.intersect_list (map (\\. \\<^sub>\_GF (\[set ys]\<^sub>\)) xs)" lemma \\<^sub>2_language: "to_omega ` DBA.language (\\<^sub>2 xs ys) = L\<^sub>2 (set xs) (set ys)" by (simp add: \\<^sub>2_def L\<^sub>2_def set_eq_iff dba_language[OF \\<^sub>\_GF_language[OF FG_advice_\LTL(1)]]) lemma \\<^sub>2_alphabet: "DBA.alphabet (\\<^sub>2 xs ys) = UNIV" by (simp add: \\<^sub>2_def \\<^sub>\_GF_def) definition \\<^sub>3 :: "'a ltln list \ 'a ltln list \ ('a set, 'ltlq list) dca" where "\\<^sub>3 xs ys = DCA_Combine.intersect_list (map (\\. \\<^sub>\_FG (\[set xs]\<^sub>\)) ys)" lemma \\<^sub>3_language: "to_omega ` DCA.language (\\<^sub>3 xs ys) = L\<^sub>3 (set xs) (set ys)" by (simp add: \\<^sub>3_def L\<^sub>3_def set_eq_iff dca_language[OF \\<^sub>\_FG_language[OF GF_advice_\LTL(1)]]) lemma \\<^sub>3_alphabet: "DCA.alphabet (\\<^sub>3 xs ys) = UNIV" by (simp add: \\<^sub>3_def \\<^sub>\_FG_def) definition "\' \ xs ys = intersect_bc (\\<^sub>2 xs ys) (DCA_Combine.intersect (\\<^sub>1 \ xs) (\\<^sub>3 xs ys))" lemma \'_language: "to_omega ` DRA.language (\' \ xs ys) = (L\<^sub>1 \ (set xs) \ L\<^sub>2 (set xs) (set ys) \ L\<^sub>3 (set xs) (set ys))" by (simp add: \'_def \\<^sub>1_language \\<^sub>2_language \\<^sub>3_language) fastforce lemma \'_alphabet: "DRA.alphabet (\' \ xs ys) = UNIV" by (simp add: \'_def \\<^sub>1_alphabet \\<^sub>2_alphabet \\<^sub>3_alphabet) subsection \A DRA for @{term "L(\)"}\ +text \ + This is the final constant constructing a deterministic Rabin automaton + using the pure version of the @{thm master_theorem}. +\ + definition "ltl_to_dra \ = DRA_Combine.union_list (map (\(xs, ys). \' \ xs ys) (advice_sets \))" lemma ltl_to_dra_language: "to_omega ` DRA.language (ltl_to_dra \) = language_ltln \" proof - have "(\(a, b)\set (advice_sets \). dra.alphabet (\' \ a b)) = (\(a, b)\set (advice_sets \). dra.alphabet (\' \ a b))" using advice_sets_not_empty by (simp add: \'_alphabet) then have *: "DRA.language (DRA_Combine.union_list (map (\(x, y). \' \ x y) (advice_sets \))) = \ (DRA.language ` set (map (\(x, y). \' \ x y) (advice_sets \)))" by (simp add: split_def) have "language_ltln \ = \ {(L\<^sub>1 \ X \ L\<^sub>2 X Y \ L\<^sub>3 X Y) | X Y. X \ subformulas\<^sub>\ \ \ Y \ subformulas\<^sub>\ \}" unfolding master_theorem_language by auto also have "\ = \ {L\<^sub>1 \ (set xs) \ L\<^sub>2 (set xs) (set ys) \ L\<^sub>3 (set xs) (set ys) | xs ys. (xs, ys) \ set (advice_sets \)}" unfolding advice_sets_subformulas by (metis (no_types, lifting)) also have "\ = \ {to_omega ` DRA.language (\' \ xs ys) | xs ys. (xs, ys) \ set (advice_sets \)}" by (simp add: \'_language) finally show ?thesis using * by (auto simp add: ltl_to_dra_def) qed lemma ltl_to_dra_alphabet: "alphabet (ltl_to_dra \) = UNIV" by (auto simp: ltl_to_dra_def \'_alphabet) +subsection \A DRA for @{term "L(\)"} with Restricted Advice Sets\ -subsection \Setting the Alphabet of a DRA\ +text \ + The following constant uses the @{thm master_theorem_restricted} to reduce + the size of the resulting automaton. +\ + +definition "ltl_to_dra_restricted \ = DRA_Combine.union_list (map (\(xs, ys). \' \ xs ys) (restricted_advice_sets \))" + +lemma ltl_to_dra_restricted_language: + "to_omega ` DRA.language (ltl_to_dra_restricted \) = language_ltln \" +proof - + have "(\(a, b)\set (restricted_advice_sets \). dra.alphabet (\' \ a b)) = + (\(a, b)\set (restricted_advice_sets \). dra.alphabet (\' \ a b))" + using restricted_advice_sets_not_empty by (simp add: \'_alphabet) + then have *: "DRA.language (DRA_Combine.union_list (map (\(x, y). \' \ x y) (restricted_advice_sets \))) = + \ (DRA.language ` set (map (\(x, y). \' \ x y) (restricted_advice_sets \)))" + by (simp add: split_def) + have "language_ltln \ = \ {(L\<^sub>1 \ X \ L\<^sub>2 X Y \ L\<^sub>3 X Y) | X Y. X \ subformulas\<^sub>\ \ \ restricted_subformulas \ \ Y \ subformulas\<^sub>\ \ \ restricted_subformulas \}" + unfolding master_theorem_restricted_language by auto + also have "\ = \ {L\<^sub>1 \ (set xs) \ L\<^sub>2 (set xs) (set ys) \ L\<^sub>3 (set xs) (set ys) | xs ys. (xs, ys) \ set (restricted_advice_sets \)}" + unfolding restricted_advice_sets_subformulas by (metis (no_types, lifting)) + also have "\ = \ {to_omega ` DRA.language (\' \ xs ys) | xs ys. (xs, ys) \ set (restricted_advice_sets \)}" + by (simp add: \'_language) + finally show ?thesis + using * by (auto simp add: ltl_to_dra_restricted_def) +qed + +lemma ltl_to_dra_restricted_alphabet: + "alphabet (ltl_to_dra_restricted \) = UNIV" + by (auto simp: ltl_to_dra_restricted_def \'_alphabet) + + +subsection \A DRA for @{term "L(\)"} with a finite alphabet\ + +text \ + Until this point, we use @{term UNIV} as the alphabet in all places. + To explore the automaton, however, we need a way to fix the alphabet + to some finite set. +\ definition dra_set_alphabet :: "('a set, 'b) dra \ 'a set set \ ('a set, 'b) dra" where "dra_set_alphabet \ \ = dra \ (initial \) (transition \) (condition \)" lemma dra_set_alphabet_language: "\ \ alphabet \ \ language (dra_set_alphabet \ \) = language \ \ {s. sset s \ \}" by (auto simp add: dra_set_alphabet_def dra.language_def set_eq_iff dra.run_alt_def) lemma dra_set_alphabet_alphabet[simp]: "alphabet (dra_set_alphabet \ \) = \" unfolding dra_set_alphabet_def by simp lemma dra_set_alphabet_nodes: "\ \ alphabet \ \ DRA.nodes (dra_set_alphabet \ \) \ DRA.nodes \" unfolding dra_set_alphabet_def dra.nodes_alt_def dra.reachable_alt_def dra.path_alt_def by auto - -subsection \A DRA for @{term "L(\)"} with a finite alphabet\ - -definition "ltl_to_dra_alphabet \ Ap = dra_set_alphabet (ltl_to_dra \) (Pow Ap)" +definition "ltl_to_dra_alphabet \ Ap = dra_set_alphabet (ltl_to_dra_restricted \) (Pow Ap)" lemma ltl_to_dra_alphabet_language: assumes "atoms_ltln \ \ Ap" shows "to_omega ` language (ltl_to_dra_alphabet \ Ap) = language_ltln \ \ {w. range w \ Pow Ap}" proof - - have 1: "Pow Ap \ alphabet (ltl_to_dra \)" - unfolding ltl_to_dra_alphabet by simp + have 1: "Pow Ap \ alphabet (ltl_to_dra_restricted \)" + unfolding ltl_to_dra_restricted_alphabet by simp show ?thesis unfolding ltl_to_dra_alphabet_def dra_set_alphabet_language[OF 1] - by (simp add: ltl_to_dra_language sset_range) force + by (simp add: ltl_to_dra_restricted_language sset_range) force qed lemma ltl_to_dra_alphabet_alphabet[simp]: "alphabet (ltl_to_dra_alphabet \ Ap) = Pow Ap" unfolding ltl_to_dra_alphabet_def by simp lemma ltl_to_dra_alphabet_nodes: - "DRA.nodes (ltl_to_dra_alphabet \ Ap) \ DRA.nodes (ltl_to_dra \)" + "DRA.nodes (ltl_to_dra_alphabet \ Ap) \ DRA.nodes (ltl_to_dra_restricted \)" unfolding ltl_to_dra_alphabet_def - by (rule dra_set_alphabet_nodes) (simp add: ltl_to_dra_alphabet) + by (rule dra_set_alphabet_nodes) (simp add: ltl_to_dra_restricted_alphabet) + +end + + +subsection \Verified Bounds for Number of Nodes\ + +text \ + Using two additional assumptions, we can show a double-exponential size bound + for the constructed automaton. +\ + +(* TODO add to HOL/Groups_List.thy *) +lemma list_prod_mono: + "f \ g \ (\x\xs. f x) \ (\x\xs. g x)" for f g :: "'a \ nat" + by (induction xs) (auto simp: le_funD mult_le_mono) + +(* TODO add to HOL/Groups_List.thy *) +lemma list_prod_const: + "(\x. x \ set xs \ f x \ c) \ (\x\xs. f x) \ c ^ length xs" for f :: "'a \ nat" + by (induction xs) (auto simp: mult_le_mono) + +(* TODO add to HOL/Finite_Set.thy *) +lemma card_insert_Suc: + "card (insert x S) \ Suc (card S)" + by (metis Suc_n_not_le_n card.infinite card_insert_if finite_insert linear) + +(* TODO add to HOL/Power.thy *) +lemma nat_power_le_imp_le: + "0 < a \ a \ b \ x ^ a \ x ^ b" for x :: nat + by (metis leD linorder_le_less_linear nat_power_less_imp_less neq0_conv power_eq_0_iff) + +(* TODO add to HOL/Power.thy *) +lemma const_less_power: + "n < x ^ n" if "x > 1" + using that by (induction n) (auto simp: less_trans_Suc) + +(* TODO add to HOL-Library/Log_Nat.thy *) +lemma floorlog_le_const: + "floorlog x n \ n" + by (induction n) (simp add: floorlog_eq_zero_iff, metis Suc_lessI floorlog_le_iff le_SucI power_inject_exp) + + +locale dra_construction_size = dra_construction + transition_functions_size + + assumes + equiv_finite: "finite P \ finite {Abs \ | \. prop_atoms \ \ P}" + assumes + equiv_card: "finite P \ card {Abs \ | \. prop_atoms \ \ P} \ 2 ^ 2 ^ card P" +begin + +lemma af\<^sub>F_lifted_range: + "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ range (\af\<^sub>F \ (Abs \)) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" + using af\<^sub>F_lifted_semantics af\<^sub>F_nested_prop_atoms by blast + +lemma af\<^sub>G_lifted_range: + "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ range (\af\<^sub>G \ (Abs \)) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" + using af\<^sub>G_lifted_semantics af\<^sub>G_nested_prop_atoms by blast + + +lemma \\<^sub>\_nodes: + "DBA.nodes (\\<^sub>\ \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" + unfolding \\<^sub>\_def + using af_lifted_semantics af_nested_prop_atoms by fastforce + +lemma \\<^sub>\_GF_nodes: + "DBA.nodes (\\<^sub>\_GF \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" + unfolding \\<^sub>\_GF_def dba.nodes_alt_def dba.reachable_alt_def + using af\<^sub>F_nested_prop_atoms[of "F\<^sub>n \"] by (auto simp: af\<^sub>F_lifted_semantics) + +lemma \\<^sub>\_nodes: + "DCA.nodes (\\<^sub>\ \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" + unfolding \\<^sub>\_def + using af_lifted_semantics af_nested_prop_atoms by fastforce + +lemma \\<^sub>\_FG_nodes: + "DCA.nodes (\\<^sub>\_FG \) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" + unfolding \\<^sub>\_FG_def dca.nodes_alt_def dca.reachable_alt_def + using af\<^sub>G_nested_prop_atoms[of "G\<^sub>n \"] by (auto simp: af\<^sub>G_lifted_semantics) + +lemma \_nodes_normalise: + "DCA.nodes (\ \ X) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \} \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ (normalise \) X}" + unfolding \_def dca.nodes_alt_def dca.reachable_alt_def + apply (auto simp add: af\<^sub>\_lifted_semantics af_letter\<^sub>\_lifted_semantics) + using af\<^sub>\_fst_nested_prop_atoms apply force + by (metis GF_advice_nested_prop_atoms\<^sub>\ af\<^sub>\_snd_nested_prop_atoms Abs_eq af\<^sub>\_lifted_semantics fst_conv normalise_eq snd_conv sup.absorb_iff1) + +lemma \_nodes: + "DCA.nodes (\ \ X) \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \} \ {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X}" + unfolding \_def dca.nodes_alt_def dca.reachable_alt_def + apply (auto simp add: af\<^sub>\_lifted_semantics af_letter\<^sub>\_lifted_semantics) + using af\<^sub>\_fst_nested_prop_atoms apply force + by (metis (no_types, hide_lams) GF_advice_nested_prop_atoms\<^sub>\ af\<^sub>\_snd_nested_prop_atoms fst_eqD nested_prop_atoms\<^sub>\_subset normalise_nested_propos order_refl order_trans snd_eqD sup.order_iff) + + + +lemma equiv_subset: + "{Abs \ |\. nested_prop_atoms \ \ P} \ {Abs \ |\. prop_atoms \ \ P}" + using prop_atoms_nested_prop_atoms by blast + +lemma equiv_finite': + "finite P \ finite {Abs \ | \. nested_prop_atoms \ \ P}" + using equiv_finite equiv_subset finite_subset by fast + +lemma equiv_card': + "finite P \ card {Abs \ | \. nested_prop_atoms \ \ P} \ 2 ^ 2 ^ card P" + by (metis (mono_tags, lifting) equiv_card equiv_subset equiv_finite card_mono le_trans) + + +lemma nested_prop_atoms_finite: + "finite {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" + using equiv_finite'[OF Equivalence_Relations.nested_prop_atoms_finite] . + +lemma nested_prop_atoms_card: + "card {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \} \ 2 ^ 2 ^ card (nested_prop_atoms \)" + using equiv_card'[OF Equivalence_Relations.nested_prop_atoms_finite] . + +lemma nested_prop_atoms\<^sub>\_finite: + "finite {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X}" + using equiv_finite'[OF nested_prop_atoms\<^sub>\_finite] by fast + +lemma nested_prop_atoms\<^sub>\_card: + "card {Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X} \ 2 ^ 2 ^ card (nested_prop_atoms \)" (is "?lhs \ ?rhs") +proof - + have "finite {Abs \ | \. prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X}" + by (simp add: nested_prop_atoms\<^sub>\_finite Advice.nested_prop_atoms\<^sub>\_finite equiv_finite) + + then have "?lhs \ card {Abs \ | \. prop_atoms \ \ (nested_prop_atoms\<^sub>\ \ X)}" + using card_mono equiv_subset by blast + + also have "\ \ 2 ^ 2 ^ card (nested_prop_atoms\<^sub>\ \ X)" + using equiv_card[OF Advice.nested_prop_atoms\<^sub>\_finite] by fast + + also have "\ \ ?rhs" + using nested_prop_atoms\<^sub>\_card by auto + + finally show ?thesis . +qed + + +lemma \\<^sub>\_GF_nodes_finite: + "finite (DBA.nodes (\\<^sub>\_GF \))" + using finite_subset[OF \\<^sub>\_GF_nodes nested_prop_atoms_finite] . + +lemma \\<^sub>\_FG_nodes_finite: + "finite (DCA.nodes (\\<^sub>\_FG \))" + using finite_subset[OF \\<^sub>\_FG_nodes nested_prop_atoms_finite] . + +lemma \\<^sub>\_GF_nodes_card: + "card (DBA.nodes (\\<^sub>\_GF \)) \ 2 ^ 2 ^ card (nested_prop_atoms (F\<^sub>n \))" + using le_trans[OF card_mono[OF nested_prop_atoms_finite \\<^sub>\_GF_nodes] nested_prop_atoms_card] . + +lemma \\<^sub>\_FG_nodes_card: + "card (DCA.nodes (\\<^sub>\_FG \)) \ 2 ^ 2 ^ card (nested_prop_atoms (G\<^sub>n \))" + using le_trans[OF card_mono[OF nested_prop_atoms_finite \\<^sub>\_FG_nodes] nested_prop_atoms_card] . + + +lemma \\<^sub>2_nodes_finite_helper: + "list_all (finite \ DBA.nodes) (map (\\. \\<^sub>\_GF (\[set ys]\<^sub>\)) xs)" + by (auto simp: list.pred_map list_all_iff \\<^sub>\_GF_nodes_finite) + +lemma \\<^sub>2_nodes_finite: + "finite (DBA.nodes (\\<^sub>2 xs ys))" + unfolding \\<^sub>2_def using DBA_Combine.intersect_list_nodes_finite \\<^sub>2_nodes_finite_helper . + +lemma \\<^sub>3_nodes_finite_helper: + "list_all (finite \ DCA.nodes) (map (\\. \\<^sub>\_FG (\[set xs]\<^sub>\)) ys)" + by (auto simp: list.pred_map list_all_iff \\<^sub>\_FG_nodes_finite) + +lemma \\<^sub>3_nodes_finite: + "finite (DCA.nodes (\\<^sub>3 xs ys))" + unfolding \\<^sub>3_def using DCA_Combine.intersect_list_nodes_finite \\<^sub>3_nodes_finite_helper . + +lemma \\<^sub>2_nodes_card: + assumes + "length xs \ n" + and + "\\. \ \ set xs \ card (nested_prop_atoms \) \ n" + shows + "card (DBA.nodes (\\<^sub>2 xs ys)) \ 2 ^ 2 ^ (n + floorlog 2 n + 2)" +proof - + have 1: "\\. \ \ set xs \ card (nested_prop_atoms (F\<^sub>n \[set ys]\<^sub>\)) \ Suc n" + proof - + fix \ + assume "\ \ set xs" + + have "card (nested_prop_atoms (F\<^sub>n (\[set ys]\<^sub>\))) + \ Suc (card (nested_prop_atoms (\[set ys]\<^sub>\)))" + by (simp add: card_insert_Suc) + + also have "\ \ Suc (card (nested_prop_atoms \))" + by (simp add: FG_advice_nested_prop_atoms_card) + + also have "\ \ Suc n" + by (simp add: assms(2) \\ \ set xs\) + + finally show "card (nested_prop_atoms (F\<^sub>n (\[set ys]\<^sub>\))) \ Suc n" . + qed + + have "(\\\xs. card (DBA.nodes (\\<^sub>\_GF (\[set ys]\<^sub>\)))) + \ (\\\xs. 2 ^ 2 ^ card (nested_prop_atoms (F\<^sub>n (\[set ys]\<^sub>\))))" + by (rule list_prod_mono) (insert \\<^sub>\_GF_nodes_card le_fun_def, blast) + + also have "\ \ (2 ^ 2 ^ Suc n) ^ length xs" + by (rule list_prod_const) (metis 1 Suc_leI nat_power_le_imp_le nat_power_eq_Suc_0_iff neq0_conv pos2 zero_less_power) + + also have "\ \ (2 ^ 2 ^ Suc n) ^ n" + using assms(1) nat_power_le_imp_le by fastforce + + also have "\ = 2 ^ (n * 2 ^ Suc n)" + by (metis Groups.mult_ac(2) power_mult) + + also have "\ \ 2 ^ (2 ^ floorlog 2 n * 2 ^ Suc n)" + by (cases "n = 0") (auto simp: floorlog_bounds less_imp_le_nat) + + also have "\ = 2 ^ 2 ^ (Suc n + floorlog 2 n)" + by (simp add: power_add) + + finally have 2: "(\\\xs. card (DBA.nodes (\\<^sub>\_GF (\[set ys]\<^sub>\)))) \ 2 ^ 2 ^ (Suc n + floorlog 2 n)" . + + have "card (DBA.nodes (\\<^sub>2 xs ys)) \ max 1 (length xs) * (\\\xs. card (DBA.nodes (\\<^sub>\_GF (\[set ys]\<^sub>\))))" + using DBA_Combine.intersect_list_nodes_card[OF \\<^sub>2_nodes_finite_helper] + by (auto simp: \\<^sub>2_def comp_def) + + also have "\ \ max 1 n * 2 ^ 2 ^ (Suc n + floorlog 2 n)" + using assms(1) 2 by (simp add: mult_le_mono) + + also have "\ \ 2 ^ (floorlog 2 n) * 2 ^ 2 ^ (Suc n + floorlog 2 n)" + by (cases "n = 0") (auto simp: floorlog_bounds less_imp_le_nat) + + also have "\ = 2 ^ (floorlog 2 n + 2 ^ (Suc n + floorlog 2 n))" + by (simp add: power_add) + + also have "\ \ 2 ^ (n + 2 ^ (Suc n + floorlog 2 n))" + by (simp add: floorlog_le_const) + + also have "\ \ 2 ^ 2 ^ (n + floorlog 2 n + 2)" + by simp (metis const_less_power Suc_1 add_Suc_right add_leE lessI less_imp_le_nat power_Suc) + + finally show ?thesis . +qed + + +lemma \\<^sub>3_nodes_card: + assumes + "length ys \ n" + and + "\\. \ \ set ys \ card (nested_prop_atoms \) \ n" + shows + "card (DCA.nodes (\\<^sub>3 xs ys)) \ 2 ^ 2 ^ (n + floorlog 2 n + 1)" +proof - + have 1: "\\. \ \ set ys \ card (DCA.nodes (\\<^sub>\_FG (\[set xs]\<^sub>\))) \ 2 ^ 2 ^ Suc n" + proof - + fix \ + assume "\ \ set ys" + + have "card (nested_prop_atoms (G\<^sub>n \[set xs]\<^sub>\)) + \ Suc (card (nested_prop_atoms (\[set xs]\<^sub>\)))" + by (simp add: card_insert_Suc) + + also have "\ \ Suc (card (nested_prop_atoms \))" + by (simp add: GF_advice_nested_prop_atoms_card) + + also have "\ \ Suc n" + by (simp add: assms(2) \\ \ set ys\) + + finally have 2: "card (nested_prop_atoms (G\<^sub>n \[set xs]\<^sub>\)) \ Suc n" . + + then show "?thesis \" + by (intro le_trans[OF \\<^sub>\_FG_nodes_card]) (meson one_le_numeral power_increasing) + qed + + + have "card (DCA.nodes (\\<^sub>3 xs ys)) \ (\\\ys. card (DCA.nodes (\\<^sub>\_FG (\[set xs]\<^sub>\))))" + unfolding \\<^sub>3_def using DCA_Combine.intersect_list_nodes_card[OF \\<^sub>3_nodes_finite_helper] + by (auto simp: comp_def) + + also have "\ \ (2 ^ 2 ^ Suc n) ^ length ys" + by (rule list_prod_const) (rule 1) + + also have "\ \ (2 ^ 2 ^ Suc n) ^ n" + by (simp add: assms(1) power_increasing) + + also have "\ \ 2 ^ (n * 2 ^ Suc n)" + by (metis le_refl mult.commute power_mult) + + also have "\ \ 2 ^ (2 ^ floorlog 2 n * 2 ^ Suc n)" + by (cases \n > 0\) (simp_all add: floorlog_bounds less_imp_le_nat) + + also have "\ = 2 ^ 2 ^ (n + floorlog 2 n + 1)" + by (simp add: power_add) + + finally show ?thesis . +qed + + +lemma \\<^sub>1_nodes_finite: + "finite (DCA.nodes (\\<^sub>1 \ xs))" + unfolding \\<^sub>1_def + by (metis (no_types, lifting) finite_subset \_nodes finite_SigmaI nested_prop_atoms\<^sub>\_finite nested_prop_atoms_finite) + +lemma \\<^sub>1_nodes_card: + assumes + "card (subfrmlsn \) \ n" + shows + "card (DCA.nodes (\\<^sub>1 \ xs)) \ 2 ^ 2 ^ (n + 1)" +proof - + let ?fst = "{Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" + let ?snd = "{Abs \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ (set xs)}" + + have 1: "card (nested_prop_atoms \) \ n" + by (meson card_mono[OF subfrmlsn_finite nested_prop_atoms_subfrmlsn] assms le_trans) + + + have "card (DCA.nodes (\\<^sub>1 \ xs)) \ card (?fst \ ?snd)" + unfolding \\<^sub>1_def + by (rule card_mono) (simp_all add: \_nodes nested_prop_atoms\<^sub>\_finite nested_prop_atoms_finite) + + also have "\ = card ?fst * card ?snd" + using nested_prop_atoms\<^sub>\_finite card_cartesian_product by blast + + also have "\ \ 2 ^ 2 ^ card (nested_prop_atoms \) * 2 ^ 2 ^ card (nested_prop_atoms \)" + using nested_prop_atoms\<^sub>\_card nested_prop_atoms_card mult_le_mono by blast + + also have "\ = 2 ^ 2 ^ (card (nested_prop_atoms \) + 1)" + by (simp add: semiring_normalization_rules(36)) + + also have "\ \ 2 ^ 2 ^ (n + 1)" + using assms 1 by simp + + finally show ?thesis . +qed + + +lemma \'_nodes_finite: + "finite (DRA.nodes (\' \ xs ys))" + unfolding \'_def + using intersect_nodes_finite intersect_bc_nodes_finite + using \\<^sub>1_nodes_finite \\<^sub>2_nodes_finite \\<^sub>3_nodes_finite + by fast + +lemma \'_nodes_card: + assumes + "length xs \ n" + and + "\\. \ \ set xs \ card (nested_prop_atoms \) \ n" + and + "length ys \ n" + and + "\\. \ \ set ys \ card (nested_prop_atoms \) \ n" + and + "card (subfrmlsn \) \ n" + shows + "card (DRA.nodes (\' \ xs ys)) \ 2 ^ 2 ^ (n + floorlog 2 n + 4)" +proof - + have "n + 1 \ n + floorlog 2 n + 2" + by auto + + then have 1: "(2::nat) ^ (n + 1) \ 2 ^ (n + floorlog 2 n + 2)" + using one_le_numeral power_increasing by blast + + + have "card (DRA.nodes (\' \ xs ys)) \ card (DCA.nodes (\\<^sub>1 \ xs)) * card (DBA.nodes (\\<^sub>2 xs ys)) * card (DCA.nodes (\\<^sub>3 xs ys))" (is "?lhs \ ?rhs") + proof (unfold \'_def) + have "card (DBA.nodes (\\<^sub>2 xs ys)) * card (DCA.nodes (DCA_Combine.intersect (\\<^sub>1 \ xs) (\\<^sub>3 xs ys))) \ ?rhs" + by (simp add: intersect_nodes_card[OF \\<^sub>1_nodes_finite \\<^sub>3_nodes_finite]) + then show "card (DRA.nodes (intersect_bc (\\<^sub>2 xs ys) (DCA_Combine.intersect (\\<^sub>1 \ xs) (\\<^sub>3 xs ys)))) \ ?rhs" + by (meson intersect_bc_nodes_card[OF \\<^sub>2_nodes_finite intersect_nodes_finite[OF \\<^sub>1_nodes_finite \\<^sub>3_nodes_finite]] basic_trans_rules(23)) + qed + + also have "\ \ 2 ^ 2 ^ (n + 1) * 2 ^ 2 ^ (n + floorlog 2 n + 2) * 2 ^ 2 ^ (n + floorlog 2 n + 1)" + using \\<^sub>1_nodes_card[OF assms(5)] \\<^sub>2_nodes_card[OF assms(1,2)] \\<^sub>3_nodes_card[OF assms(3,4)] + by (metis mult_le_mono) + + also have "\ = 2 ^ (2 ^ (n + 1) + 2 ^ (n + floorlog 2 n + 2) + 2 ^ (n + floorlog 2 n + 1))" + by (metis power_add) + + also have "\ \ 2 ^ (4 * 2 ^ (n + floorlog 2 n + 2))" + using 1 by auto + + finally show ?thesis + by (simp add: numeral.simps(2) power_add) +qed + +lemma subformula_nested_prop_atoms_subfrmlsn: + "\ \ subfrmlsn \ \ nested_prop_atoms \ \ subfrmlsn \" + using nested_prop_atoms_subfrmlsn subfrmlsn_subset by blast + + +lemma ltl_to_dra_nodes_finite: + "finite (DRA.nodes (ltl_to_dra \))" + unfolding ltl_to_dra_def + apply (rule DRA_Combine.union_list_nodes_finite) + apply (simp add: split_def \'_alphabet advice_sets_not_empty) + apply (simp add: list.pred_set split_def \'_nodes_finite) + done + +lemma ltl_to_dra_restricted_nodes_finite: + "finite (DRA.nodes (ltl_to_dra_restricted \))" + unfolding ltl_to_dra_restricted_def + apply (rule DRA_Combine.union_list_nodes_finite) + apply (simp add: split_def \'_alphabet advice_sets_not_empty) + apply (simp add: list.pred_set split_def \'_nodes_finite) + done + +lemma ltl_to_dra_alphabet_nodes_finite: + "finite (DRA.nodes (ltl_to_dra_alphabet \ AP))" + using ltl_to_dra_alphabet_nodes ltl_to_dra_restricted_nodes_finite finite_subset by fast + + +lemma ltl_to_dra_nodes_card: + assumes + "card (subfrmlsn \) \ n" + shows + "card (DRA.nodes (ltl_to_dra \)) \ 2 ^ 2 ^ (2 * n + floorlog 2 n + 4)" +proof - + let ?map = "map (\(x, y). \' \ x y) (advice_sets \)" + + have 1: "\x::nat. x > 0 \ x ^ length (advice_sets \) \ x ^ 2 ^ card (subfrmlsn \)" + by (metis advice_sets_length linorder_not_less nat_power_less_imp_less) + + have "card (DRA.nodes (ltl_to_dra \)) \ prod_list (map (card \ DRA.nodes) ?map)" + unfolding ltl_to_dra_def + apply (rule DRA_Combine.union_list_nodes_card) + unfolding list.pred_set using \'_nodes_finite by auto + + also have "\ = (\(x, y)\advice_sets \. card (DRA.nodes (\' \ x y)))" + by (induction "advice_sets \") (auto, metis (no_types, lifting) comp_apply split_def) + + also have "\ \ (2 ^ 2 ^ (n + floorlog 2 n + 4)) ^ length (advice_sets \)" + proof (rule list_prod_const, unfold split_def, rule \'_nodes_card) + show "\x. x \ set (advice_sets \) \ length (fst x) \ n" + using advice_sets_element_length assms by fastforce + + show "\x \. \x \ set (advice_sets \); \ \ set (fst x)\ \ card (nested_prop_atoms \) \ n" + using advice_sets_element_subfrmlsn(1) assms subformula_nested_prop_atoms_subfrmlsn subformulas\<^sub>\_subfrmlsn + by (metis (no_types, lifting) card_mono subfrmlsn_finite subset_iff sup.absorb_iff2 sup.coboundedI1 surjective_pairing) + + show "\x. x \ set (advice_sets \) \ length (snd x) \ n" + using advice_sets_element_length assms by fastforce + + show "\x \. \x \ set (advice_sets \); \ \ set (snd x)\ \ card (nested_prop_atoms \) \ n" + using advice_sets_element_subfrmlsn(2) assms subformula_nested_prop_atoms_subfrmlsn subformulas\<^sub>\_subfrmlsn + by (metis (no_types, lifting) card_mono subfrmlsn_finite subset_iff sup.absorb_iff2 sup.coboundedI1 surjective_pairing) + qed (insert assms, blast) + + also have "\ \ (2 ^ 2 ^ (n + floorlog 2 n + 4)) ^ (2 ^ card (subfrmlsn \))" + by (simp add: 1) + + also have "\ \ (2 ^ 2 ^ (n + floorlog 2 n + 4)) ^ (2 ^ n)" + by (simp add: assms power_increasing) + + also have "\ = 2 ^ (2 ^ n * 2 ^ (n + floorlog 2 n + 4))" + by (simp add: ac_simps power_mult [symmetric]) + + also have "\ = 2 ^ 2 ^ (2 * n + floorlog 2 n + 4)" + by (simp add: power_add) (simp add: mult_2 power_add) + + finally show ?thesis . +qed + +text \We verify the size bound of the automaton to be double exponential.\ + +theorem ltl_to_dra_size: + "card (DRA.nodes (ltl_to_dra \)) \ 2 ^ 2 ^ (2 * size \ + floorlog 2 (size \) + 4)" + using ltl_to_dra_nodes_card subfrmlsn_card by blast end end diff --git a/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Implementation.thy b/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Implementation.thy --- a/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Implementation.thy +++ b/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Implementation.thy @@ -1,203 +1,157 @@ (* Author: Benedikt Seidl License: BSD *) section \Implementation of the DRA Construction\ theory DRA_Implementation imports - DRA_Instantiation + DRA_Construction LTL.Rewriting - LTL.Disjunctive_Normal_Form Transition_Systems_and_Automata.DRA_Translate - Deriving.Derive -begin - -subsection \Hash functions for LTL\ - -derive hashable ltln - -definition cube :: "'a :: times \ 'a" -where - "cube a = a * a * a" - -instantiation set :: (hashable) hashable begin -definition [simp]: "hashcode (x :: 'a set) = Finite_Set.fold (plus o cube o hashcode) (uint32_of_nat (card x)) x" -definition "def_hashmap_size = (\_ :: 'a set itself. 2 * def_hashmap_size TYPE('a))" - -instance -proof - from def_hashmap_size[where ?'a = "'a"] - show "1 < def_hashmap_size TYPE('a set)" - by (simp add: def_hashmap_size_set_def) -qed - -end - -instantiation fset :: (hashable) hashable -begin - -definition [simp]: "hashcode (x :: 'a fset) = hashcode (fset x)" -definition "def_hashmap_size = (\_ :: 'a fset itself. 2 * def_hashmap_size TYPE('a))" - -instance -proof - from def_hashmap_size[where ?'a = "'a"] - show "1 < def_hashmap_size TYPE('a fset)" - by (simp add: def_hashmap_size_fset_def) -qed - -end - -instantiation ltln\<^sub>P :: (hashable) hashable -begin - -definition [simp]: "hashcode (\ :: 'a ltln\<^sub>P) = hashcode (min_dnf (rep_ltln\<^sub>P \))" -definition "def_hashmap_size = (\_ :: 'a ltln\<^sub>P itself. def_hashmap_size TYPE('a ltln))" - -instance -proof - from def_hashmap_size[where ?'a = "'a"] - show "1 < def_hashmap_size TYPE('a ltln\<^sub>P)" - by (simp add: def_hashmap_size_ltln\<^sub>P_def def_hashmap_size_ltln_def) -qed - -end - - subsection \Generating the Explicit Automaton\ text \ We convert the implicit automaton to its explicit representation and afterwards proof the final correctness theorem and the overall size bound. \ definition dra_to_drai :: "('a, 'b) dra \ 'a list \ ('a, 'b) drai" where "dra_to_drai \ \ = drai \ (initial \) (transition \) (condition \)" lemma dra_to_drai_language: "set \ = alphabet \ \ language (drai_dra (dra_to_drai \ \)) = language \" by (simp add: dra_to_drai_def drai_dra_def) definition drai_to_draei :: "nat \ ('a, 'b :: hashable) drai \ ('a, nat) draei" where "drai_to_draei hms = to_draei_impl (=) bounded_hashcode_nat hms" + +lemma dra_to_drai_rel: + assumes + "(\, alphabet A) \ \Id\ list_set_rel" + shows + "(dra_to_drai A \, A) \ \Id, Id\drai_dra_rel" +proof - + have "(A, A) \ \Id, Id\dra_rel" + by simp + + then have "(dra_to_drai A \, dra (alphabet A) (initial A) (transition A) (condition A)) \ \Id, Id\drai_dra_rel" + unfolding dra_to_drai_def using assms by parametricity + + then show ?thesis + by simp +qed + +lemma draei_language_rel: + fixes + A :: "('label, 'state :: hashable) dra" + assumes + "(\, alphabet A) \ \Id\ list_set_rel" + and + "finite (DRA.nodes A)" + and + "is_valid_def_hm_size TYPE('state) hms" + shows + "DRA.language (drae_dra (draei_drae (drai_to_draei hms (dra_to_drai A \)))) = DRA.language A" +proof - + have "(dra_to_drai A \, A) \ \Id, Id\drai_dra_rel" + using dra_to_drai_rel assms by fast + + then have "(drai_to_draei hms (dra_to_drai A \), to_draei A) \ \Id_on (dra.alphabet A), rel (dra_to_drai A \) A (=) bounded_hashcode_nat hms\ draei_dra_rel" + unfolding drai_to_draei_def + using to_draei_impl_refine[unfolded autoref_tag_defs] + by parametricity (simp_all add: assms is_bounded_hashcode_def bounded_hashcode_nat_bounds) + + then have "(DRA.language ((drae_dra \ draei_drae) (drai_to_draei hms (dra_to_drai A \))), DRA.language (id (to_draei A))) \ \\Id_on (dra.alphabet A)\ stream_rel\ set_rel" + by parametricity + + then show ?thesis + by (simp add: to_draei_def) +qed + + +subsection \Defining the Alphabet\ + fun atoms_ltlc_list :: "'a ltlc \ 'a list" where "atoms_ltlc_list true\<^sub>c = []" | "atoms_ltlc_list false\<^sub>c = []" | "atoms_ltlc_list prop\<^sub>c(q) = [q]" | "atoms_ltlc_list (not\<^sub>c \) = atoms_ltlc_list \" | "atoms_ltlc_list (\ and\<^sub>c \) = List.union (atoms_ltlc_list \) (atoms_ltlc_list \)" | "atoms_ltlc_list (\ or\<^sub>c \) = List.union (atoms_ltlc_list \) (atoms_ltlc_list \)" | "atoms_ltlc_list (\ implies\<^sub>c \) = List.union (atoms_ltlc_list \) (atoms_ltlc_list \)" | "atoms_ltlc_list (X\<^sub>c \) = atoms_ltlc_list \" | "atoms_ltlc_list (F\<^sub>c \) = atoms_ltlc_list \" | "atoms_ltlc_list (G\<^sub>c \) = atoms_ltlc_list \" | "atoms_ltlc_list (\ U\<^sub>c \) = List.union (atoms_ltlc_list \) (atoms_ltlc_list \)" | "atoms_ltlc_list (\ R\<^sub>c \) = List.union (atoms_ltlc_list \) (atoms_ltlc_list \)" | "atoms_ltlc_list (\ W\<^sub>c \) = List.union (atoms_ltlc_list \) (atoms_ltlc_list \)" | "atoms_ltlc_list (\ M\<^sub>c \) = List.union (atoms_ltlc_list \) (atoms_ltlc_list \)" lemma atoms_ltlc_list_set: "set (atoms_ltlc_list \) = atoms_ltlc \" by (induction \) simp_all lemma atoms_ltlc_list_distinct: "distinct (atoms_ltlc_list \)" by (induction \) simp_all definition ltl_alphabet :: "'a list \ 'a set list" where "ltl_alphabet AP = map set (subseqs AP)" -definition ltln_to_draei :: "'a list \ ('a :: hashable) ltln \ ('a set, nat) draei" + +subsection \The Final Constant\ + +text \ + We require the quotient type to be hashable in order to efficiently explore the automaton. +\ + +locale dra_implementation = dra_construction_size _ _ _ Abs + for + Abs :: "'a ltln \ 'ltlq :: hashable" +begin + +definition ltln_to_draei :: "'a list \ 'a ltln \ ('a set, nat) draei" where "ltln_to_draei AP \ = drai_to_draei (Suc (size \)) (dra_to_drai (ltl_to_dra_alphabet \ (set AP)) (ltl_alphabet AP))" -definition ltlc_to_draei :: "('a :: hashable) ltlc \ ('a set, nat) draei" +definition ltlc_to_draei :: "'a ltlc \ ('a set, nat) draei" where "ltlc_to_draei \ = ltln_to_draei (atoms_ltlc_list \) (simplify Slow (ltlc_to_ltln \))" - -subsection \Final Proof of Correctness\ - -lemma dra_to_drai_rel: - assumes - "(\, alphabet A) \ \Id\ list_set_rel" - shows - "(dra_to_drai A \, A) \ \Id, Id\drai_dra_rel" -proof - - have "(A, A) \ \Id, Id\dra_rel" - by simp - - then have "(dra_to_drai A \, dra (alphabet A) (initial A) (transition A) (condition A)) \ \Id, Id\drai_dra_rel" - unfolding dra_to_drai_def using assms by parametricity - - then show ?thesis - by simp -qed - -lemma draei_language: - fixes - A :: "('label, 'state :: hashable) dra" - assumes - "(\, alphabet A) \ \Id\ list_set_rel" - and - "finite (DRA.nodes A)" - and - "is_valid_def_hm_size TYPE('state) hms" - shows - "DRA.language (drae_dra (draei_drae (drai_to_draei hms (dra_to_drai A \)))) = DRA.language A" -proof - - have "(dra_to_drai A \, A) \ \Id, Id\drai_dra_rel" - using dra_to_drai_rel assms by fast - - then have "(drai_to_draei hms (dra_to_drai A \), to_draei A) \ \Id_on (dra.alphabet A), rel (dra_to_drai A \) A (=) bounded_hashcode_nat hms\ draei_dra_rel" - unfolding drai_to_draei_def - using to_draei_impl_refine[unfolded autoref_tag_defs] - by parametricity (simp_all add: assms is_bounded_hashcode_def bounded_hashcode_nat_bounds) - - then have "(DRA.language ((drae_dra \ draei_drae) (drai_to_draei hms (dra_to_drai A \))), DRA.language (id (to_draei A))) \ \\Id_on (dra.alphabet A)\ stream_rel\ set_rel" - by parametricity - - then show ?thesis - by (simp add: to_draei_def) -qed - - lemma ltl_to_dra_alphabet_rel: "distinct AP \ (ltl_alphabet AP, alphabet (ltl_to_dra_alphabet \ (set AP))) \ \Id\ list_set_rel" - unfolding ltl_to_dra.ltl_to_dra_alphabet_alphabet ltl_alphabet_def + unfolding ltl_to_dra_alphabet_alphabet ltl_alphabet_def by (simp add: list_set_rel_def in_br_conv subseqs_powset distinct_set_subseqs) -lemma ltl_to_dra_alphabet_nodes_finite: - "finite (DRA.nodes (ltl_to_dra_alphabet \ AP))" - using ltl_to_dra.ltl_to_dra_alphabet_nodes ltl_to_dra_nodes_finite finite_subset by fast - lemma ltlc_to_ltln_simplify_atoms: "atoms_ltln (simplify Slow (ltlc_to_ltln \)) \ atoms_ltlc \" using ltlc_to_ltln_atoms simplify_atoms by fast lemma valid_def_hm_size: "is_valid_def_hm_size TYPE('state) (Suc (size \))" for \ :: "'a ltln" unfolding is_valid_def_hm_size_def using ltln.size_neq by auto theorem final_correctness: "to_omega ` language (drae_dra (draei_drae (ltlc_to_draei \))) = language_ltlc \ \ {w. range w \ Pow (atoms_ltlc \)}" unfolding ltlc_to_draei_def ltln_to_draei_def - unfolding draei_language[OF ltl_to_dra_alphabet_rel[OF atoms_ltlc_list_distinct] ltl_to_dra_alphabet_nodes_finite valid_def_hm_size] + unfolding draei_language_rel[OF ltl_to_dra_alphabet_rel[OF atoms_ltlc_list_distinct] ltl_to_dra_alphabet_nodes_finite valid_def_hm_size] unfolding atoms_ltlc_list_set - unfolding ltl_to_dra.ltl_to_dra_alphabet_language[OF ltlc_to_ltln_simplify_atoms] + unfolding ltl_to_dra_alphabet_language[OF ltlc_to_ltln_simplify_atoms] unfolding ltlc_to_ltln_atoms language_ltln_def language_ltlc_def ltlc_to_ltln_semantics simplify_correct .. end + +end diff --git a/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Instantiation.thy b/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Instantiation.thy --- a/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Instantiation.thy +++ b/thys/LTL_Master_Theorem/LTL_to_DRA/DRA_Instantiation.thy @@ -1,417 +1,163 @@ (* Author: Benedikt Seidl License: BSD *) section \Instantiation of the LTL to DRA construction\ theory DRA_Instantiation imports - DRA_Construction + DRA_Implementation LTL.Equivalence_Relations + LTL.Disjunctive_Normal_Form + "../Logical_Characterization/Extra_Equivalence_Relations" "HOL-Library.Log_Nat" + Deriving.Derive begin -text \We instantiate the construction locale with propositional equivalence - and obtain a function converting a formula into an abstract automaton.\ - -global_interpretation ltl_to_dra: dra_construction "(\\<^sub>P)" rep_ltln\<^sub>P abs_ltln\<^sub>P - defines ltl_to_dra = ltl_to_dra.ltl_to_dra - and ltl_to_dra_alphabet = ltl_to_dra.ltl_to_dra_alphabet - and \' = ltl_to_dra.\' - and \\<^sub>1 = ltl_to_dra.\\<^sub>1 - and \\<^sub>2 = ltl_to_dra.\\<^sub>2 - and \\<^sub>3 = ltl_to_dra.\\<^sub>3 - and \\<^sub>\_FG = ltl_to_dra.\\<^sub>\_FG - and \\<^sub>\_GF = ltl_to_dra.\\<^sub>\_GF - and af_letter\<^sub>G = ltl_to_dra.af_letter\<^sub>G - and af_letter\<^sub>F = ltl_to_dra.af_letter\<^sub>F - and af_letter\<^sub>G_lifted = ltl_to_dra.af_letter\<^sub>G_lifted - and af_letter\<^sub>F_lifted = ltl_to_dra.af_letter\<^sub>F_lifted - and af_letter\<^sub>\_lifted = ltl_to_dra.af_letter\<^sub>\_lifted - and \ = ltl_to_dra.\ - and af_letter\<^sub>\ = ltl_to_dra.af_letter\<^sub>\ - by unfold_locales (meson Quotient_abs_rep Quotient_ltln\<^sub>P, simp add: Quotient_abs_rep Quotient_ltln\<^sub>P ltln\<^sub>P.abs_eq_iff) - -text \We obtain the following theorem:\ - -thm ltl_to_dra.ltl_to_dra_language - - -text \Furthermore, we verify the size bound of the automaton to be double-exponential.\ - -lemma prop_equiv_nested_prop_atoms_finite: - "finite {abs_ltln\<^sub>P \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" - using prop_equiv_finite'[OF nested_prop_atoms_finite] . - -lemma prop_equiv_nested_prop_atoms_card: - "card {abs_ltln\<^sub>P \ | \. nested_prop_atoms \ \ nested_prop_atoms \} \ 2 ^ 2 ^ card (nested_prop_atoms \)" - using prop_equiv_card'[OF nested_prop_atoms_finite] . - - -lemma prop_equiv_nested_prop_atoms\<^sub>\_finite: - "finite {abs_ltln\<^sub>P \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X}" - using prop_equiv_finite'[OF nested_prop_atoms\<^sub>\_finite] by fast - -lemma prop_equiv_nested_prop_atoms\<^sub>\_card: - "card {abs_ltln\<^sub>P \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X} \ 2 ^ 2 ^ card (nested_prop_atoms \)" (is "?lhs \ ?rhs") -proof - - have "finite {abs_ltln\<^sub>P \ | \. prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X}" - by (simp add: prop_equiv_nested_prop_atoms\<^sub>\_finite nested_prop_atoms\<^sub>\_finite prop_equiv_finite) - - then have "?lhs \ card {abs_ltln\<^sub>P \ | \. prop_atoms \ \ (nested_prop_atoms\<^sub>\ \ X)}" - using card_mono prop_equiv_subset by blast - - also have "\ \ 2 ^ 2 ^ card (nested_prop_atoms\<^sub>\ \ X)" - using prop_equiv_card[OF nested_prop_atoms\<^sub>\_finite] by fast - - also have "\ \ ?rhs" - using nested_prop_atoms\<^sub>\_card by auto - - finally show ?thesis . -qed - - -lemma \\<^sub>\_GF_nodes_finite: - "finite (DBA.nodes (\\<^sub>\_GF \))" - using finite_subset[OF ltl_to_dra.\\<^sub>\_GF_nodes prop_equiv_nested_prop_atoms_finite] . - -lemma \\<^sub>\_FG_nodes_finite: - "finite (DCA.nodes (\\<^sub>\_FG \))" - using finite_subset[OF ltl_to_dra.\\<^sub>\_FG_nodes prop_equiv_nested_prop_atoms_finite] . - -lemma \\<^sub>\_GF_nodes_card: - "card (DBA.nodes (\\<^sub>\_GF \)) \ 2 ^ 2 ^ card (nested_prop_atoms (F\<^sub>n \))" - using le_trans[OF card_mono[OF prop_equiv_nested_prop_atoms_finite ltl_to_dra.\\<^sub>\_GF_nodes] prop_equiv_nested_prop_atoms_card] . - -lemma \\<^sub>\_FG_nodes_card: - "card (DCA.nodes (\\<^sub>\_FG \)) \ 2 ^ 2 ^ card (nested_prop_atoms (G\<^sub>n \))" - using le_trans[OF card_mono[OF prop_equiv_nested_prop_atoms_finite ltl_to_dra.\\<^sub>\_FG_nodes] prop_equiv_nested_prop_atoms_card] . - - -lemma \\<^sub>2_nodes_finite_helper: - "list_all (finite \ DBA.nodes) (map (\\. \\<^sub>\_GF (\[set ys]\<^sub>\)) xs)" - by (auto simp: list.pred_map list_all_iff \\<^sub>\_GF_nodes_finite) - -lemma \\<^sub>2_nodes_finite: - "finite (DBA.nodes (\\<^sub>2 xs ys))" - unfolding ltl_to_dra.\\<^sub>2_def using DBA_Combine.intersect_list_nodes_finite \\<^sub>2_nodes_finite_helper . - -lemma \\<^sub>3_nodes_finite_helper: - "list_all (finite \ DCA.nodes) (map (\\. \\<^sub>\_FG (\[set xs]\<^sub>\)) ys)" - by (auto simp: list.pred_map list_all_iff \\<^sub>\_FG_nodes_finite) - -lemma \\<^sub>3_nodes_finite: - "finite (DCA.nodes (\\<^sub>3 xs ys))" - unfolding ltl_to_dra.\\<^sub>3_def using DCA_Combine.intersect_list_nodes_finite \\<^sub>3_nodes_finite_helper . +subsection \Hash Functions for Quotient Types\ -(* TODO add to HOL/Groups_List.thy *) -lemma list_prod_mono: - "f \ g \ (\x\xs. f x) \ (\x\xs. g x)" for f g :: "'a \ nat" - by (induction xs) (auto simp: le_funD mult_le_mono) - -(* TODO add to HOL/Groups_List.thy *) -lemma list_prod_const: - "(\x. x \ set xs \ f x \ c) \ (\x\xs. f x) \ c ^ length xs" for f :: "'a \ nat" - by (induction xs) (auto simp: mult_le_mono) - -(* TODO add to HOL/Finite_Set.thy *) -lemma card_insert_Suc: - "card (insert x S) \ Suc (card S)" - by (metis Suc_n_not_le_n card.infinite card_insert_if finite_insert linear) - -(* TODO add to HOL/Power.thy *) -lemma nat_power_le_imp_le: - "0 < a \ a \ b \ x ^ a \ x ^ b" for x :: nat - by (metis leD linorder_le_less_linear nat_power_less_imp_less neq0_conv power_eq_0_iff) - -(* TODO add to HOL/Power.thy *) -lemma const_less_power: - "n < x ^ n" if "x > 1" - using that by (induction n) (auto simp: less_trans_Suc) - -(* TODO add to HOL-Library/Log_Nat.thy *) -lemma floorlog_le_const: - "floorlog x n \ n" - by (induction n) (simp add: floorlog_eq_zero_iff, metis Suc_lessI floorlog_le_iff le_SucI power_inject_exp) - -lemma \\<^sub>2_nodes_card: - assumes - "length xs \ n" - and - "\\. \ \ set xs \ card (nested_prop_atoms \) \ n" - shows - "card (DBA.nodes (\\<^sub>2 xs ys)) \ 2 ^ 2 ^ (n + floorlog 2 n + 2)" -proof - - have 1: "\\. \ \ set xs \ card (nested_prop_atoms (F\<^sub>n \[set ys]\<^sub>\)) \ Suc n" - proof - - fix \ - assume "\ \ set xs" - - have "card (nested_prop_atoms (F\<^sub>n (\[set ys]\<^sub>\))) - \ Suc (card (nested_prop_atoms (\[set ys]\<^sub>\)))" - by (simp add: card_insert_Suc) +derive hashable ltln - also have "\ \ Suc (card (nested_prop_atoms \))" - by (simp add: FG_advice_nested_prop_atoms_card) - - also have "\ \ Suc n" - by (simp add: assms(2) \\ \ set xs\) - - finally show "card (nested_prop_atoms (F\<^sub>n (\[set ys]\<^sub>\))) \ Suc n" . - qed - - have "(\\\xs. card (DBA.nodes (\\<^sub>\_GF (\[set ys]\<^sub>\)))) - \ (\\\xs. 2 ^ 2 ^ card (nested_prop_atoms (F\<^sub>n (\[set ys]\<^sub>\))))" - by (rule list_prod_mono) (insert \\<^sub>\_GF_nodes_card le_fun_def, blast) - - also have "\ \ (2 ^ 2 ^ Suc n) ^ length xs" - by (rule list_prod_const) (metis 1 Suc_leI nat_power_le_imp_le nat_power_eq_Suc_0_iff neq0_conv pos2 zero_less_power) - - also have "\ \ (2 ^ 2 ^ Suc n) ^ n" - using assms(1) nat_power_le_imp_le by fastforce - - also have "\ = 2 ^ (n * 2 ^ Suc n)" - by (metis Groups.mult_ac(2) power_mult) - - also have "\ \ 2 ^ (2 ^ floorlog 2 n * 2 ^ Suc n)" - by (cases "n = 0") (auto simp: floorlog_bounds less_imp_le_nat) - - also have "\ = 2 ^ 2 ^ (Suc n + floorlog 2 n)" - by (simp add: power_add) - - finally have 2: "(\\\xs. card (DBA.nodes (\\<^sub>\_GF (\[set ys]\<^sub>\)))) \ 2 ^ 2 ^ (Suc n + floorlog 2 n)" . - - have "card (DBA.nodes (\\<^sub>2 xs ys)) \ max 1 (length xs) * (\\\xs. card (DBA.nodes (\\<^sub>\_GF (\[set ys]\<^sub>\))))" - using DBA_Combine.intersect_list_nodes_card[OF \\<^sub>2_nodes_finite_helper] - by (auto simp: ltl_to_dra.\\<^sub>2_def comp_def) - - also have "\ \ max 1 n * 2 ^ 2 ^ (Suc n + floorlog 2 n)" - using assms(1) 2 by (simp add: mult_le_mono) - - also have "\ \ 2 ^ (floorlog 2 n) * 2 ^ 2 ^ (Suc n + floorlog 2 n)" - by (cases "n = 0") (auto simp: floorlog_bounds less_imp_le_nat) - - also have "\ = 2 ^ (floorlog 2 n + 2 ^ (Suc n + floorlog 2 n))" - by (simp add: power_add) - - also have "\ \ 2 ^ (n + 2 ^ (Suc n + floorlog 2 n))" - by (simp add: floorlog_le_const) - - also have "\ \ 2 ^ 2 ^ (n + floorlog 2 n + 2)" - by simp (metis const_less_power Suc_1 add_Suc_right add_leE lessI less_imp_le_nat power_Suc) - - finally show ?thesis . -qed +definition "cube a = a * a * a" -lemma \\<^sub>3_nodes_card: - assumes - "length ys \ n" - and - "\\. \ \ set ys \ card (nested_prop_atoms \) \ n" - shows - "card (DCA.nodes (\\<^sub>3 xs ys)) \ 2 ^ 2 ^ (n + floorlog 2 n + 1)" -proof - - have 1: "\\. \ \ set ys \ card (DCA.nodes (\\<^sub>\_FG (\[set xs]\<^sub>\))) \ 2 ^ 2 ^ Suc n" - proof - - fix \ - assume "\ \ set ys" - - have "card (nested_prop_atoms (G\<^sub>n \[set xs]\<^sub>\)) - \ Suc (card (nested_prop_atoms (\[set xs]\<^sub>\)))" - by (simp add: card_insert_Suc) - - also have "\ \ Suc (card (nested_prop_atoms \))" - by (simp add: GF_advice_nested_prop_atoms_card) - - also have "\ \ Suc n" - by (simp add: assms(2) \\ \ set ys\) - - finally have 2: "card (nested_prop_atoms (G\<^sub>n \[set xs]\<^sub>\)) \ Suc n" . +instantiation set :: (hashable) hashable +begin - then show "?thesis \" - by (intro le_trans[OF \\<^sub>\_FG_nodes_card]) (meson one_le_numeral power_increasing) - qed - - - have "card (DCA.nodes (\\<^sub>3 xs ys)) \ (\\\ys. card (DCA.nodes (\\<^sub>\_FG (\[set xs]\<^sub>\))))" - unfolding ltl_to_dra.\\<^sub>3_def using DCA_Combine.intersect_list_nodes_card[OF \\<^sub>3_nodes_finite_helper] - by (auto simp: comp_def) - - also have "\ \ (2 ^ 2 ^ Suc n) ^ length ys" - by (rule list_prod_const) (rule 1) +definition [simp]: "hashcode (x :: 'a set) = Finite_Set.fold (plus o cube o hashcode) (uint32_of_nat (card x)) x" +definition "def_hashmap_size = (\_ :: 'a set itself. 2 * def_hashmap_size TYPE('a))" - also have "\ \ (2 ^ 2 ^ Suc n) ^ n" - by (simp add: assms(1) power_increasing) - - also have "\ \ 2 ^ (n * 2 ^ Suc n)" - by (metis le_refl mult.commute power_mult) - - also have "\ \ 2 ^ (2 ^ floorlog 2 n * 2 ^ Suc n)" - by (cases \n > 0\) (simp_all add: floorlog_bounds less_imp_le_nat) - - also have "\ = 2 ^ 2 ^ (n + floorlog 2 n + 1)" - by (simp add: power_add) - - finally show ?thesis . +instance +proof + from def_hashmap_size[where ?'a = "'a"] + show "1 < def_hashmap_size TYPE('a set)" + by (simp add: def_hashmap_size_set_def) qed - -lemma \\<^sub>1_nodes_finite: - "finite (DCA.nodes (\\<^sub>1 \ xs))" - unfolding ltl_to_dra.\\<^sub>1_def - by (metis (no_types, lifting) finite_subset ltl_to_dra.\_nodes finite_SigmaI prop_equiv_nested_prop_atoms\<^sub>\_finite prop_equiv_nested_prop_atoms_finite) - -lemma \\<^sub>1_nodes_card: - assumes - "card (subfrmlsn \) \ n" - shows - "card (DCA.nodes (\\<^sub>1 \ xs)) \ 2 ^ 2 ^ (n + 1)" -proof - - let ?fst = "{abs_ltln\<^sub>P \ | \. nested_prop_atoms \ \ nested_prop_atoms \}" - let ?snd = "{abs_ltln\<^sub>P \ | \. nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ (set xs)}" - - have 1: "card (nested_prop_atoms \) \ n" - by (meson card_mono[OF subfrmlsn_finite nested_prop_atoms_subfrmlsn] assms le_trans) - - - have "card (DCA.nodes (\\<^sub>1 \ xs)) \ card (?fst \ ?snd)" - unfolding ltl_to_dra.\\<^sub>1_def - by (rule card_mono) (simp_all add: ltl_to_dra.\_nodes prop_equiv_nested_prop_atoms\<^sub>\_finite prop_equiv_nested_prop_atoms_finite) - - also have "\ = card ?fst * card ?snd" - using prop_equiv_nested_prop_atoms\<^sub>\_finite card_cartesian_product by blast - - also have "\ \ 2 ^ 2 ^ card (nested_prop_atoms \) * 2 ^ 2 ^ card (nested_prop_atoms \)" - using prop_equiv_nested_prop_atoms\<^sub>\_card prop_equiv_nested_prop_atoms_card mult_le_mono by blast - - also have "\ = 2 ^ 2 ^ (card (nested_prop_atoms \) + 1)" - by (simp add: semiring_normalization_rules(36)) - - also have "\ \ 2 ^ 2 ^ (n + 1)" - using assms 1 by simp - - finally show ?thesis . -qed +end -lemma \'_nodes_finite: - "finite (DRA.nodes (\' \ xs ys))" - unfolding ltl_to_dra.\'_def - using intersect_nodes_finite intersect_bc_nodes_finite - using \\<^sub>1_nodes_finite \\<^sub>2_nodes_finite \\<^sub>3_nodes_finite - by fast - -lemma \'_nodes_card: - assumes - "length xs \ n" - and - "\\. \ \ set xs \ card (nested_prop_atoms \) \ n" - and - "length ys \ n" - and - "\\. \ \ set ys \ card (nested_prop_atoms \) \ n" - and - "card (subfrmlsn \) \ n" - shows - "card (DRA.nodes (\' \ xs ys)) \ 2 ^ 2 ^ (n + floorlog 2 n + 4)" -proof - - have "n + 1 \ n + floorlog 2 n + 2" - by auto +instantiation fset :: (hashable) hashable +begin - then have 1: "(2::nat) ^ (n + 1) \ 2 ^ (n + floorlog 2 n + 2)" - using one_le_numeral power_increasing by blast - - - have "card (DRA.nodes (\' \ xs ys)) \ card (DCA.nodes (\\<^sub>1 \ xs)) * card (DBA.nodes (\\<^sub>2 xs ys)) * card (DCA.nodes (\\<^sub>3 xs ys))" (is "?lhs \ ?rhs") - proof (unfold ltl_to_dra.\'_def) - have "card (DBA.nodes (\\<^sub>2 xs ys)) * card (DCA.nodes (DCA_Combine.intersect (\\<^sub>1 \ xs) (\\<^sub>3 xs ys))) \ ?rhs" - by (simp add: intersect_nodes_card[OF \\<^sub>1_nodes_finite \\<^sub>3_nodes_finite]) - then show "card (DRA.nodes (intersect_bc (\\<^sub>2 xs ys) (DCA_Combine.intersect (\\<^sub>1 \ xs) (\\<^sub>3 xs ys)))) \ ?rhs" - by (meson intersect_bc_nodes_card[OF \\<^sub>2_nodes_finite intersect_nodes_finite[OF \\<^sub>1_nodes_finite \\<^sub>3_nodes_finite]] basic_trans_rules(23)) - qed +definition [simp]: "hashcode (x :: 'a fset) = hashcode (fset x)" +definition "def_hashmap_size = (\_ :: 'a fset itself. 2 * def_hashmap_size TYPE('a))" - also have "\ \ 2 ^ 2 ^ (n + 1) * 2 ^ 2 ^ (n + floorlog 2 n + 2) * 2 ^ 2 ^ (n + floorlog 2 n + 1)" - using \\<^sub>1_nodes_card[OF assms(5)] \\<^sub>2_nodes_card[OF assms(1,2)] \\<^sub>3_nodes_card[OF assms(3,4)] - by (metis mult_le_mono) - - also have "\ = 2 ^ (2 ^ (n + 1) + 2 ^ (n + floorlog 2 n + 2) + 2 ^ (n + floorlog 2 n + 1))" - by (metis power_add) - - also have "\ \ 2 ^ (4 * 2 ^ (n + floorlog 2 n + 2))" - using 1 by auto - - finally show ?thesis - by (simp add: numeral.simps(2) power_add) +instance +proof + from def_hashmap_size[where ?'a = "'a"] + show "1 < def_hashmap_size TYPE('a fset)" + by (simp add: def_hashmap_size_fset_def) qed -lemma subformula_nested_prop_atoms_subfrmlsn: - "\ \ subfrmlsn \ \ nested_prop_atoms \ \ subfrmlsn \" - using nested_prop_atoms_subfrmlsn subfrmlsn_subset by blast +end -lemma ltl_to_dra_nodes_finite: - "finite (DRA.nodes (ltl_to_dra \))" - unfolding ltl_to_dra.ltl_to_dra_def - apply (rule DRA_Combine.union_list_nodes_finite) - apply (simp add: split_def ltl_to_dra.\'_alphabet advice_sets_not_empty) - apply (simp add: list.pred_set split_def \'_nodes_finite) - done - -lemma ltl_to_dra_nodes_card: - assumes - "card (subfrmlsn \) \ n" - shows - "card (DRA.nodes (ltl_to_dra \)) \ 2 ^ 2 ^ (2 * n + floorlog 2 n + 4)" -proof - - let ?map = "map (\(x, y). \' \ x y) (advice_sets \)" - - have 1: "\x::nat. x > 0 \ x ^ length (advice_sets \) \ x ^ 2 ^ card (subfrmlsn \)" - by (metis advice_sets_length linorder_not_less nat_power_less_imp_less) - - have "card (DRA.nodes (ltl_to_dra \)) \ prod_list (map (card \ DRA.nodes) ?map)" - unfolding ltl_to_dra.ltl_to_dra_def - apply (rule DRA_Combine.union_list_nodes_card) - unfolding list.pred_set using \'_nodes_finite by auto - - also have "\ = (\(x, y)\advice_sets \. card (DRA.nodes (\' \ x y)))" - by (induction "advice_sets \") (auto, metis (no_types, lifting) comp_apply split_def) +instantiation ltln\<^sub>P:: (hashable) hashable +begin - also have "\ \ (2 ^ 2 ^ (n + floorlog 2 n + 4)) ^ length (advice_sets \)" - proof (rule list_prod_const, unfold split_def, rule \'_nodes_card) - show "\x. x \ set (advice_sets \) \ length (fst x) \ n" - using advice_sets_element_length assms by fastforce - - show "\x \. \x \ set (advice_sets \); \ \ set (fst x)\ \ card (nested_prop_atoms \) \ n" - using advice_sets_element_subfrmlsn(1) assms subformula_nested_prop_atoms_subfrmlsn subformulas\<^sub>\_subfrmlsn - by (metis (no_types, lifting) card_mono subfrmlsn_finite subset_iff sup.absorb_iff2 sup.coboundedI1 surjective_pairing) - - show "\x. x \ set (advice_sets \) \ length (snd x) \ n" - using advice_sets_element_length assms by fastforce +definition [simp]: "hashcode (\ :: 'a ltln\<^sub>P) = hashcode (min_dnf (rep_ltln\<^sub>P \))" +definition "def_hashmap_size = (\_ :: 'a ltln\<^sub>P itself. def_hashmap_size TYPE('a ltln))" - show "\x \. \x \ set (advice_sets \); \ \ set (snd x)\ \ card (nested_prop_atoms \) \ n" - using advice_sets_element_subfrmlsn(2) assms subformula_nested_prop_atoms_subfrmlsn subformulas\<^sub>\_subfrmlsn - by (metis (no_types, lifting) card_mono subfrmlsn_finite subset_iff sup.absorb_iff2 sup.coboundedI1 surjective_pairing) - qed (insert assms, blast) - - also have "\ \ (2 ^ 2 ^ (n + floorlog 2 n + 4)) ^ (2 ^ card (subfrmlsn \))" - by (simp add: 1) - - also have "\ \ (2 ^ 2 ^ (n + floorlog 2 n + 4)) ^ (2 ^ n)" - by (simp add: assms power_increasing) - - also have "\ = 2 ^ (2 ^ n * 2 ^ (n + floorlog 2 n + 4))" - by (simp add: ac_simps power_mult [symmetric]) - - also have "\ = 2 ^ 2 ^ (2 * n + floorlog 2 n + 4)" - by (simp add: power_add) (simp add: mult_2 power_add) - - finally show ?thesis . +instance +proof + from def_hashmap_size[where ?'a = "'a"] + show "1 < def_hashmap_size TYPE('a ltln\<^sub>P)" + by (simp add: def_hashmap_size_ltln\<^sub>P_def def_hashmap_size_ltln_def) qed -theorem ltl_to_dra_size: - "card (DRA.nodes (ltl_to_dra \)) \ 2 ^ 2 ^ (2 * size \ + floorlog 2 (size \) + 4)" - using ltl_to_dra_nodes_card subfrmlsn_card by blast +end + + +instantiation ltln\<^sub>Q :: (hashable) hashable +begin + +definition [simp]: "hashcode (\ :: 'a ltln\<^sub>Q) = hashcode (min_dnf (Unf (rep_ltln\<^sub>Q \)))" +definition "def_hashmap_size = (\_ :: 'a ltln\<^sub>Q itself. def_hashmap_size TYPE('a ltln))" + +instance +proof + from def_hashmap_size[where ?'a = "'a"] + show "1 < def_hashmap_size TYPE('a ltln\<^sub>Q)" + by (simp add: def_hashmap_size_ltln\<^sub>Q_def def_hashmap_size_ltln_def) +qed end + + +subsection \Interpretations with Equivalence Relations\ + +text \ + We instantiate the construction locale with propositional equivalence + and obtain a function converting a formula into an abstract automaton. +\ + +global_interpretation ltl_to_dra\<^sub>P: dra_implementation "(\\<^sub>P)" id rep_ltln\<^sub>P abs_ltln\<^sub>P + defines ltl_to_dra\<^sub>P = ltl_to_dra\<^sub>P.ltl_to_dra + and ltl_to_dra_restricted\<^sub>P = ltl_to_dra\<^sub>P.ltl_to_dra_restricted + and ltl_to_dra_alphabet\<^sub>P = ltl_to_dra\<^sub>P.ltl_to_dra_alphabet + and \'\<^sub>P = ltl_to_dra\<^sub>P.\' + and \\<^sub>1\<^sub>P = ltl_to_dra\<^sub>P.\\<^sub>1 + and \\<^sub>2\<^sub>P = ltl_to_dra\<^sub>P.\\<^sub>2 + and \\<^sub>3\<^sub>P = ltl_to_dra\<^sub>P.\\<^sub>3 + and \\<^sub>\_FG\<^sub>P = ltl_to_dra\<^sub>P.\\<^sub>\_FG + and \\<^sub>\_GF\<^sub>P = ltl_to_dra\<^sub>P.\\<^sub>\_GF + and af_letter\<^sub>G\<^sub>P = ltl_to_dra\<^sub>P.af_letter\<^sub>G + and af_letter\<^sub>F\<^sub>P = ltl_to_dra\<^sub>P.af_letter\<^sub>F + and af_letter\<^sub>G_lifted\<^sub>P = ltl_to_dra\<^sub>P.af_letter\<^sub>G_lifted + and af_letter\<^sub>F_lifted\<^sub>P = ltl_to_dra\<^sub>P.af_letter\<^sub>F_lifted + and af_letter\<^sub>\_lifted\<^sub>P = ltl_to_dra\<^sub>P.af_letter\<^sub>\_lifted + and \\<^sub>P = ltl_to_dra\<^sub>P.\ + and af_letter\<^sub>\\<^sub>P = ltl_to_dra\<^sub>P.af_letter\<^sub>\ + and ltln_to_draei\<^sub>P = ltl_to_dra\<^sub>P.ltln_to_draei + and ltlc_to_draei\<^sub>P = ltl_to_dra\<^sub>P.ltlc_to_draei + by unfold_locales (meson Quotient_abs_rep Quotient_ltln\<^sub>P, simp_all add: Quotient_abs_rep Quotient_ltln\<^sub>P ltln\<^sub>P.abs_eq_iff prop_equiv_card prop_equiv_finite) + +thm ltl_to_dra\<^sub>P.ltl_to_dra_language +thm ltl_to_dra\<^sub>P.ltl_to_dra_size +thm ltl_to_dra\<^sub>P.final_correctness + +text \ + Similarly, we instantiate the locale with a different equivalence relation and obtain another + constant for translation of LTL to deterministic Rabin automata. +\ + +global_interpretation ltl_to_dra\<^sub>Q: dra_implementation "(\\<^sub>Q)" Unf rep_ltln\<^sub>Q abs_ltln\<^sub>Q + defines ltl_to_dra\<^sub>Q = ltl_to_dra\<^sub>Q.ltl_to_dra + and ltl_to_dra_restricted\<^sub>Q = ltl_to_dra\<^sub>Q.ltl_to_dra_restricted + and ltl_to_dra_alphabet\<^sub>Q = ltl_to_dra\<^sub>Q.ltl_to_dra_alphabet + and \'\<^sub>Q = ltl_to_dra\<^sub>Q.\' + and \\<^sub>1\<^sub>Q = ltl_to_dra\<^sub>Q.\\<^sub>1 + and \\<^sub>2\<^sub>Q = ltl_to_dra\<^sub>Q.\\<^sub>2 + and \\<^sub>3\<^sub>Q = ltl_to_dra\<^sub>Q.\\<^sub>3 + and \\<^sub>\_FG\<^sub>Q = ltl_to_dra\<^sub>Q.\\<^sub>\_FG + and \\<^sub>\_GF\<^sub>Q = ltl_to_dra\<^sub>Q.\\<^sub>\_GF + and af_letter\<^sub>G\<^sub>Q = ltl_to_dra\<^sub>Q.af_letter\<^sub>G + and af_letter\<^sub>F\<^sub>Q = ltl_to_dra\<^sub>Q.af_letter\<^sub>F + and af_letter\<^sub>G_lifted\<^sub>Q = ltl_to_dra\<^sub>Q.af_letter\<^sub>G_lifted + and af_letter\<^sub>F_lifted\<^sub>Q = ltl_to_dra\<^sub>Q.af_letter\<^sub>F_lifted + and af_letter\<^sub>\_lifted\<^sub>Q = ltl_to_dra\<^sub>Q.af_letter\<^sub>\_lifted + and \\<^sub>Q = ltl_to_dra\<^sub>Q.\ + and af_letter\<^sub>\\<^sub>Q = ltl_to_dra\<^sub>Q.af_letter\<^sub>\ + and ltln_to_draei\<^sub>Q = ltl_to_dra\<^sub>Q.ltln_to_draei + and ltlc_to_draei\<^sub>Q = ltl_to_dra\<^sub>Q.ltlc_to_draei + by unfold_locales (meson Quotient_abs_rep Quotient_ltln\<^sub>Q, simp_all add: Quotient_abs_rep Quotient_ltln\<^sub>Q ltln\<^sub>Q.abs_eq_iff nested_prop_atoms_Unf prop_unfold_equiv_finite prop_unfold_equiv_card) + +thm ltl_to_dra\<^sub>Q.ltl_to_dra_language +thm ltl_to_dra\<^sub>Q.ltl_to_dra_size +thm ltl_to_dra\<^sub>Q.final_correctness + + +text \ + We allow the user to choose one of the two equivalence relations. +\ + +datatype equiv = Prop | PropUnfold + +fun ltlc_to_draei :: "equiv \ ('a :: hashable) ltlc \ ('a set, nat) draei" +where + "ltlc_to_draei Prop = ltlc_to_draei\<^sub>P" +| "ltlc_to_draei PropUnfold = ltlc_to_draei\<^sub>Q" + +end diff --git a/thys/LTL_Master_Theorem/LTL_to_DRA/Transition_Functions.thy b/thys/LTL_Master_Theorem/LTL_to_DRA/Transition_Functions.thy --- a/thys/LTL_Master_Theorem/LTL_to_DRA/Transition_Functions.thy +++ b/thys/LTL_Master_Theorem/LTL_to_DRA/Transition_Functions.thy @@ -1,592 +1,609 @@ (* Author: Benedikt Seidl License: BSD *) section \Transition Functions for Deterministic Automata\ theory Transition_Functions imports "../Logical_Characterization/After" "../Logical_Characterization/Advice" begin -text \This theory defines three functions based on the ``after''-function - which we use as transition functions for deterministic automata.\ +text \ + This theory defines three functions based on the ``after''-function + which we use as transition functions for deterministic automata. +\ locale transition_functions = af_congruent + GF_advice_congruent begin subsection \After Functions with Resets for @{term "GF(\LTL)"} and @{term "FG(\LTL)"}\ definition af_letter\<^sub>F :: "'a ltln \ 'a ltln \ 'a set \ 'a ltln" where "af_letter\<^sub>F \ \ \ = (if \ \ true\<^sub>n then F\<^sub>n \ else af_letter \ \)" definition af_letter\<^sub>G :: "'a ltln \ 'a ltln \ 'a set \ 'a ltln" where "af_letter\<^sub>G \ \ \ = (if \ \ false\<^sub>n then G\<^sub>n \ else af_letter \ \)" abbreviation af\<^sub>F :: "'a ltln \ 'a ltln \ 'a set list \ 'a ltln" where "af\<^sub>F \ \ w \ foldl (af_letter\<^sub>F \) \ w" abbreviation af\<^sub>G :: "'a ltln \ 'a ltln \ 'a set list \ 'a ltln" where "af\<^sub>G \ \ w \ foldl (af_letter\<^sub>G \) \ w" -lemma af_letter\<^sub>F_nested_prop_atoms: - "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ nested_prop_atoms (af_letter\<^sub>F \ \ \) \ nested_prop_atoms (F\<^sub>n \)" - by (induction \) (auto simp: af_letter\<^sub>F_def, insert af_letter_nested_prop_atoms, blast+) - -lemma af\<^sub>F_nested_prop_atoms: - "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ nested_prop_atoms (af\<^sub>F \ \ w) \ nested_prop_atoms (F\<^sub>n \)" - by (induction w rule: rev_induct) (insert af_letter\<^sub>F_nested_prop_atoms, auto) - -lemma af_letter\<^sub>F_range: - "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ range (af_letter\<^sub>F \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" - using af_letter\<^sub>F_nested_prop_atoms by blast - -lemma af\<^sub>F_range: - "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ range (af\<^sub>F \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" - using af\<^sub>F_nested_prop_atoms by blast - - -lemma af_letter\<^sub>G_nested_prop_atoms: - "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ nested_prop_atoms (af_letter\<^sub>G \ \ \) \ nested_prop_atoms (G\<^sub>n \)" - by (induction \) (auto simp: af_letter\<^sub>G_def, insert af_letter_nested_prop_atoms, blast+) - -lemma af\<^sub>G_nested_prop_atoms: - "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ nested_prop_atoms (af\<^sub>G \ \ w) \ nested_prop_atoms (G\<^sub>n \)" - by (induction w rule: rev_induct) (insert af_letter\<^sub>G_nested_prop_atoms, auto) - -lemma af_letter\<^sub>G_range: - "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ range (af_letter\<^sub>G \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" - using af_letter\<^sub>G_nested_prop_atoms by blast - -lemma af\<^sub>G_range: - "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ range (af\<^sub>G \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" - using af\<^sub>G_nested_prop_atoms by blast - - lemma af\<^sub>F_step: "af\<^sub>F \ \ w \ true\<^sub>n \ af\<^sub>F \ \ (w @ [\]) = F\<^sub>n \" by (induction w rule: rev_induct) (auto simp: af_letter\<^sub>F_def) lemma af\<^sub>G_step: "af\<^sub>G \ \ w \ false\<^sub>n \ af\<^sub>G \ \ (w @ [\]) = G\<^sub>n \" by (induction w rule: rev_induct) (auto simp: af_letter\<^sub>G_def) lemma af\<^sub>F_segments: "af\<^sub>F \ \ w = F\<^sub>n \ \ af\<^sub>F \ \ (w @ w') = af\<^sub>F \ (F\<^sub>n \) w'" by simp lemma af\<^sub>G_segments: "af\<^sub>G \ \ w = G\<^sub>n \ \ af\<^sub>G \ \ (w @ w') = af\<^sub>G \ (G\<^sub>n \) w'" by simp lemma af_not_true_implies_af_equals_af\<^sub>F: "(\xs ys. w = xs @ ys \ \ af \ xs \ true\<^sub>n) \ af\<^sub>F \ \ w = af \ w" proof (induction w rule: rev_induct) case (snoc x xs) then have "af\<^sub>F \ \ xs = af \ xs" by simp moreover have "\ af \ xs \ true\<^sub>n" using snoc.prems by blast ultimately show ?case by (metis af_letter\<^sub>F_def foldl_Cons foldl_Nil foldl_append) qed simp lemma af_not_false_implies_af_equals_af\<^sub>G: "(\xs ys. w = xs @ ys \ \ af \ xs \ false\<^sub>n) \ af\<^sub>G \ \ w = af \ w" proof (induction w rule: rev_induct) case (snoc x xs) then have "af\<^sub>G \ \ xs = af \ xs" by simp moreover have "\ af \ xs \ false\<^sub>n" using snoc.prems by blast ultimately show ?case by (metis af_letter\<^sub>G_def foldl_Cons foldl_Nil foldl_append) qed simp lemma af\<^sub>F_not_true_implies_af_equals_af\<^sub>F: "(\xs ys. w = xs @ ys \ \ af\<^sub>F \ \ xs \ true\<^sub>n) \ af\<^sub>F \ \ w = af \ w" proof (induction w rule: rev_induct) case (snoc x xs) then have "af\<^sub>F \ \ xs = af \ xs" by simp moreover have "\ af\<^sub>F \ \ xs \ true\<^sub>n" using snoc.prems by blast ultimately show ?case by (metis af_letter\<^sub>F_def foldl_Cons foldl_Nil foldl_append) qed simp lemma af\<^sub>G_not_false_implies_af_equals_af\<^sub>G: "(\xs ys. w = xs @ ys \ \ af\<^sub>G \ \ xs \ false\<^sub>n) \ af\<^sub>G \ \ w = af \ w" proof (induction w rule: rev_induct) case (snoc x xs) then have "af\<^sub>G \ \ xs = af \ xs" by simp moreover have "\ af\<^sub>G \ \ xs \ false\<^sub>n" using snoc.prems by blast ultimately show ?case by (metis af_letter\<^sub>G_def foldl_Cons foldl_Nil foldl_append) qed simp lemma af\<^sub>F_true_implies_af_true: "af\<^sub>F \ \ w \ true\<^sub>n \ af \ w \ true\<^sub>n" by (metis af_append_true af_not_true_implies_af_equals_af\<^sub>F) lemma af\<^sub>G_false_implies_af_false: "af\<^sub>G \ \ w \ false\<^sub>n \ af \ w \ false\<^sub>n" by (metis af_append_false af_not_false_implies_af_equals_af\<^sub>G) lemma af_equiv_true_af\<^sub>F_prefix_true: "af \ w \ true\<^sub>n \ \xs ys. w = xs @ ys \ af\<^sub>F \ \ xs \ true\<^sub>n" proof (induction w rule: rev_induct) case (snoc a w) then show ?case proof (cases "af \ w \ true\<^sub>n") case False then have "\xs ys. w = xs @ ys \ \ af \ xs \ true\<^sub>n" using af_append_true by blast then have "af\<^sub>F \ \ w = af \ w" using af_not_true_implies_af_equals_af\<^sub>F by auto then have "af\<^sub>F \ \ (w @ [a]) = af \ (w @ [a])" by (simp add: False af_letter\<^sub>F_def) then show ?thesis by (metis append_Nil2 snoc.prems) qed (insert snoc, force) qed (simp add: const_implies_eq) lemma af_equiv_false_af\<^sub>G_prefix_false: "af \ w \ false\<^sub>n \ \xs ys. w = xs @ ys \ af\<^sub>G \ \ xs \ false\<^sub>n" proof (induction w rule: rev_induct) case (snoc a w) then show ?case proof (cases "af \ w \ false\<^sub>n") case False then have "\xs ys. w = xs @ ys \ \ af \ xs \ false\<^sub>n" using af_append_false by blast then have "af\<^sub>G \ \ w = af \ w" using af_not_false_implies_af_equals_af\<^sub>G by auto then have "af\<^sub>G \ \ (w @ [a]) = af \ (w @ [a])" by (simp add: False af_letter\<^sub>G_def) then show ?thesis by (metis append_Nil2 snoc.prems) qed (insert snoc, force) qed (simp add: const_implies_eq) lemma append_take_drop: "w = xs @ ys \ xs = take (length xs) w \ ys = drop (length xs) w" by (metis append_eq_conv_conj) lemma subsequence_split: "(w [i \ j]) = xs @ ys \ xs = (w [i \ i + length xs])" by (simp add: append_take_drop) (metis add_diff_cancel_left' subsequence_length subsequence_prefix_suffix) lemma subsequence_append_general: "i \ k \ k \ j \ (w [i \ j]) = (w [i \ k]) @ (w [k \ j])" by (metis le_Suc_ex map_append subsequence_def upt_add_eq_append) lemma af\<^sub>F_semantics_rtl: assumes "\i. \j>i. af\<^sub>F \ (F\<^sub>n \) (w [0 \ j]) \ true\<^sub>n" shows "\i. \j. af (F\<^sub>n \) (w [i \ j]) \\<^sub>L true\<^sub>n" proof fix i from assms obtain j where "j > i" and "af\<^sub>F \ (F\<^sub>n \) (w [0 \ j]) \ true\<^sub>n" by blast then have X: "af\<^sub>F \ (F\<^sub>n \) (w [0 \ Suc j]) = F\<^sub>n \" using af\<^sub>F_step by auto - obtain k where "k > j" and "af\<^sub>F \ (F\<^sub>n \) (w [0 \ k]) \ true\<^sub>n" + obtain k where "k > j" and "af\<^sub>F \ (F\<^sub>n \) (w [0 \ k]) \ true\<^sub>n" using assms using Suc_le_eq by blast then have "af\<^sub>F \ (F\<^sub>n \) (w [Suc j \ k]) \ true\<^sub>n" using af\<^sub>F_segments[OF X] by (metis le_Suc_ex le_simps(3) subsequence_append) then have "af (F\<^sub>n \) (w [Suc j \ k]) \ true\<^sub>n" using af\<^sub>F_true_implies_af_true by blast then show "\k. af (F\<^sub>n \) (w [i \ k]) \\<^sub>L true\<^sub>n" by (metis (full_types) af_F_prefix_lang_equiv_true eq_implies_lang subsequence_append_general Suc_le_eq \i < j\ \j < k\ less_SucI order.order_iff_strict) qed lemma af\<^sub>F_semantics_ltr: assumes "\i. \j. af (F\<^sub>n \) (w [i \ j]) \ true\<^sub>n" shows "\i. \j>i. af\<^sub>F \ (F\<^sub>n \) (w [0 \ j]) \ true\<^sub>n" proof (rule ccontr) define resets where "resets = {i. af\<^sub>F \ (F\<^sub>n \) (w [0 \ i]) \ true\<^sub>n}" define m where "m = (if resets = {} then 0 else Suc (Max resets))" assume "\ (\i. \j>i. af\<^sub>F \ (F\<^sub>n \) (w [0 \ j]) \ true\<^sub>n)" then have "finite resets" using infinite_nat_iff_unbounded resets_def by force then have "resets \ {} \ af\<^sub>F \ (F\<^sub>n \) (w [0 \ Max resets]) \ true\<^sub>n" unfolding resets_def using Max_in by blast then have m_reset: "af\<^sub>F \ (F\<^sub>n \) (w [0 \ m]) = F\<^sub>n \" unfolding m_def using af\<^sub>F_step by auto { fix i assume "i \ m" with m_reset have "\ af\<^sub>F \ (F\<^sub>n \) (w [0 \ i]) \ true\<^sub>n" by (metis (mono_tags, lifting) Max_ge_iff Suc_n_not_le_n \finite resets\ empty_Collect_eq m_def mem_Collect_eq resets_def) with m_reset have "\ af\<^sub>F \ (F\<^sub>n \)(w [m \ i]) \ true\<^sub>n" by (metis (mono_tags, hide_lams) \m \ i\ af\<^sub>F_segments bot_nat_def le0 subsequence_append_general) } then have "\j. af\<^sub>F \ (F\<^sub>n \) (w [m \ j]) \ true\<^sub>n" by (metis le_cases subseq_to_smaller) then have "\j. af (F\<^sub>n \) (w [m \ j]) \ true\<^sub>n" by (metis af_equiv_true_af\<^sub>F_prefix_true subsequence_split) then show False using assms by blast qed lemma af\<^sub>G_semantics_rtl: assumes "\i. \j>i. \ af\<^sub>G \ (G\<^sub>n \) (w [0 \ j]) \ false\<^sub>n" shows "\i. \j. \ af (G\<^sub>n \) (w [i \ j]) \ false\<^sub>n" proof define resets where "resets = {i. af\<^sub>G \ (G\<^sub>n \) (w [0 \ i]) \ false\<^sub>n}" define m where "m = (if resets = {} then 0 else Suc (Max resets))" from assms have "finite resets" by (metis (mono_tags, lifting) infinite_nat_iff_unbounded mem_Collect_eq resets_def) then have "resets \ {} \ af\<^sub>G \ (G\<^sub>n \) (w [0 \ Max resets]) \ false\<^sub>n" unfolding resets_def using Max_in by blast then have m_reset: "af\<^sub>G \ (G\<^sub>n \) (w [0 \ m]) = G\<^sub>n \" unfolding m_def using af\<^sub>G_step by auto { fix i assume "i \ m" with m_reset have "\ af\<^sub>G \ (G\<^sub>n \) (w [0 \ i]) \ false\<^sub>n" by (metis (mono_tags, lifting) Max_ge_iff Suc_n_not_le_n \finite resets\ empty_Collect_eq m_def mem_Collect_eq resets_def) with m_reset have "\ af\<^sub>G \ (G\<^sub>n \) (w [m \ i]) \ false\<^sub>n" by (metis (mono_tags, hide_lams) \m \ i\ af\<^sub>G_segments bot_nat_def le0 subsequence_append_general) } then have "\j. \ af\<^sub>G \ (G\<^sub>n \) (w [m \ j]) \ false\<^sub>n" by (metis le_cases subseq_to_smaller) then show "\j. \ af (G\<^sub>n \) (w [m \ j]) \ false\<^sub>n" by (metis af_equiv_false_af\<^sub>G_prefix_false subsequence_split) qed lemma af\<^sub>G_semantics_ltr: assumes "\i. \j. \ af (G\<^sub>n \) (w [i \ j]) \\<^sub>L false\<^sub>n" shows "\i. \j>i. \ af\<^sub>G \ (G\<^sub>n \) (w [0 \ j]) \ false\<^sub>n" proof (rule ccontr, auto) assume 1: "\i. \j>i. af\<^sub>G \ (G\<^sub>n \) (w [0 \ j]) \ false\<^sub>n" { fix i obtain j where "j > i" and "af\<^sub>G \ (G\<^sub>n \) (w [0 \ j]) \ false\<^sub>n" using 1 by blast then have X: "af\<^sub>G \ (G\<^sub>n \) (w [0 \ Suc j]) = G\<^sub>n \" using af\<^sub>G_step by auto obtain k where "k > j" and "af\<^sub>G \ (G\<^sub>n \) (w [0 \ k]) \ false\<^sub>n" using 1 using Suc_le_eq by blast then have "af\<^sub>G \ (G\<^sub>n \) (w [Suc j \ k]) \ false\<^sub>n" using af\<^sub>G_segments[OF X] by (metis le_Suc_ex le_simps(3) subsequence_append) then have "af (G\<^sub>n \) (w [Suc j \ k]) \ false\<^sub>n" using af\<^sub>G_false_implies_af_false by fastforce then have "af (G\<^sub>n \) (w [Suc j \ k]) \\<^sub>L false\<^sub>n" using eq_implies_lang by fastforce then have "af (G\<^sub>n \) (w [i \ k]) \\<^sub>L false\<^sub>n" by (metis (full_types) af_G_prefix_lang_equiv_false subsequence_append_general Suc_le_eq \i < j\ \j < k\ less_SucI order.order_iff_strict) then have "\j. af (G\<^sub>n \) (w [i \ j]) \\<^sub>L false\<^sub>n" by fast } then show False using assms by blast qed subsection \After Function using GF-advice\ definition af_letter\<^sub>\ :: "'a ltln set \ 'a ltln \ 'a ltln \ 'a set \ 'a ltln \ 'a ltln" where "af_letter\<^sub>\ X p \ = (if snd p \ false\<^sub>n - then (af_letter (fst p) \, (af_letter (fst p) \)[X]\<^sub>\) + then (af_letter (fst p) \, (normalise (af_letter (fst p) \))[X]\<^sub>\) else (af_letter (fst p) \, af_letter (snd p) \))" abbreviation af\<^sub>\ :: "'a ltln set \ 'a ltln \ 'a ltln \ 'a set list \ 'a ltln \ 'a ltln" where "af\<^sub>\ X p w \ foldl (af_letter\<^sub>\ X) p w" lemma af_letter\<^sub>\_fst[simp]: "fst (af_letter\<^sub>\ X p \) = af_letter (fst p) \" by (simp add: af_letter\<^sub>\_def) lemma af_letter\<^sub>\_snd[simp]: - "snd p \ false\<^sub>n \ snd (af_letter\<^sub>\ X p \) = (af_letter (fst p) \)[X]\<^sub>\" + "snd p \ false\<^sub>n \ snd (af_letter\<^sub>\ X p \) = (normalise (af_letter (fst p) \))[X]\<^sub>\" "\ (snd p) \ false\<^sub>n \ snd (af_letter\<^sub>\ X p \) = af_letter (snd p) \" by (simp_all add: af_letter\<^sub>\_def) +lemma af\<^sub>\_fst: + "fst (af\<^sub>\ X p w) = af (fst p) w" + by (induction w rule: rev_induct) simp+ + +lemma af\<^sub>\_snd: + "\ af (snd p) w \ false\<^sub>n \ snd (af\<^sub>\ X p w) = af (snd p) w" + by (induction w rule: rev_induct) (simp_all, metis af_letter\<^sub>\_snd(2) af_letter.simps(2) af_letter_congruent) + +lemma af\<^sub>\_snd': + "\i. \ snd (af\<^sub>\ X p (take i w)) \ false\<^sub>n \ snd (af\<^sub>\ X p w) = af (snd p) w" + by (induction w rule: rev_induct) (simp_all, metis af_letter\<^sub>\_snd(2) diff_is_0_eq foldl_Nil le_cases take_all take_eq_Nil) + +lemma af\<^sub>\_step: + "snd (af\<^sub>\ X (\, \) w) \ false\<^sub>n \ snd (af\<^sub>\ X (\, \) (w @ [\])) = (normalise (af \ (w @ [\])))[X]\<^sub>\" + by (simp add: af\<^sub>\_fst) + +lemma af\<^sub>\_segments: + "af\<^sub>\ X (\, \) w = (af \ w, (af \ w)[X]\<^sub>\) \ af\<^sub>\ X (\, \) (w @ w') = af\<^sub>\ X (af \ w, (af \ w)[X]\<^sub>\) w'" + by (induction w' rule: rev_induct) fastforce+ + + +lemma af\<^sub>\_semantics_ltr: + assumes + "\i. suffix i w \\<^sub>n (af \ (prefix i w))[X]\<^sub>\" + shows + "\m. \k\m. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" +proof + define resets where "resets = {i. snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix i w)) \ false\<^sub>n}" + define m where "m = (if resets = {} then 0 else Suc (Max resets))" + + from assms obtain i where 1: "suffix i w \\<^sub>n (af \ (prefix i w))[X]\<^sub>\" + by blast + + { + fix j + assume "i \ j" and "j \ resets" + + let ?\ = "af \ (prefix (Suc j) w)" + + from 1 have "\n. suffix n (suffix i w) \\<^sub>n (normalise (af \ (prefix i w @ prefix n (suffix i w))))[X]\<^sub>\" + using normalise_monotonic by (simp add: GF_advice_af) + + then have "suffix (Suc j) w \\<^sub>n (normalise (af \ (prefix (Suc j) w)))[X]\<^sub>\" + by (metis (no_types) \i \ j\ add.right_neutral le_SucI le_Suc_ex subsequence_append subsequence_shift suffix_suffix) + + then have "\k>j. \ af ((normalise (af \ (prefix (Suc j) w)))[X]\<^sub>\) (w [Suc j \ k]) \ false\<^sub>n" + by (metis ltl_implies_satisfiable_prefix subsequence_prefix_suffix) + + then have "\k>j. \ snd (af\<^sub>\ X (?\, (normalise ?\)[X]\<^sub>\) (w [Suc j \ k])) \ false\<^sub>n" + by (metis af\<^sub>\_snd snd_eqD) + + moreover + + { + have "fst (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Suc j) w)) = ?\" + by (simp add: af\<^sub>\_fst) + + moreover + + have "snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix j w)) \ false\<^sub>n" + using \j \ resets\ resets_def by blast + + ultimately have "af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Suc j) w) = (?\, (normalise ?\)[X]\<^sub>\)" + by (metis (no_types) af\<^sub>\_step prod.collapse subseq_to_Suc zero_le) + } + + ultimately have "\k>j. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) ((w [0 \ Suc j]) @ (w [Suc j \ k]))) \ false\<^sub>n" + by (simp add: af\<^sub>\_segments) + + then have "\k>j. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix k w)) \ false\<^sub>n" + by (metis Suc_leI le0 subsequence_append_general) + + then have "\k \ resets. k \ j" + using \j \ resets\ resets_def le_less_linear by blast + } + + then have "finite resets" + by (meson finite_nat_set_iff_bounded_le infinite_nat_iff_unbounded_le) + + then have "resets \ {} \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Max resets) w)) \ false\<^sub>n" + using Max_in resets_def by blast + + then have "\k\m. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix k w)) \ false\<^sub>n" + by (metis (mono_tags, lifting) Max_ge Suc_n_not_le_n \finite resets\ empty_Collect_eq m_def mem_Collect_eq order.trans resets_def) + + then show "\k\m. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" + using le_SucI by blast +qed + +lemma af\<^sub>\_semantics_rtl: + assumes + "\n. \k\n. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" + shows + "\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" +proof - + define resets where "resets = {i. snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix i w)) \ false\<^sub>n}" + define m where "m = (if resets = {} then 0 else Suc (Max resets))" + + from assms obtain n where "\k\n. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" + by blast + + then have "\k>n. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix k w)) \ false\<^sub>n" + by (metis le_SucE lessE less_imp_le_nat) + + then have "finite resets" + by (metis (mono_tags, lifting) infinite_nat_iff_unbounded mem_Collect_eq resets_def) + + then have "\i\m. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix i w)) \ false\<^sub>n" + unfolding resets_def m_def using Max_ge not_less_eq_eq by auto + + then have "\i. \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) ((w [0 \ m]) @ (w [m \ i]))) \ false\<^sub>n" + by (metis le0 nat_le_linear subseq_to_smaller subsequence_append_general) + + moreover + + let ?\ = "af \ (prefix m w)" + + have "resets \ {} \ snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix (Max resets) w)) \ false\<^sub>n" + using Max_in \finite resets\ resets_def by blast + + then have prefix_\': "snd (af\<^sub>\ X (\, (normalise \)[X]\<^sub>\) (prefix m w)) = (normalise ?\)[X]\<^sub>\" + by (auto simp: GF_advice_congruent m_def af\<^sub>\_fst) + + ultimately have "\i. \ snd (af\<^sub>\ X (?\, (normalise ?\)[X]\<^sub>\) (w [m \ i])) \ false\<^sub>n" + by (metis af\<^sub>\_fst foldl_append fst_conv prod.collapse) + + then have "\i. \ af ((normalise ?\)[X]\<^sub>\) (w [m \ i]) \ false\<^sub>n" + by (metis prefix_\' af\<^sub>\_fst af\<^sub>\_snd' fst_conv prod.collapse subsequence_take) + + then have "suffix m w \\<^sub>n (normalise (af \ (prefix m w)))[X]\<^sub>\" + by (metis GF_advice_\LTL(1) satisfiable_prefix_implies_\LTL add.right_neutral subsequence_shift) + + from this[THEN normalise_eventually_equivalent] + show "\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" + by (metis add.commute af_subsequence_append le_add1 le_add_same_cancel1 prefix_suffix_subsequence suffix_suffix) +qed + +end + + +subsection \Reachability Bounds\ + +text \ + We show that the reach of each after-function is bounded by the atomic + propositions of the input formula. +\ + +locale transition_functions_size = transition_functions + + assumes + normalise_nested_propos: "nested_prop_atoms \ \ nested_prop_atoms (normalise \)" +begin + +lemma af_letter\<^sub>F_nested_prop_atoms: + "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ nested_prop_atoms (af_letter\<^sub>F \ \ \) \ nested_prop_atoms (F\<^sub>n \)" + by (induction \) (auto simp: af_letter\<^sub>F_def, insert af_letter_nested_prop_atoms, blast+) + +lemma af\<^sub>F_nested_prop_atoms: + "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ nested_prop_atoms (af\<^sub>F \ \ w) \ nested_prop_atoms (F\<^sub>n \)" + by (induction w rule: rev_induct) (insert af_letter\<^sub>F_nested_prop_atoms, auto) + +lemma af_letter\<^sub>F_range: + "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ range (af_letter\<^sub>F \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" + using af_letter\<^sub>F_nested_prop_atoms by blast + +lemma af\<^sub>F_range: + "nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \) \ range (af\<^sub>F \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (F\<^sub>n \)}" + using af\<^sub>F_nested_prop_atoms by blast + +lemma af_letter\<^sub>G_nested_prop_atoms: + "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ nested_prop_atoms (af_letter\<^sub>G \ \ \) \ nested_prop_atoms (G\<^sub>n \)" + by (induction \) (auto simp: af_letter\<^sub>G_def, insert af_letter_nested_prop_atoms, blast+) + +lemma af\<^sub>G_nested_prop_atoms: + "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ nested_prop_atoms (af\<^sub>G \ \ w) \ nested_prop_atoms (G\<^sub>n \)" + by (induction w rule: rev_induct) (insert af_letter\<^sub>G_nested_prop_atoms, auto) + +lemma af_letter\<^sub>G_range: + "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ range (af_letter\<^sub>G \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" + using af_letter\<^sub>G_nested_prop_atoms by blast + +lemma af\<^sub>G_range: + "nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \) \ range (af\<^sub>G \ \) \ {\. nested_prop_atoms \ \ nested_prop_atoms (G\<^sub>n \)}" + using af\<^sub>G_nested_prop_atoms by blast + +lemma af_letter\<^sub>\_snd_nested_prop_atoms_helper: + "snd p \ false\<^sub>n \ nested_prop_atoms (snd (af_letter\<^sub>\ X p \)) \ nested_prop_atoms\<^sub>\ (fst p) X" + "\ snd p \ false\<^sub>n \ nested_prop_atoms (snd (af_letter\<^sub>\ X p \)) \ nested_prop_atoms (snd p)" + by (simp_all add: af_letter_nested_prop_atoms nested_prop_atoms\<^sub>\_def) + (metis GF_advice_nested_prop_atoms\<^sub>\ af_letter_nested_prop_atoms nested_prop_atoms\<^sub>\_subset dual_order.trans nested_prop_atoms\<^sub>\_def normalise_nested_propos) + lemma af_letter\<^sub>\_fst_nested_prop_atoms: "nested_prop_atoms (fst (af_letter\<^sub>\ X p \)) \ nested_prop_atoms (fst p)" by (simp add: af_letter_nested_prop_atoms) -lemma af_letter\<^sub>\_snd_nested_prop_atoms_helper: - "snd p \ false\<^sub>n \ nested_prop_atoms (snd (af_letter\<^sub>\ X p \)) \ nested_prop_atoms\<^sub>\ (fst p) X" - "\ snd p \ false\<^sub>n \ nested_prop_atoms (snd (af_letter\<^sub>\ X p \)) \ nested_prop_atoms (snd p)" - by simp_all (insert GF_advice_nested_prop_atoms\<^sub>\ af_letter_nested_prop_atoms nested_prop_atoms\<^sub>\_def, blast) - lemma af_letter\<^sub>\_snd_nested_prop_atoms: "nested_prop_atoms (snd (af_letter\<^sub>\ X p \)) \ (nested_prop_atoms\<^sub>\ (fst p) X) \ (nested_prop_atoms (snd p))" using af_letter\<^sub>\_snd_nested_prop_atoms_helper by blast lemma af_letter\<^sub>\_fst_range: "range (fst \ af_letter\<^sub>\ X p) \ {\. nested_prop_atoms \ \ nested_prop_atoms (fst p)}" using af_letter\<^sub>\_fst_nested_prop_atoms by force lemma af_letter\<^sub>\_snd_range: "range (snd \ af_letter\<^sub>\ X p) \ {\. nested_prop_atoms \ \ (nested_prop_atoms\<^sub>\ (fst p) X) \ nested_prop_atoms (snd p)}" using af_letter\<^sub>\_snd_nested_prop_atoms by force lemma af_letter\<^sub>\_range: "range (af_letter\<^sub>\ X p) \ {\. nested_prop_atoms \ \ nested_prop_atoms (fst p)} \ {\. nested_prop_atoms \ \ (nested_prop_atoms\<^sub>\ (fst p) X) \ nested_prop_atoms (snd p)}" proof - have "range (af_letter\<^sub>\ X p) \ range (fst \ af_letter\<^sub>\ X p) \ range (snd \ af_letter\<^sub>\ X p)" by (simp add: image_subset_iff mem_Times_iff) also have "\ \ {\. nested_prop_atoms \ \ nested_prop_atoms (fst p)} \ {\. nested_prop_atoms \ \ (nested_prop_atoms\<^sub>\ (fst p) X) \ nested_prop_atoms (snd p)}" using af_letter\<^sub>\_fst_range af_letter\<^sub>\_snd_range by blast finally show ?thesis . qed - lemma af\<^sub>\_fst_nested_prop_atoms: "nested_prop_atoms (fst (af\<^sub>\ X p w)) \ nested_prop_atoms (fst p)" by (induction w rule: rev_induct) (auto, insert af_letter_nested_prop_atoms, blast) lemma af_letter_nested_prop_atoms\<^sub>\: "nested_prop_atoms\<^sub>\ (af_letter \ \) X \ nested_prop_atoms\<^sub>\ \ X" by (induction \) (simp_all add: nested_prop_atoms\<^sub>\_def, blast+) lemma af\<^sub>\_fst_nested_prop_atoms\<^sub>\: "nested_prop_atoms\<^sub>\ (fst (af\<^sub>\ X p w)) X \ nested_prop_atoms\<^sub>\ (fst p) X" by (induction w rule: rev_induct) (auto, insert af_letter_nested_prop_atoms\<^sub>\, blast) +lemma af\<^sub>\_fst_range: + "range (fst \ af\<^sub>\ X p) \ {\. nested_prop_atoms \ \ nested_prop_atoms (fst p)}" + using af\<^sub>\_fst_nested_prop_atoms by fastforce + lemma af\<^sub>\_snd_nested_prop_atoms: "nested_prop_atoms (snd (af\<^sub>\ X p w)) \ (nested_prop_atoms\<^sub>\ (fst p) X) \ (nested_prop_atoms (snd p))" proof (induction w arbitrary: p rule: rev_induct) case (snoc x xs) let ?p = "af\<^sub>\ X p xs" have "nested_prop_atoms (snd (af\<^sub>\ X p (xs @ [x]))) \ (nested_prop_atoms\<^sub>\ (fst ?p) X) \ (nested_prop_atoms (snd ?p))" by (simp add: af_letter\<^sub>\_snd_nested_prop_atoms) then show ?case using snoc af\<^sub>\_fst_nested_prop_atoms\<^sub>\ by blast qed (simp add: nested_prop_atoms\<^sub>\_def) - -lemma af\<^sub>\_fst_range: - "range (fst \ af\<^sub>\ X p) \ {\. nested_prop_atoms \ \ nested_prop_atoms (fst p)}" - using af\<^sub>\_fst_nested_prop_atoms by fastforce - lemma af\<^sub>\_snd_range: "range (snd \ af\<^sub>\ X p) \ {\. nested_prop_atoms \ \ (nested_prop_atoms\<^sub>\ (fst p) X) \ nested_prop_atoms (snd p)}" using af\<^sub>\_snd_nested_prop_atoms by fastforce lemma af\<^sub>\_range: "range (af\<^sub>\ X p) \ {\. nested_prop_atoms \ \ nested_prop_atoms (fst p)} \ {\. nested_prop_atoms \ \ (nested_prop_atoms\<^sub>\ (fst p) X) \ nested_prop_atoms (snd p)}" proof - have "range (af\<^sub>\ X p) \ range (fst \ af\<^sub>\ X p) \ range (snd \ af\<^sub>\ X p)" by (simp add: image_subset_iff mem_Times_iff) also have "\ \ {\. nested_prop_atoms \ \ nested_prop_atoms (fst p)} \ {\. nested_prop_atoms \ \ (nested_prop_atoms\<^sub>\ (fst p) X) \ nested_prop_atoms (snd p)}" using af\<^sub>\_fst_range af\<^sub>\_snd_range by blast finally show ?thesis . qed - -lemma af\<^sub>\_fst: - "fst (af\<^sub>\ X p w) = af (fst p) w" - by (induction w rule: rev_induct) simp+ - -lemma af\<^sub>\_snd: - "\ af (snd p) w \ false\<^sub>n \ snd (af\<^sub>\ X p w) = af (snd p) w" - by (induction w rule: rev_induct) (simp_all, metis af_letter\<^sub>\_snd(2) af_letter.simps(2) af_letter_congruent) - -lemma af\<^sub>\_snd': - "\i. \ snd (af\<^sub>\ X p (take i w)) \ false\<^sub>n \ snd (af\<^sub>\ X p w) = af (snd p) w" - by (induction w rule: rev_induct) (simp_all, metis af_letter\<^sub>\_snd(2) diff_is_0_eq foldl_Nil le_cases take_all take_eq_Nil) - -lemma af\<^sub>\_step: - "snd (af\<^sub>\ X (\, \) w) \ false\<^sub>n \ snd (af\<^sub>\ X (\, \) (w @ [\])) = (af \ (w @ [\]))[X]\<^sub>\" - by (simp add: af\<^sub>\_fst) - -lemma af\<^sub>\_segments: - "af\<^sub>\ X (\, \) w = (af \ w, (af \ w)[X]\<^sub>\) \ af\<^sub>\ X (\, \) (w @ w') = af\<^sub>\ X (af \ w, (af \ w)[X]\<^sub>\) w'" - by (induction w' rule: rev_induct) fastforce+ - - -lemma af\<^sub>\_semantics_ltr: - assumes - "\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" - shows - "\m. \k\m. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" -proof - define resets where "resets = {i. snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix i w)) \ false\<^sub>n}" - define m where "m = (if resets = {} then 0 else Suc (Max resets))" - - from assms obtain i where 1: "suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" - by blast - - { - fix j - assume "i \ j" and "j \ resets" - - let ?\ = "af \ (prefix (Suc j) w)" - - from 1 have "\n. suffix n (suffix i w) \\<^sub>n af \ (prefix i w @ prefix n (suffix i w))[X]\<^sub>\" - by (simp add: GF_advice_af) - - then have "suffix (Suc j) w \\<^sub>n af \ (prefix (Suc j) w)[X]\<^sub>\" - by (metis (no_types) \i \ j\ add.right_neutral le_SucI le_Suc_ex subsequence_append subsequence_shift suffix_suffix) - - then have "\k>j. \ af (af \ (prefix (Suc j) w)[X]\<^sub>\) (w [Suc j \ k]) \ false\<^sub>n" - by (metis ltl_implies_satisfiable_prefix subsequence_prefix_suffix) - - then have "\k>j. \ snd (af\<^sub>\ X (?\, ?\[X]\<^sub>\) (w [Suc j \ k])) \ false\<^sub>n" - by (metis af\<^sub>\_snd snd_eqD) - - moreover - - { - have "fst (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Suc j) w)) = ?\" - by (simp add: af\<^sub>\_fst) - - moreover - - have "snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix j w)) \ false\<^sub>n" - using \j \ resets\ resets_def by blast - - ultimately have "af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Suc j) w) = (?\, ?\[X]\<^sub>\)" - by (metis (no_types) af\<^sub>\_step prod.collapse subseq_to_Suc zero_le) - } - - ultimately have "\k>j. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) ((w [0 \ Suc j]) @ (w [Suc j \ k]))) \ false\<^sub>n" - by (simp add: af\<^sub>\_segments) - - then have "\k>j. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix k w)) \ false\<^sub>n" - by (metis Suc_leI le0 subsequence_append_general) - - then have "\k \ resets. k \ j" - using \j \ resets\ resets_def le_less_linear by blast - } - - then have "finite resets" - by (meson finite_nat_set_iff_bounded_le infinite_nat_iff_unbounded_le) - - then have "resets \ {} \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Max resets) w)) \ false\<^sub>n" - using Max_in resets_def by blast - - then have "\k\m. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix k w)) \ false\<^sub>n" - by (metis (mono_tags, lifting) Max_ge Suc_n_not_le_n \finite resets\ empty_Collect_eq m_def mem_Collect_eq order.trans resets_def) - - then show "\k\m. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" - using le_SucI by blast -qed - -lemma af\<^sub>\_semantics_rtl: - assumes - "\n. \k\n. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" - shows - "\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" -proof - define resets where "resets = {i. snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix i w)) \ false\<^sub>n}" - define m where "m = (if resets = {} then 0 else Suc (Max resets))" - - from assms obtain n where "\k\n. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Suc k) w)) \ false\<^sub>n" - by blast - - then have "\k>n. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix k w)) \ false\<^sub>n" - by (metis le_SucE lessE less_imp_le_nat) - - then have "finite resets" - by (metis (mono_tags, lifting) infinite_nat_iff_unbounded mem_Collect_eq resets_def) - - then have "\i\m. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix i w)) \ false\<^sub>n" - unfolding resets_def m_def using Max_ge not_less_eq_eq by auto - - then have "\i. \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) ((w [0 \ m]) @ (w [m \ i]))) \ false\<^sub>n" - by (metis le0 nat_le_linear subseq_to_smaller subsequence_append_general) - - moreover - - let ?\ = "af \ (prefix m w)" - - have "resets \ {} \ snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix (Max resets) w)) \ false\<^sub>n" - using Max_in \finite resets\ resets_def by blast - - then have prefix_\': "snd (af\<^sub>\ X (\, \[X]\<^sub>\) (prefix m w)) = ?\[X]\<^sub>\" - by (auto simp: GF_advice_congruent m_def af\<^sub>\_fst) - - ultimately have "\i. \ snd (af\<^sub>\ X (?\, ?\[X]\<^sub>\) (w [m \ i])) \ false\<^sub>n" - by (metis af\<^sub>\_fst foldl_append fst_conv prod.collapse) - - then have "\i. \ af (?\[X]\<^sub>\) (w [m \ i]) \ false\<^sub>n" - by (metis prefix_\' af\<^sub>\_fst af\<^sub>\_snd' fst_conv prod.collapse subsequence_take) - - then show "suffix m w \\<^sub>n af \ (prefix m w)[X]\<^sub>\" - by (metis GF_advice_\LTL(1) satisfiable_prefix_implies_\LTL add.right_neutral subsequence_shift) -qed +end end - -end \ No newline at end of file diff --git a/thys/LTL_Master_Theorem/Logical_Characterization/Advice.thy b/thys/LTL_Master_Theorem/Logical_Characterization/Advice.thy --- a/thys/LTL_Master_Theorem/Logical_Characterization/Advice.thy +++ b/thys/LTL_Master_Theorem/Logical_Characterization/Advice.thy @@ -1,996 +1,1012 @@ (* Author: Benedikt Seidl Author: Salomon Sickert License: BSD *) section \Advice functions\ theory Advice imports LTL.LTL LTL.Equivalence_Relations Syntactic_Fragments_and_Stability After begin subsection \The GF and FG Advice Functions\ fun GF_advice :: "'a ltln \ 'a ltln set \ 'a ltln" ("_[_]\<^sub>\" [90,60] 89) where "(X\<^sub>n \)[X]\<^sub>\ = X\<^sub>n (\[X]\<^sub>\)" | "(\\<^sub>1 and\<^sub>n \\<^sub>2)[X]\<^sub>\ = (\\<^sub>1[X]\<^sub>\) and\<^sub>n (\\<^sub>2[X]\<^sub>\)" | "(\\<^sub>1 or\<^sub>n \\<^sub>2)[X]\<^sub>\ = (\\<^sub>1[X]\<^sub>\) or\<^sub>n (\\<^sub>2[X]\<^sub>\)" | "(\\<^sub>1 W\<^sub>n \\<^sub>2)[X]\<^sub>\ = (\\<^sub>1[X]\<^sub>\) W\<^sub>n (\\<^sub>2[X]\<^sub>\)" | "(\\<^sub>1 R\<^sub>n \\<^sub>2)[X]\<^sub>\ = (\\<^sub>1[X]\<^sub>\) R\<^sub>n (\\<^sub>2[X]\<^sub>\)" | "(\\<^sub>1 U\<^sub>n \\<^sub>2)[X]\<^sub>\ = (if (\\<^sub>1 U\<^sub>n \\<^sub>2) \ X then (\\<^sub>1[X]\<^sub>\) W\<^sub>n (\\<^sub>2[X]\<^sub>\) else false\<^sub>n)" | "(\\<^sub>1 M\<^sub>n \\<^sub>2)[X]\<^sub>\ = (if (\\<^sub>1 M\<^sub>n \\<^sub>2) \ X then (\\<^sub>1[X]\<^sub>\) R\<^sub>n (\\<^sub>2[X]\<^sub>\) else false\<^sub>n)" | "\[_]\<^sub>\ = \" fun FG_advice :: "'a ltln \ 'a ltln set \ 'a ltln" ("_[_]\<^sub>\" [90,60] 89) where "(X\<^sub>n \)[Y]\<^sub>\ = X\<^sub>n (\[Y]\<^sub>\)" | "(\\<^sub>1 and\<^sub>n \\<^sub>2)[Y]\<^sub>\ = (\\<^sub>1[Y]\<^sub>\) and\<^sub>n (\\<^sub>2[Y]\<^sub>\)" | "(\\<^sub>1 or\<^sub>n \\<^sub>2)[Y]\<^sub>\ = (\\<^sub>1[Y]\<^sub>\) or\<^sub>n (\\<^sub>2[Y]\<^sub>\)" | "(\\<^sub>1 U\<^sub>n \\<^sub>2)[Y]\<^sub>\ = (\\<^sub>1[Y]\<^sub>\) U\<^sub>n (\\<^sub>2[Y]\<^sub>\)" | "(\\<^sub>1 M\<^sub>n \\<^sub>2)[Y]\<^sub>\ = (\\<^sub>1[Y]\<^sub>\) M\<^sub>n (\\<^sub>2[Y]\<^sub>\)" | "(\\<^sub>1 W\<^sub>n \\<^sub>2)[Y]\<^sub>\ = (if (\\<^sub>1 W\<^sub>n \\<^sub>2) \ Y then true\<^sub>n else (\\<^sub>1[Y]\<^sub>\) U\<^sub>n (\\<^sub>2[Y]\<^sub>\))" | "(\\<^sub>1 R\<^sub>n \\<^sub>2)[Y]\<^sub>\ = (if (\\<^sub>1 R\<^sub>n \\<^sub>2) \ Y then true\<^sub>n else (\\<^sub>1[Y]\<^sub>\) M\<^sub>n (\\<^sub>2[Y]\<^sub>\))" | "\[_]\<^sub>\ = \" lemma GF_advice_\LTL: "\[X]\<^sub>\ \ \LTL" "\ \ \LTL \ \[X]\<^sub>\ = \" by (induction \) auto lemma FG_advice_\LTL: "\[X]\<^sub>\ \ \LTL" "\ \ \LTL \ \[X]\<^sub>\ = \" by (induction \) auto lemma GF_advice_subfrmlsn: "subfrmlsn (\[X]\<^sub>\) \ {\[X]\<^sub>\ | \. \ \ subfrmlsn \}" by (induction \) force+ lemma FG_advice_subfrmlsn: "subfrmlsn (\[Y]\<^sub>\) \ {\[Y]\<^sub>\ | \. \ \ subfrmlsn \}" by (induction \) force+ lemma GF_advice_subfrmlsn_card: "card (subfrmlsn (\[X]\<^sub>\)) \ card (subfrmlsn \)" proof - have "card (subfrmlsn (\[X]\<^sub>\)) \ card {\[X]\<^sub>\ | \. \ \ subfrmlsn \}" by (simp add: subfrmlsn_finite GF_advice_subfrmlsn card_mono) also have "\ \ card (subfrmlsn \)" by (metis Collect_mem_eq card_image_le image_Collect subfrmlsn_finite) finally show ?thesis . qed lemma FG_advice_subfrmlsn_card: "card (subfrmlsn (\[Y]\<^sub>\)) \ card (subfrmlsn \)" proof - have "card (subfrmlsn (\[Y]\<^sub>\)) \ card {\[Y]\<^sub>\ | \. \ \ subfrmlsn \}" by (simp add: subfrmlsn_finite FG_advice_subfrmlsn card_mono) also have "\ \ card (subfrmlsn \)" by (metis Collect_mem_eq card_image_le image_Collect subfrmlsn_finite) finally show ?thesis . qed lemma GF_advice_monotone: "X \ Y \ w \\<^sub>n \[X]\<^sub>\ \ w \\<^sub>n \[Y]\<^sub>\" proof (induction \ arbitrary: w) case (Until_ltln \ \) then show ?case by (cases "\ U\<^sub>n \ \ X") (simp_all, blast) next case (Release_ltln \ \) then show ?case by (simp, blast) next case (WeakUntil_ltln \ \) then show ?case by (simp, blast) next case (StrongRelease_ltln \ \) then show ?case by (cases "\ M\<^sub>n \ \ X") (simp_all, blast) qed auto lemma FG_advice_monotone: "X \ Y \ w \\<^sub>n \[X]\<^sub>\ \ w \\<^sub>n \[Y]\<^sub>\" proof (induction \ arbitrary: w) case (Until_ltln \ \) then show ?case by (simp, blast) next case (Release_ltln \ \) then show ?case by (cases "\ R\<^sub>n \ \ X") (auto, blast) next case (WeakUntil_ltln \ \) then show ?case by (cases "\ W\<^sub>n \ \ X") (auto, blast) next case (StrongRelease_ltln \ \) then show ?case by (simp, blast) qed auto lemma GF_advice_ite_simps[simp]: "(if P then true\<^sub>n else false\<^sub>n)[X]\<^sub>\ = (if P then true\<^sub>n else false\<^sub>n)" "(if P then false\<^sub>n else true\<^sub>n)[X]\<^sub>\ = (if P then false\<^sub>n else true\<^sub>n)" by simp_all lemma FG_advice_ite_simps[simp]: "(if P then true\<^sub>n else false\<^sub>n)[Y]\<^sub>\ = (if P then true\<^sub>n else false\<^sub>n)" "(if P then false\<^sub>n else true\<^sub>n)[Y]\<^sub>\ = (if P then false\<^sub>n else true\<^sub>n)" by simp_all subsection \Advice Functions on Nested Propositions\ definition nested_prop_atoms\<^sub>\ :: "'a ltln \ 'a ltln set \ 'a ltln set" where "nested_prop_atoms\<^sub>\ \ X = {\[X]\<^sub>\ | \. \ \ nested_prop_atoms \}" definition nested_prop_atoms\<^sub>\ :: "'a ltln \ 'a ltln set \ 'a ltln set" where "nested_prop_atoms\<^sub>\ \ X = {\[X]\<^sub>\ | \. \ \ nested_prop_atoms \}" lemma nested_prop_atoms\<^sub>\_finite: "finite (nested_prop_atoms\<^sub>\ \ X)" by (simp add: nested_prop_atoms\<^sub>\_def nested_prop_atoms_finite) lemma nested_prop_atoms\<^sub>\_finite: "finite (nested_prop_atoms\<^sub>\ \ X)" by (simp add: nested_prop_atoms\<^sub>\_def nested_prop_atoms_finite) lemma nested_prop_atoms\<^sub>\_card: "card (nested_prop_atoms\<^sub>\ \ X) \ card (nested_prop_atoms \)" unfolding nested_prop_atoms\<^sub>\_def by (metis Collect_mem_eq card_image_le image_Collect nested_prop_atoms_finite) lemma nested_prop_atoms\<^sub>\_card: "card (nested_prop_atoms\<^sub>\ \ X) \ card (nested_prop_atoms \)" unfolding nested_prop_atoms\<^sub>\_def by (metis Collect_mem_eq card_image_le image_Collect nested_prop_atoms_finite) lemma GF_advice_nested_prop_atoms\<^sub>\: "nested_prop_atoms (\[X]\<^sub>\) \ nested_prop_atoms\<^sub>\ \ X" by (induction \) (unfold nested_prop_atoms\<^sub>\_def, force+) lemma FG_advice_nested_prop_atoms\<^sub>\: "nested_prop_atoms (\[Y]\<^sub>\) \ nested_prop_atoms\<^sub>\ \ Y" by (induction \) (unfold nested_prop_atoms\<^sub>\_def, force+) lemma nested_prop_atoms\<^sub>\_subset: "nested_prop_atoms \ \ nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ X \ nested_prop_atoms\<^sub>\ \ X" unfolding nested_prop_atoms\<^sub>\_def by blast lemma nested_prop_atoms\<^sub>\_subset: "nested_prop_atoms \ \ nested_prop_atoms \ \ nested_prop_atoms\<^sub>\ \ Y \ nested_prop_atoms\<^sub>\ \ Y" unfolding nested_prop_atoms\<^sub>\_def by blast lemma GF_advice_nested_prop_atoms_card: "card (nested_prop_atoms (\[X]\<^sub>\)) \ card (nested_prop_atoms \)" proof - have "card (nested_prop_atoms (\[X]\<^sub>\)) \ card (nested_prop_atoms\<^sub>\ \ X)" by (simp add: nested_prop_atoms\<^sub>\_finite GF_advice_nested_prop_atoms\<^sub>\ card_mono) then show ?thesis using nested_prop_atoms\<^sub>\_card le_trans by blast qed lemma FG_advice_nested_prop_atoms_card: "card (nested_prop_atoms (\[Y]\<^sub>\)) \ card (nested_prop_atoms \)" proof - have "card (nested_prop_atoms (\[Y]\<^sub>\)) \ card (nested_prop_atoms\<^sub>\ \ Y)" by (simp add: nested_prop_atoms\<^sub>\_finite FG_advice_nested_prop_atoms\<^sub>\ card_mono) then show ?thesis using nested_prop_atoms\<^sub>\_card le_trans by blast qed subsection \Intersecting the Advice Set\ lemma GF_advice_inter: "X \ subformulas\<^sub>\ \ \ S \ \[X \ S]\<^sub>\ = \[X]\<^sub>\" by (induction \) auto lemma GF_advice_inter_subformulas: "\[X \ subformulas\<^sub>\ \]\<^sub>\ = \[X]\<^sub>\" using GF_advice_inter by blast lemma GF_advice_minus_subformulas: "\ \ subformulas\<^sub>\ \ \ \[X - {\}]\<^sub>\ = \[X]\<^sub>\" proof - assume "\ \ subformulas\<^sub>\ \" then have "subformulas\<^sub>\ \ \ X \ X - {\}" by blast then show "\[X - {\}]\<^sub>\ = \[X]\<^sub>\" by (metis GF_advice_inter Diff_subset Int_absorb1 inf.commute) qed lemma GF_advice_minus_size: "\size \ \ size \; \ \ \\ \ \[X - {\}]\<^sub>\ = \[X]\<^sub>\" using subfrmlsn_size subformulas\<^sub>\_subfrmlsn GF_advice_minus_subformulas by fastforce lemma FG_advice_inter: "Y \ subformulas\<^sub>\ \ \ S \ \[Y \ S]\<^sub>\ = \[Y]\<^sub>\" by (induction \) auto lemma FG_advice_inter_subformulas: "\[Y \ subformulas\<^sub>\ \]\<^sub>\ = \[Y]\<^sub>\" using FG_advice_inter by blast lemma FG_advice_minus_subformulas: "\ \ subformulas\<^sub>\ \ \ \[Y - {\}]\<^sub>\ = \[Y]\<^sub>\" proof - assume "\ \ subformulas\<^sub>\ \" then have "subformulas\<^sub>\ \ \ Y \ Y - {\}" by blast then show "\[Y - {\}]\<^sub>\ = \[Y]\<^sub>\" by (metis FG_advice_inter Diff_subset Int_absorb1 inf.commute) qed lemma FG_advice_minus_size: "\size \ \ size \; \ \ \\ \ \[Y - {\}]\<^sub>\ = \[Y]\<^sub>\" using subfrmlsn_size subformulas\<^sub>\_subfrmlsn FG_advice_minus_subformulas by fastforce lemma FG_advice_insert: "\\ \ Y; size \ < size \\ \ \[insert \ Y]\<^sub>\ = \[Y]\<^sub>\" by (metis FG_advice_minus_size Diff_insert_absorb less_imp_le neq_iff) subsection \Correctness GF-advice function\ lemma GF_advice_a1: "\\ \ w \ X; w \\<^sub>n \\ \ w \\<^sub>n \[X]\<^sub>\" proof (induction \ arbitrary: w) case (Next_ltln \) then show ?case using \_suffix by simp blast next case (Until_ltln \1 \2) have "\ (\1 W\<^sub>n \2) w \ \ (\1 U\<^sub>n \2) w" by fastforce then have "\ (\1 W\<^sub>n \2) w \ X" and "w \\<^sub>n \1 W\<^sub>n \2" using Until_ltln.prems ltln_strong_to_weak by blast+ then have "w \\<^sub>n \1[X]\<^sub>\ W\<^sub>n \2[X]\<^sub>\" using Until_ltln.IH by simp (meson \_suffix subset_trans sup.boundedE) moreover have "w \\<^sub>n \1 U\<^sub>n \2" using Until_ltln.prems by simp then have "\1 U\<^sub>n \2 \ \ (\1 U\<^sub>n \2) w" by force then have "\1 U\<^sub>n \2 \ X" using Until_ltln.prems by fast ultimately show ?case by auto next case (Release_ltln \1 \2) then show ?case by simp (meson \_suffix subset_trans sup.boundedE) next case (WeakUntil_ltln \1 \2) then show ?case by simp (meson \_suffix subset_trans sup.boundedE) next case (StrongRelease_ltln \1 \2) have "\ (\1 R\<^sub>n \2) w \ \ (\1 M\<^sub>n \2) w" by fastforce then have "\ (\1 R\<^sub>n \2) w \ X" and "w \\<^sub>n \1 R\<^sub>n \2" using StrongRelease_ltln.prems ltln_strong_to_weak by blast+ then have "w \\<^sub>n \1[X]\<^sub>\ R\<^sub>n \2[X]\<^sub>\" using StrongRelease_ltln.IH by simp (meson \_suffix subset_trans sup.boundedE) moreover have "w \\<^sub>n \1 M\<^sub>n \2" using StrongRelease_ltln.prems by simp then have "\1 M\<^sub>n \2 \ \ (\1 M\<^sub>n \2) w" by force then have "\1 M\<^sub>n \2 \ X" using StrongRelease_ltln.prems by fast ultimately show ?case by auto qed auto lemma GF_advice_a2_helper: "\\\ \ X. w \\<^sub>n G\<^sub>n (F\<^sub>n \); w \\<^sub>n \[X]\<^sub>\\ \ w \\<^sub>n \" proof (induction \ arbitrary: w) case (Next_ltln \) then show ?case unfolding GF_advice.simps semantics_ltln.simps(7) using GF_suffix by blast next case (Until_ltln \1 \2) then have "\1 U\<^sub>n \2 \ X" using ccontr[of "\1 U\<^sub>n \2 \ X"] by force then have "w \\<^sub>n F\<^sub>n \2" using Until_ltln.prems by fastforce moreover have "w \\<^sub>n (\1 U\<^sub>n \2)[X]\<^sub>\" using Until_ltln.prems by simp then have "w \\<^sub>n (\1[X]\<^sub>\) W\<^sub>n (\2[X]\<^sub>\)" unfolding GF_advice.simps using `\1 U\<^sub>n \2 \ X` by simp then have "w \\<^sub>n \1 W\<^sub>n \2" unfolding GF_advice.simps semantics_ltln.simps(10) by (metis GF_suffix Until_ltln.IH Until_ltln.prems(1)) ultimately show ?case using ltln_weak_to_strong by blast next case (Release_ltln \1 \2) then show ?case unfolding GF_advice.simps semantics_ltln.simps(9) by (metis GF_suffix Release_ltln.IH Release_ltln.prems(1)) next case (WeakUntil_ltln \1 \2) then show ?case unfolding GF_advice.simps semantics_ltln.simps(10) by (metis GF_suffix) next case (StrongRelease_ltln \1 \2) then have "\1 M\<^sub>n \2 \ X" using ccontr[of "\1 M\<^sub>n \2 \ X"] by force then have "w \\<^sub>n F\<^sub>n \1" using StrongRelease_ltln.prems by fastforce moreover have "w \\<^sub>n (\1 M\<^sub>n \2)[X]\<^sub>\" using StrongRelease_ltln.prems by simp then have "w \\<^sub>n (\1[X]\<^sub>\) R\<^sub>n (\2[X]\<^sub>\)" unfolding GF_advice.simps using `\1 M\<^sub>n \2 \ X` by simp then have "w \\<^sub>n \1 R\<^sub>n \2" unfolding GF_advice.simps semantics_ltln.simps(9) by (metis GF_suffix StrongRelease_ltln.IH StrongRelease_ltln.prems(1)) ultimately show ?case using ltln_weak_to_strong by blast qed auto lemma GF_advice_a2: "\X \ \\ \ w; w \\<^sub>n \[X]\<^sub>\\ \ w \\<^sub>n \" by (metis GF_advice_a2_helper \\_elim subset_eq) lemma GF_advice_a3: "\X = \ \ w; X = \\ \ w\ \ w \\<^sub>n \ \ w \\<^sub>n \[X]\<^sub>\" using GF_advice_a1 GF_advice_a2 by fastforce subsection \Correctness FG-advice function\ lemma FG_advice_b1: "\\\ \ w \ Y; w \\<^sub>n \\ \ w \\<^sub>n \[Y]\<^sub>\" proof (induction \ arbitrary: w) case (Next_ltln \) then show ?case using \\_suffix by simp blast next case (Until_ltln \1 \2) then show ?case by simp (metis \\_suffix) next case (Release_ltln \1 \2) show ?case proof (cases "\1 R\<^sub>n \2 \ Y") case False then have "\1 R\<^sub>n \2 \ \\ (\1 R\<^sub>n \2) w" using Release_ltln.prems by blast then have "\ w \\<^sub>n G\<^sub>n \2" by fastforce then have "w \\<^sub>n \1 M\<^sub>n \2" using Release_ltln.prems ltln_weak_to_strong by blast moreover have "\\ (\1 M\<^sub>n \2) w \ \\ (\1 R\<^sub>n \2) w" by fastforce then have "\\ (\1 M\<^sub>n \2) w \ Y" using Release_ltln.prems by blast ultimately show ?thesis using Release_ltln.IH by simp (metis \\_suffix) qed simp next case (WeakUntil_ltln \1 \2) show ?case proof (cases "\1 W\<^sub>n \2 \ Y") case False then have "\1 W\<^sub>n \2 \ \\ (\1 W\<^sub>n \2) w" using WeakUntil_ltln.prems by blast then have "\ w \\<^sub>n G\<^sub>n \1" by fastforce then have "w \\<^sub>n \1 U\<^sub>n \2" using WeakUntil_ltln.prems ltln_weak_to_strong by blast moreover have "\\ (\1 U\<^sub>n \2) w \ \\ (\1 W\<^sub>n \2) w" by fastforce then have "\\ (\1 U\<^sub>n \2) w \ Y" using WeakUntil_ltln.prems by blast ultimately show ?thesis using WeakUntil_ltln.IH by simp (metis \\_suffix) qed simp next case (StrongRelease_ltln \1 \2) then show ?case by simp (metis \\_suffix) qed auto lemma FG_advice_b2_helper: "\\\ \ Y. w \\<^sub>n G\<^sub>n \; w \\<^sub>n \[Y]\<^sub>\\ \ w \\<^sub>n \" proof (induction \ arbitrary: w) case (Until_ltln \1 \2) then show ?case by simp (metis (no_types, lifting) suffix_suffix) next case (Release_ltln \1 \2) then show ?case proof (cases "\1 R\<^sub>n \2 \ Y") case True then show ?thesis using Release_ltln.prems by force next case False then have "w \\<^sub>n (\1[Y]\<^sub>\) M\<^sub>n (\2[Y]\<^sub>\)" using Release_ltln.prems by simp then have "w \\<^sub>n \1 M\<^sub>n \2" using Release_ltln by simp (metis (no_types, lifting) suffix_suffix) then show ?thesis using ltln_strong_to_weak by fast qed next case (WeakUntil_ltln \1 \2) then show ?case proof (cases "\1 W\<^sub>n \2 \ Y") case True then show ?thesis using WeakUntil_ltln.prems by force next case False then have "w \\<^sub>n (\1[Y]\<^sub>\) U\<^sub>n (\2[Y]\<^sub>\)" using WeakUntil_ltln.prems by simp then have "w \\<^sub>n \1 U\<^sub>n \2" using WeakUntil_ltln by simp (metis (no_types, lifting) suffix_suffix) then show ?thesis using ltln_strong_to_weak by fast qed next case (StrongRelease_ltln \1 \2) then show ?case by simp (metis (no_types, lifting) suffix_suffix) qed auto lemma FG_advice_b2: "\Y \ \ \ w; w \\<^sub>n \[Y]\<^sub>\\ \ w \\<^sub>n \" by (metis FG_advice_b2_helper \_elim subset_eq) lemma FG_advice_b3: "\Y = \\ \ w; Y = \ \ w\ \ w \\<^sub>n \ \ w \\<^sub>n \[Y]\<^sub>\" using FG_advice_b1 FG_advice_b2 by fastforce subsection \Advice Functions and the ``after'' Function\ lemma GF_advice_af_letter: "(x ## w) \\<^sub>n \[X]\<^sub>\ \ w \\<^sub>n (af_letter \ x)[X]\<^sub>\" proof (induction \) case (Until_ltln \1 \2) then have "w \\<^sub>n af_letter ((\1 U\<^sub>n \2)[X]\<^sub>\) x" using af_letter_build by blast then show ?case using Until_ltln.IH af_letter_build by fastforce next case (Release_ltln \1 \2) then have "w \\<^sub>n af_letter ((\1 R\<^sub>n \2)[X]\<^sub>\) x" using af_letter_build by blast then show ?case using Release_ltln.IH af_letter_build by auto next case (WeakUntil_ltln \1 \2) then have "w \\<^sub>n af_letter ((\1 W\<^sub>n \2)[X]\<^sub>\) x" using af_letter_build by blast then show ?case using WeakUntil_ltln.IH af_letter_build by auto next case (StrongRelease_ltln \1 \2) then have "w \\<^sub>n af_letter ((\1 M\<^sub>n \2)[X]\<^sub>\) x" using af_letter_build by blast then show ?case using StrongRelease_ltln.IH af_letter_build by force qed auto lemma FG_advice_af_letter: "w \\<^sub>n (af_letter \ x)[Y]\<^sub>\ \ (x ## w) \\<^sub>n \[Y]\<^sub>\" proof (induction \) case (Prop_ltln a) then show ?case using semantics_ltln.simps(3) by fastforce next case (Until_ltln \1 \2) then show ?case unfolding af_letter.simps FG_advice.simps semantics_ltln.simps(5,6) using af_letter_build apply (cases "w \\<^sub>n af_letter \2 x[Y]\<^sub>\") apply force by (metis af_letter.simps(8) semantics_ltln.simps(5) semantics_ltln.simps(6)) next case (Release_ltln \1 \2) then show ?case apply (cases "\1 R\<^sub>n \2 \ Y") apply simp unfolding af_letter.simps FG_advice.simps semantics_ltln.simps(5,6) using af_letter_build apply (cases "w \\<^sub>n af_letter \1 x[Y]\<^sub>\") apply force by (metis (full_types) af_letter.simps(11) semantics_ltln.simps(5) semantics_ltln.simps(6)) next case (WeakUntil_ltln \1 \2) then show ?case apply (cases "\1 W\<^sub>n \2 \ Y") apply simp unfolding af_letter.simps FG_advice.simps semantics_ltln.simps(5,6) using af_letter_build apply (cases "w \\<^sub>n af_letter \2 x[Y]\<^sub>\") apply force by (metis (full_types) af_letter.simps(8) semantics_ltln.simps(5) semantics_ltln.simps(6)) next case (StrongRelease_ltln \1 \2) then show ?case unfolding af_letter.simps FG_advice.simps semantics_ltln.simps(5,6) using af_letter_build apply (cases "w \\<^sub>n af_letter \1 x[Y]\<^sub>\") apply force by (metis af_letter.simps(11) semantics_ltln.simps(5) semantics_ltln.simps(6)) qed auto lemma GF_advice_af: "(w \ w') \\<^sub>n \[X]\<^sub>\ \ w' \\<^sub>n (af \ w)[X]\<^sub>\" by (induction w arbitrary: \) (simp, insert GF_advice_af_letter, fastforce) lemma FG_advice_af: "w' \\<^sub>n (af \ w)[X]\<^sub>\ \ (w \ w') \\<^sub>n \[X]\<^sub>\" by (induction w arbitrary: \) (simp, insert FG_advice_af_letter, fastforce) lemma GF_advice_af_2: "w \\<^sub>n \[X]\<^sub>\ \ suffix i w \\<^sub>n (af \ (prefix i w))[X]\<^sub>\" using GF_advice_af by force lemma FG_advice_af_2: "suffix i w \\<^sub>n (af \ (prefix i w))[X]\<^sub>\ \ w \\<^sub>n \[X]\<^sub>\" using FG_advice_af by force (* TODO move to Omega_Words_Fun.thy ?? *) lemma prefix_suffix_subsequence: "prefix i (suffix j w) = (w [j \ i + j])" by (simp add: add.commute) text \We show this generic lemma to prove the following theorems:\ lemma GF_advice_sync: fixes index :: "nat \ nat" fixes formula :: "nat \ 'a ltln" assumes "\i. i < n \ \j. suffix ((index i) + j) w \\<^sub>n af (formula i) (w [index i \ (index i) + j])[X]\<^sub>\" shows "\k. (\i < n. k \ index i \ suffix k w \\<^sub>n af (formula i) (w [index i \ k])[X]\<^sub>\)" using assms proof (induction n) case (Suc n) obtain k1 where leq1: "\i. i < n \ k1 \ index i" and suffix1: "\i. i < n \ suffix k1 w \\<^sub>n af (formula i) (w [(index i) \ k1])[X]\<^sub>\" using Suc less_SucI by blast obtain k2 where leq2: "k2 \ index n" and suffix2: "suffix k2 w \\<^sub>n af (formula n) (w [index n \ k2])[X]\<^sub>\" using le_add1 Suc.prems by blast define k where "k \ k1 + k2" have "\i. i < Suc n \ k \ index i" unfolding k_def by (metis leq1 leq2 less_SucE trans_le_add1 trans_le_add2) moreover { have "\i. i < n \ suffix k w \\<^sub>n af (formula i) (w [(index i) \ k])[X]\<^sub>\" unfolding k_def by (metis GF_advice_af_2[OF suffix1, unfolded suffix_suffix prefix_suffix_subsequence] af_subsequence_append leq1 add.commute le_add1) moreover have "suffix k w \\<^sub>n af (formula n) (w [index n \ k])[X]\<^sub>\" unfolding k_def by (metis GF_advice_af_2[OF suffix2, unfolded suffix_suffix prefix_suffix_subsequence] af_subsequence_append leq2 add.commute le_add1) ultimately have "\i. i \ n \ suffix k w \\<^sub>n af (formula i) (w [(index i) \ k])[X]\<^sub>\" using nat_less_le by blast } ultimately show ?case by (meson less_Suc_eq_le) qed simp lemma GF_advice_sync_and: assumes "\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" assumes "\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" shows "\i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\ \ suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" proof - let ?formula = "\i :: nat. (if (i = 0) then \ else \)" have assms: "\i. i < 2 \ \j. suffix j w \\<^sub>n af (?formula i) (w [0 \ j])[X]\<^sub>\" using assms by simp obtain k where k_def: "\i :: nat. i < 2 \ suffix k w \\<^sub>n af (if i = 0 then \ else \) (prefix k w)[X]\<^sub>\" using GF_advice_sync[of "2" "\i. 0" w ?formula, simplified, OF assms, simplified] by blast show ?thesis using k_def[of 0] k_def[of 1] by auto qed lemma GF_advice_sync_less: assumes "\i. i < n \ \j. suffix (i + j) w \\<^sub>n af \ (w [i \ j + i])[X]\<^sub>\" assumes "\j. suffix (n + j) w \\<^sub>n af \ (w [n \ j + n])[X]\<^sub>\" shows "\k \ n. (\j < n. suffix k w \\<^sub>n af \ (w [j \ k])[X]\<^sub>\) \ suffix k w \\<^sub>n af \ (w [n \ k])[X]\<^sub>\" proof - let ?index = "\i. min i n" let ?formula = "\i. if (i < n) then \ else \" { fix i assume "i < Suc n" then have min_def: "min i n = i" by simp have "\j. suffix ((?index i) + j) w \\<^sub>n af (?formula i) (w [?index i \ (?index i) + j])[X]\<^sub>\" unfolding min_def by (cases "i < n") (metis (full_types) assms(1) add.commute, metis (full_types) assms(2) \i < Suc n\ add.commute less_SucE) } then obtain k where leq: "(\i. i < Suc n \ min i n \ k)" and suffix: "\i. i < Suc n \ suffix k w \\<^sub>n af (if i < n then \ else \) (w [min i n \ k])[X]\<^sub>\" using GF_advice_sync[of "Suc n" ?index w ?formula X] by metis have "\j < n. suffix k w \\<^sub>n af \ (w [j \ k])[X]\<^sub>\" using suffix by (metis (full_types) less_SucI min.strict_order_iff) moreover have "suffix k w \\<^sub>n af \ (w [n \ k])[X]\<^sub>\" using suffix[of n, simplified] by blast moreover have "k \ n" using leq by presburger ultimately show ?thesis by auto qed lemma GF_advice_sync_lesseq: assumes "\i. i \ n \ \j. suffix (i + j) w \\<^sub>n af \ (w [i \ j + i])[X]\<^sub>\" assumes "\j. suffix (n + j) w \\<^sub>n af \ (w [n \ j + n])[X]\<^sub>\" shows "\k \ n. (\j \ n. suffix k w \\<^sub>n af \ (w [j \ k])[X]\<^sub>\) \ suffix k w \\<^sub>n af \ (w [n \ k])[X]\<^sub>\" proof - let ?index = "\i. min i n" let ?formula = "\i. if (i \ n) then \ else \" { fix i assume "i < Suc (Suc n)" hence "\j. suffix ((?index i) + j) w \\<^sub>n af (?formula i) (w [?index i \ (?index i) + j])[X]\<^sub>\" proof (cases "i < Suc n") case True then have min_def: "min i n = i" by simp show ?thesis unfolding min_def by (metis (full_types) assms(1) Suc_leI Suc_le_mono True add.commute) next case False then have i_def: "i = Suc n" using \i < Suc (Suc n)\ less_antisym by blast have min_def: "min i n = n" unfolding i_def by simp show ?thesis using assms(2) False by (simp add: min_def add.commute) qed } then obtain k where leq: "(\i. i \ Suc n \ min i n \ k)" and suffix: "\i :: nat. i < Suc (Suc n) \ suffix k w \\<^sub>n af (if i \ n then \ else \) (w [min i n \ k])[X]\<^sub>\" using GF_advice_sync[of "Suc (Suc n)" ?index w ?formula X] by (metis (no_types, hide_lams) less_Suc_eq min_le_iff_disj) have "\j \ n. suffix k w \\<^sub>n af \ (w [j \ k])[X]\<^sub>\" using suffix by (metis (full_types) le_SucI less_Suc_eq_le min.orderE) moreover have "suffix k w \\<^sub>n af \ (w [n \ k])[X]\<^sub>\" using suffix[of "Suc n", simplified] by linarith moreover have "k \ n" using leq by presburger ultimately show ?thesis by auto qed lemma af_subsequence_U_GF_advice: assumes "i \ n" assumes "suffix n w \\<^sub>n ((af \ (w [i \ n]))[X]\<^sub>\)" assumes "\j. j < i \ suffix n w \\<^sub>n ((af \ (w [j \ n]))[X]\<^sub>\)" shows "suffix (Suc n) w \\<^sub>n (af (\ U\<^sub>n \) (prefix (Suc n) w))[X]\<^sub>\" using assms proof (induction i arbitrary: w n) case 0 then have A: "suffix n w \\<^sub>n ((af \ (w [0 \ n]))[X]\<^sub>\)" by blast then have "suffix (Suc n) w \\<^sub>n (af \ (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF A, of 1] by simp then show ?case unfolding GF_advice.simps af_subsequence_U semantics_ltln.simps by blast next case (Suc i) have "suffix (Suc n) w \\<^sub>n (af \ (prefix (Suc n) w))[X]\<^sub>\" using Suc.prems(3)[OF zero_less_Suc, THEN GF_advice_af_2, unfolded suffix_suffix, of 1] by simp moreover have B: "(Suc (n - 1)) = n" using Suc by simp note Suc.IH[of "n - 1" "suffix 1 w", unfolded suffix_suffix] Suc.prems then have "suffix (Suc n) w \\<^sub>n (af (\ U\<^sub>n \) (w [1 \ (Suc n)]))[X]\<^sub>\" by (metis B One_nat_def Suc_le_mono Suc_mono plus_1_eq_Suc subsequence_shift) ultimately show ?case unfolding af_subsequence_U semantics_ltln.simps GF_advice.simps by blast qed lemma af_subsequence_M_GF_advice: assumes "i \ n" assumes "suffix n w \\<^sub>n ((af \ (w [i \ n]))[X]\<^sub>\)" assumes "\j. j \ i \ suffix n w \\<^sub>n ((af \ (w [j \ n]))[X]\<^sub>\)" shows "suffix (Suc n) w \\<^sub>n (af (\ M\<^sub>n \) (prefix (Suc n) w))[X]\<^sub>\" using assms proof (induction i arbitrary: w n) case 0 then have A: "suffix n w \\<^sub>n ((af \ (w [0 \ n]))[X]\<^sub>\)" by blast have "suffix (Suc n) w \\<^sub>n (af \ (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF A, of 1] by simp moreover have "suffix (Suc n) w \\<^sub>n (af \ (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF "0.prems"(2), of 1, unfolded suffix_suffix] by auto ultimately show ?case unfolding af_subsequence_M GF_advice.simps semantics_ltln.simps by blast next case (Suc i) have "suffix 1 (suffix n w) \\<^sub>n af (af \ (prefix n w)) [suffix n w 0][X]\<^sub>\" by (metis (no_types) GF_advice_af_2 Suc.prems(3) plus_1_eq_Suc subsequence_singleton suffix_0 suffix_suffix zero_le) then have "suffix (Suc n) w \\<^sub>n (af \ (prefix (Suc n) w))[X]\<^sub>\" using Suc.prems(3)[THEN GF_advice_af_2, unfolded suffix_suffix, of 1] by simp moreover have B: "(Suc (n - 1)) = n" using Suc by simp note Suc.IH[of _ "suffix 1 w", unfolded subsequence_shift suffix_suffix] then have "suffix (Suc n) w \\<^sub>n (af (\ M\<^sub>n \) (w [1 \ (Suc n)]))[X]\<^sub>\" by (metis B One_nat_def Suc_le_mono plus_1_eq_Suc Suc.prems) ultimately show ?case unfolding af_subsequence_M semantics_ltln.simps GF_advice.simps by blast qed lemma af_subsequence_R_GF_advice: assumes "i \ n" assumes "suffix n w \\<^sub>n ((af \ (w [i \ n]))[X]\<^sub>\)" assumes "\j. j \ i \ suffix n w \\<^sub>n ((af \ (w [j \ n]))[X]\<^sub>\)" shows "suffix (Suc n) w \\<^sub>n (af (\ R\<^sub>n \) (prefix (Suc n) w))[X]\<^sub>\" using assms proof (induction i arbitrary: w n) case 0 then have A: "suffix n w \\<^sub>n ((af \ (w [0 \ n]))[X]\<^sub>\)" by blast have "suffix (Suc n) w \\<^sub>n (af \ (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF A, of 1] by simp moreover have "suffix (Suc n) w \\<^sub>n (af \ (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF "0.prems"(2), of 1, unfolded suffix_suffix] by auto ultimately show ?case unfolding af_subsequence_R GF_advice.simps semantics_ltln.simps by blast next case (Suc i) have "suffix 1 (suffix n w) \\<^sub>n af (af \ (prefix n w)) [suffix n w 0][X]\<^sub>\" by (metis (no_types) GF_advice_af_2 Suc.prems(3) plus_1_eq_Suc subsequence_singleton suffix_0 suffix_suffix zero_le) then have "suffix (Suc n) w \\<^sub>n (af \ (prefix (Suc n) w))[X]\<^sub>\" using Suc.prems(3)[THEN GF_advice_af_2, unfolded suffix_suffix, of 1] by simp moreover have B: "(Suc (n - 1)) = n" using Suc by simp note Suc.IH[of _ "suffix 1 w", unfolded subsequence_shift suffix_suffix] then have "suffix (Suc n) w \\<^sub>n (af (\ R\<^sub>n \) (w [1 \ (Suc n)]))[X]\<^sub>\" by (metis B One_nat_def Suc_le_mono plus_1_eq_Suc Suc.prems) ultimately show ?case unfolding af_subsequence_R semantics_ltln.simps GF_advice.simps by blast qed lemma af_subsequence_W_GF_advice: assumes "i \ n" assumes "suffix n w \\<^sub>n ((af \ (w [i \ n]))[X]\<^sub>\)" assumes "\j. j < i \ suffix n w \\<^sub>n ((af \ (w [j \ n]))[X]\<^sub>\)" shows "suffix (Suc n) w \\<^sub>n (af (\ W\<^sub>n \) (prefix (Suc n) w))[X]\<^sub>\" using assms proof (induction i arbitrary: w n) case 0 then have A: "suffix n w \\<^sub>n ((af \ (w [0 \ n]))[X]\<^sub>\)" by blast have "suffix (Suc n) w \\<^sub>n (af \ (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF A, of 1] by simp then show ?case unfolding af_subsequence_W GF_advice.simps semantics_ltln.simps by blast next case (Suc i) have "suffix (Suc n) w \\<^sub>n (af \ (prefix (Suc n) w))[X]\<^sub>\" using Suc.prems(3)[OF zero_less_Suc, THEN GF_advice_af_2, unfolded suffix_suffix, of 1] by simp moreover have B: "(Suc (n - 1)) = n" using Suc by simp note Suc.IH[of "n - 1" "suffix 1 w", unfolded suffix_suffix] Suc.prems then have "suffix (Suc n) w \\<^sub>n (af (\ W\<^sub>n \) (w [1 \ (Suc n)]))[X]\<^sub>\" by (metis B One_nat_def Suc_le_mono Suc_mono plus_1_eq_Suc subsequence_shift) ultimately show ?case unfolding af_subsequence_W unfolding semantics_ltln.simps GF_advice.simps by simp qed lemma af_subsequence_R_GF_advice_connect: assumes "i \ n" assumes "suffix n w \\<^sub>n af (\ R\<^sub>n \) (w [i \ n])[X]\<^sub>\" assumes "\j. j \ i \ suffix n w \\<^sub>n ((af \ (w [j \ n]))[X]\<^sub>\)" shows "suffix (Suc n) w \\<^sub>n (af (\ R\<^sub>n \) (prefix (Suc n) w))[X]\<^sub>\" using assms proof (induction i arbitrary: w n) case 0 then have A: "suffix n w \\<^sub>n ((af \ (w [0 \ n]))[X]\<^sub>\)" by blast have "suffix (Suc n) w \\<^sub>n (af \ (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF A, of 1] by simp moreover have "suffix (Suc n) w \\<^sub>n (af (\ R\<^sub>n \) (w [0 \ Suc n]))[X]\<^sub>\" using GF_advice_af_2[OF "0.prems"(2), of 1, unfolded suffix_suffix] by simp ultimately show ?case unfolding af_subsequence_R GF_advice.simps semantics_ltln.simps by blast next case (Suc i) have "suffix 1 (suffix n w) \\<^sub>n af (af \ (prefix n w)) [suffix n w 0][X]\<^sub>\" by (metis (no_types) GF_advice_af_2 Suc.prems(3) plus_1_eq_Suc subsequence_singleton suffix_0 suffix_suffix zero_le) then have "suffix (Suc n) w \\<^sub>n (af \ (prefix (Suc n) w))[X]\<^sub>\" using Suc.prems(3)[THEN GF_advice_af_2, unfolded suffix_suffix, of 1] by simp moreover have B: "(Suc (n - 1)) = n" using Suc by simp note Suc.IH[of _ "suffix 1 w", unfolded subsequence_shift suffix_suffix] then have "suffix (Suc n) w \\<^sub>n (af (\ R\<^sub>n \) (w [1 \ (Suc n)]))[X]\<^sub>\" by (metis B One_nat_def Suc_le_mono plus_1_eq_Suc Suc.prems) ultimately show ?case unfolding af_subsequence_R semantics_ltln.simps GF_advice.simps by blast qed lemma af_subsequence_W_GF_advice_connect: assumes "i \ n" assumes "suffix n w \\<^sub>n af (\ W\<^sub>n \) (w [i \ n])[X]\<^sub>\" assumes "\j. j < i \ suffix n w \\<^sub>n ((af \ (w [j \ n]))[X]\<^sub>\)" shows "suffix (Suc n) w \\<^sub>n (af (\ W\<^sub>n \) (prefix (Suc n) w))[X]\<^sub>\" using assms proof (induction i arbitrary: w n) case 0 have "suffix (Suc n) w \\<^sub>n af_letter (af (\ W\<^sub>n \) (prefix n w)) (w n)[X]\<^sub>\" by (simp add: "0.prems"(2) GF_advice_af_letter) moreover have "prefix (Suc n) w = prefix n w @ [w n]" using subseq_to_Suc by blast ultimately show ?case by (metis (no_types) foldl.simps(1) foldl.simps(2) foldl_append) next case (Suc i) have "suffix (Suc n) w \\<^sub>n (af \ (prefix (Suc n) w))[X]\<^sub>\" using Suc.prems(3)[OF zero_less_Suc, THEN GF_advice_af_2, unfolded suffix_suffix, of 1] by simp moreover have "n > 0" and B: "(Suc (n - 1)) = n" using Suc by simp+ note Suc.IH[of "n - 1" "suffix 1 w", unfolded suffix_suffix] Suc.prems then have "suffix (Suc n) w \\<^sub>n (af (\ W\<^sub>n \) (w [1 \ (Suc n)]))[X]\<^sub>\" by (metis B One_nat_def Suc_le_mono Suc_mono plus_1_eq_Suc subsequence_shift) ultimately show ?case unfolding af_subsequence_W unfolding semantics_ltln.simps GF_advice.simps by simp qed subsection \Advice Functions and Propositional Entailment\ lemma GF_advice_prop_entailment: "\ \\<^sub>P \[X]\<^sub>\ \ {\. \[X]\<^sub>\ \ \} \\<^sub>P \" "false\<^sub>n \ \ \ {\. \[X]\<^sub>\ \ \} \\<^sub>P \ \ \ \\<^sub>P \[X]\<^sub>\" by (induction \) (auto, meson, meson) lemma GF_advice_iff_prop_entailment: "false\<^sub>n \ \ \ \ \\<^sub>P \[X]\<^sub>\ \ {\. \[X]\<^sub>\ \ \} \\<^sub>P \" by (metis GF_advice_prop_entailment) lemma FG_advice_prop_entailment: "true\<^sub>n \ \ \ \ \\<^sub>P \[Y]\<^sub>\ \ {\. \[Y]\<^sub>\ \ \} \\<^sub>P \" "{\. \[Y]\<^sub>\ \ \} \\<^sub>P \ \ \ \\<^sub>P \[Y]\<^sub>\" by (induction \) auto lemma FG_advice_iff_prop_entailment: "true\<^sub>n \ \ \ \ \\<^sub>P \[X]\<^sub>\ \ {\. \[X]\<^sub>\ \ \} \\<^sub>P \" by (metis FG_advice_prop_entailment) lemma GF_advice_subst: "\[X]\<^sub>\ = subst \ (\\. Some (\[X]\<^sub>\))" by (induction \) auto lemma FG_advice_subst: "\[X]\<^sub>\ = subst \ (\\. Some (\[X]\<^sub>\))" by (induction \) auto lemma GF_advice_prop_congruent: "\ \\<^sub>P \ \ \[X]\<^sub>\ \\<^sub>P \[X]\<^sub>\" "\ \\<^sub>P \ \ \[X]\<^sub>\ \\<^sub>P \[X]\<^sub>\" by (metis GF_advice_subst subst_respects_ltl_prop_entailment)+ lemma FG_advice_prop_congruent: "\ \\<^sub>P \ \ \[X]\<^sub>\ \\<^sub>P \[X]\<^sub>\" "\ \\<^sub>P \ \ \[X]\<^sub>\ \\<^sub>P \[X]\<^sub>\" by (metis FG_advice_subst subst_respects_ltl_prop_entailment)+ + +subsection \GF-advice with Equivalence Relations\ + locale GF_advice_congruent = ltl_equivalence + + fixes + normalise :: "'a ltln \ 'a ltln" assumes - GF_advice_congruent: "\ \ \ \ \[X]\<^sub>\ \ \[X]\<^sub>\" + normalise_eq: "\ \ normalise \" + assumes + normalise_monotonic: "w \\<^sub>n \[X]\<^sub>\ \ w \\<^sub>n (normalise \)[X]\<^sub>\" + assumes + normalise_eventually_equivalent: + "w \\<^sub>n (normalise \)[X]\<^sub>\ \ (\i. suffix i w \\<^sub>n (af \ (prefix i w))[X]\<^sub>\)" + assumes + GF_advice_congruent: "\ \ \ \ (normalise \)[X]\<^sub>\ \ (normalise \)[X]\<^sub>\" begin +lemma normalise_language_equivalent[simp]: + "w \\<^sub>n normalise \ \ w \\<^sub>n \" + using normalise_eq ltl_lang_equiv_def eq_implies_lang by blast + end -interpretation prop_GF_advice_compatible: GF_advice_congruent "(\\<^sub>P)" - by unfold_locales (simp add: GF_advice_prop_congruent(2)) +interpretation prop_GF_advice_compatible: GF_advice_congruent "(\\<^sub>P)" "id" + by unfold_locales (simp add: GF_advice_af GF_advice_prop_congruent(2))+ end diff --git a/thys/LTL_Master_Theorem/Logical_Characterization/Extra_Equivalence_Relations.thy b/thys/LTL_Master_Theorem/Logical_Characterization/Extra_Equivalence_Relations.thy new file mode 100644 --- /dev/null +++ b/thys/LTL_Master_Theorem/Logical_Characterization/Extra_Equivalence_Relations.thy @@ -0,0 +1,247 @@ +(* + Author: Salomon Sickert + License: BSD +*) + +section \Additional Equivalence Relations\ + +theory Extra_Equivalence_Relations +imports + LTL.LTL LTL.Equivalence_Relations After Advice +begin + +subsection \Propositional Equivalence with Implicit LTL Unfolding\ + +fun Unf :: "'a ltln \ 'a ltln" +where + "Unf (\ U\<^sub>n \) = ((\ U\<^sub>n \) and\<^sub>n Unf \) or\<^sub>n Unf \" +| "Unf (\ W\<^sub>n \) = ((\ W\<^sub>n \) and\<^sub>n Unf \) or\<^sub>n Unf \" +| "Unf (\ M\<^sub>n \) = ((\ M\<^sub>n \) or\<^sub>n Unf \) and\<^sub>n Unf \" +| "Unf (\ R\<^sub>n \) = ((\ R\<^sub>n \) or\<^sub>n Unf \) and\<^sub>n Unf \" +| "Unf (\ and\<^sub>n \) = Unf \ and\<^sub>n Unf \" +| "Unf (\ or\<^sub>n \) = Unf \ or\<^sub>n Unf \" +| "Unf \ = \" + +lemma Unf_sound: + "w \\<^sub>n Unf \ \ w \\<^sub>n \" +proof (induction \ arbitrary: w) + case (Until_ltln \1 \2) + then show ?case + by (simp, metis less_linear not_less0 suffix_0) +next + case (Release_ltln \1 \2) + then show ?case + by (simp, metis less_linear not_less0 suffix_0) +next + case (WeakUntil_ltln \1 \2) + then show ?case + by (simp, metis bot.extremum_unique bot_nat_def less_eq_nat.simps(1) suffix_0) +qed (simp_all, fastforce) + +lemma Unf_lang_equiv: + "\ \\<^sub>L Unf \" + by (simp add: Unf_sound ltl_lang_equiv_def) + +lemma Unf_idem: + "Unf (Unf \) \\<^sub>P Unf \" + by (induction \) (auto simp: ltl_prop_equiv_def) + +definition ltl_prop_unfold_equiv :: "'a ltln \ 'a ltln \ bool" (infix "\\<^sub>Q" 75) +where + "\ \\<^sub>Q \ \ (Unf \) \\<^sub>P (Unf \)" + +lemma ltl_prop_unfold_equiv_equivp: + "equivp (\\<^sub>Q)" + by (metis ltl_prop_equiv_equivp ltl_prop_unfold_equiv_def equivpI equivp_def reflpI sympI transpI) + +lemma unfolding_prop_unfold_idem: + "Unf \ \\<^sub>Q \" + unfolding ltl_prop_unfold_equiv_def by (rule Unf_idem) + +lemma unfolding_is_subst: "Unf \ = subst \ (\\. Some (Unf \))" + by (induction \) auto + +lemma ltl_prop_equiv_implies_ltl_prop_unfold_equiv: + "\ \\<^sub>P \ \ \ \\<^sub>Q \" + by (metis ltl_prop_unfold_equiv_def unfolding_is_subst subst_respects_ltl_prop_entailment(2)) + +lemma ltl_prop_unfold_equiv_implies_ltl_lang_equiv: + "\ \\<^sub>Q \ \ \ \\<^sub>L \" + by (metis ltl_prop_equiv_implies_ltl_lang_equiv ltl_lang_equiv_def Unf_sound ltl_prop_unfold_equiv_def) + +lemma ltl_prop_unfold_equiv_gt_and_lt: + "(\\<^sub>C) \ (\\<^sub>Q)" "(\\<^sub>P) \ (\\<^sub>Q)" "(\\<^sub>Q) \ (\\<^sub>L)" + using ltl_prop_equiv_implies_ltl_prop_unfold_equiv ltl_prop_equivalence.ge_const_equiv ltl_prop_unfold_equiv_implies_ltl_lang_equiv + by blast+ + +quotient_type 'a ltln\<^sub>Q = "'a ltln" / "(\\<^sub>Q)" + by (rule ltl_prop_unfold_equiv_equivp) + +instantiation ltln\<^sub>Q :: (type) equal +begin + +lift_definition ltln\<^sub>Q_eq_test :: "'a ltln\<^sub>Q \ 'a ltln\<^sub>Q \ bool" is "\x y. x \\<^sub>Q y" + by (metis ltln\<^sub>Q.abs_eq_iff) + +definition + eq\<^sub>Q: "equal_class.equal \ ltln\<^sub>Q_eq_test" + +instance + by (standard; simp add: eq\<^sub>Q ltln\<^sub>Q_eq_test.rep_eq, metis Quotient_ltln\<^sub>Q Quotient_rel_rep) + +end + +lemma af_letter_unfolding: + "af_letter (Unf \) \ \\<^sub>P af_letter \ \" + by (induction \) (simp_all add: ltl_prop_equiv_def, blast+) + +lemma af_letter_prop_unfold_congruent: + assumes "\ \\<^sub>Q \" + shows "af_letter \ \ \\<^sub>Q af_letter \ \" +proof - + have "Unf \ \\<^sub>P Unf \" + using assms by (simp add: ltl_prop_unfold_equiv_def ltl_prop_equiv_def) + then have "af_letter (Unf \) \ \\<^sub>P af_letter (Unf \) \" + by (simp add: prop_af_congruent.af_letter_congruent) + then have "af_letter \ \ \\<^sub>P af_letter \ \" + by (metis af_letter_unfolding ltl_prop_equivalence.eq_sym ltl_prop_equivalence.eq_trans) + then show "af_letter \ \ \\<^sub>Q af_letter \ \" + by (rule ltl_prop_equiv_implies_ltl_prop_unfold_equiv) +qed + +lemma GF_advice_prop_unfold_congruent: + assumes "\ \\<^sub>Q \" + shows "(Unf \)[X]\<^sub>\ \\<^sub>Q (Unf \)[X]\<^sub>\" +proof - + have "Unf \ \\<^sub>P Unf \" + using assms + by (simp add: ltl_prop_unfold_equiv_def ltl_prop_equiv_def) + then have "(Unf \)[X]\<^sub>\ \\<^sub>P (Unf \)[X]\<^sub>\" + by (simp add: GF_advice_prop_congruent(2)) + then show "(Unf \)[X]\<^sub>\ \\<^sub>Q (Unf \)[X]\<^sub>\" + by (simp add: ltl_prop_equiv_implies_ltl_prop_unfold_equiv) +qed + +interpretation prop_unfold_equivalence: ltl_equivalence "(\\<^sub>Q)" + by unfold_locales (metis ltl_prop_unfold_equiv_equivp ltl_prop_unfold_equiv_gt_and_lt)+ + +interpretation af_congruent "(\\<^sub>Q)" + by unfold_locales (rule af_letter_prop_unfold_congruent) + +lemma unfolding_monotonic: + "w \\<^sub>n \[X]\<^sub>\ \ w \\<^sub>n (Unf \)[X]\<^sub>\" +proof (induction \) + case (Until_ltln \1 \2) + then show ?case + by (cases "(\1 U\<^sub>n \2) \ X") force+ +next + case (Release_ltln \1 \2) + then show ?case + using ltln_expand_Release by auto +next + case (WeakUntil_ltln \1 \2) + then show ?case + using ltln_expand_WeakUntil by auto +next + case (StrongRelease_ltln \1 \2) + then show ?case + by (cases "(\1 M\<^sub>n \2) \ X") force+ +qed auto + +lemma unfolding_next_step_equivalent: + "w \\<^sub>n (Unf \)[X]\<^sub>\ \ suffix 1 w \\<^sub>n (af_letter \ (w 0))[X]\<^sub>\" +proof (induction \) + case (Next_ltln \) + then show ?case + unfolding Unf.simps by (metis GF_advice_af_letter build_split) +next + case (Until_ltln \1 \2) + then show ?case + unfolding Unf.simps + by (metis GF_advice.simps(2) GF_advice.simps(3) GF_advice_af_letter af_letter.simps(8) build_split semantics_ltln.simps(5) semantics_ltln.simps(6)) +next + case (Release_ltln \1 \2) + then show ?case + unfolding Unf.simps + by (metis GF_advice.simps(2) GF_advice.simps(3) GF_advice_af_letter One_nat_def af_letter.simps(9) build_first semantics_ltln.simps(5) semantics_ltln.simps(6)) +next + case (WeakUntil_ltln \1 \2) + then show ?case + unfolding Unf.simps + by (metis GF_advice.simps(2) GF_advice.simps(3) GF_advice_af_letter af_letter.simps(10) build_split semantics_ltln.simps(5) semantics_ltln.simps(6)) +next + case (StrongRelease_ltln \1 \2) + then show ?case + unfolding Unf.simps + by (metis GF_advice.simps(2) GF_advice.simps(3) GF_advice_af_letter af_letter.simps(11) build_split semantics_ltln.simps(5) semantics_ltln.simps(6)) +qed auto + +lemma nested_prop_atoms_Unf: + "nested_prop_atoms (Unf \) \ nested_prop_atoms \" + by (induction \) auto + +(* TODO move somewhere?? *) +lemma refine_image: + assumes "\x y. f x = f y \ g x = g y" + assumes "finite (f ` X)" + shows "finite (g ` X)" + and "card (f ` X) \ card (g ` X)" +proof - + obtain Y where "Y \ X" and "finite Y" and Y_def: "f ` X = f ` Y" + using assms by (meson finite_subset_image subset_refl) + moreover + { + fix x + assume "x \ X" + then have "g x \ g ` Y" + by (metis (no_types, hide_lams) \x \ X\ assms(1) Y_def image_iff) + } + then have "g ` X = g ` Y" + using assms `Y \ X` by blast + ultimately + show "finite (g ` X)" + by simp + + from \finite Y\ have "card (f ` Y) \ card (g ` Y)" + proof (induction Y rule: finite_induct) + case (insert x F) + + then have 1: "finite (g ` F)" and 2: "finite (f ` F)" + by simp_all + + have "f x \ f ` F \ g x \ g ` F" + using assms(1) by blast + + then show ?case + using insert by (simp add: card_insert_if[OF 1] card_insert_if[OF 2]) + qed simp + + then show "card (f ` X) \ card (g ` X)" + by (simp add: Y_def \g ` X = g ` Y\) +qed + +lemma abs_ltln\<^sub>P_implies_abs_ltln\<^sub>Q: + "abs_ltln\<^sub>P \ = abs_ltln\<^sub>P \ \ abs_ltln\<^sub>Q \ = abs_ltln\<^sub>Q \" + by (simp add: ltl_prop_equiv_implies_ltl_prop_unfold_equiv ltln\<^sub>P.abs_eq_iff ltln\<^sub>Q.abs_eq_iff) + +lemmas prop_unfold_equiv_helper = refine_image[of abs_ltln\<^sub>P abs_ltln\<^sub>Q, OF abs_ltln\<^sub>P_implies_abs_ltln\<^sub>Q] + +lemma prop_unfold_equiv_finite: + "finite P \ finite {abs_ltln\<^sub>Q \ |\. prop_atoms \ \ P}" + using prop_unfold_equiv_helper(1)[OF prop_equiv_finite[unfolded image_Collect[symmetric]]] + unfolding image_Collect[symmetric] . + +lemma prop_unfold_equiv_card: + "finite P \ card {abs_ltln\<^sub>Q \ |\. prop_atoms \ \ P} \ 2 ^ 2 ^ card P" + using prop_unfold_equiv_helper(2)[OF prop_equiv_finite[unfolded image_Collect[symmetric]]] prop_equiv_card + unfolding image_Collect[symmetric] + by fastforce + +lemma Unf_eventually_equivalent: + "w \\<^sub>n Unf \[X]\<^sub>\ \ \i. suffix i w \\<^sub>n af \ (prefix i w)[X]\<^sub>\" + by (metis (full_types) One_nat_def foldl.simps(1) foldl.simps(2) subsequence_singleton unfolding_next_step_equivalent) + +interpretation prop_unfold_GF_advice_compatible: GF_advice_congruent "(\\<^sub>Q)" Unf + by unfold_locales (simp_all add: unfolding_prop_unfold_idem prop_unfold_equivalence.eq_sym unfolding_monotonic Unf_eventually_equivalent GF_advice_prop_unfold_congruent) + +end \ No newline at end of file diff --git a/thys/LTL_Master_Theorem/code/ltl_to_dra_cli.sml b/thys/LTL_Master_Theorem/code/ltl_to_dra_cli.sml --- a/thys/LTL_Master_Theorem/code/ltl_to_dra_cli.sml +++ b/thys/LTL_Master_Theorem/code/ltl_to_dra_cli.sml @@ -1,20 +1,20 @@ (* Initialise Parser *) structure LtlParser = Ltl(PropLtl) (* Printers *) fun println x = print (x ^ "\n") fun println_err x = (TextIO.output (TextIO.stdErr, x ^ "\n"); TextIO.flushOut TextIO.stdErr) (* Main *) fun usage () = println ("Usage: " ^ CommandLine.name () ^ " ltlformula"); fun main () = let val e = fn () => OS.Process.exit (OS.Process.failure) val u = fn () => (usage(); e()) val input = case CommandLine.arguments () of [] => valOf (TextIO.inputLine TextIO.stdIn) | x :: _ => x val phi = LtlParser.compile_from_string input handle LtlParser.LtlError msg => (println_err ("LTL Error: " ^ msg); usage (); e ()) - val aut = LTL.ltlc_to_draei_literals phi + val aut = LTL.ltlc_to_draei_literals LTL.PropUnfold phi in println (HOA.serialize phi aut) end