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,906 +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 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) 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 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 ((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 (\, (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 ((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 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\ 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) + by (auto simp add: dra_set_alphabet_def dra.language_def set_eq_iff dra.run_alt_def streams_iff_sset) 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 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_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_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_restricted \)" unfolding ltl_to_dra_alphabet_def 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