diff --git a/metadata/entries/Universal_Hash_Families.toml b/metadata/entries/Universal_Hash_Families.toml --- a/metadata/entries/Universal_Hash_Families.toml +++ b/metadata/entries/Universal_Hash_Families.toml @@ -1,38 +1,39 @@ title = "Universal Hash Families" date = 2022-02-20 topics = [ "Computer science/Algorithms/Randomized", ] abstract = """ A k-universal hash family is a probability space of functions, which have uniform distribution and form k-wise independent random variables. They can often be used in place of classic (or cryptographic) hash functions and allow the rigorous analysis of the performance of randomized algorithms and data structures that rely on hash functions. In 1981 Wegman and Carter introduced a generic construction for such families with arbitrary k using polynomials over a finite field. This entry contains a formalization of them and establishes the property of k-universality. To be useful the formalization also provides an explicit construction of finite fields using the factor ring of integers modulo a prime. Additionally, some generic results about independent families are shown that might be of independent interest.""" license = "bsd" note = "" [authors] [authors.karayel] homepage = "karayel_homepage" [contributors] [notify] karayel = "karayel_email" [history] +2024-01-25 = "Added combinator library for pseudorandom objects." [extra] [related] diff --git a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy.thy b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy.thy --- a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy.thy +++ b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy.thy @@ -1,328 +1,327 @@ section \Accuracy with cutoff\label{sec:accuracy}\ text \This section verifies that each of the $l$ estimate have the required accuracy with high probability assuming as long as the cutoff is below @{term "q_max"}, generalizing the result from Section~\ref{sec:accuracy_wo_cutoff}.\ theory Distributed_Distinct_Elements_Accuracy imports Distributed_Distinct_Elements_Accuracy_Without_Cutoff Distributed_Distinct_Elements_Cutoff_Level begin unbundle intro_cong_syntax lemma (in semilattice_set) Union: assumes "finite I" "I \ {}" assumes "\i. i \ I \ finite (Z i)" assumes "\i. i \ I \ Z i \ {}" shows "F (\ (Z ` I)) = F ((\i. (F (Z i))) ` I)" using assms(1,2,3,4) proof (induction I rule:finite_ne_induct) case (singleton x) then show ?case by simp next case (insert x I) have "F (\ (Z ` insert x I)) = F ((Z x) \ (\ (Z ` I)))" by simp also have "... = f (F (Z x)) (F (\ (Z ` I)))" using insert by (intro union finite_UN_I) auto also have "... = f (F {F (Z x)}) (F ((\i. F (Z i)) ` I))" using insert(5,6) by (subst insert(4)) auto also have "... = F ({F (Z x)} \ (\i. F (Z i)) ` I)" using insert(1,2) by (intro union[symmetric] finite_imageI) auto also have "... = F ((\i. F (Z i)) ` insert x I)" by simp finally show ?case by simp qed text \This is similar to the existing @{thm [source] hom_Max_commute} with the crucial difference that it works even if the function is a homomorphism between distinct lattices. An example application is @{term "Max (int ` A) = int (Max A)"}.\ lemma hom_Max_commute': assumes "finite A" "A \ {}" assumes "\x y. x \ A \ y \ A \ max (f x) (f y) = f (max x y)" shows "Max (f ` A) = f (Max A)" using assms by (induction A rule:finite_ne_induct) auto context inner_algorithm_fix_A begin definition t\<^sub>c where "t\<^sub>c \ \ = (Max ((\j. \\<^sub>1 \ A \ j + \) ` {..c (* tilde t *) where "s\<^sub>c \ \ = nat (t\<^sub>c \ \)" definition p\<^sub>c (* tilde p *) where "p\<^sub>c \ \ = card {j\ {..\<^sub>1 \ A \ j + \ \ s\<^sub>c \ \}" definition Y\<^sub>c (* tilde A* *) where "Y\<^sub>c \ \ = 2 ^ s\<^sub>c \ \ * \_inv (p\<^sub>c \ \)" lemma s\<^sub>c_eq_s: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ sample_pro \" assumes "\ \ s f" shows "s\<^sub>c (f,g,h) \ = s f" proof - have "int (Max (f ` A)) - int b_exp + 9 \ int (Max (f ` A)) - 26 + 9" using b_exp_ge_26 by (intro add_mono diff_left_mono) auto also have "... \ int (Max (f ` A))" by simp finally have 1:"int (Max (f ` A)) - int b_exp + 9 \ int (Max (f ` A))" by simp have "\ \ int (s f)" using assms(2) by simp also have "... = max 0 (t f)" unfolding s_def by simp also have "... \ max 0 (int (Max (f ` A)))" unfolding t_def using 1 by simp also have "... = int (Max (f ` A))" by simp finally have "\ \ int (Max (f ` A))" by simp hence 0: "int \ - 1 \ int (Max (f ` A))" by simp - have c:"h \ sample_set (\ k (C\<^sub>7 * b\<^sup>2) [b]\<^sub>S)" + have c:"h \ sample_pro (\ k (C\<^sub>7 * b\<^sup>2) (\ b))" using assms(1) sample_set_\ by auto hence h_range: "h x < b" for x using h_range_1 by simp have "(MAX j\{..\<^sub>1 (f, g, h) A \ j + int \) = (MAX x\{.. A \ h (g a) = x} \ {-1} \ {int \ -1}))" using fin_f[OF assms(1)] by (simp add:max_add_distrib_left max.commute \\<^sub>1_def) also have "... = Max (\x A \ h (g a) = x} \ {- 1} \ {int \ - 1})" using fin_f[OF assms(1)] b_ne by (intro Max.Union[symmetric]) auto also have "... = Max ({int (f a) |a. a \ A} \ {- 1, int \ - 1})" using h_range by (intro arg_cong[where f="Max"]) auto also have "... = max (Max (int ` f ` A)) (int \ - 1)" using A_nonempty fin_A unfolding Setcompr_eq_image image_image by (subst Max.union) auto also have "... = max (int (Max (f ` A))) (int \ - 1)" using fin_A A_nonempty by (subst hom_Max_commute') auto also have "... = int (Max (f ` A))" by (intro max_absorb1 0) finally have "(MAX j\{..\<^sub>1 (f, g, h) A \ j + int \) = Max (f ` A)" by simp thus ?thesis unfolding s\<^sub>c_def t\<^sub>c_def s_def t_def by simp qed lemma p\<^sub>c_eq_p: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ sample_pro \" assumes "\ \ s f" shows "p\<^sub>c (f,g,h) \ = p (f,g,h)" proof - have "{j \ {.. max (\\<^sub>0 (f, g, h) A j) (int \ - 1)} = {j \ {.. max (\\<^sub>0 (f, g, h) A j) (- 1)}" using assms(2) unfolding le_max_iff_disj by simp thus ?thesis unfolding p\<^sub>c_def p_def s\<^sub>c_eq_s[OF assms] by (simp add:max_add_distrib_left \\<^sub>1_def del:\\<^sub>0.simps) qed lemma Y\<^sub>c_eq_Y: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ sample_pro \" assumes "\ \ s f" shows "Y\<^sub>c (f,g,h) \ = Y (f,g,h)" unfolding Y\<^sub>c_def Y_def s\<^sub>c_eq_s[OF assms] p\<^sub>c_eq_p[OF assms] by simp lemma accuracy_single: "measure \ {\. \\ \ q_max. \Y\<^sub>c \ \ - real X\ > \ * X} \ 1/2^4" (is "?L \ ?R") proof - have "measure \ {\. \\ \ q_max. \Y\<^sub>c \ \ - real X\ > \ * real X} \ measure \ {(f,g,h). \Y (f,g,h) - real X\ > \ * real X \ s f < q_max}" proof (rule pmf_mono) fix \ assume a:"\ \ {\. \\\q_max. \ * real X < \Y\<^sub>c \ \ - real X\}" - assume d:"\ \ set_pmf (sample_pmf \)" + assume d:"\ \ set_pmf (sample_pro \)" obtain \ where b:"\ \ q_max" and c:" \ * real X < \Y\<^sub>c \ \ - real X\" using a by auto obtain f g h where \_def: "\ = (f,g,h)" by (metis prod_cases3) - hence e:"(f,g,h) \ sample_set \" - using d unfolding sample_space_alt[OF sample_space_\] by simp + hence e:"(f,g,h) \ sample_pro \" using d by simp show "\ \ {(f, g, h). \ * real X < \Y (f, g, h) - real X\ \ s f < q_max}" proof (cases "s f \ q_max") case True hence f:"\ \ s f" using b by simp have "\ * real X < \Y \ - real X\" using Y\<^sub>c_eq_Y[OF e f] c unfolding \_def by simp then show ?thesis unfolding \_def by simp next case False then show ?thesis unfolding \_def by simp qed qed also have "... \ 1/2^4" using accuracy_without_cutoff by simp finally show ?thesis by simp qed lemma estimate1_eq: assumes "j < l" shows "estimate1 (\\<^sub>2 \ A \, \) j = Y\<^sub>c (\ j) \" (is "?L = ?R") proof - define t where "t = max 0 (Max ((\\<^sub>2 \ A \ j) ` {.. - \log 2 b\ + 9)" define p where "p = card { k. k \ {.. (\\<^sub>2 \ A \ j k) + \ \ t }" have 0: "int (nat x) = max 0 x" for x by simp have 1: "\log 2 b\ = b_exp" unfolding b_def by simp have "b > 0" using b_min by simp hence 2: " {.. {}" by auto have "t = int (nat (Max ((\\<^sub>2 \ A \ j) ` {.. - b_exp + 9))" unfolding t_def 0 1 by (rule refl) also have "... = int (nat (Max ((\x. x + \) ` (\\<^sub>2 \ A \ j) ` {..\<^sub>1 int,\\<^sub>1 nat,\\<^sub>2(+),\\<^sub>2(-)]" more:hom_Max_commute) (simp_all add:2) also have "... = int (s\<^sub>c (\ j) \)" using assms unfolding s\<^sub>c_def t\<^sub>c_def \\<^sub>2_def image_image by simp finally have 3:"t = int (s\<^sub>c (\ j) \)" by simp have 4: "p = p\<^sub>c (\ j) \" using assms unfolding p_def p\<^sub>c_def 3 \\<^sub>2_def by simp have "?L = 2 powr t * ln (1-p/b) / ln(1-1/b)" unfolding estimate1.simps \_def \\<^sub>3_def by (simp only:t_def p_def Let_def) also have "... = 2 powr (s\<^sub>c (\ j) \) * \_inv p" unfolding 3 \_inv_def by (simp) also have "... = ?R" unfolding Y\<^sub>c_def 3 4 by (simp add:powr_realpow) finally show ?thesis by blast qed lemma estimate_result_1: "measure \ {\. (\\\q_max. \*X < \estimate (\\<^sub>2 \ A \,\)-X\) } \ \/2" (is "?L \ ?R") proof - define I :: "real set" where "I = {x. \x - real X\ \ \*X}" define \ where "\ = measure \ {\. \\\q_max. Y\<^sub>c \ \\I}" have int_I: "interval I" unfolding interval_def I_def by auto have "\ = measure \ {\. \\ \ q_max. \Y\<^sub>c \ \ - real X\ > \ * X}" unfolding \_def I_def by (simp add:not_le) also have "... \ 1 / 2 ^ 4" by (intro accuracy_single) also have "... = 1/ 16" by simp finally have 1:"\ \ 1 / 16" by simp have "(\ + \) \ 1/16 + 1/16" unfolding \_def by (intro add_mono 1) auto also have "... \ 1/8" by simp finally have 2:"(\ + \) \ 1/8" by simp hence 0: "(\ + \) \ 1/2" by simp have "\ \ 0" unfolding \_def by simp hence 3: "\ + \ > 0" by (intro add_nonneg_pos \_gt_0) have "?L = measure \ {\. (\\\q_max. \*X < \median l (estimate1 (\\<^sub>2 \ A \,\))-X\) }" by simp also have "... = measure \ {\. (\\\q_max. median l (estimate1 (\\<^sub>2 \ A \,\)) \ I)}" unfolding I_def by (intro measure_pmf_cong) auto also have "... \ measure \ {\. real(card{i\{..\\q_max. Y\<^sub>c (\ i) \\I)})\ real l/2}" proof (rule pmf_mono) fix \ assume "\ \ set_pmf \" "\ \ {\. \\\q_max. median l (estimate1 (\\<^sub>2 \ A \, \)) \ I}" then obtain \ where \_def: "median l (estimate1 (\\<^sub>2 \ A \, \)) \ I" "\\q_max" by auto have "real l = 2 * real l - real l" by simp also have "... \ 2 * real l - 2 * card {i. i < l \ estimate1 (\\<^sub>2 \ A \, \) i \ I}" using \_def median_est[OF int_I, where n="l"] not_less by (intro diff_left_mono Nat.of_nat_mono) (auto simp del:estimate1.simps) also have "... = 2 * (real (card {.. estimate1 (\\<^sub>2 \ A \, \) i \ I})" by (simp del:estimate1.simps) also have "... = 2 * real (card {.. estimate1 (\\<^sub>2 \ A \, \) i \ I})" by (intro_cong "[\\<^sub>2 (*)]" more:of_nat_diff[symmetric] card_mono) (auto simp del:estimate1.simps) also have "... = 2 * real (card ({.. estimate1 (\\<^sub>2 \ A \, \) i \ I}))" by (intro_cong "[\\<^sub>2 (*), \\<^sub>1 of_nat]" more:card_Diff_subset[symmetric]) (auto simp del:estimate1.simps) also have "... = 2 * real (card {i\{..\<^sub>2 \ A \, \) i \ I})" by (intro_cong "[\\<^sub>2 (*), \\<^sub>1 of_nat, \\<^sub>1 card]") (auto simp del:estimate1.simps) also have "... = 2 * real (card {i \ {..c (\ i) \ \ I})" using estimate1_eq by (intro_cong "[\\<^sub>2 (*), \\<^sub>1 of_nat, \\<^sub>1 card]" more:restr_Collect_cong) auto also have "... \ 2 * real (card {i \ {..\\q_max. Y\<^sub>c (\ i) \ \ I)})" using \_def(2) by (intro mult_left_mono Nat.of_nat_mono card_mono) auto finally have "real l \ 2 * real (card {i \ {..\\q_max. Y\<^sub>c (\ i) \ \ I)})" by simp thus "\ \ {\. real l/2 \ real (card {i \ {..\\q_max. Y\<^sub>c (\ i) \ \ I})}" by simp qed also have "... = measure \ {\. real (card{i\{..\\q_max. Y\<^sub>c (\ i) \\I)}) \ (1/2)*real l}" - unfolding sample_pmf_alt[OF \.sample_space] p_def by simp + unfolding p_def by simp also have "... \ exp (- real l * ((1/2) * ln (1 / (\ + \)) - 2 * exp (- 1)))" - using 0 unfolding \_def by (intro \.tail_bound l_gt_0 \_gt_0) auto + using 0 unfolding \_def by (intro walk_tail_bound l_gt_0 \_gt_0) auto also have "... = exp (- (real l * ((1/2) * ln (1 / (\ + \)) - 2 * exp (- 1))))" by simp also have "... \ exp (- (real l * ((1/2) * ln 8 - 2 * exp (- 1))))" using 2 3 l_gt_0 by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le mult_left_mono diff_mono) (auto simp add:divide_simps) also have "... \ exp (- (real l * (1/4)))" by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le mult_left_mono of_nat_0_le_iff) (approximation 5) also have "... \ exp (- (C\<^sub>6 * ln (2/ \)*(1/4)))" by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le mult_right_mono l_lbound) auto also have "... = exp ( - ln (2/ \))" unfolding C\<^sub>6_def by simp also have "... = ?R" using \_gt_0 by (subst ln_inverse[symmetric]) auto finally show ?thesis by simp qed theorem estimate_result: "measure \ {\. \estimate (\ \ A)- X\ > \ * X} \ \" (is "?L \ ?R") proof - let ?P = "measure \" have "?L \ ?P {\. (\\\q_max. \*real X<\estimate (\\<^sub>2 \ A \, \)-real X\)\q \ A> q_max}" unfolding \_def \\<^sub>3_def not_le[symmetric] by (intro pmf_mono) auto also have "...\ ?P {\. (\\\q_max. \*real X<\estimate (\\<^sub>2 \ A \,\)-X\)} + ?P {\. q \ A> q_max}" by (intro pmf_add) auto also have "...\ \/2 + \/2" by (intro add_mono cutoff_level estimate_result_1) also have "... = \" by simp finally show ?thesis by simp qed end lemma (in inner_algorithm) estimate_result: assumes "A \ {.. {}" shows "measure \ {\. \estimate (\ \ A)- real (card A)\ > \ * real (card A)} \ \" (is "?L \ ?R") proof - interpret inner_algorithm_fix_A using assms by unfold_locales auto have "?L = measure \ {\. \estimate (\ \ A)- X\ > \ * X}" unfolding X_def by simp also have "... \ ?R" by (intro estimate_result) finally show ?thesis by simp qed unbundle no_intro_cong_syntax end \ No newline at end of file diff --git a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy_Without_Cutoff.thy b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy_Without_Cutoff.thy --- a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy_Without_Cutoff.thy +++ b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Accuracy_Without_Cutoff.thy @@ -1,1008 +1,1004 @@ section \Accuracy without cutoff\label{sec:accuracy_wo_cutoff}\ text \This section verifies that each of the $l$ estimate have the required accuracy with high probability assuming that there was no cut-off, i.e., that $s=0$. Section~\ref{sec:accuracy} will then show that this remains true as long as the cut-off is below @{term "t f"} the subsampling threshold.\ theory Distributed_Distinct_Elements_Accuracy_Without_Cutoff imports Concentration_Inequalities.Bienaymes_Identity Distributed_Distinct_Elements_Inner_Algorithm Distributed_Distinct_Elements_Balls_and_Bins begin no_notation Polynomials.var ("X\") locale inner_algorithm_fix_A = inner_algorithm + fixes A assumes A_range: "A \ {.. A" begin definition X :: nat where "X = card A" definition q_max where "q_max = nat (\log 2 X\ - b_exp)" definition t :: "(nat \ nat) \ int" where "t f = int (Max (f ` A)) - b_exp + 9" definition s :: "(nat \ nat) \ nat" where "s f = nat (t f)" definition R :: "(nat \ nat) \ nat set" where "R f = {a. a \ A \ f a \ s f}" definition r :: "nat \ (nat \ nat) \ nat" where "r x f = card {a. a \ A \ f a \ x}" definition p where "p = (\(f,g,h). card {j\ {..\<^sub>1 (f,g,h) A 0 j \ s f})" definition Y where "Y = (\(f,g,h). 2 ^ s f * \_inv (p (f,g,h)))" lemma fin_A: "finite A" using A_range finite_nat_iff_bounded by auto lemma X_le_n: "X \ n" proof - have "card A \ card {.. 1" unfolding X_def using fin_A A_nonempty by (simp add: leI) lemma of_bool_square: "(of_bool x)\<^sup>2 = ((of_bool x)::real)" by (cases x, auto) lemma r_eq: "r x f = (\ a \ A.( of_bool( x \ f a) :: real))" unfolding r_def of_bool_def sum.If_cases[OF fin_A] by (simp add: Collect_conj_eq) lemma shows r_exp: "(\\. real (r x \) \ \\<^sub>1) = real X * (of_bool (x \ max (nat \log 2 n\) 1) / 2^x)" and r_var: "measure_pmf.variance \\<^sub>1 (\\. real (r x \)) \ (\\. real (r x \) \ \\<^sub>1)" proof - define V :: "nat \ (nat \ nat) \ real" where "V = (\a f. of_bool (x \ f a))" have V_exp: "(\\. V a \ \\\<^sub>1) = of_bool (x \ max (nat \log 2 n\) 1)/2^x" (is "?L = ?R") if "a \ A" for a proof - have a_le_n: "a < n" using that A_range by auto have "?L = (\\. indicator {f. x \ f a} \ \ \\<^sub>1)" unfolding V_def by (intro integral_cong_AE) auto - also have "... = measure (map_pmf (\\. \ a) (sample_pmf \\<^sub>1)) {f. x \ f}" + also have "... = measure (map_pmf (\\. \ a) (sample_pro \\<^sub>1)) {f. x \ f}" by simp also have "... = measure (\ n_exp) {f. x \ f}" - unfolding \\<^sub>1.single[OF a_le_n] by simp + by (subst hash_pro_component[OF \\<^sub>1 a_le_n]) auto also have "... = of_bool (x \ max (nat \log 2 n\) 1)/2^x" - unfolding \_prob n_exp_def by simp + unfolding geom_pro_prob n_exp_def by simp finally show ?thesis by simp qed have b:"(\\. real (r x \) \ \\<^sub>1) = (\ a \ A. (\\. V a \ \\\<^sub>1))" - unfolding r_eq V_def using \\<^sub>1.sample_space - by (intro Bochner_Integration.integral_sum) auto + unfolding r_eq V_def by (intro Bochner_Integration.integral_sum) auto also have "... = (\ a \ A. of_bool (x \ max (nat \log 2 n\) 1)/2^x)" using V_exp by (intro sum.cong) auto also have "... = X * (of_bool (x \ max (nat \log 2 n\) 1) / 2^x)" using X_def by simp finally show "(\\. real (r x \) \ \\<^sub>1) = real X * (of_bool (x \ max (nat \log 2 n\) 1)/ 2^x)" by simp have "(\\. (V a \)^2 \ \\<^sub>1) = (\\. V a \ \ \\<^sub>1)" for a unfolding V_def of_bool_square by simp hence a:"measure_pmf.variance \\<^sub>1 (V a) \ measure_pmf.expectation \\<^sub>1 (V a)" for a - using \\<^sub>1.sample_space by (subst measure_pmf.variance_eq) auto + by (subst measure_pmf.variance_eq) auto have "J \ A \ card J = 2 \ prob_space.indep_vars \\<^sub>1 (\_. borel) V J" for J unfolding V_def using A_range finite_subset[OF _ fin_A] - by (intro prob_space.indep_vars_compose2[where Y="\i y. of_bool(x \ y)" and M'="\_. discrete"] - prob_space.k_wise_indep_vars_subset[OF _ \\<^sub>1.indep]) (auto simp:prob_space_measure_pmf) + by (intro prob_space.indep_vars_compose2[where Y="\i y. of_bool(x \ y)" and M'="\_. discrete"] + hash_pro_indep[OF \\<^sub>1]) (auto simp:prob_space_measure_pmf) hence "measure_pmf.variance \\<^sub>1 (\\. real (r x \)) = (\ a \ A. measure_pmf.variance \\<^sub>1 (V a))" - unfolding r_eq V_def using \\<^sub>1.sample_space - by (intro measure_pmf.bienaymes_identity_pairwise_indep_2 fin_A) (simp_all) + unfolding r_eq V_def by (intro measure_pmf.bienaymes_identity_pairwise_indep_2 fin_A) simp_all also have "... \ (\ a \ A. (\\. V a \ \ \\<^sub>1))" by (intro sum_mono a) also have "... = (\\. real (r x \) \ \\<^sub>1)" unfolding b by simp finally show "measure_pmf.variance \\<^sub>1 (\\. real (r x \)) \ (\\. real (r x \) \ \\<^sub>1)" by simp qed definition E\<^sub>1 where "E\<^sub>1 = (\(f,g,h). 2 powr (-t f) * X \ {b/2^16..b/2})" lemma t_low: "measure \\<^sub>1 {f. of_int (t f) < log 2 (real X) + 1 - b_exp} \ 1/2^7" (is "?L \ ?R") proof (cases "log 2 (real X) \ 8") case True define Z :: "(nat \ nat) \ real" where "Z = r (nat \log 2 (real X) - 8\)" have "log 2 (real X) \ log 2 (real n)" using X_le_n X_ge_1 by (intro log_mono) auto hence "nat \log 2 (real X) - 8\ \ nat \log 2 (real n)\" by (intro nat_mono ceiling_mono) simp hence a:"(nat \log 2 (real X) - 8\ \ max (nat \log 2 (real n)\) 1)" by simp have b:"real (nat (\log 2 (real X)\ - 8)) \ log 2 (real X) - 7" using True by linarith have "2 ^ 7 = real X / (2 powr (log 2 X) * 2 powr (-7))" using X_ge_1 by simp also have "... = real X / (2 powr (log 2 X - 7))" by (subst powr_add[symmetric]) simp also have "... \ real X / (2 powr (real (nat \log 2 (real X) - 8\)))" using b by (intro divide_left_mono powr_mono) auto also have "... = real X / 2 ^ nat \log 2 (real X) - 8\" by (subst powr_realpow) auto finally have "2 ^ 7 \ real X / 2 ^ nat \log 2 (real X) - 8\" by simp hence exp_Z_gt_2_7: "(\\. Z \ \\\<^sub>1) \ 2^7" using a unfolding Z_def r_exp by simp have var_Z_le_exp_Z: "measure_pmf.variance \\<^sub>1 Z \ (\\. Z \ \\\<^sub>1)" unfolding Z_def by (intro r_var) have "?L \ measure \\<^sub>1 {f. of_nat (Max (f ` A)) < log 2 (real X) - 8}" unfolding t_def by (intro pmf_mono) (auto simp add:int_of_nat_def) also have "... \ measure \\<^sub>1 {f \ space \\<^sub>1. (\\. Z \ \\\<^sub>1) \ \Z f - (\\. Z \ \\\<^sub>1) \}" proof (rule pmf_mono) - fix f assume "f \ set_pmf (sample_pmf \\<^sub>1)" + fix f assume "f \ set_pmf (sample_pro \\<^sub>1)" have fin_f_A: "finite (f ` A)" using fin_A finite_imageI by blast assume " f \ {f. real (Max (f ` A)) < log 2 (real X) - 8}" hence "real (Max (f ` A)) < log 2 (real X) - 8" by auto hence "real (f a) < log 2 (real X) - 8" if "a \ A" for a using Max_ge[OF fin_f_A] imageI[OF that] order_less_le_trans by fastforce hence "of_nat (f a) < \log 2 (real X) - 8\" if "a \ A" for a using that by (subst less_ceiling_iff) auto hence "f a < nat \log 2 (real X) - 8\" if "a \ A" for a using that True by fastforce hence "r (nat \log 2 (real X) - 8\) f = 0" unfolding r_def card_eq_0_iff using not_less by auto hence "Z f = 0" unfolding Z_def by simp thus "f \ {f \ space \\<^sub>1. (\\. Z \ \\\<^sub>1) \ \Z f - (\\. Z \ \\\<^sub>1)\}" by auto qed also have "... \ measure_pmf.variance \\<^sub>1 Z / (\\. Z \ \\\<^sub>1)^2" - using exp_Z_gt_2_7 \\<^sub>1.sample_space by (intro measure_pmf.second_moment_method) simp_all + using exp_Z_gt_2_7 by (intro measure_pmf.second_moment_method) simp_all also have "... \ (\\. Z \ \\\<^sub>1) / (\\. Z \ \\\<^sub>1)^2" by (intro divide_right_mono var_Z_le_exp_Z) simp also have "... = 1 / (\\. Z \ \\\<^sub>1)" using exp_Z_gt_2_7 by (simp add:power2_eq_square) also have "... \ ?R" using exp_Z_gt_2_7 by (intro divide_left_mono) auto finally show ?thesis by simp next case "False" have "?L \ measure \\<^sub>1 {f. of_nat (Max (f ` A)) < log 2 (real X) - 8}" unfolding t_def by (intro pmf_mono) (auto simp add:int_of_nat_def) also have "... \ measure \\<^sub>1 {}" using False by (intro pmf_mono) simp also have "... = 0" by simp also have "... \ ?R" by simp finally show ?thesis by simp qed lemma t_high: "measure \\<^sub>1 {f. of_int (t f) > log 2 (real X) + 16 - b_exp} \ 1/2^7" (is "?L \ ?R") proof - define Z :: "(nat \ nat) \ real" where "Z = r (nat \log 2 (real X) + 8\)" have Z_nonneg: "Z f \ 0" for f unfolding Z_def r_def by simp have "(\\. Z \ \\\<^sub>1) \ real X / (2 ^ nat \log 2 (real X) + 8\)" unfolding Z_def r_exp by simp also have "... \ real X / (2 powr (real (nat \log 2 (real X) + 8\)))" by (subst powr_realpow) auto also have "... \ real X / (2 powr \log 2 (real X) + 8\)" by (intro divide_left_mono powr_mono) auto also have "... \ real X / (2 powr (log 2 (real X) + 7))" by (intro divide_left_mono powr_mono, linarith) auto also have "... = real X / 2 powr (log 2 (real X)) / 2 powr 7" by (subst powr_add) simp also have "... \ 1/2 powr 7" using X_ge_1 by (subst powr_log_cancel) auto finally have Z_exp: "(\\. Z \ \\\<^sub>1) \ 1/2^7" by simp have "?L \ measure \\<^sub>1 {f. of_nat (Max (f ` A)) > log 2 (real X) + 7}" unfolding t_def by (intro pmf_mono) (auto simp add:int_of_nat_def) also have "... \ measure \\<^sub>1 {f. Z f \ 1}" proof (rule pmf_mono) - fix f assume "f \ set_pmf (sample_pmf \\<^sub>1)" + fix f assume "f \ set_pmf (sample_pro \\<^sub>1)" assume " f \ {f. real (Max (f ` A)) > log 2 (real X) + 7}" hence "real (Max (f ` A)) > log 2 (real X) + 7" by simp hence "int (Max (f ` A)) \ \log 2 (real X) + 8\" by linarith hence "Max (f ` A) \ nat \log 2 (real X) + 8\" by simp moreover have "f ` A \ {}" "finite (f ` A)" using fin_A finite_imageI A_nonempty by auto ultimately obtain fa where "fa \ f ` A" " fa \ nat \log 2 (real X) + 8\" using Max_in by auto then obtain ae where ae_def: "ae \ A" "nat \log 2 (real X) + 8\ \ f ae" by auto hence "r (nat \log 2 (real X) + 8\) f > 0" unfolding r_def card_gt_0_iff using fin_A by auto hence "Z f \ 1" unfolding Z_def by simp thus "f \ {f. 1 \ Z f}" by simp qed also have "... \ (\\. Z \ \\\<^sub>1) / 1" - using Z_nonneg using \\<^sub>1.sample_space by (intro pmf_markov) auto + using Z_nonneg by (intro pmf_markov) auto also have "... \ ?R" using Z_exp by simp finally show ?thesis by simp qed lemma e_1: "measure \ {\. \E\<^sub>1 \} \ 1/2^6" proof - have "measure \\<^sub>1 {f. 2 powr (of_int (-t f)) * real X \ {real b/2^16..real b/2}} \ measure \\<^sub>1 {f. 2 powr (of_int (-t f)) * real X < real b/2^16} + measure \\<^sub>1 {f. 2 powr (of_int (-t f)) * real X > real b/2}" by (intro pmf_add) auto also have "... \ measure \\<^sub>1 {f. of_int (t f) > log 2 X + 16 - b_exp} + measure \\<^sub>1 {f. of_int (t f) < log 2 X + 1 - b_exp}" proof (rule add_mono) show "measure \\<^sub>1 {f. 2 powr (of_int (-t f)) * real X < real b/2^16} \ measure \\<^sub>1 {f. of_int (t f) > log 2 X + 16 - b_exp}" proof (rule pmf_mono) fix f assume "f \ {f. 2 powr real_of_int (-t f) * real X < real b / 2 ^ 16}" hence "2 powr real_of_int (-t f) * real X < real b / 2 ^ 16" by simp hence "log 2 (2 powr of_int (-t f) * real X) < log 2 (real b / 2^16)" using b_min X_ge_1 by (intro iffD2[OF log_less_cancel_iff]) auto hence "of_int (-t f) + log 2 (real X) < log 2 (real b / 2^16)" using X_ge_1 by (subst (asm) log_mult) auto also have "... = real b_exp - log 2 (2 powr 16)" unfolding b_def by (subst log_divide) auto also have "... = real b_exp - 16" by (subst log_powr_cancel) auto finally have "of_int (-t f) + log 2 (real X) < real b_exp - 16" by simp thus "f \ {f. of_int (t f) > log 2 (real X) + 16 - b_exp}" by simp qed next show "measure \\<^sub>1 {f. 2 powr of_int (-t f) * real X > real b/2} \ measure \\<^sub>1 {f. of_int (t f) < log 2 X + 1 - b_exp}" proof (rule pmf_mono) fix f assume "f \ {f. 2 powr real_of_int (-t f) * real X > real b / 2}" hence "2 powr real_of_int (-t f) * real X > real b / 2" by simp hence "log 2 (2 powr of_int (-t f) * real X) > log 2 (real b / 2)" using b_min X_ge_1 by (intro iffD2[OF log_less_cancel_iff]) auto hence "of_int (-t f) + log 2 (real X) > log 2 (real b / 2)" using X_ge_1 by (subst (asm) log_mult) auto hence "of_int (-t f) + log 2 (real X) > real b_exp - 1" unfolding b_def by (subst (asm) log_divide) auto hence "of_int (t f) < log 2 (real X) + 1 - b_exp" by simp thus "f \ {f. of_int (t f) < log 2 (real X) + 1 - b_exp}" by simp qed qed also have "... \ 1/2^7 + 1/2^7" by (intro add_mono t_low t_high) also have "... = 1/2^6" by simp finally have "measure \\<^sub>1 {f. 2 powr of_int (-t f) * real X \ {real b/2^16..real b/2}} \ 1/2^6" by simp thus ?thesis - unfolding sample_pmf_\ E\<^sub>1_def case_prod_beta + unfolding sample_pro_\ E\<^sub>1_def case_prod_beta by (subst pair_pmf_prob_left) qed definition E\<^sub>2 where "E\<^sub>2 = (\(f,g,h). \card (R f) - X / 2^(s f)\ \ \/3 * X / 2^(s f))" lemma e_2: "measure \ {\. E\<^sub>1 \ \ \E\<^sub>2 \} \ 1/2^6" (is "?L \ ?R") proof - define t\<^sub>m :: int where "t\<^sub>m = \log 2 (real X)\ + 16 - b_exp" have t_m_bound: "t\<^sub>m \ \log 2 (real X)\ - 10" unfolding t\<^sub>m_def using b_exp_ge_26 by simp have "real b / 2^16 = (real X * (1/ X)) * (real b / 2^16)" using X_ge_1 by simp also have "... = (real X * 2 powr (-log 2 X)) * (real b / 2^16)" using X_ge_1 by (subst powr_minus_divide) simp also have "... \ (real X * 2 powr (- \log 2 (real X)\)) * (2 powr b_exp / 2^16)" unfolding b_def using powr_realpow by (intro mult_mono powr_mono) auto also have "... = real X * (2 powr (- \log 2 (real X)\) * 2 powr(real b_exp-16))" by (subst powr_diff) simp also have "... = real X * 2 powr (- \log 2 (real X)\ + (int b_exp - 16))" by (subst powr_add[symmetric]) simp also have "... = real X * 2 powr (-t\<^sub>m)" unfolding t\<^sub>m_def by (simp add:algebra_simps) finally have c:"real b / 2^16 \ real X * 2 powr (-t\<^sub>m)" by simp define T :: "nat set" where "T = {x. (real X / 2^x \ real b / 2^16)}" have "x \ T \ int x \ t\<^sub>m" for x proof - have "x \ T \ 2^ x \ real X * 2^16 / b" using b_min by (simp add: field_simps T_def) also have "... \ log 2 (2^x) \ log 2 (real X * 2^16 / b)" using X_ge_1 b_min by (intro log_le_cancel_iff[symmetric] divide_pos_pos) auto also have "... \ x \ log 2 (real X * 2^16) - log 2 b" using X_ge_1 b_min by (subst log_divide) auto also have "... \ x \ log 2 (real X) + log 2 (2 powr 16) - b_exp" unfolding b_def using X_ge_1 by (subst log_mult) auto also have "... \ x \ \log 2 (real X) + log 2 (2 powr 16) - b_exp\" by linarith also have "... \ x \ \log 2 (real X) + 16 - real_of_int (int b_exp)\" by (subst log_powr_cancel) auto also have "... \ x \ t\<^sub>m" unfolding t\<^sub>m_def by linarith finally show ?thesis by simp qed hence T_eq: "T = {x. int x \ t\<^sub>m}" by auto have "T = {x. int x < t\<^sub>m+1}" unfolding T_eq by simp also have "... = {x. x < nat (t\<^sub>m + 1)}" unfolding zless_nat_eq_int_zless by simp finally have T_eq_2: "T = {x. x < nat (t\<^sub>m + 1)}" by simp have inj_1: "inj_on ((-) (nat t\<^sub>m)) T" unfolding T_eq by (intro inj_onI) simp have fin_T: "finite T" unfolding T_eq_2 by simp have r_exp: "(\\. real (r t \) \\\<^sub>1) = real X / 2^t" if "t \ T" for t proof - have "t \ t\<^sub>m" using that unfolding T_eq by simp also have "... \ \log 2 (real X)\ - 10" using t_m_bound by simp also have "... \ \log 2 (real X)\" by simp also have "... \ \log 2 (real n)\" using X_le_n X_ge_1 by (intro floor_mono log_mono) auto also have "... \ \log 2 (real n)\" by simp finally have "t \ \log 2 (real n)\" by simp hence "t \ max (nat \log 2 (real n)\) 1"by simp thus ?thesis unfolding r_exp by simp qed have r_var: "measure_pmf.variance \\<^sub>1 (\\. real (r t \)) \ real X / 2^t" if "t \ T" for t using r_exp[OF that] r_var by metis have "9 = C\<^sub>4 / \\<^sup>2 * \^2/2^23" using \_gt_0 by (simp add:C\<^sub>4_def) also have "... = 2 powr (log 2 (C\<^sub>4 / \\<^sup>2)) * \^2/2^23" using \_gt_0 C\<^sub>4_def by (subst powr_log_cancel) auto also have "... \ 2 powr b_exp * \^2/2^23" unfolding b_exp_def by (intro divide_right_mono mult_right_mono powr_mono, linarith) auto also have "... = b * \^2/2^23" using powr_realpow unfolding b_def by simp also have "... = (b/2^16) * (\^2/2^7)" by simp also have "... \ (X * 2 powr (-t\<^sub>m)) * (\^2/2^7)" by (intro mult_mono c) auto also have "... = X * (2 powr (-t\<^sub>m) * 2 powr (-7)) * \^2" using powr_realpow by simp also have "... = 2 powr (-t\<^sub>m-7) * (\^2 * X)" by (subst powr_add[symmetric]) (simp ) finally have "9 \ 2 powr (-t\<^sub>m-7) * (\^2 * X)" by simp hence b: "9/ (\^2 * X) \ 2 powr (-t\<^sub>m -7)" using \_gt_0 X_ge_1 by (subst pos_divide_le_eq) auto have a: "measure \\<^sub>1 {f.\real (r t f)-real X/2^t\> \/3 *real X/2^t} \ 2 powr (real t-t\<^sub>m-7)" (is"?L1 \ ?R1") if "t \ T" for t proof - have "?L1 \ \

(f in \\<^sub>1. \real (r t f) - real X / 2^t\ \ \/3 * real X / 2^t)" by (intro pmf_mono) auto also have "... = \

(f in \\<^sub>1. \real (r t f)-(\\. real (r t \) \ \\<^sub>1)\ \ \/3 * real X/2^t)" by (simp add: r_exp[OF that]) also have "... \ measure_pmf.variance \\<^sub>1 (\\. real (r t \)) / (\/3 * real X / 2^t)^2" - using X_ge_1 \_gt_0 \\<^sub>1.sample_space + using X_ge_1 \_gt_0 by (intro measure_pmf.Chebyshev_inequality divide_pos_pos mult_pos_pos) auto also have "... \ (X / 2^t) / (\/3 * X / 2^t)^2" by (intro divide_right_mono r_var[OF that]) simp also have "... = 2^t*(9/ ( \^2 * X))" by (simp add:power2_eq_square algebra_simps) also have "... \ 2^t*(2 powr (-t\<^sub>m-7))" by (intro mult_left_mono b) simp also have "... = 2 powr t * 2 powr (-t\<^sub>m-7)" by (subst powr_realpow[symmetric]) auto also have "... = ?R1" by (subst powr_add[symmetric]) (simp add:algebra_simps) finally show "?L1 \ ?R1" by simp qed have "\ym + 1). x = nat t\<^sub>m - y" if "x < nat (t\<^sub>m+1)" for x using that by (intro exI[where x="nat t\<^sub>m - x"]) simp hence T_reindex: "(-) (nat t\<^sub>m) ` {x. x < nat (t\<^sub>m + 1)} = {..m + 1)}" by (auto simp add: set_eq_iff image_iff) have "?L \ measure \ {\. (\t \ T. \real (r t (fst \))-real X/2^t\ > \/3 * real X / 2^t)}" proof (rule pmf_mono) fix \ - assume "\ \ set_pmf (sample_pmf \)" + assume "\ \ set_pmf (sample_pro \)" obtain f g h where \_def: "\ = (f,g,h)" by (metis prod_cases3) assume "\ \ {\. E\<^sub>1 \ \ \ E\<^sub>2 \}" hence a:"2 powr ( -real_of_int (t f)) * real X \ {real b/2^16..real b/2}" and b:"\card (R f) - real X / 2^(s f)\ > \/3 * X / 2^(s f)" unfolding E\<^sub>1_def E\<^sub>2_def by (auto simp add:\_def) have "\card (R f) - X / 2^(s f)\ = 0" if "s f= 0" using that by (simp add:R_def X_def) moreover have "( \/3) * (X / 2^s f) \ 0" using \_gt_0 X_ge_1 by (intro mult_nonneg_nonneg) auto ultimately have "False" if "s f = 0" using b that by simp hence "s f > 0" by auto hence "t f = s f" unfolding s_def by simp hence "2 powr (-real (s f)) * X \ b / 2^16" using a by simp hence "X / 2 powr (real (s f)) \ b / 2^16" by (simp add: divide_powr_uminus mult.commute) hence "real X / 2 ^ (s f) \ b / 2^16" by (subst (asm) powr_realpow, auto) hence "s f \ T" unfolding T_def by simp moreover have "\r (s f) f - X / 2^s f\ > \/3 * X / 2^s f" using R_def r_def b by simp ultimately have "\t \ T. \r t (fst \) - X / 2^t\ > \/3 * X / 2^t" using \_def by (intro bexI[where x="s f"]) simp thus "\ \ {\. (\t \ T. \r t (fst \) - X / 2^t\ > \/3 * X / 2^t)}" by simp qed also have "... = measure \\<^sub>1 {f. (\t \ T. \real (r t f)-real X / 2^t\ > \/3 * real X/2^t)}" - unfolding sample_pmf_\ by (intro pair_pmf_prob_left) + unfolding sample_pro_\ by (intro pair_pmf_prob_left) also have "... = measure \\<^sub>1 (\t \ T. {f. \real (r t f)-real X / 2^t\ > \/3 * real X/2^t})" by (intro measure_pmf_cong) auto also have "... \ (\t \ T. measure \\<^sub>1 {f.\real (r t f)-real X / 2^t\ > \/3 * real X/2^t})" by (intro measure_UNION_le fin_T) (simp) also have "... \ (\t \ T. 2 powr (real t - of_int t\<^sub>m - 7))" by (intro sum_mono a) also have "... = (\t \ T. 2 powr (-int (nat t\<^sub>m-t) - 7))" unfolding T_eq by (intro sum.cong refl arg_cong2[where f="(powr)"]) simp also have "... = (\x \ (\x. nat t\<^sub>m - x) ` T. 2 powr (-real x - 7))" by (subst sum.reindex[OF inj_1]) simp also have "... = (\x \ (\x. nat t\<^sub>m - x) ` T. 2 powr (-7) * 2 powr (-real x))" by (subst powr_add[symmetric]) (simp add:algebra_simps) also have "... = 1/2^7 * (\x \ (\x. nat t\<^sub>m - x) ` T. 2 powr (-real x))" by (subst sum_distrib_left) simp also have "... = 1/2^7 * (\x m+1). 2 powr (-real x))" unfolding T_eq_2 T_reindex by (intro arg_cong2[where f="(*)"] sum.cong) auto also have "... = 1/2^7 * (\x m+1). (2 powr (-1)) powr (real x))" by (subst powr_powr) simp also have "... = 1/2^7 * (\x m+1). (1/2)^x)" using powr_realpow by simp also have "... \ 1/2^7 * 2" by(subst geometric_sum) auto also have "... = 1/2^6" by simp finally show ?thesis by simp qed definition E\<^sub>3 where "E\<^sub>3 = (\(f,g,h). inj_on g (R f))" lemma R_bound: fixes f g h assumes "E\<^sub>1 (f,g,h)" assumes "E\<^sub>2 (f,g,h)" shows "card (R f) \ 2/3 * b" proof - have "real (card (R f)) \ ( \ / 3) * (real X / 2 ^ s f) + real X / 2 ^ s f" using assms(2) unfolding E\<^sub>2_def by simp also have "... \ (1/3) * (real X / 2 ^ s f) + real X / 2 ^ s f" using \_lt_1 by (intro add_mono mult_right_mono) auto also have "... = (4/3) * (real X / 2 powr s f)" using powr_realpow by simp also have "... \ (4/3) * (real X / 2 powr t f)" unfolding s_def by (intro mult_left_mono divide_left_mono powr_mono) auto also have "... = (4/3) * (2 powr (-(of_int (t f))) * real X)" by (subst powr_minus_divide) simp also have "... = (4/3) * (2 powr (- t f) * real X)" by simp also have "... \ (4/3) * (b/2)" using assms(1) unfolding E\<^sub>1_def by (intro mult_left_mono) auto also have "... \ (2/3) * b" by simp finally show ?thesis by simp qed lemma e_3: "measure \ {\. E\<^sub>1 \ \ E\<^sub>2 \ \ \E\<^sub>3 \} \ 1/2^6" (is "?L \ ?R") proof - let ?\ = "(\(z,x,y) f. z < C\<^sub>7*b^2 \ x \ R f \ y \ R f \ x < y)" let ?\ = "(\(z,x,y) g. g x = z \ g y = z)" have \_prob: "measure \\<^sub>2 {g. ?\ \ g} \ (1/real (C\<^sub>7*b^2)^2)" if "?\ \ f" for \ f proof - obtain x y z where \_def: "\ = (z,x,y)" by (metis prod_cases3) - have a:"prob_space.k_wise_indep_vars \\<^sub>2 2 (\i. discrete) (\x \. \ x = z) {..\<^sub>2.indep]) - (simp_all add:prob_space_measure_pmf) + have a:"prob_space.indep_vars \\<^sub>2 (\i. discrete) (\x \. \ x = z) I" + if "I \ {.. 2" for I + by (intro prob_space.indep_vars_compose2[OF _ hash_pro_indep[OF \\<^sub>2]] that) + (simp_all add:prob_space_measure_pmf) have "u \ R f \ u < n" for u unfolding R_def using A_range by auto hence b: "x < n" "y < n" "card {x, y} = 2" using that \_def by auto have c: "z < C\<^sub>7*b\<^sup>2" using \_def that by simp have "measure \\<^sub>2 {g. ?\ \ g} = measure \\<^sub>2 {g. (\\ \ {x,y}. g \ = z)}" by (simp add:\_def) also have "... = (\\ \ {x,y}. measure \\<^sub>2 {g. g \ = z})" - using b by (intro measure_pmf.split_indep_events[OF refl, where I="{x,y}"] - prob_space.k_wise_indep_vars_subset[OF _ a]) (simp_all add:prob_space_measure_pmf) - also have "... = (\\ \ {x,y}. measure (map_pmf (\\. \ \) (sample_pmf \\<^sub>2)) {g. g = z}) " + using b by (intro measure_pmf.split_indep_events[OF refl, where I="{x,y}"] a) + (simp_all add:prob_space_measure_pmf) + also have "... = (\\ \ {x,y}. measure (map_pmf (\\. \ \) (sample_pro \\<^sub>2)) {g. g = z}) " by (simp add:vimage_def) - also have "... = (\\ \ {x,y}. measure [C\<^sub>7 * b\<^sup>2]\<^sub>S {g. g=z})" - using b \\<^sub>2.single by (intro prod.cong) fastforce+ + also have "... = (\\ \ {x,y}. measure (\ (C\<^sub>7 * b\<^sup>2)) {g. g=z})" + using b hash_pro_component[OF \\<^sub>2] by (intro prod.cong) fastforce+ also have "... = (\\ \ {x,y}. measure (pmf_of_set {..7 * b\<^sup>2}) {z})" - by (subst nat_sample_pmf) simp + by (subst nat_pro) (simp_all add:C\<^sub>7_def b_def) also have "... = (measure (pmf_of_set {..7 * b\<^sup>2}) {z})^2" using b by simp also have "... \ (1 /(C\<^sub>7*b\<^sup>2))^2" using c by (subst measure_pmf_of_set) auto also have "... = (1 /(C\<^sub>7*b\<^sup>2)^2)" by (simp add:algebra_simps power2_eq_square) finally show ?thesis by simp qed have \_card: "card {\. ?\ \ f} \ (C\<^sub>7*b^2) * (card (R f) * (card (R f)-1)/2)" (is "?TL \ ?TR") and fin_\: "finite {\. ?\ \ f}" (is "?T2") for f proof - have t1: "{\. ?\ \ f} \ {..7*b^2} \ {(x,y) \ R f \ R f. x < y}" by (intro subsetI) auto moreover have "card ({..7*b^2} \ {(x,y) \ R f \ R f. x < y}) = ?TR" using card_ordered_pairs'[where M="R f"] by (simp add: card_cartesian_product) moreover have "finite (R f)" unfolding R_def using fin_A finite_subset by simp hence "finite {(x, y). (x, y) \ R f \ R f \ x < y}" by (intro finite_subset[where B="R f \ R f", OF _ finite_cartesian_product]) auto hence t2: "finite ({..7*b^2} \ {(x,y) \ R f \ R f. x < y})" by (intro finite_cartesian_product) auto ultimately show "?TL \ ?TR" using card_mono of_nat_le_iff by (metis (no_types, lifting)) show ?T2 using finite_subset[OF t1 t2] by simp qed have "?L \ measure \ {(f,g,h). card (R f) \ b \ (\ x y z. ?\ (x,y,z) f \ ?\ (x,y,z) g)}" proof (rule pmf_mono) - fix \ assume b:"\ \ set_pmf (sample_pmf \)" + fix \ assume b:"\ \ set_pmf (sample_pro \)" obtain f g h where \_def:"\ = (f,g,h)" by (metis prod_cases3) - have "(f,g,h) \ sample_set \" - using sample_space_alt[OF sample_space_\] b \_def by simp + have "(f,g,h) \ pro_set \" using b \_def by simp hence c:"g x < C\<^sub>7*b^2" for x using g_range by simp assume a:"\ \ {\. E\<^sub>1 \ \ E\<^sub>2 \ \ \ E\<^sub>3 \}" hence "card (R f) \ 2/3 * b" using R_bound \_def by force moreover have "\a b. a \ R f \ b \ R f \ a \ b \ g a = g b" using a unfolding \_def E\<^sub>3_def inj_on_def by auto hence "\x y. x \ R f \ y \ R f \ x < y \ g x = g y" by (metis not_less_iff_gr_or_eq) hence "\x y z. ?\ (x,y,z) f \ ?\ (x,y,z) g" using c by blast ultimately show "\ \ {(f, g, h). card (R f) \ b \ (\ x y z. ?\ (x,y,z) f \ ?\ (x,y,z) g)}" unfolding \_def by auto qed also have "... = (\f. measure (pair_pmf \\<^sub>2 \\<^sub>3) {g. card (R f) \ b \ (\x y z. ?\ (x,y,z) f \ ?\ (x,y,z) (fst g))} \\\<^sub>1)" - unfolding sample_pmf_\ split_pair_pmf by (simp add: case_prod_beta) + unfolding sample_pro_\ split_pair_pmf by (simp add: case_prod_beta) also have "... = (\f. measure \\<^sub>2 {g. card (R f) \ b \ (\x y z. ?\ (x,y,z) f \ ?\ (x,y,z) g)} \\\<^sub>1)" by (subst pair_pmf_prob_left) simp also have "... \ (\f. 1/real (2*C\<^sub>7) \\\<^sub>1)" - proof (rule pmf_exp_mono[OF integrable_sample_pmf[OF \\<^sub>1.sample_space] - integrable_sample_pmf[OF \\<^sub>1.sample_space]]) - fix f assume "f \ set_pmf (sample_pmf \\<^sub>1)" + proof (rule pmf_exp_mono[OF integrable_sample_pro integrable_sample_pro]) + fix f assume "f \ set_pmf (sample_pro \\<^sub>1)" show "measure \\<^sub>2 {g. card (R f) \ b \ (\x y z. ?\ (x,y,z) f \ ?\ (x,y,z) g)} \ 1 / real (2 * C\<^sub>7)" (is "?L1 \ ?R1") proof (cases "card (R f) \ b") case True have "?L1 \ measure \\<^sub>2 (\ \ \ {\. ?\ \ f}. {g. ?\ \ g})" by (intro pmf_mono) auto also have "... \ (\\ \ {\. ?\ \ f}. measure \\<^sub>2 {g. ?\ \ g})" by (intro measure_UNION_le fin_\) auto also have "... \ (\\ \ {\. ?\ \ f}. (1/real (C\<^sub>7*b^2)^2))" by (intro sum_mono \_prob) auto also have "... = card {\. ?\ \ f} /(C\<^sub>7*b^2)^2" by simp also have "... \ (C\<^sub>7*b^2) * (card (R f) * (card (R f)-1)/2) / (C\<^sub>7*b^2)^2" by (intro \_card divide_right_mono) simp also have "... \ (C\<^sub>7*b^2) * (b * b / 2) / (C\<^sub>7*b^2)^2" unfolding C\<^sub>7_def using True by (intro divide_right_mono Nat.of_nat_mono mult_mono) auto also have "... = 1/(2*C\<^sub>7)" using b_min by (simp add:algebra_simps power2_eq_square) finally show ?thesis by simp next case False then show ?thesis by simp qed qed also have "... \ 1/2^6" unfolding C\<^sub>7_def by simp finally show ?thesis by simp qed definition E\<^sub>4 where "E\<^sub>4 = (\(f,g,h). \p (f,g,h) - \ (card (R f))\ \ \/12 * card (R f))" lemma e_4_h: "9 / sqrt b \ \ / 12" proof - have "108 \ sqrt (C\<^sub>4)" unfolding C\<^sub>4_def by (approximation 5) also have "... \ sqrt( \^2 * real b)" using b_lower_bound \_gt_0 by (intro real_sqrt_le_mono) (simp add: pos_divide_le_eq algebra_simps) also have "... = \ * sqrt b" using \_gt_0 by (simp add:real_sqrt_mult) finally have "108 \ \ * sqrt b" by simp thus ?thesis using b_min by (simp add:pos_divide_le_eq) qed lemma e_4: "measure \ {\. E\<^sub>1 \ \ E\<^sub>2 \ \ E\<^sub>3 \ \ \E\<^sub>4 \} \ 1/2^6" (is "?L \ ?R") proof - have a: "measure \\<^sub>3 {h. E\<^sub>1 (f,g,h) \ E\<^sub>2 (f,g,h) \ E\<^sub>3 (f,g,h) \ \E\<^sub>4 (f,g,h)} \ 1/2^6" - (is "?L1 \ ?R1") if "f \ set_pmf (sample_pmf \\<^sub>1)" "g \ set_pmf(sample_pmf \\<^sub>2)" + (is "?L1 \ ?R1") if "f \ set_pmf (sample_pro \\<^sub>1)" "g \ set_pmf(sample_pro \\<^sub>2)" for f g proof (cases "card (R f) \ b \ inj_on g (R f)") case True have g_inj: "inj_on g (R f)" using True by simp have fin_R: "finite (g ` R f)" unfolding R_def using fin_A by (intro finite_imageI) simp interpret B:balls_and_bins_abs "g ` R f" "{.. {..7 * b\<^sup>2}" - using g_range_1 that(2) unfolding sample_space_alt[OF \\<^sub>2.sample_space] by auto + using g_range_1 that(2) by auto hence g_ran: "g ` R f \ {..7 * b\<^sup>2}" by auto - have "sample_pmf [b]\<^sub>S = pmf_of_set {..\. \ x) (sample_pmf (\ k (C\<^sub>7 * b\<^sup>2) [b]\<^sub>S)) = pmf_of_set {.. b) = pmf_of_set {..\. \ x) (sample_pro (\ k (C\<^sub>7 * b\<^sup>2) (\ b))) = pmf_of_set {.. g ` R f" for x - using g_ran \\<^sub>3.single that by auto + using g_ran hash_pro_component[OF \\<^sub>3 _ k_gt_0] that by auto moreover have "prob_space.k_wise_indep_vars \\<^sub>3 k (\_. discrete) (\x \. \ x) (g ` R f)" - by (intro prob_space.k_wise_indep_subset[OF _ _ \\<^sub>3.indep] g_ran prob_space_measure_pmf) - ultimately have lim_balls_and_bins: "B.lim_balls_and_bins k (sample_pmf (\ k (C\<^sub>7 * b\<^sup>2) [b]\<^sub>S))" + by (intro prob_space.k_wise_indep_subset[OF _ _ hash_pro_k_indep[OF \\<^sub>3]] g_ran + prob_space_measure_pmf) + ultimately have lim_balls_and_bins: "B.lim_balls_and_bins k (sample_pro (\ k (C\<^sub>7 * b\<^sup>2) (\ b)))" unfolding B.lim_balls_and_bins_def by auto have card_g_R: "card (g ` R f) = card (R f)" using True card_image by auto hence b_mu: "\ (card (R f)) = B.\" unfolding B.\_def \_def using b_min by (simp add:powr_realpow) have card_g_le_b: "card (g ` R f) \ card {.. measure \\<^sub>3 {h. \B.Y h - B.\\ > 9 * real (card (g ` R f)) / sqrt (card {.. {h. E\<^sub>1 (f,g,h) \ E\<^sub>2 (f,g,h) \ E\<^sub>3 (f,g,h) \ \E\<^sub>4 (f,g,h)}" hence b: "\p (f,g,h) -\ (card (R f))\ > \/12 * card (R f)" unfolding E\<^sub>4_def by simp - assume "h \ set_pmf (sample_pmf \\<^sub>3)" - hence h_range: "h x < b" for x - unfolding sample_space_alt[OF \\<^sub>3.sample_space,symmetric] using h_range_1 by simp + assume "h \ set_pmf (sample_pro \\<^sub>3)" + hence h_range: "h x < b" for x using h_range_1 by simp have "{j \ {.. \\<^sub>1 (f, g, h) A 0 j} = {j \ {.. max (Max ({int (f a) |a. a \ A \ h (g a) = j} \ {-1})) (- 1)}" unfolding \\<^sub>1_def by simp also have "... = {j \ {.. Max ({int (f a) |a. a \ A \ h (g a) = j} \ {-1})}" using fin_A by (subst max_absorb1) (auto intro: Max_ge) also have "... = {j \ {..a \ R f. h (g a) = j)}" unfolding R_def using fin_A by (subst Max_ge_iff) auto also have "... = {j. \a \ R f. h (g a) = j}" using h_range by auto also have "... = (h \ g) ` (R f)" by (auto simp add:set_eq_iff image_iff) also have "... = h ` (g ` (R f))" by (simp add:image_image) finally have c:"{j \ {.. \\<^sub>1 (f, g, h) A 0 j} = h ` (g ` R f)" by simp have "9 * real (card (g ` R f)) / sqrt (card {.. \/12 * card (R f)" by (intro mult_right_mono e_4_h) simp also have "... < \B.Y h - B.\\" using b c unfolding B.Y_def p_def b_mu by simp finally show "h \ {h. \B.Y h - B.\\ > 9 * real (card (g ` R f)) / sqrt (card {.. 1/2^6" using k_min by (intro B.devitation_bound[OF card_g_le_b lim_balls_and_bins]) auto finally show ?thesis by simp next case False have "?L1 \ measure \\<^sub>3 {}" proof (rule pmf_mono) fix h assume b:"h \ {h. E\<^sub>1 (f, g, h) \ E\<^sub>2 (f, g, h) \ E\<^sub>3 (f, g, h) \ \ E\<^sub>4 (f, g, h)}" hence "card (R f) \ (2/3)*b" by (auto intro!: R_bound[simplified]) hence "card (R f) \ b" by simp moreover have "inj_on g (R f)" using b by (simp add:E\<^sub>3_def) ultimately have "False" using False by simp thus "h \ {}" by simp qed also have "... = 0" by simp finally show ?thesis by simp qed have "?L = (\f. (\g. measure \\<^sub>3 {h. E\<^sub>1 (f,g,h) \ E\<^sub>2 (f,g,h) \ E\<^sub>3 (f,g,h) \ \E\<^sub>4 (f,g,h)} \\\<^sub>2) \\\<^sub>1)" - unfolding sample_pmf_\ split_pair_pmf by simp + unfolding sample_pro_\ split_pair_pmf by simp also have "... \ (\f. (\g. 1/2^6 \\\<^sub>2) \\\<^sub>1)" - using a \\<^sub>1.sample_space \\<^sub>2.sample_space - by (intro integral_mono_AE AE_pmfI) simp_all + using a by (intro integral_mono_AE AE_pmfI) simp_all also have "... = 1/2^6" by simp finally show ?thesis by simp qed lemma \_inverse: "\_inv (\ x) = x" proof - have a:"1-1/b \ 0" using b_min by simp have "\ x = b * (1-(1-1/b) powr x)" unfolding \_def by simp hence "\ x / real b = 1-(1-1/b) powr x" by simp hence "ln (1 - \ x / real b) = ln ((1-1/b) powr x)" by simp also have "... = x * ln (1 - 1/ b)" using a by (intro ln_powr) finally have "ln (1 - \ x / real b) = x * ln (1- 1/ b)" by simp moreover have "ln (1-1/b) < 0" using b_min by (subst ln_less_zero_iff) auto ultimately show ?thesis using \_inv_def by simp qed lemma rho_mono: assumes "x \ y" shows "\ x \ \ y" proof- have "(1 - 1 / real b) powr y \ (1 - 1 / real b) powr x" using b_min by (intro powr_mono_rev assms) auto thus ?thesis unfolding \_def by (intro mult_left_mono) auto qed lemma rho_two_thirds: "\ (2/3 * b) \ 3/5 *b" proof - have "1/3 \ exp ( - 13 / 12::real )" by (approximation 8) also have "... \ exp ( - 1 - 2 / real b )" using b_min by (intro iffD2[OF exp_le_cancel_iff]) (simp add:algebra_simps) also have "... \ exp ( b * (-(1/real b)-2*(1/real b)^2))" using b_min by (simp add:algebra_simps power2_eq_square) also have "... \ exp ( b * ln (1-1/real b))" using b_min by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono ln_one_minus_pos_lower_bound) auto also have "... = exp ( ln ( (1-1/real b) powr b))" using b_min by (subst ln_powr) auto also have "... = (1-1/real b) powr b" using b_min by (subst exp_ln) auto finally have a:"1/3 \ (1-1/real b) powr b" by simp have "2/5 \ (1/3) powr (2/3::real)" by (approximation 5) also have "... \ ((1-1/real b) powr b) powr (2/3)" by (intro powr_mono2 a) auto also have "... = (1-1/real b) powr (2/3 * real b)" by (subst powr_powr) (simp add:algebra_simps) finally have "2/5 \ (1 - 1 / real b) powr (2 / 3 * real b)" by simp hence "1 - (1 - 1 / real b) powr (2 / 3 * real b) \ 3/5" by simp hence "\ (2/3 * b) \ b * (3/5)" unfolding \_def by (intro mult_left_mono) auto thus ?thesis by simp qed definition \_inv' :: "real \ real" where "\_inv' x = -1 / (real b * (1-x / real b) * ln (1 - 1 / real b))" lemma \_inv'_bound: assumes "x \ 0" assumes "x \ 59/90*b" shows "\\_inv' x\ \ 4" proof - have c:"ln (1 - 1 / real b) < 0" using b_min by (subst ln_less_zero_iff) auto hence d:"real b * (1 - x / real b) * ln (1 - 1 / real b) < 0" using b_min assms by (intro Rings.mult_pos_neg) auto have "(1::real) \ 31/30" by simp also have "... \ (31/30) * (b * -(- 1 / real b))" using b_min by simp also have "... \ (31/30) * (b * -ln (1 + (- 1 / real b)))" using b_min by (intro mult_left_mono le_imp_neg_le ln_add_one_self_le_self2) auto also have "... \ 3 * (31/90) * (- b * ln (1 - 1 / real b))" by simp also have "... \ 3 * (1 - x / real b) * (- b * ln (1 - 1 / real b))" using assms b_min pos_divide_le_eq[where c="b"] c by (intro mult_right_mono mult_left_mono mult_nonpos_nonpos) auto also have "... \ 3 * (real b * (1 - x / real b) * (-ln (1 - 1 / real b)))" by (simp add:algebra_simps) finally have "3 * (real b * (1 - x / real b) * (-ln (1 - 1 / real b))) \ 1" by simp hence "3 * (real b * (1 - x / real b) * ln (1 - 1 / real b)) \ -1" by simp hence "\_inv' x \ 3" unfolding \_inv'_def using d by (subst neg_divide_le_eq) auto moreover have "\_inv' x > 0" unfolding \_inv'_def using d by (intro divide_neg_neg) auto ultimately show ?thesis by simp qed lemma \_inv': fixes x :: real assumes "x < b" shows "DERIV \_inv x :> \_inv' x" proof - have "DERIV (ln \ (\x. (1 - x / real b))) x :> 1 / (1-x / real b) * (0 -1/b)" using assms b_min by (intro DERIV_chain DERIV_ln_divide DERIV_cdivide derivative_intros) auto hence "DERIV \_inv x :> (1 / (1-x / real b) * (-1/b)) / ln (1-1/real b)" unfolding comp_def \_inv_def by (intro DERIV_cdivide) auto thus ?thesis by (simp add:\_inv'_def algebra_simps) qed lemma accuracy_without_cutoff: "measure \ {(f,g,h). \Y (f,g,h) - real X\ > \ * X \ s f < q_max} \ 1/2^4" (is "?L \ ?R") proof - have "?L \ measure \ {\. \E\<^sub>1 \ \ \E\<^sub>2 \ \ \E\<^sub>3 \ \ \E\<^sub>4 \}" proof (rule pmf_rev_mono) - fix \ assume "\ \ set_pmf (sample_pmf \)" + fix \ assume "\ \ set_pmf (sample_pro \)" obtain f g h where \_def: "\ = (f,g,h)" by (metis prod_cases3) assume "\ \ {\. \ E\<^sub>1 \ \ \ E\<^sub>2 \ \ \ E\<^sub>3 \ \ \ E\<^sub>4 \}" hence assms: "E\<^sub>1 (f,g,h)" "E\<^sub>2 (f,g,h)" "E\<^sub>3 (f,g,h)" "E\<^sub>4 (f,g,h)" unfolding \_def by auto define I :: "real set" where "I = {0..59/90*b}" have "p (f,g,h) \ \ (card (R f)) + \/12 * card (R f)" using assms(4) E\<^sub>4_def unfolding abs_le_iff by simp also have "... \ \(2/3*b) + 1/12* (2/3*b)" using \_lt_1 R_bound[OF assms(1,2)] by (intro add_mono rho_mono mult_mono) auto also have "... \ 3/5 * b + 1/18*b" by (intro add_mono rho_two_thirds) auto also have "... \ 59/90 * b" by simp finally have "p (f,g,h) \ 59/90 * b" by simp hence p_in_I: "p (f,g,h) \ I" unfolding I_def by simp have "\ (card (R f)) \ \(2/3 * b)" using R_bound[OF assms(1,2)] by (intro rho_mono) auto also have "... \ 3/5 * b" using rho_two_thirds by simp also have "... \ b * 59/90" by simp finally have "\ (card (R f)) \ b * 59/90" by simp moreover have "(1 - 1 / real b) powr (real (card (R f))) \ 1 powr (real (card (R f)))" using b_min by (intro powr_mono2) auto hence "\ (card (R f)) \ 0" unfolding \_def by (intro mult_nonneg_nonneg) auto ultimately have "\ (card (R f)) \ I" unfolding I_def by simp moreover have "interval I" unfolding I_def interval_def by simp moreover have "59 / 90 * b < b" using b_min by simp hence "DERIV \_inv x :> \_inv' x" if "x \ I" for x using that I_def by (intro \_inv') simp ultimately obtain \ :: real where \_def: "\ \ I" "\_inv (p(f,g,h)) - \_inv (\ (card (R f))) = (p (f,g,h) - \(card (R f))) * \_inv' \" using p_in_I MVT_interval by blast have "\\_inv(p (f,g,h)) - card (R f)\ = \\_inv(p (f,g,h)) - \_inv(\(card (R f)))\" by (subst \_inverse) simp also have "... = \(p (f,g,h) - \ (card (R f)))\ * \\_inv' \ \" using \_def(2) abs_mult by simp also have "... \ \p (f,g,h) - \ (card (R f))\ * 4" using \_def(1) I_def by (intro mult_left_mono \_inv'_bound) auto also have "... \ ( \/12 * card (R f)) * 4" using assms(4) E\<^sub>4_def by (intro mult_right_mono) auto also have "... = \/3 * card (R f)" by simp finally have b: "\\_inv(p (f,g,h)) - card (R f)\ \ \/3 * card (R f)" by simp have "\\_inv(p (f,g,h)) - X / 2 ^ (s f)\ \ \\_inv(p (f,g,h)) - card (R f)\ + \card (R f) - X / 2 ^ (s f)\" by simp also have "... \ \/3 * card (R f) + \card (R f) - X / 2 ^ (s f)\" by (intro add_mono b) auto also have "... = \/3 * \X / 2 ^ (s f) + (card (R f) - X / 2 ^ (s f))\ + \card (R f) - X / 2 ^ (s f)\" by simp also have "... \ \/3 * (\X / 2 ^ (s f)\ + \card (R f) - X / 2 ^ (s f)\) + \card (R f) - X / 2 ^ (s f)\" using \_gt_0 by (intro mult_left_mono add_mono abs_triangle_ineq) auto also have "... \ \/3 * \X / 2 ^ (s f)\ + (1+ \/3) * \card (R f) - X / 2 ^ (s f)\" using \_gt_0 \_lt_1 by (simp add:algebra_simps) also have "... \ \/3 * \X / 2 ^ s f\ + (4/3) * ( \ / 3 * real X / 2 ^ s f)" using assms(2) \_gt_0 \_lt_1 unfolding E\<^sub>2_def by (intro add_mono mult_mono) auto also have "... = (7/9) * \ * real X / 2^s f" using X_ge_1 by (subst abs_of_nonneg) auto also have "... \ 1 * \ * real X / 2^s f" using \_gt_0 by (intro mult_mono divide_right_mono) auto also have "... = \ * real X / 2^s f" by simp finally have a:"\\_inv(p (f,g,h)) - X / 2 ^ (s f)\ \ \ * X / 2 ^ (s f)" by simp have "\Y (f, g, h) - real X\ = \2 ^ (s f)\ * \\_inv(p (f,g,h)) - real X / 2 ^ (s f)\" unfolding Y_def by (subst abs_mult[symmetric]) (simp add:algebra_simps powr_add[symmetric]) also have "... \ 2 ^ (s f) * (\ * X / 2 ^ (s f))" by (intro mult_mono a) auto also have "... = \ * X" by (simp add:algebra_simps powr_add[symmetric]) finally have "\Y (f, g, h) - real X\ \ \ * X" by simp moreover have "2 powr (\log 2 (real X)\ - t f) \ 2 powr b_exp" (is "?L1 \ ?R1") proof - have "?L1 \ 2 powr (1 + log 2 (real X)- t f)" by (intro powr_mono, linarith) auto also have "... = 2 powr 1 * 2 powr (log 2 (real X)) * 2 powr (- t f)" unfolding powr_add[symmetric] by simp also have "... = 2 * (2 powr (-t f) * X)" using X_ge_1 by simp also have "... \ 2 * (b/2)" using assms(1) unfolding E\<^sub>1_def by (intro mult_left_mono) auto also have "... = b" by simp also have "... = ?R1" unfolding b_def by (simp add: powr_realpow) finally show ?thesis by simp qed hence "\log 2 (real X)\ - t f \ real b_exp" unfolding not_less[symmetric] using powr_less_mono[where x="2"] by simp hence "s f \ q_max" unfolding s_def q_max_def by (intro nat_mono) auto ultimately show "\ \ {(f, g, h). \ * X < \Y (f, g, h) - real X\ \ s f < q_max}" unfolding \_def by auto qed also have "... \ measure \ {\. \E\<^sub>1 \ \ \E\<^sub>2 \ \ \E\<^sub>3 \} + measure \ {\. E\<^sub>1 \ \ E\<^sub>2 \ \ E\<^sub>3 \ \ \E\<^sub>4 \}" by (intro pmf_add) auto also have "... \ (measure \ {\. \E\<^sub>1 \ \ \E\<^sub>2 \} + measure \ {\. E\<^sub>1 \ \ E\<^sub>2 \ \ \E\<^sub>3 \}) + 1/2^6" by (intro add_mono e_4 pmf_add) auto also have "... \ ((measure \ {\. \E\<^sub>1 \} + measure \ {\. E\<^sub>1 \ \ \E\<^sub>2 \}) + 1/2^6) + 1/2^6" by (intro add_mono e_3 pmf_add) auto also have "... \ ((1/2^6 + 1/2^6) + 1/2^6) + 1/2^6" by (intro add_mono e_2 e_1) auto also have "... = ?R" by simp finally show ?thesis by simp qed end end diff --git a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Cutoff_Level.thy b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Cutoff_Level.thy --- a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Cutoff_Level.thy +++ b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Cutoff_Level.thy @@ -1,463 +1,461 @@ section \Cutoff Level\ text \This section verifies that the cutoff will be below @{term "q_max"} with high probability. The result will be needed in Section~\ref{sec:accuracy}, where it is shown that the estimates will be accurate for any cutoff below @{term "q_max"}.\ theory Distributed_Distinct_Elements_Cutoff_Level imports Distributed_Distinct_Elements_Accuracy_Without_Cutoff Distributed_Distinct_Elements_Tail_Bounds begin hide_const Quantum.Z unbundle intro_cong_syntax lemma mono_real_of_int: "mono real_of_int" unfolding mono_def by auto lemma Max_le_Sum: fixes f :: "'a \ int" assumes "finite A" assumes "\a. a \ A \ f a \ 0" shows "Max (insert 0 (f ` A)) \ (\a \A .f a)" (is "?L \ ?R") proof (cases "A\{}") case True have 0: "f a \ (\a \A .f a)" if "a \ A" for a using that assms by (intro member_le_sum) auto have "?L = max 0 (Max (f ` A))" using True assms(1) by (subst Max_insert) auto also have "... = Max (max 0 ` f ` A)" using assms True by (intro mono_Max_commute monoI) auto also have "... = Max (f ` A)" unfolding image_image using assms by (intro arg_cong[where f="Max"] image_cong) auto also have "... \ ?R" using 0 True assms(1) by (intro iffD2[OF Max_le_iff]) auto finally show ?thesis by simp next case False hence "A = {}" by simp then show ?thesis by simp qed context inner_algorithm_fix_A begin text \The following inequality is true for base e on the entire domain ($x > 0$). It is shown in @{thm [source] ln_add_one_self_le_self}. In the following it is established for base $2$, where it holds for $x \geq 1$.\ lemma log_2_estimate: assumes "x \ (1::real)" shows "log 2 (1+x) \ x" proof - define f where "f x = x - log 2 (1+ x)" for x :: real define f' where "f' x = 1 - 1/((x+1)*ln 2)" for x :: real have 0:"(f has_real_derivative (f' x)) (at x)" if "x > 0" for x unfolding f_def f'_def using that by (auto intro!: derivative_eq_intros) have "f' x \ 0" if "1 \ x" for x :: real proof - have "(1::real) \ 2*ln 2" by (approximation 5) also have "... \ (x+1)*ln 2" using that by (intro mult_right_mono) auto finally have "1 \ (x+1)*ln 2" by simp hence "1/((x+1)*ln 2) \ 1" by simp thus ?thesis unfolding f'_def by simp qed hence "\y. (f has_real_derivative y) (at x) \ 0 \ y" if "x \ 1" for x :: real using that order_less_le_trans[OF exp_gt_zero] by (intro exI[where x="f' x"] conjI 0) auto hence "f 1 \ f x" by (intro DERIV_nonneg_imp_nondecreasing[OF assms]) auto thus "?thesis" unfolding f_def by simp qed lemma cutoff_eq_7: "real X * 2 powr (-real q_max) / b \ 1" proof - have "real X = 2 powr (log 2 X)" using X_ge_1 by (intro powr_log_cancel[symmetric]) auto also have "... \ 2 powr (nat \log 2 X\)" by (intro powr_mono) linarith+ also have "... = 2 ^ (nat \log 2 X\)" by (subst powr_realpow) auto also have "... = real (2 ^ (nat \log 2 (real X)\))" by simp also have "... \ real (2 ^ (b_exp + nat (\log 2 (real X)\ - int b_exp)))" by (intro Nat.of_nat_mono power_increasing) linarith+ also have "... = b * 2^q_max" unfolding q_max_def b_def by (simp add: power_add) finally have "real X \ b * 2 ^ q_max" by simp thus ?thesis using b_min unfolding powr_minus inverse_eq_divide by (simp add:field_simps powr_realpow) qed lemma cutoff_eq_6: fixes k assumes "a \ A" shows " (\f. real_of_int (max 0 (int (f a) - int k)) \\\<^sub>1) \ 2 powr (-real k)" (is "?L \ ?R") proof (cases "k \ n_exp - 1") case True have a_le_n: "a < n" using assms A_range by auto have "?L = (\x. real_of_int (max 0 (int x - k)) \map_pmf (\x. x a) \\<^sub>1)" by simp also have "... = (\x. real_of_int (max 0 (int x - k)) \(\ n_exp))" - unfolding \\<^sub>1.single[OF a_le_n] by simp + by (subst hash_pro_component[OF \\<^sub>1 a_le_n]) auto also have "... = (\x. max 0 (real x - real k) \(\ n_exp))" unfolding max_of_mono[OF mono_real_of_int,symmetric] by simp also have "... = (\x\n_exp. max 0 (real x - real k) * pmf (\ n_exp) x)" - using \_range unfolding sample_space_alt[OF \_sample_space] - by (intro integral_measure_pmf_real) auto + using geom_pro_range by (intro integral_measure_pmf_real) auto also have "... = (\x=k+1..n_exp. (real x - real k) * pmf (\ n_exp) x)" by (intro sum.mono_neutral_cong_right) auto also have "... = (\x=k+1..n_exp. (real x - real k) * measure (\ n_exp) {x})" unfolding measure_pmf_single by simp also have "... = (\x=k+1..n_exp. (real x-real k)*(measure (\ n_exp) ({\. \\x}-{\. \\(x+1)})))" by (intro sum.cong arg_cong2[where f="(*)"] measure_pmf_cong) auto also have "... = (\x=k+1..n_exp. (real x-real k)* (measure (\ n_exp) {\. \\x} - measure (\ n_exp) {\. \\(x+1)}))" by (intro sum.cong arg_cong2[where f="(*)"] measure_Diff) auto also have "... = (\x=k+1..n_exp. (real x - real k) * (1/2^x - of_bool(x+1\n_exp)/2^(x+1)))" - unfolding \_prob by (intro_cong "[\\<^sub>2 (*), \\<^sub>2 (-), \\<^sub>2 (/)]" more:sum.cong) auto + unfolding geom_pro_prob by (intro_cong "[\\<^sub>2 (*), \\<^sub>2 (-), \\<^sub>2 (/)]" more:sum.cong) auto also have "... = (\x=k+1..n_exp. (real x-k)/2^x) - (\x=k+1..n_exp. (real x-k)* of_bool(x+1\n_exp)/2^(x+1))" by (simp add:algebra_simps sum_subtractf) also have "...=(\x=k+1..n_exp. (real x-k)/2^x)-(\x=k+1..n_exp-1. (real x-k)/2^(x+1))" by (intro arg_cong2[where f="(-)"] refl sum.mono_neutral_cong_right) auto also have "...=(\x=k+1..(n_exp-1)+1. (real x-k)/2^x)-(\x=k+1..n_exp-1. (real x-k)/2^(x+1))" using n_exp_gt_0 by (intro arg_cong2[where f="(-)"] refl sum.cong) auto also have "...= (\x\insert k {k+1..n_exp-1}. (real (x+1)-k)/2^(x+1))- (\x=k+1..n_exp-1. (real x-k)/2^(x+1))" unfolding sum.shift_bounds_cl_nat_ivl using True by (intro arg_cong2[where f="(-)"] sum.cong) auto also have "... = 1/2^(k+1)+(\x=k+1..n_exp-1. (real (x+1)-k)/2^(x+1)- (real x-k)/2^(x+1))" by (subst sum.insert) (auto simp add:sum_subtractf) also have "... = 1/2^(k+1)+(\x=k+1..n_exp-1. (1/2^(x+1)))" by (intro arg_cong2[where f="(+)"] sum.cong refl) (simp add:field_simps) also have "... = (\x\insert k {k+1..n_exp-1}. (1/2^(x+1)))" by (subst sum.insert) auto also have "... = (\x=0+k..(n_exp-1-k)+k. 1/2^(x+1))" using True by (intro sum.cong) auto also have "... = (\xx (1/2)^(k+1) * 2 * (1-0)" by (intro mult_left_mono diff_mono) auto also have "... = (1/2)^k" unfolding power_add by simp also have "... = ?R" unfolding powr_minus by (simp add:powr_realpow inverse_eq_divide power_divide) finally show ?thesis by simp next case False hence k_ge_n_exp: "k \ n_exp" by simp have a_lt_n: "a < n" using assms A_range by auto have "?L = (\x. real_of_int (max 0 (int x - k)) \map_pmf (\x. x a) \\<^sub>1)" by simp also have "... = (\x. real_of_int (max 0 (int x - k)) \(\ n_exp))" - unfolding \\<^sub>1.single[OF a_lt_n] by simp + by (subst hash_pro_component[OF \\<^sub>1 a_lt_n]) auto also have "... = (\x. real_of_int 0 \(\ n_exp))" - using \_range k_ge_n_exp unfolding sample_space_alt[OF \_sample_space] + using geom_pro_range k_ge_n_exp by (intro integral_cong_AE AE_pmfI iffD2[OF of_int_eq_iff] max_absorb1) force+ also have "... = 0" by simp finally show ?thesis by simp qed lemma cutoff_eq_5: assumes "x \ (-1 :: real)" shows "real_of_int \log 2 (x+2)\ \ (real c+2) + max (x - 2^c) 0" (is "?L \ ?R") proof - have 0: "1 \ 2 ^ 1 * ln (2::real)" by (approximation 5) consider (a) "c = 0 \ x \ 2^c+1" | (b) "c > 0 \ x \ 2^c+1" | (c) "x \ 2^c+1" by linarith hence "log 2 (x+2) \ ?R" proof (cases) case a have "log 2 (x+2) = log 2 (1+(x+1))" by (simp add:algebra_simps) also have "... \ x+1" using a by (intro log_2_estimate) auto also have "... = ?R" using a by auto finally show ?thesis by simp next case b have "0 < 0 + (1::real)" by simp also have "... \ 2^c+(1::real)" by (intro add_mono) auto also have "... \ x" using b by simp finally have x_gt_0: "x > 0" by simp have "log 2 (x+2) = log 2 ((x+2)/2^c) + c" using x_gt_0 by (subst log_divide) auto also have "... = log 2 (1+(x+2-2^c)/2^c) + c" by (simp add:divide_simps) also have "... \ (x+2-2^c)/2^c / ln 2 + c" using b unfolding log_def by (intro add_mono divide_right_mono ln_add_one_self_le_self divide_nonneg_pos) auto also have "... = (x+2-2^c)/(2^c*ln 2) + c" by simp also have "... \ (x+2-2^c)/(2^1*ln 2)+c" using b by (intro add_mono divide_left_mono mult_right_mono power_increasing) simp_all also have "... \ (x+2-2^c)/1 + c" using b by (intro add_mono divide_left_mono 0) auto also have "... \ (c+2) + max (x - 2^c) 0" using b by simp finally show ?thesis by simp next case c hence "log 2 (x+2) \ log 2 ((2^c+1)+2)" using assms by (intro log_mono add_mono) auto also have "... = log 2 (2^c*(1+3/2^c))" by (simp add:algebra_simps) also have "... = c + log 2 (1+3/2^c)" by (subst log_mult) (auto intro:add_pos_nonneg) also have "... \ c + log 2 (1+3/2^0)" by (intro add_mono log_mono divide_left_mono power_increasing add_pos_nonneg) auto also have "... = c + log 2 (2*2)" by simp also have "... = real c + 2" by (subst log_mult) auto also have "... \ (c+2) + max (x - 2^c) 0" by simp finally show ?thesis by simp qed moreover have "\log 2 (x+2)\ \ log 2 (x+2)" by simp ultimately show ?thesis using order_trans by blast qed lemma cutoff_level: "measure \ {\. q \ A > q_max} \ \/2" (is "?L \ ?R") proof - have C\<^sub>1_est: "C\<^sub>1 * l \ 30 * real l" unfolding C\<^sub>1_def by (intro mult_right_mono of_nat_0_le_iff) (approximation 10) define Z where "Z \ = (\jlog 2 (of_int (max (\\<^sub>1 \ A q_max j) (-1)) + 2)\)" for \ define V where "V \ = Z \ / real b - 3" for \ have 2:"Z \ \ real b*(real c+2) + of_int (\a\A. max 0 (int (fst \ a) - q_max -2^c))" - (is "?L1 \ ?R1") if "\ \ sample_set \" for c \ + (is "?L1 \ ?R1") if "\ \ sample_pro \" for c \ proof - obtain f g h where \_def: "\ = (f,g,h)" using prod_cases3 by blast - have \_range: "(f,g,h) \ sample_set \" + have \_range: "(f,g,h) \ sample_pro \" using that unfolding \_def by simp have "- 1 - 2^c \ -1-(1::real)" by (intro diff_mono) auto also have "... \ 0" by simp finally have "- 1 - 2 ^ c \ (0::real)" by simp hence aux3: "max (-1-2^c) 0 = (0::real)" by (intro max_absorb2) have "- 1 - int q_max - 2 ^ c \ -1 - 0 - 1" by (intro diff_mono) auto also have "... \ 0" by simp finally have "- 1 - int q_max - 2 ^ c \ 0" by simp hence aux3_2: "max 0 (- 1 - int q_max - 2 ^ c) = 0" by (intro max_absorb1) have "?L1 \ (\j\<^sub>1 \ A q_max j) (- 1)) - 2^c) 0)" unfolding Z_def by (intro sum_mono cutoff_eq_5) auto also have "... = (\j\<^sub>0 \ A j - q_max - 2^c) 0)" unfolding \\<^sub>1_def max_of_mono[OF mono_real_of_int,symmetric] by (intro_cong "[\\<^sub>2 (+)]" more:sum.cong) (simp add:max_diff_distrib_left max.assoc aux3) also have "... = real b * (real c + 2) + of_int (\j A \ h (g a) = j})-q_max - 2^c)))" unfolding \_def by (simp add:max.commute) also have "... = real b * (real c + 2) + of_int (\jx. x-q_max-2^c)`(insert(-1){int (f a) |a. a \ A\h(g a)=j}))))" using fin_A by (intro_cong "[\\<^sub>2 (+), \\<^sub>1 of_int, \\<^sub>2 max]" more:sum.cong mono_Max_commute) (auto simp:monoI) also have "... = real b * (real c + 2) + of_int(\j A \ h (g a) = j})))" by (intro_cong "[\\<^sub>2 (+), \\<^sub>1 of_int, \\<^sub>2 max, \\<^sub>1 Max]" more:sum.cong) auto also have "... = real b * (real c + 2) + of_int (\j A \ h (g a) = j})))" using fin_A by (intro_cong "[\\<^sub>2 (+), \\<^sub>1 of_int]" more:sum.cong mono_Max_commute) (auto simp add:monoI setcompr_eq_image) also have "... = real b * (real c + 2) + of_int (\j A \ h (g a) = j}))" using aux3_2 by (intro_cong "[\\<^sub>2 (+), \\<^sub>1 of_int, \\<^sub>1 Max]" more:sum.cong) (simp add:setcompr_eq_image image_image) also have "... \ b*(real c+2)+ of_int(\ja|a\A\h(g(a))=j. max 0(int(f a)-q_max-2^c)))" using fin_A Max_le_Sum unfolding setcompr_eq_image by (intro add_mono iffD2[OF of_int_le_iff] sum_mono Max_le_Sum) (simp_all) also have "... = real b*(real c+2)+ of_int(\a\(\j\{..A\ h(g(a)) = j}). max 0(int(f a)-q_max-2^c))" using fin_A by (intro_cong "[\\<^sub>2 (+), \\<^sub>1 of_int]" more:sum.UNION_disjoint[symmetric]) auto also have "... = real b*(real c+2) + of_int(\a\A. max 0(int(f a)-q_max-2^c))" using h_range[OF \_range] by (intro_cong "[\\<^sub>2 (+), \\<^sub>1 of_int]" more:sum.cong) auto also have "... = ?R1" unfolding \_def by simp finally show ?thesis by simp qed have 1: "measure \ {\. real c \ V \} \ 2 powr (- (2^c))" (is "?L1 \ ?R1") for c proof - have "?L1 = measure \ {\. real b * (real c + 3) \ Z \}" unfolding V_def using b_min by (intro measure_pmf_cong) (simp add:field_simps) also have "... \ measure \ {\. real b*(real c+3)\ real b*(real c+2)+ of_int (\a\A. max 0 (int (fst \ a)-q_max -2^c))}" - using 2 order_trans unfolding sample_space_alt[OF sample_space_\] - by (intro pmf_mono) blast + using 2 order_trans by (intro pmf_mono) blast also have "... = measure \ {\. real b \ (\a\A. of_int (max 0 (int (fst \ a) -q_max -2^c)))}" by (intro measure_pmf_cong) (simp add:algebra_simps) also have "... \ (\\. (\a\A. of_int (max 0 (int (fst \ a) -q_max -2^c))) \\)/real b" - using b_min sample_space_\ by (intro pmf_markov sum_nonneg) simp_all + using b_min by (intro pmf_markov sum_nonneg) simp_all also have "... = (\a\A. (\\. of_int (max 0 (int (fst \ a) -q_max -2^c)) \\))/real b" - using sample_space_\ by (intro_cong "[\\<^sub>2(/)]" more:Bochner_Integration.integral_sum) simp + by (intro_cong "[\\<^sub>2(/)]" more:Bochner_Integration.integral_sum) simp also have "... = (\a\A. (\f. of_int (max 0 (int (f a)-q_max -2^c)) \(map_pmf fst \)))/real b" by simp also have "... = (\a\A. (\f. of_int (max 0 (int (f a) - (q_max +2^c))) \\\<^sub>1))/real b" - unfolding sample_pmf_\ map_fst_pair_pmf by (simp add:algebra_simps) + unfolding sample_pro_\ map_fst_pair_pmf by (simp add:algebra_simps) also have "... \ (\a\A. 2 powr -real (q_max + 2^c))/real b" using b_min by (intro sum_mono divide_right_mono cutoff_eq_6) auto also have "... = real X * 2 powr (- real q_max + (- (2 ^ c))) / real b" unfolding X_def by simp also have "... = (real X * 2 powr (-real q_max) / b) * 2 powr (-(2^c))" unfolding powr_add by (simp add:algebra_simps) also have "... \ 1 * 2 powr (-(2^c))" using cutoff_eq_7 by (intro mult_right_mono) auto finally show ?thesis by simp qed have 0: "measure \ {\. x \ V \} \ exp (- x * ln x ^ 3)" (is "?L1 \ ?R1") if "x \ 20" for x proof - define c where "c = nat \x\" have "x * ln x^3 \ exp (x * ln 2) * ln 2/2" if "x \ 150" for x::real proof - have aux_aux_0: "x^4 \ 0" by simp have "x * ln x^3 \ x * x^3" using that by (intro mult_left_mono power_mono ln_bound) auto also have "... = x^4 * 1" by (simp add:numeral_eq_Suc) also have "... \ x^4 * ((ln 2 / 10)^4 * (150 * (ln 2 / 10))^6 * (ln 2/2))" by (intro mult_left_mono aux_aux_0) (approximation 8) also have "... = (x * (ln 2 / 10))^4 * (150 * (ln 2 / 10))^6 * (ln 2/2)" unfolding power_mult_distrib by (simp add:algebra_simps) also have "... \ (x * (ln 2 / 10))^4 * (x * (ln 2 / 10))^6 * (ln 2/2)" by (intro mult_right_mono mult_left_mono power_mono that) auto also have "... = (0+x * (ln 2 / 10))^10 * (ln 2/2)" unfolding power_add[symmetric] by simp also have "... \ (1+x * ln 2 / 10)^10 * (ln 2/2)" using that by (intro mult_right_mono power_mono add_mono) auto also have "... \ exp (x * ln 2 / 10)^10 * (ln 2/2)" using that by (intro mult_right_mono power_mono exp_ge_add_one_self) auto also have "... = exp (x * ln 2) * (ln 2/2)" unfolding exp_of_nat_mult[symmetric] by simp finally show ?thesis by simp qed moreover have "x * ln x^3 \ exp (x * ln 2) * ln 2/2" if "x \ {20..150}" using that by (approximation 10 splitting: x=1) ultimately have "x * ln x^3 \ exp (x * ln 2) * ln 2/2" using that by fastforce also have "... = 2 powr (x-1) * ln 2" unfolding powr_diff unfolding powr_def by simp also have "... \ 2 powr c * ln 2" unfolding c_def using that by (intro mult_right_mono powr_mono) auto also have "... = 2^c * ln 2" using powr_realpow by simp finally have aux0: "x * ln x^3 \ 2^c * ln 2" by simp have "real c \ x" using that unfolding c_def by linarith hence "?L1 \ measure \ {\. real c \ V \}" by (intro pmf_mono) auto also have "... \ 2 powr (-(2^c))" by (intro 1) also have "... = exp (- (2 ^ c * ln 2))" by (simp add:powr_def) also have "... \ exp (- (x *ln x^3))" using aux0 by (intro iffD2[OF exp_le_cancel_iff]) auto also have "... = ?R1" by simp finally show ?thesis by simp qed have "?L \ measure \ {\. is_too_large (\\<^sub>2 \ A q_max)}" using lt_s_too_large by (intro pmf_mono) (simp del:is_too_large.simps) also have "... = measure \ {\. (\(i,j)\{..{..log 2 (of_int (max (\\<^sub>2 \ A q_max i j) (-1)) + 2)\) > C\<^sub>5 * b *l}" by simp also have "... = measure \ {\. real_of_int (\(i,j)\{..{..log 2 (of_int (max (\\<^sub>2 \ A q_max i j) (-1)) + 2)\) > of_int (C\<^sub>5 * b * l)}" unfolding of_int_less_iff by simp also have "... = measure \ {\. real_of_int C\<^sub>5 * real b * real l < of_int (\x\{.. {..log 2 (real_of_int (\\<^sub>1 (\ (fst x)) A q_max (snd x)) + 2)\)}" by (intro_cong "[\\<^sub>2 measure, \\<^sub>1 Collect, \\<^sub>1 of_int, \\<^sub>2 (<)]" more:ext sum.cong) (auto simp add:case_prod_beta \\<^sub>2_def \\<^sub>1_def) also have "... = measure \ {\. (\i i)) > of_int C\<^sub>5 * real b * real l}" unfolding Z_def sum.cartesian_product \\<^sub>1_def by (simp add:case_prod_beta) also have "... = measure \ {\. (\i i) + 3) > of_int C\<^sub>5 * real l}" unfolding V_def using b_min by (intro measure_pmf_cong) (simp add:sum_divide_distrib[symmetric] field_simps sum.distrib) also have "... = measure \ {\. (\i i)) > of_int (C\<^sub>5-3) * real l}" by (simp add:sum.distrib algebra_simps) also have "... \ measure \ {\. (\i i)) \ C\<^sub>1 * real l}" unfolding C\<^sub>5_def using C\<^sub>1_est by (intro pmf_mono) auto also have "... \ exp (- real l)" - by (intro \.deviation_bound l_gt_0 0) (simp_all add: \_def) + by (intro deviation_bound l_gt_0 0) (simp_all add: \_def) also have "... \ exp (- (C\<^sub>6 * ln (2 / \)))" using l_lbound by (intro iffD2[OF exp_le_cancel_iff]) auto also have "... \ exp (- (1 * ln (2 / \)))" unfolding C\<^sub>6_def using \_gt_0 \_lt_1 by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le mult_right_mono ln_ge_zero) auto also have "... = exp ( ln ( \ / 2))" using \_gt_0 by (simp add: ln_div) also have "... = \/2" using \_gt_0 by simp finally show ?thesis by simp qed end unbundle no_intro_cong_syntax end \ No newline at end of file diff --git a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Inner_Algorithm.thy b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Inner_Algorithm.thy --- a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Inner_Algorithm.thy +++ b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Inner_Algorithm.thy @@ -1,1104 +1,1074 @@ section \Inner Algorithm\label{sec:inner_algorithm}\ text \This section introduces the inner algorithm (as mentioned it is already a solution to the cardinality estimation with the caveat that, if $\varepsilon$ is too small it requires to much space. The outer algorithm in Section~\ref{sec:outer_algorithm} resolved this problem. The algorithm makes use of the balls and bins model, more precisely, the fact that the number of hit bins can be used to estimate the number of balls thrown (even if there are collusions). I.e. it assigns each universe element to a bin using a $k$-wise independent hash function. Then it counts the number of bins hit. This strategy however would only work if the number of balls is roughly equal to the number of bins, to remedy that the algorithm performs an adaptive sub-sampling strategy. This works by assigning each universe element a level (using a second hash function) with a geometric distribution. The algorithm then selects a level that is appropriate based on a rough estimate obtained using the maximum level in the bins. To save space the algorithm drops information about small levels, whenever the space usage would be too high otherwise. This level will be called the cutoff-level. This is okey as long as the cutoff level is not larger than the sub-sampling threshold. A lot of the complexity in the proof is devoted to verifying that the cutoff-level will not cross it, it works by defining a third value @{term "s\<^sub>M"} that is both an upper bound for the cutoff level and a lower bound for the subsampling threshold simultaneously with high probability.\ theory Distributed_Distinct_Elements_Inner_Algorithm imports - Pseudorandom_Combinators + Universal_Hash_Families.Pseudorandom_Objects_Hash_Families Distributed_Distinct_Elements_Preliminary Distributed_Distinct_Elements_Balls_and_Bins Distributed_Distinct_Elements_Tail_Bounds Prefix_Free_Code_Combinators.Prefix_Free_Code_Combinators begin unbundle intro_cong_syntax hide_const Abstract_Rewriting.restrict definition C\<^sub>4 :: real where "C\<^sub>4 = 3^2*2^23" definition C\<^sub>5 :: int where "C\<^sub>5 = 33" definition C\<^sub>6 :: real where "C\<^sub>6 = 4" definition C\<^sub>7 :: nat where "C\<^sub>7 = 2^5" locale inner_algorithm = fixes n :: nat fixes \ :: real fixes \ :: real assumes n_gt_0: "n > 0" assumes \_gt_0: "\ > 0" and \_lt_1: "\ < 1" assumes \_gt_0: "\ > 0" and \_lt_1: "\ < 1" begin definition b_exp where "b_exp = nat \log 2 (C\<^sub>4 / \^2)\" definition b :: nat where "b = 2^b_exp" definition l where "l = nat \C\<^sub>6 * ln (2/ \)\" definition k where "k = nat \C\<^sub>2*ln b + C\<^sub>3\" definition \ :: real where "\ = min (1/16) (exp (-l * ln l^3))" definition \ :: "real \ real" where "\ x = b * (1 - (1-1/b) powr x)" definition \_inv :: "real \ real" where "\_inv x = ln (1-x/b) / ln (1-1/b)" lemma l_lbound: "C\<^sub>6 * ln (2 / \) \ l" unfolding l_def by linarith lemma k_min: "C\<^sub>2 * ln (real b) + C\<^sub>3 \ real k" unfolding k_def by linarith lemma \_gt_0: "\ > 0" unfolding \_def min_less_iff_conj by auto lemma \_le_1: "\ \ 1" unfolding \_def by auto lemma l_gt_0: "l > 0" proof - have "0 < C\<^sub>6 * ln (2 / \)" unfolding C\<^sub>6_def using \_gt_0 \_lt_1 by (intro Rings.mult_pos_pos ln_gt_zero) auto also have "... \ l" by (intro l_lbound) finally show ?thesis by simp qed lemma l_ubound: "l \ C\<^sub>6 * ln(1 / \)+C\<^sub>6*ln 2 + 1" proof - have "l = of_int \C\<^sub>6 * ln (2/ \)\" using l_gt_0 unfolding l_def by (intro of_nat_nat) simp also have "... \ C\<^sub>6 * ln (1/ \*2)+1" by simp also have "... = C\<^sub>6 * ln (1/ \)+C\<^sub>6 * ln 2+1" using \_gt_0 \_lt_1 by (subst ln_mult) (auto simp add:algebra_simps) finally show ?thesis by simp qed lemma b_exp_ge_26: "b_exp \ 26" proof - have "2 powr 25 < C\<^sub>4 / 1 " unfolding C\<^sub>4_def by simp also have "... \ C\<^sub>4 / \^2" using \_gt_0 \_lt_1 unfolding C\<^sub>4_def by (intro divide_left_mono power_le_one) auto finally have "2 powr 25 < C\<^sub>4 / \^2" by simp hence "log 2 (C\<^sub>4 / \^2) > 25" using \_gt_0 unfolding C\<^sub>4_def by (intro iffD2[OF less_log_iff] divide_pos_pos zero_less_power) auto hence "\log 2 (C\<^sub>4 / \^2)\ \ 26" by simp thus ?thesis unfolding b_exp_def by linarith qed lemma b_min: "b \ 2^26" unfolding b_def by (meson b_exp_ge_26 nat_power_less_imp_less not_less power_eq_0_iff power_zero_numeral) lemma k_gt_0: "k > 0" proof - have "(0::real) < 7.5 * 0 + 16" by simp also have "... \ 7.5 * ln(real b) + 16" using b_min by (intro add_mono mult_left_mono ln_ge_zero) auto finally have "0 < real k" using k_min unfolding C\<^sub>2_def C\<^sub>3_def by simp thus ?thesis by simp qed lemma b_ne: "{.. {}" proof - have "0 \ {0..4 / \^2 \ real b" proof - have "C\<^sub>4 / \^2 = 2 powr (log 2 (C\<^sub>4 / \^2))" using \_gt_0 unfolding C\<^sub>4_def by (intro powr_log_cancel[symmetric] divide_pos_pos) auto also have "... \ 2 powr (nat \log 2 (C\<^sub>4 / \^2)\)" by (intro powr_mono of_nat_ceiling) simp also have "... = real b" unfolding b_def b_exp_def by (simp add:powr_realpow) finally show ?thesis by simp qed definition n_exp where "n_exp = max (nat \log 2 n\) 1" lemma n_exp_gt_0: "n_exp > 0" unfolding n_exp_def by simp abbreviation \\<^sub>1 where "\\<^sub>1 \ \ 2 n (\ n_exp)" -abbreviation \\<^sub>2 where "\\<^sub>2 \ \ 2 n [C\<^sub>7*b\<^sup>2]\<^sub>S" -abbreviation \\<^sub>3 where "\\<^sub>3 \ \ k (C\<^sub>7*b\<^sup>2) [b]\<^sub>S" +abbreviation \\<^sub>2 where "\\<^sub>2 \ \ 2 n (\ (C\<^sub>7*b\<^sup>2))" +abbreviation \\<^sub>3 where "\\<^sub>3 \ \ k (C\<^sub>7*b\<^sup>2) (\ b)" -definition \ where "\ = \\<^sub>1 \\<^sub>S \\<^sub>2 \\<^sub>S \\<^sub>3" +definition \ where "\ = \\<^sub>1 \\<^sub>P \\<^sub>2 \\<^sub>P \\<^sub>3" abbreviation \ where "\ \ \ l \ \" type_synonym state = "(nat \ nat \ int) \ (nat)" fun is_too_large :: "(nat \ nat \ int) \ bool" where "is_too_large B = ((\ (i,j) \ {.. {..log 2 (max (B i j) (-1) + 2)\) > C\<^sub>5 * b * l)" fun compress_step :: "state \ state" where "compress_step (B,q) = (\ i j. max (B i j - 1) (-1), q+1)" function compress :: "state \ state" where "compress (B,q) = ( if is_too_large B then (compress (compress_step (B,q))) else (B,q))" by auto fun compress_termination :: "state \ nat" where "compress_termination (B,q) = (\ (i,j) \ {.. {.. nat (B i j + 1)" for i j by simp assume "\ compress_termination (compress_step (B, q)) < compress_termination (B, q)" hence "(\ (i,j) \ ?I. nat (B i j + 1)) \ (\ (i,j) \ ?I. nat (max (B i j - 1) (-1) + 1))" by simp moreover have "(\ (i,j) \ ?I. nat (B i j + 1)) \ (\ (i,j) \ ?I. nat (max (B i j - 1) (-1) + 1))" by (intro sum_mono) auto ultimately have b: "(\ (i,j) \ ?I. nat (max (B i j - 1) (-1) + 1)) = (\ (i,j) \ ?I. nat (B i j + 1))" using order_antisym by simp have "nat (B i j + 1) = nat (max (B i j - 1) (-1) + 1)" if "(i,j) \ ?I" for i j using sum_mono_inv[OF b] that a by auto hence "max (B i j) (-1) = -1" if "(i,j) \ ?I" for i j using that by fastforce hence "(\(i,j) \ ?I. \log 2 (max (B i j) (-1) + 2)\) = (\(i,j) \ ?I. 0)" by (intro sum.cong, auto) also have "... = 0" by simp also have "... \ C\<^sub>5 * b * l" unfolding C\<^sub>5_def by simp finally have "\ is_too_large B" by simp thus "False" using assms by simp qed termination compress using measure_def compress_termination by (relation "Wellfounded.measure (compress_termination)", auto) fun merge1 :: "state \ state \ state" where "merge1 (B1,q\<^sub>1) (B2, q\<^sub>2) = ( let q = max q\<^sub>1 q\<^sub>2 in (\ i j. max (B1 i j + q\<^sub>1 - q) (B2 i j + q\<^sub>2 - q), q))" fun merge :: "state \ state \ state" where "merge x y = compress (merge1 x y)" type_synonym seed = "nat \ (nat \ nat) \ (nat \ nat) \ (nat \ nat)" fun single1 :: "seed \ nat \ state" where "single1 \ x = (\ i j. let (f,g,h) = \ i in ( if h (g x) = j \ i < l then int (f x) else (-1)), 0)" fun single :: "seed \ nat \ state" where "single \ x = compress (single1 \ x)" fun estimate1 :: "state \ nat \ real" where "estimate1 (B,q) i = ( let s = max 0 (Max ((B i) ` {..log 2 b\ + 9); p = card { j. j \ {.. B i j + q \ s } in 2 powr s * ln (1-p/b) / ln(1-1/b))" fun estimate :: "state \ real" where "estimate x = median l (estimate1 x)" subsection \History Independence\ fun \\<^sub>0 :: "((nat \ nat) \ (nat \ nat) \ (nat \ nat)) \ nat set \ nat \ int" where "\\<^sub>0 (f,g,h) A j = Max ({ int (f a) | a . a \ A \ h (g a) = j } \ {-1}) " definition \\<^sub>1 :: "((nat \ nat) \ (nat \ nat) \ (nat \ nat)) \ nat set \ nat \ nat \ int" where "\\<^sub>1 \ A q j = max (\\<^sub>0 \ A j - q) (-1)" definition \\<^sub>2 :: "seed \ nat set \ nat \ nat \ nat \ int" where "\\<^sub>2 \ A q i j = (if i < l then \\<^sub>1 (\ i) A q j else (-1))" definition \\<^sub>3 :: "seed \ nat set \ nat \ state" where "\\<^sub>3 \ A q = (\\<^sub>2 \ A q, q)" definition q :: "seed \ nat set \ nat" where "q \ A = (LEAST q . \(is_too_large (\\<^sub>2 \ A q)))" definition \ :: "seed \ nat set \ state" where "\ \ A = \\<^sub>3 \ A (q \ A)" lemma \\<^sub>2_step: "\\<^sub>2 \ A (x+y) = (\i j. max (\\<^sub>2 \ A x i j - y) (- 1))" by (intro ext) (auto simp add:\\<^sub>2_def \\<^sub>1_def) lemma \\<^sub>3_step: "compress_step (\\<^sub>3 \ A x) = \\<^sub>3 \ A (x+1)" unfolding \\<^sub>3_def using \\<^sub>2_step[where y="1"] by simp -sublocale \\<^sub>1: hash_sample_space 2 n 2 n_exp "\ n_exp" - using n_exp_gt_0 unfolding hash_sample_space_def \_def by auto - -sublocale \\<^sub>2: hash_sample_space 2 n 2 "5 + b_exp*2" "[(C\<^sub>7*b\<^sup>2)]\<^sub>S" - unfolding hash_sample_space_def nat_sample_space_def b_def C\<^sub>7_def - by (auto simp add:power_mult power_add) - -sublocale \\<^sub>3: hash_sample_space k "C\<^sub>7*b\<^sup>2" 2 "b_exp" "[b]\<^sub>S" - unfolding hash_sample_space_def b_def nat_sample_space_def using k_gt_0 b_exp_ge_26 - by auto +lemma \\<^sub>1: "is_prime_power (pro_size (\ n_exp))" + unfolding geom_pro_size by (intro is_prime_powerI n_exp_gt_0) auto -lemma sample_pmf_\: "sample_pmf \ = pair_pmf \\<^sub>1 (pair_pmf \\<^sub>2 \\<^sub>3)" - unfolding \_def - using \\<^sub>1.sample_space \\<^sub>2.sample_space \\<^sub>3.sample_space - by (simp add:prod_sample_pmf) +lemma \\<^sub>2: "is_prime_power (pro_size (\ (C\<^sub>7 * b^2)))" +proof - + have 0:"pro_size (\ (C\<^sub>7 * b^2)) = 2 ^ (5 + 2 * b_exp)" + unfolding C\<^sub>7_def b_def by (subst nat_pro_size) (auto simp add: power_add power_even_eq) + thus ?thesis unfolding 0 by (intro is_prime_powerI) auto +qed -lemma sample_set_\: - "sample_set \ = sample_set \\<^sub>1 \ sample_set \\<^sub>2 \ sample_set \\<^sub>3" - using \\<^sub>1.sample_space \\<^sub>2.sample_space \\<^sub>3.sample_space unfolding \_def - by (simp add: prod_sample_set) +lemma \\<^sub>3: "is_prime_power (pro_size (\ b))" +proof - + have 0:"pro_size (\ b) = 2 ^ b_exp" unfolding b_def by (subst nat_pro_size) auto + thus ?thesis using b_exp_ge_26 unfolding 0 by (intro is_prime_powerI) auto +qed -lemma sample_space_\: "sample_space \" - unfolding \_def - using \\<^sub>1.sample_space \\<^sub>2.sample_space \\<^sub>3.sample_space - by simp +lemma sample_pro_\: + "sample_pro \ = pair_pmf (sample_pro \\<^sub>1) (pair_pmf (sample_pro \\<^sub>2) (sample_pro \\<^sub>3))" + unfolding \_def by (simp add:prod_pro) + +lemma sample_set_\: "pro_set \ = pro_set \\<^sub>1 \ pro_set \\<^sub>2 \ pro_set \\<^sub>3" + unfolding \_def by (simp add:prod_pro_set) lemma f_range: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ pro_set \" shows "f x \ n_exp" proof - - have "f \ sample_set \\<^sub>1" - using sample_set_\ assms by auto - then obtain i where f_def:"f = select \\<^sub>1 i" unfolding sample_set_def by auto - hence "f x \ sample_set (\ n_exp)" - using \\<^sub>1.range by auto - also have "... \ {..n_exp}" - by (intro \_range) - finally have "f x \ {..n_exp}" - by simp - thus ?thesis by simp + have "f \ pro_set \\<^sub>1" using sample_set_\ assms by auto + hence "f \ pro_select \\<^sub>1 ` {..\<^sub>1}" unfolding set_sample_pro by auto + hence "f x \ pro_set (\ n_exp)" using hash_pro_range[OF \\<^sub>1] by auto + thus ?thesis using geom_pro_range by auto qed lemma g_range_1: - assumes "g \ sample_set \\<^sub>2" + assumes "g \ pro_set \\<^sub>2" shows "g x < C\<^sub>7*b^2" proof - - obtain i where f_def:"g = select (\ 2 n [(C\<^sub>7*b\<^sup>2)]\<^sub>S) i" - using assms unfolding sample_set_def by auto - hence "range g \ sample_set ([(C\<^sub>7*b\<^sup>2)]\<^sub>S)" - unfolding f_def by (intro \\<^sub>2.range) - thus ?thesis - unfolding sample_set_alt[OF \\<^sub>2.sample_space_R] - unfolding nat_sample_space_def by auto + have "g \ pro_select \\<^sub>2 ` {..\<^sub>2}" using assms unfolding set_sample_pro by auto + hence "g x \ pro_set (\ ( C\<^sub>7*b^2))" using hash_pro_range[OF \\<^sub>2] by auto + moreover have "C\<^sub>7*b^2 > 0" unfolding C\<^sub>7_def b_def by simp + ultimately show ?thesis using nat_pro_set by auto qed lemma h_range_1: - assumes "h \ sample_set \\<^sub>3" + assumes "h \ pro_set \\<^sub>3" shows "h x < b" proof - - obtain i where f_def:"h = select \\<^sub>3 i" - using assms unfolding sample_set_def by auto - hence "range h \ sample_set ([b]\<^sub>S)" - unfolding f_def by (intro \\<^sub>3.range) - thus ?thesis - unfolding sample_set_alt[OF \\<^sub>3.sample_space_R] - unfolding nat_sample_space_def by auto + have "h \ pro_select \\<^sub>3 ` {..\<^sub>3}" using assms unfolding set_sample_pro by auto + hence "h x \ pro_set (\ b)" using hash_pro_range[OF \\<^sub>3] by auto + moreover have "b > 0" unfolding b_def by simp + ultimately show ?thesis using nat_pro_set by auto qed lemma g_range: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ pro_set \" shows "g x < C\<^sub>7*b^2" -proof - - have "g \ sample_set \\<^sub>2" - using sample_set_\ assms by auto - thus ?thesis - using g_range_1 by simp -qed + using g_range_1 sample_set_\ assms by simp lemma h_range: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ pro_set \" shows "h x < b" -proof - - have "h \ sample_set \\<^sub>3" - using sample_set_\ assms by auto - thus ?thesis - using h_range_1 by simp -qed + using h_range_1 sample_set_\ assms by simp lemma fin_f: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ pro_set \" shows "finite { int (f a) | a. P a }" (is "finite ?M") proof - have "finite (range f)" using f_range[OF assms] finite_nat_set_iff_bounded_le by auto hence "finite (range (int \ f))" by (simp add:image_image[symmetric]) moreover have "?M \ (range (int \ f))" using image_mono by (auto simp add: setcompr_eq_image) ultimately show ?thesis using finite_subset by auto qed lemma Max_int_range: "x \ (y::int) \ Max {x..y} = y" by auto -sublocale \: expander_sample_space l \ \ - unfolding expander_sample_space_def using sample_space_\ l_gt_0 \_gt_0 by auto +lemma \: "l > 0" "\ > 0" using l_gt_0 \_gt_0 by auto + +lemma \_range: + assumes "\ \ pro_set \" + shows "\ i \ pro_set \" +proof - + have "\ \ pro_select \ ` {..}" using assms unfolding set_sample_pro by auto + thus "\ i \ pro_set \" using expander_pro_range[OF \] assms by auto +qed lemma max_q_1: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "\\<^sub>2 \ A (nat \log 2 n\+2) i j = (-1)" proof (cases "i < l") case True - obtain f g h where w_i: "\ i = (f,g,h)" - by (metis prod_cases3) + obtain f g h where w_i: "\ i = (f,g,h)" by (metis prod_cases3) let ?max_q = "max \log 2 (real n)\ 1" - have "\ i \ sample_set \" - using \.sample_set assms unfolding Pi_def by auto - hence c: "(f,g,h) \ sample_set \" - using w_i by auto + have c: "(f,g,h) \ pro_set \" using \_range[OF assms] w_i[symmetric] by auto have a:"int (f x) \ ?max_q" for x proof - have "int (f x) \ int n_exp" using f_range[OF c] by auto also have "... = ?max_q" unfolding n_exp_def by simp finally show ?thesis by simp qed have "\\<^sub>0 (\ i) A j \ Max {(-1)..?max_q}" unfolding w_i \\<^sub>0.simps using a by (intro Max_mono) auto also have "... = ?max_q" by (intro Max_int_range) auto finally have "\\<^sub>0 (\ i) A j \ ?max_q" by simp hence "max (\\<^sub>0 (\ i) A j - int (nat \log 2 (real n)\ + 2)) (- 1) = (-1)" by (intro max_absorb2) linarith thus ?thesis unfolding \\<^sub>2_def \\<^sub>1_def using True by auto next case False - thus ?thesis - unfolding \\<^sub>2_def \\<^sub>1_def by simp + thus ?thesis unfolding \\<^sub>2_def \\<^sub>1_def by simp qed lemma max_q_2: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "\ (is_too_large (\\<^sub>2 \ A (nat \log 2 n\+2)))" using max_q_1[OF assms] by (simp add:C\<^sub>5_def case_prod_beta mult_less_0_iff) lemma max_s_3: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "q \ A \ (nat \log 2 n\+2)" unfolding q_def by (intro wellorder_Least_lemma(2) max_q_2 assms) lemma max_mono: "x \ (y::'a::linorder) \ max x z \ max y z" using max.coboundedI1 by auto lemma max_mono_2: "y \ (z::'a::linorder) \ max x y \ max x z" using max.coboundedI2 by auto lemma \\<^sub>0_mono: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" assumes "A \ B" shows "\\<^sub>0 \ A j \ \\<^sub>0 \ B j" proof - obtain f g h where w_i: "\ = (f,g,h)" by (metis prod_cases3) show ?thesis using assms fin_f unfolding \\<^sub>0.simps w_i by (intro Max_mono) auto qed lemma \\<^sub>2_mono: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" assumes "A \ B" shows "\\<^sub>2 \ A x i j \ \\<^sub>2 \ B x i j" proof - have "max (\\<^sub>0 (\ i) A j - int x) (- 1) \ max (\\<^sub>0 (\ i) B j - int x) (- 1)" if "i < l" - using assms(1) \.sample_set that - by (intro max_mono diff_mono \\<^sub>0_mono assms(2) order.refl) auto - thus ?thesis - by (cases "i < l") (auto simp add:\\<^sub>2_def \\<^sub>1_def) + using that \_range[OF assms(1)] by (intro max_mono diff_mono \\<^sub>0_mono assms(2) order.refl) + thus ?thesis by (cases "i < l") (auto simp add:\\<^sub>2_def \\<^sub>1_def) qed lemma is_too_large_antimono: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" assumes "A \ B" assumes "is_too_large (\\<^sub>2 \ A x)" shows "is_too_large (\\<^sub>2 \ B x)" proof - have "C\<^sub>5 * b * l < (\ (i,j) \ {.. {..log 2 (max (\\<^sub>2 \ A x i j) (-1) + 2)\)" using assms(3) by simp also have "... = (\ y \ {.. {..log 2 (max (\\<^sub>2 \ A x (fst y) (snd y)) (-1) + 2)\)" by (simp add:case_prod_beta) also have "... \ (\ y \ {.. {..log 2 (max (\\<^sub>2 \ B x (fst y) (snd y)) (-1) + 2)\)" by (intro sum_mono floor_mono iffD2[OF log_le_cancel_iff] iffD2[OF of_int_le_iff] add_mono max_mono \\<^sub>2_mono[OF assms(1,2)]) auto also have "... = (\ (i,j) \ {.. {..log 2 (max (\\<^sub>2 \ B x i j) (-1) + 2)\)" by (simp add:case_prod_beta) finally have "(\ (i,j) \ {.. {..log 2 (max (\\<^sub>2 \ B x i j) (-1) + 2)\) > C\<^sub>5 * b * l" by simp thus ?thesis by simp qed lemma q_compact: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "\ (is_too_large (\\<^sub>2 \ A (q \ A)))" unfolding q_def using max_q_2[OF assms] by (intro wellorder_Least_lemma(1)) blast lemma q_mono: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" assumes "A \ B" shows "q \ A \ q \ B" proof - have "\ (is_too_large (\\<^sub>2 \ A (q \ B)))" using is_too_large_antimono[OF assms] q_compact[OF assms(1)] by blast hence "(LEAST q . \(is_too_large (\\<^sub>2 \ A q))) \ q \ B" by (intro Least_le) blast thus ?thesis by (simp add:q_def) qed lemma lt_s_too_large: "x < q \ A \ is_too_large (\\<^sub>2 \ A x)" using not_less_Least unfolding q_def by auto lemma compress_result_1: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "compress (\\<^sub>3 \ A (q \ A - i)) = \ \ A" proof (induction i) case 0 - then show ?case - using q_compact[OF assms] by (simp add:\\<^sub>3_def \_def) + then show ?case using q_compact[OF assms] by (simp add:\\<^sub>3_def \_def) next case (Suc i) show ?case proof (cases "i < q \ A") case True have "is_too_large (\\<^sub>2 \ A (q \ A - Suc i))" using True by (intro lt_s_too_large) simp hence "compress (\\<^sub>3 \ A (q \ A - Suc i)) = compress (compress_step (\\<^sub>3 \ A (q \ A - Suc i)))" unfolding \\<^sub>3_def compress.simps by (simp del: compress.simps compress_step.simps) also have "... = compress (\\<^sub>3 \ A ((q \ A - Suc i)+1))" by (subst \\<^sub>3_step) blast also have "... = compress (\\<^sub>3 \ A (q \ A - i))" using True by (metis Suc_diff_Suc Suc_eq_plus1) also have "... = \ \ A" using Suc by auto finally show ?thesis by simp next case False then show ?thesis using Suc by simp qed qed lemma compress_result: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" assumes "x \ q \ A" shows "compress (\\<^sub>3 \ A x) = \ \ A" proof - obtain i where i_def: "x = q \ A - i" using assms by (metis diff_diff_cancel) have "compress (\\<^sub>3 \ A x) = compress (\\<^sub>3 \ A (q \ A - i))" by (subst i_def) blast also have "... = \ \ A" using compress_result_1[OF assms(1)] by blast finally show ?thesis by simp qed lemma \\<^sub>0_merge: - assumes "(f,g,h) \ sample_set \" + assumes "(f,g,h) \ pro_set \" shows "\\<^sub>0 (f,g,h) (A \ B) j = max (\\<^sub>0 (f,g,h) A j) (\\<^sub>0 (f,g,h) B j)" (is "?L = ?R") proof- let ?f = "\a. int (f a)" have "?L = Max (({ int (f a) | a . a \ A \ h (g a) = j } \ {-1}) \ ({ int (f a) | a . a \ B \ h (g a) = j } \ {-1}))" unfolding \\<^sub>0.simps by (intro arg_cong[where f="Max"]) auto also have "... = max (Max ({ int (f a) | a . a \ A \ h (g a) = j } \ {-1})) (Max ({ int (f a) | a . a \ B \ h (g a) = j } \ {-1}))" by (intro Max_Un finite_UnI fin_f[OF assms]) auto also have "... = ?R" by (simp) finally show ?thesis by simp qed lemma \\<^sub>2_merge: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "\\<^sub>2 \ (A \ B) x i j = max (\\<^sub>2 \ A x i j) (\\<^sub>2 \ B x i j)" proof (cases "i < l") case True - obtain f g h where w_i: "\ i = (f,g,h)" - by (metis prod_cases3) + obtain f g h where w_i: "\ i = (f,g,h)" by (metis prod_cases3) - have "\ i \ sample_set \" - using \.sample_set assms unfolding Pi_def by auto - hence a: "(f,g,h) \ sample_set \" - using w_i by auto + have a: "(f,g,h) \ pro_set \" using w_i[symmetric] \_range[OF assms(1)] by auto show ?thesis unfolding \\<^sub>2_def \\<^sub>1_def using True by (simp add:w_i \\<^sub>0_merge[OF a] del:\\<^sub>0.simps) next case False thus ?thesis by (simp add:\\<^sub>2_def) qed lemma merge1_result: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "merge1 (\ \ A) (\ \ B) = \\<^sub>3 \ (A \ B) (max (q \ A) (q \ B))" proof - let ?qmax = "max (q \ A) (q \ B)" obtain u where u_def: "q \ A + u = ?qmax" by (metis add.commute max.commute nat_minus_add_max) obtain v where v_def: "q \ B + v = ?qmax" by (metis add.commute nat_minus_add_max) have "u = 0 \ v = 0" using u_def v_def by linarith moreover have "\\<^sub>2 \ A (q \ A) i j - u \ (-1)" if "u = 0" for i j using that by (simp add:\\<^sub>2_def \\<^sub>1_def) moreover have "\\<^sub>2 \ B (q \ B) i j - v \ (-1)" if "v = 0" for i j using that by (simp add:\\<^sub>2_def \\<^sub>1_def) ultimately have a:"max (\\<^sub>2 \ A (q \ A) i j - u) (\\<^sub>2 \ B (q \ B) i j - v) \ (-1)" for i j unfolding le_max_iff_disj by blast have "\\<^sub>2 \ (A \ B) ?qmax = (\ i j. max (\\<^sub>2 \ A ?qmax i j) (\\<^sub>2 \ B ?qmax i j))" using \\<^sub>2_merge[OF assms] by blast also have "... = (\ i j. max (\\<^sub>2 \ A (q \ A + u) i j) (\\<^sub>2 \ B (q \ B + v) i j))" unfolding u_def v_def by blast also have "... = (\ i j. max (max (\\<^sub>2 \ A (q \ A) i j - u) (-1)) (max (\\<^sub>2 \ B (q \ B) i j - v) (-1)))" by (simp only: \\<^sub>2_step) also have "... = (\ i j. max (max (\\<^sub>2 \ A (q \ A) i j - u) (\\<^sub>2 \ B (q \ B) i j - v)) (-1))" by (metis (no_types, opaque_lifting) max.commute max.left_commute max.left_idem) also have "... = (\ i j. max (\\<^sub>2 \ A (q \ A) i j - u) (\\<^sub>2 \ B (q \ B) i j - v))" using a by simp also have "... = (\i j. max (\\<^sub>2 \ A (q \ A) i j + int (q \ A) - ?qmax) (\\<^sub>2 \ B (q \ B) i j + int (q \ B) - ?qmax))" by (subst u_def[symmetric], subst v_def[symmetric]) simp finally have "\\<^sub>2 \ (A \ B) (max (q \ A) (q \ B)) = (\i j. max (\\<^sub>2 \ A (q \ A) i j + int (q \ A) - int (?qmax)) (\\<^sub>2 \ B (q \ B) i j + int (q \ B) - int (?qmax)))" by simp thus ?thesis by (simp add:Let_def \_def \\<^sub>3_def) qed lemma merge_result: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "merge (\ \ A) (\ \ B) = \ \ (A \ B)" (is "?L = ?R") proof - have a:"max (q \ A) (q \ B) \ q \ (A \ B)" using q_mono[OF assms] by simp have "?L = compress (merge1 (\ \ A) (\ \ B))" by simp also have "... = compress ( \\<^sub>3 \ (A \ B) (max (q \ A) (q \ B)))" by (subst merge1_result[OF assms]) blast also have "... = ?R" by (intro compress_result[OF assms] a Un_least) finally show ?thesis by blast qed lemma single1_result: "single1 \ x = \\<^sub>3 \ {x} 0" proof - have "(case \ i of (f, g, h) \ if h (g x) = j \ i < l then int (f x) else - 1) = \\<^sub>2 \ {x} 0 i j" for i j proof - obtain f g h where w_i:"\ i = (f, g,h)" by (metis prod_cases3) show ?thesis by (simp add:w_i \\<^sub>2_def \\<^sub>1_def) qed thus ?thesis unfolding \\<^sub>3_def by fastforce qed lemma single_result: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "single \ x = \ \ {x}" (is "?L = ?R") proof - have "?L = compress (single1 \ x)" by (simp) also have "... = compress (\\<^sub>3 \ {x} 0)" by (subst single1_result) blast also have "... = ?R" by (intro compress_result[OF assms]) auto finally show ?thesis by blast qed subsection \Encoding states of the inner algorithm\ definition is_state_table :: "(nat \ nat \ int) \ bool" where "is_state_table g = (range g \ {-1..} \ g ` (-({.. {.. {-1})" text \Encoding for state table values:\ definition V\<^sub>e :: "int encoding" where "V\<^sub>e x = (if x \ -1 then N\<^sub>e (nat (x+1)) else None)" text \Encoding for state table:\ definition T\<^sub>e' :: "(nat \ nat \ int) encoding" where "T\<^sub>e' g = ( if is_state_table g then (List.product [0..\<^sub>e V\<^sub>e) (restrict g ({..{..e :: "(nat \ nat \ int) encoding" where "T\<^sub>e f = T\<^sub>e' (case_prod f)" definition encode_state :: "state encoding" where "encode_state = T\<^sub>e \\<^sub>e Nb\<^sub>e (nat \log 2 n\+3)" lemma inj_on_restrict: assumes "B \ {f. f ` (- A) \ {c}}" shows "inj_on (\x. restrict x A) B" proof (rule inj_onI) fix f g assume a:"f \ B" "g \ B" "restrict f A = restrict g A" have "f x = g x" if "x \ A" for x by (intro restrict_eq_imp[OF a(3) that]) moreover have "f x = g x" if "x \ A" for x proof - have "f x = c" "g x = c" using that a(1,2) assms(1) by auto thus ?thesis by simp qed ultimately show "f = g" by (intro ext) auto qed lemma encode_state: "is_encoding encode_state" proof - have "is_encoding V\<^sub>e" unfolding V\<^sub>e_def by (intro encoding_compose[OF exp_golomb_encoding] inj_onI) auto hence 0:"is_encoding (List.product [0..\<^sub>e V\<^sub>e)" by (intro fun_encoding) have "is_encoding T\<^sub>e'" unfolding T\<^sub>e'_def is_state_table_def by (intro encoding_compose[OF 0] inj_on_restrict[where c="-1"]) auto moreover have " inj case_prod" by (intro injI) (metis curry_case_prod) ultimately have "is_encoding T\<^sub>e" unfolding T\<^sub>e_def by (rule encoding_compose_2) thus ?thesis unfolding encode_state_def by (intro dependent_encoding bounded_nat_encoding) qed lemma state_bit_count: - assumes "\ \ sample_set \" + assumes "\ \ pro_set \" shows "bit_count (encode_state (\ \ A)) \ 2^36 * (ln(1/\)+1)/ \^2 + log 2 (log 2 n + 3)" (is "?L \ ?R") proof - define t where "t = \\<^sub>2 \ A (q \ A)" have "log 2 (real n) \ 0" using n_gt_0 by simp hence 0: "- 1 < log 2 (real n)" by simp have "t x y = -1" if "x < l" "y \ b" for x y proof - obtain f g h where \_def: "\ x = (f,g,h)" by (metis prod_cases3) - have "(f, g, h) \ sample_set \" - using \.sample_set assms unfolding Pi_def \_def[symmetric] by auto + have "(f, g, h) \ pro_set \" + using \_range[OF assms] unfolding Pi_def \_def[symmetric] by auto hence "h (g a) < b" for a using h_range by auto hence "y \ h (g a)" for a using that(2) not_less by blast hence aux_4: "{int (f a) |a. a \ A \ h (g a) = y} = {}" by auto hence "max (Max (insert (- 1) {int (f a) |a. a \ A \ h (g a) = y}) - int (q \ A)) (- 1) = - 1" unfolding aux_4 by simp thus ?thesis unfolding t_def \\<^sub>2_def \\<^sub>1_def by (simp add:\_def) qed moreover have "t x y = -1" if "x \ l" for x y using that unfolding t_def \\<^sub>2_def \\<^sub>1_def by simp ultimately have 1: "t x y = -1" if "x \ l \ y \ b" for x y using that by (meson not_less) have 2: "t x y \ -1" for x y unfolding t_def \\<^sub>2_def \\<^sub>1_def by simp hence 3: "t x y + 1 \ 0" for x y by (metis add.commute le_add_same_cancel1 minus_add_cancel) have 4:"is_state_table (case_prod t)" using 2 1 unfolding is_state_table_def by auto have "bit_count(T\<^sub>e (\\<^sub>2 \ A (q \ A))) = bit_count(T\<^sub>e t)" unfolding t_def by simp also have "... = bit_count ((List.product [0..\<^sub>e V\<^sub>e) (\(x, y)\{..{..e_def T\<^sub>e'_def by simp also have "... = (\x\List.product [0..e ((\(x, y)\{.. {..(x,y)\List.product [0..e (t x y)))" by (intro arg_cong[where f="sum_list"] map_cong refl) (simp add:atLeast0LessThan case_prod_beta) also have "... = (\x\{0.. {0..e (t (fst x) (snd x))))" by (subst sum_list_distinct_conv_sum_set) (auto intro:distinct_product simp add:case_prod_beta) also have "... = (\x\{.. {..e (nat (t (fst x) (snd x)+1))))" using 2 unfolding V\<^sub>e_def not_less[symmetric] by (intro sum.cong refl arg_cong[where f="bit_count"]) auto also have "...=(\x\{..{..log 2(1+real(nat(t (fst x)(snd x)+1)))\)" unfolding exp_golomb_bit_count_exact is_too_large.simps not_less by simp also have "...=(\x\{..{..log 2(2+ of_int(t (fst x)(snd x)))\)" using 3 by (subst of_nat_nat) (auto simp add:ac_simps) also have "...=b*l + 2* of_int (\(i,j)\{..{..log 2(2+ of_int(max (t i j) (-1)))\)" using 2 by (subst max_absorb1) (auto simp add:case_prod_beta sum.distrib sum_distrib_left) also have "... \ b*l + 2 * of_int (C\<^sub>5 * int b * int l)" using q_compact[OF assms, where A="A"] unfolding is_too_large.simps not_less t_def[symmetric] by (intro add_mono ereal_mono iffD2[OF of_int_le_iff] mult_left_mono order.refl) (simp_all add:ac_simps) also have "... = (2 * C\<^sub>5 + 1) * b * l" by (simp add:algebra_simps) finally have 5:"bit_count (T\<^sub>e (\\<^sub>2 \ A (q \ A))) \ (2 * C\<^sub>5 + 1) * b * l" by simp have "C\<^sub>4 \ 1" unfolding C\<^sub>4_def by simp moreover have "\\<^sup>2 \ 1" using \_lt_1 \_gt_0 by (intro power_le_one) auto ultimately have "0 \ log 2 (C\<^sub>4 / \\<^sup>2)" using \_gt_0 \_lt_1 by (intro iffD2[OF zero_le_log_cancel_iff] divide_pos_pos)auto hence 6: "- 1 < log 2 (C\<^sub>4 / \\<^sup>2)" by simp have "b = 2 powr (real (nat \log 2 (C\<^sub>4 / \\<^sup>2)\))" unfolding b_def b_exp_def by (simp add:powr_realpow) also have "... = 2 powr (\log 2 (C\<^sub>4 / \^2)\)" using 6 by (intro arg_cong2[where f="(powr)"] of_nat_nat refl) simp also have "... \ 2 powr (log 2 (C\<^sub>4 / \^2) + 1)" by (intro powr_mono) auto also have "... = 2 * C\<^sub>4 / \^2" using \_gt_0 unfolding powr_add C\<^sub>4_def by (subst powr_log_cancel) (auto intro:divide_pos_pos) finally have 7:"b \ 2 * C\<^sub>4 / \^2" by simp have "l \ C\<^sub>6 * ln (1 / \) + C\<^sub>6 * ln 2 + 1" by (intro l_ubound) also have "... \ 4 * ln(1/\) + 3+1" unfolding C\<^sub>6_def by (intro add_mono order.refl) (approximation 5) also have "... = 4 * (ln(1/\)+1)" by simp finally have 8:"l \ 4 * (ln(1/\)+1)" by simp have "\\<^sup>2 = 0 + \\<^sup>2" by simp also have "... \ ln (1 / \) + 1" using \_gt_0 \_lt_1 \_gt_0 \_lt_1 by (intro add_mono power_le_one) auto finally have 9: "\\<^sup>2 \ ln (1 / \) + 1" by simp have 10: "0 \ ln (1 / \) + 1" using \_gt_0 \_lt_1 by (intro add_nonneg_nonneg) auto have "?L = bit_count (T\<^sub>e (\\<^sub>2 \ A (q \ A))) + bit_count (Nb\<^sub>e (nat \log 2 (real n)\+3) (q \ A))" unfolding encode_state_def \_def \\<^sub>3_def by (simp add:dependent_bit_count) also have "...=bit_count(T\<^sub>e(\\<^sub>2 \ A (q \ A)))+ereal (1+ of_int\log 2 (2 + real (nat \log 2 n\))\)" using max_s_3[OF assms] by (subst bounded_nat_bit_count_2) (simp_all add:numeral_eq_Suc le_imp_less_Suc floorlog_def) also have "... = bit_count(T\<^sub>e(\\<^sub>2 \ A (q \ A)))+ereal (1+ of_int\log 2 (2 + of_int \log 2 n\)\)" using 0 by simp also have "... \ bit_count(T\<^sub>e(\\<^sub>2 \ A (q \ A)))+ereal (1+log 2 (2 + of_int \log 2 n\))" by (intro add_mono ereal_mono) simp_all also have "... \ bit_count(T\<^sub>e(\\<^sub>2 \ A (q \ A)))+ereal (1+log 2 (2 + (log 2 n + 1)))" using 0 n_gt_0 by (intro add_mono ereal_mono iffD2[OF log_le_cancel_iff] add_pos_nonneg) auto also have "... = bit_count(T\<^sub>e(\\<^sub>2 \ A (q \ A)))+ereal (1+log 2 (log 2 n + 3))" by (simp add:ac_simps) also have "... \ ereal ((2 * C\<^sub>5 + 1) * b * l) + ereal (1+log 2 (log 2 n + 3))" by (intro add_mono 5) auto also have "... = (2 * C\<^sub>5 + 1) * real b * real l + log 2 (log 2 n + 3) + 1" by simp also have "... \ (2 * C\<^sub>5 + 1) * (2 * C\<^sub>4 / \^2) * real l + log 2 (log 2 n + 3) + 1" unfolding C\<^sub>5_def by (intro ereal_mono mult_right_mono mult_left_mono add_mono 7) auto also have "... = (4 * of_int C\<^sub>5+2)*C\<^sub>4*real l/ \^2 + log 2 (log 2 n + 3) + 1" by simp also have "... \ (4 * of_int C\<^sub>5+2)*C\<^sub>4*(4*(ln(1/ \)+1))/ \^2 + log 2 (log 2 n + 3) + 1" using \_gt_0 unfolding C\<^sub>5_def C\<^sub>4_def by (intro ereal_mono add_mono order.refl divide_right_mono mult_left_mono 8) auto also have "... = ((2*33+1)*9*2^26)*(ln(1/ \)+1)/ \^2 + log 2 (log 2 n + 3) + 1" unfolding C\<^sub>5_def C\<^sub>4_def by simp also have "... \ (2^36-1) * (ln(1/\)+1)/ \^2 + log 2 (log 2 n + 3) + (ln (1/ \)+1)/ \^2" using \_gt_0 \_gt_0 \_lt_1 9 10 by (intro add_mono ereal_mono divide_right_mono mult_right_mono mult_left_mono) simp_all also have "... = 2^36* (ln(1/\)+1)/ \^2 + log 2 (log 2 n + 3)" by (simp add:divide_simps) finally show ?thesis by simp qed lemma random_bit_count: - "size \ \ 2 powr (4 * log 2 n + 48 * (log 2 (1 / \) + 16)^2 + (55 + 60 * ln (1 / \))^3)" + "pro_size \ \ 2 powr (4 * log 2 n + 48 * (log 2 (1 / \) + 16)^2 + (55 + 60 * ln (1 / \))^3)" (is "?L \ ?R") proof - have 1:"log 2 (real n) \ 0" using n_gt_0 by simp hence 0: "- 1 < log 2 (real n)" by simp have 10: "log 2 C\<^sub>4 \ 27" unfolding C\<^sub>4_def by (approximation 10) have "\\<^sup>2 \ 1" using \_gt_0 \_lt_1 by (intro power_le_one) auto also have "... \ C\<^sub>4" unfolding C\<^sub>4_def by simp finally have " \\<^sup>2 \ C\<^sub>4" by simp hence 9: "0 \ log 2 (C\<^sub>4 / \\<^sup>2)" using \_gt_0 unfolding C\<^sub>4_def by (intro iffD2[OF zero_le_log_cancel_iff]) simp_all hence 2: "- 1 < log 2 (C\<^sub>4 / \\<^sup>2)" by simp - have 3: "0 < C\<^sub>7 * b\<^sup>2" - unfolding C\<^sub>7_def using b_min - by (intro Rings.mult_pos_pos) auto + have 3: "0 < C\<^sub>7 * b\<^sup>2" unfolding C\<^sub>7_def using b_min by (intro Rings.mult_pos_pos) auto have "0 \ log 2 (real C\<^sub>7) + real (b_exp * 2)" - unfolding C\<^sub>7_def - by (intro add_nonneg_nonneg) auto - hence 4: "-1 < log 2 (real C\<^sub>7) + real (b_exp * 2)" - by simp - - have "real (size \\<^sub>1) = 2 ^ (max (nat \log 2 (real n)\) 1 * 2)" - using \\<^sub>1.size[OF n_gt_0] unfolding n_exp_def by simp + unfolding C\<^sub>7_def by (intro add_nonneg_nonneg) auto + hence 4: "-1 < log 2 (real C\<^sub>7) + real (b_exp * 2)" by simp + have "(2, n_exp) = split_power (pro_size (\ n_exp))" + unfolding geom_pro_size by (intro split_power_prime[symmetric] n_exp_gt_0) auto + hence "real (pro_size \\<^sub>1) = real (2 ^ (2 * max n_exp (nat \log (real 2) (real n)\)))" + by (intro arg_cong[where f="real"] hash_pro_size'[OF \\<^sub>1 n_gt_0]) + also have "... = 2 ^ (2 * max n_exp (nat \log 2 (real n)\))" by simp + also have "... = 2 ^ (2 * max 1 (nat \log 2 (real n)\))" unfolding n_exp_def by simp also have "... \ 2 powr (2 * max (nat \log 2 (real n)\) 1)" by (subst powr_realpow) auto also have "... = 2 powr (2 * max (real (nat \log 2 (real n)\)) 1)" using n_gt_0 unfolding of_nat_mult of_nat_max by simp also have "... = 2 powr (2 * max (of_int \log 2 (real n)\) 1)" using 0 by (subst of_nat_nat) simp_all also have "... \ 2 powr (2 * max (log 2 (real n) + 1) 1)" by (intro powr_mono mult_left_mono max_mono) auto also have "... = 2 powr (2 * (log 2 (real n) + 1))" using 1 by (subst max_absorb1) auto - finally have 5:"real (size \\<^sub>1) \ 2 powr (2 * log 2 n + 2)" + finally have 5:"real (pro_size \\<^sub>1) \ 2 powr (2 * log 2 n + 2)" by simp - have "real (size \\<^sub>2) = 2 ^ (max (5 + b_exp * 2) (nat \log 2 (real n)\) * 2)" - unfolding \\<^sub>2.size[OF n_gt_0] by simp + have "(2, 5 + b_exp * 2) = split_power (2^(5+b_exp*2))" + by (intro split_power_prime[symmetric]) auto + also have "... = split_power (C\<^sub>7 * b\<^sup>2)" + unfolding C\<^sub>7_def b_def power_mult[symmetric] power_add by simp + also have "... = split_power (pro_size (\ (C\<^sub>7 * b\<^sup>2)))" + unfolding C\<^sub>7_def b_def by (subst nat_pro_size) auto + finally have "(2, 5 + b_exp * 2) = split_power (pro_size (\ (C\<^sub>7 * b\<^sup>2)))" by simp + hence "real (pro_size \\<^sub>2) = real (2 ^ (2 * max (5 + b_exp * 2) (nat \log (real 2) (real n)\)))" + by (intro arg_cong[where f="real"] hash_pro_size'[OF \\<^sub>2 n_gt_0]) + also have "... = 2 ^ (max (5 + b_exp * 2) (nat \log 2 (real n)\) * 2)" by simp also have "... \ 2 ^ (((5 + b_exp * 2) + (nat \log 2 (real n)\)) * 2)" by (intro power_increasing mult_right_mono) auto also have "... = 2 powr ((5 + b_exp * 2 + real (nat \log 2 (real n)\))*2)" by (subst powr_realpow[symmetric]) auto also have "... = 2 powr ((5 + of_int b_exp * 2 + of_int \log 2 (real n)\)*2)" using 0 by (subst of_nat_nat) auto also have "... \ 2 powr ((5 + of_int b_exp * 2 + (log 2 (real n) + 1))*2)" by (intro powr_mono mult_right_mono add_mono) simp_all also have "... = 2 powr (12 + 4 * real( nat \log 2 (C\<^sub>4 / \\<^sup>2)\) + log 2 (real n) * 2)" unfolding b_exp_def by (simp add:ac_simps) also have "... = 2 powr (12 + 4 * real_of_int \log 2 (C\<^sub>4 / \\<^sup>2)\ + log 2 (real n) * 2)" using 2 by (subst of_nat_nat) simp_all also have "... \ 2 powr (12 + 4 * (log 2 (C\<^sub>4 / \\<^sup>2) + 1) + log 2 (real n) * 2)" by (intro powr_mono add_mono order.refl mult_left_mono) simp_all also have "... = 2 powr (2 * log 2 n + 4 * log 2 (C\<^sub>4 / \\<^sup>2) + 16)" by (simp add:ac_simps) - finally have 6:"real (size \\<^sub>2) \ 2 powr (2 * log 2 n + 4 * log 2 (C\<^sub>4 / \\<^sup>2) + 16)" + finally have 6:"real (pro_size \\<^sub>2) \ 2 powr (2 * log 2 n + 4 * log 2 (C\<^sub>4 / \\<^sup>2) + 16)" by simp - - have "real (size \\<^sub>3) = 2 ^ (max b_exp (nat \log 2 (real C\<^sub>7 * (2 ^ (b_exp*2)))\) * k)" - unfolding \\<^sub>3.size[OF 3] power_mult by (simp add:b_def) + have "(2, b_exp) = split_power (2 ^ b_exp)" + using b_exp_ge_26 by (intro split_power_prime[symmetric]) auto + also have "... = split_power (pro_size (\ b))" + unfolding b_def by (subst nat_pro_size) auto + finally have "(2, b_exp) = split_power (pro_size (\ b))" by simp + hence "real (pro_size \\<^sub>3) = real (2 ^ (k * max b_exp (nat \log (real 2) (real (C\<^sub>7*b^2))\)))" + by (intro arg_cong[where f="real"] hash_pro_size'[OF \\<^sub>3]) (simp_all add:C\<^sub>7_def b_def) + also have "... = 2 ^ (k * max b_exp (nat \log 2 (real C\<^sub>7 * (2 ^ (b_exp*2)))\))" + unfolding b_def power_mult by simp also have "... = 2 ^ (max b_exp (nat \log 2 C\<^sub>7 + log 2 (2 ^ (b_exp*2))\) * k)" unfolding C\<^sub>7_def by (subst log_mult) simp_all also have "... = 2 ^ (max b_exp (nat \log 2 C\<^sub>7 + (b_exp*2)\) * k)" by (subst log_nat_power) simp_all also have "... = 2 powr (max (real b_exp) (real (nat \log 2 C\<^sub>7 + (b_exp*2)\)) * real k)" by (subst powr_realpow[symmetric]) simp_all also have "... = 2 powr (max (real b_exp) (of_int \log 2 C\<^sub>7 + (b_exp*2)\) * real k)" using 4 by (subst of_nat_nat) simp_all also have "... \ 2 powr (max (real b_exp) (log 2 C\<^sub>7 + real b_exp*2 +1) * real k)" by (intro powr_mono mult_right_mono max_mono_2) simp_all also have "... = 2 powr ((log 2 (2^5) + real b_exp*2 +1) * real k)" unfolding C\<^sub>7_def by (subst max_absorb2) simp_all also have "... = 2 powr ((real b_exp*2 +6) * real k)" unfolding C\<^sub>7_def by (subst log_nat_power) (simp_all add:ac_simps) also have "... = 2 powr ((of_int \log 2 (C\<^sub>4 / \\<^sup>2)\ * 2 + 6) * real k)" using 2 unfolding b_exp_def by (subst of_nat_nat) simp_all also have "... \ 2 powr (((log 2 (C\<^sub>4 / \^2)+1) * 2 + 6) * real k)" by (intro powr_mono mult_right_mono add_mono) simp_all also have "... = 2 powr ((log 2 (C\<^sub>4 / \\<^sup>2) * 2 + 8 ) * real k)" by (simp add:ac_simps) - finally have 7:"real (size \\<^sub>3) \ 2 powr ((log 2 (C\<^sub>4 / \\<^sup>2) * 2 + 8 ) * real k)" + finally have 7:"real (pro_size \\<^sub>3) \ 2 powr ((log 2 (C\<^sub>4 / \\<^sup>2) * 2 + 8 ) * real k)" by simp have "ln (real b) \ 0" using b_min by simp hence "real k = of_int \7.5 * ln (real b) + 16\" unfolding k_def C\<^sub>2_def C\<^sub>3_def by (subst of_nat_nat) simp_all also have "... \ (7.5 * ln (real b) + 16) + 1" unfolding b_def by (intro of_int_ceiling_le_add_one) also have "... = 7.5 * ln (2 powr b_exp) + 17" unfolding b_def using powr_realpow by simp also have "... = real b_exp * (7.5 * ln 2) + 17" unfolding powr_def by simp also have "... \ real b_exp * 6 + 17" by (intro add_mono mult_left_mono order.refl of_nat_0_le_iff) (approximation 5) also have "... = of_int \log 2 (C\<^sub>4 / \\<^sup>2)\ * 6 + 17" using 2 unfolding b_exp_def by (subst of_nat_nat) simp_all also have "... \ (log 2 (C\<^sub>4 / \^2) + 1) * 6 + 17" by (intro add_mono mult_right_mono) simp_all also have "... = 6 * log 2 (C\<^sub>4 / \^2) + 23" by simp finally have 8:"real k \ 6 * log 2 (C\<^sub>4 / \^2) + 23" by simp - have "real (size \) = real (size \\<^sub>1) * real (size \\<^sub>2) * real (size \\<^sub>3)" - unfolding \_def prod_sample_space_def by simp + have "real (pro_size \) = real (pro_size \\<^sub>1) * real (pro_size \\<^sub>2) * real (pro_size \\<^sub>3)" + unfolding \_def prod_pro_size by simp also have "... \ 2 powr(2*log 2 n+2)*2 powr (2*log 2 n+4*log 2 (C\<^sub>4/\\<^sup>2)+16)*2 powr((log 2 (C\<^sub>4/\\<^sup>2)*2+8)*real k)" by (intro mult_mono 5 6 7 mult_nonneg_nonneg) simp_all also have "... = 2 powr (2*log 2 n + 2 + 2 * log 2 n+4*log 2 (C\<^sub>4/\\<^sup>2)+16+(log 2 (C\<^sub>4/\\<^sup>2)*2+8)*real k)" unfolding powr_add by simp also have "... = 2 powr (4*log 2 n + 4*log 2 (C\<^sub>4/\\<^sup>2) + 18 + (2*log 2 (C\<^sub>4/\\<^sup>2)+8)*real k)" by (simp add:ac_simps) also have "... \ 2 powr (4* log 2 n + 4* log 2 (C\<^sub>4/ \^2) + 18 + (2*log 2 (C\<^sub>4/\\<^sup>2)+8)*(6 * log 2 (C\<^sub>4 / \^2) + 23))" using 9 by (intro powr_mono add_mono order.refl mult_left_mono 8 add_nonneg_nonneg) simp_all also have "... = 2 powr (4 * log 2 n+12 * log 2 (C\<^sub>4 / \^2)^2 + 98 * log 2 (C\<^sub>4 / \^2)+202)" by (simp add:algebra_simps power2_eq_square) also have "... \ 2 powr (4 * log 2 n+12 * log 2 (C\<^sub>4 / \^2)^2 + 120 * log 2 (C\<^sub>4 / \^2)+300)" using 9 by (intro powr_mono add_mono order.refl mult_right_mono) simp_all also have "... = 2 powr (4 * log 2 n+12 * (log 2 (C\<^sub>4* (1/ \)^2) + 5)^2)" by (simp add:power2_eq_square algebra_simps) also have "... = 2 powr (4 * log 2 n + 12 * (log 2 C\<^sub>4 + log 2 ((1 / \)^2) + 5)^2)" unfolding C\<^sub>4_def using \_gt_0 by (subst log_mult) auto also have "... \ 2 powr (4 * log 2 n + 12 * (27 + log 2 ((1/ \)^2) + 5)^2)" using \_gt_0 \_lt_1 by (intro powr_mono add_mono order.refl mult_left_mono power_mono add_nonneg_nonneg 10) (simp_all add:C\<^sub>4_def) also have "... = 2 powr (4 * log 2 n + 12 * (2 * (log 2 (1 / \) + 16))^2)" using \_gt_0 by (subst log_nat_power) (simp_all add:ac_simps) also have "... = 2 powr (4 * log 2 n + 48 * (log 2 (1 / \) + 16)^2)" unfolding power_mult_distrib by simp - finally have 19:"real (size \) \ 2 powr (4 * log 2 n + 48 * (log 2 (1 / \) + 16)^2)" + finally have 19:"real (pro_size \) \ 2 powr (4 * log 2 n + 48 * (log 2 (1 / \) + 16)^2)" by simp have "0 \ ln \ / ln (19 / 20)" - using \_gt_0 \_le_1 - by (intro divide_nonpos_neg) simp_all - hence 11: "-1 < ln \ / ln (19 / 20)" - by simp + using \_gt_0 \_le_1 by (intro divide_nonpos_neg) simp_all + hence 11: "-1 < ln \ / ln (19 / 20)" by simp - have 12: "ln (19 / 20) \ -(0.05::real)" "- ln (1 / 16) \ (2.8::real)" - by (approximation 10)+ + have 12: "ln (19 / 20) \ -(0.05::real)" "- ln (1 / 16) \ (2.8::real)" by (approximation 10)+ - have 13: "ln l \ 0" - using l_gt_0 by auto + have 13: "ln l \ 0" using l_gt_0 by auto - have "ln l^3 = 27 * (0 + ln l/3)^3" - by (simp add:power3_eq_cube) + have "ln l^3 = 27 * (0 + ln l/3)^3" by (simp add:power3_eq_cube) also have "... \ 27 * (1 + ln l/real 3)^3" using l_gt_0 by (intro mult_left_mono add_mono power_mono) auto also have "... \ 27 * (exp (ln l))" - using l_gt_0 13 - by (intro mult_left_mono exp_ge_one_plus_x_over_n_power_n) linarith+ - also have "... = 27 * real l" - using l_gt_0 by (subst exp_ln) auto - finally have 14:"ln l^3 \ 27 * real l" - by simp + using l_gt_0 13 by (intro mult_left_mono exp_ge_one_plus_x_over_n_power_n) linarith+ + also have "... = 27 * real l" using l_gt_0 by (subst exp_ln) auto + finally have 14:"ln l^3 \ 27 * real l" by simp have 15:"C\<^sub>6 * ln (2 / \) > 0" using \_lt_1 \_gt_0 unfolding C\<^sub>6_def by (intro Rings.mult_pos_pos ln_gt_zero) auto - hence "1 \ real_of_int \C\<^sub>6 * ln (2 / \)\" - by simp - hence 16: "1 \ 3 * real_of_int \C\<^sub>6 * ln (2 / \)\" - by argo + hence "1 \ real_of_int \C\<^sub>6 * ln (2 / \)\" by simp + hence 16: "1 \ 3 * real_of_int \C\<^sub>6 * ln (2 / \)\" by argo - have 17: "12 * ln 2 \ (9::real)" - by (approximation 5) + have 17: "12 * ln 2 \ (9::real)" by (approximation 5) have "16 ^ ((l - 1) * nat\ln \ / ln 0.95\) = 16 powr (real (l-1)*real(nat \ln \ / ln (19 / 20)\))" by (subst powr_realpow[symmetric]) auto also have "... = 16 powr (real (l-1)* of_int \ln \ / ln (19 / 20)\)" using 11 by (subst of_nat_nat) simp_all also have "... \ 16 powr (real (l-1)* (ln \ / ln (19/20)+1))" by (intro powr_mono mult_left_mono) auto also have "... = 16 powr ((real l - 1)*(ln \ / ln (19/20)+1))" using l_gt_0 by (subst of_nat_diff) auto also have "... \ 16 powr ((real l - 1)*(ln \ / (-0.05)+1))" using l_gt_0 \_gt_0 \_le_1 by (intro powr_mono mult_left_mono add_mono divide_left_mono_neg 12) auto also have "... = 16 powr ((real l - 1)*(20 * (-ln \)+1))" by (simp add:algebra_simps) also have "... = 16 powr ((real l - 1)*(20 * -(min (ln (1/16)) (-l*ln l^3))+1))" unfolding \_def by (subst ln_min_swap) auto also have "... = 16 powr ((real l - 1)*(20 * max (-ln (1/16)) (l*ln l^3)+1))" by (intro_cong "[\\<^sub>2 (powr), \\<^sub>2(+), \\<^sub>2 (*)]") simp also have "... \ 16 powr ((real l - 1)*(20 * max (2.8) (l*ln l^3)+1))" using l_gt_0 by (intro powr_mono mult_left_mono add_mono max_mono 12) auto also have "... \ 16 powr ((real l - 1)*(20 * (2.8+l*ln l^3)+1))" using l_gt_0 by (intro powr_mono mult_left_mono add_mono) auto also have "... = 16 powr ((real l - 1)*(20 * (l*ln l^3)+57))" by (simp add:algebra_simps) also have "... \ 16 powr ((real l - 1)*(20 * (real l*(27*real l))+57))" using l_gt_0 by (intro powr_mono mult_left_mono add_mono 14) auto also have "... = 16 powr (540 * real l^3 - 540 * real l^2 + 57* real l - 57)" by (simp add:algebra_simps numeral_eq_Suc) also have "... \ 16 powr (540 * real l^3 - 540 * real l^2 + 180* real l - 20)" by (intro powr_mono add_mono diff_mono order.refl mult_right_mono) auto also have "... = 16 powr (20 * (3*real l - 1)^3)" by (simp add: algebra_simps power3_eq_cube power2_eq_square) also have "... = 16 powr (20 * (3 * of_int \C\<^sub>6 * ln (2 / \)\ - 1) ^ 3)" using 15 unfolding l_def by (subst of_nat_nat) auto also have "... \ 16 powr (20 * (3 * (C\<^sub>6 * ln (2 / \) + 1) - 1) ^ 3)" using 16 by (intro powr_mono mult_left_mono power_mono diff_mono) auto also have "... = 16 powr (20 * (2 + 12 * ln (2 * (1 / \))) ^ 3)" by (simp add:algebra_simps C\<^sub>6_def) also have "... = (2 powr 4) powr (20 * (2+ 12 * (ln 2 + ln(1/ \)))^3)" using \_gt_0 by (subst ln_mult) auto also have "... = 2 powr (80 * (2 + 12 * ln 2 + 12 * ln (1 / \)) ^ 3)" unfolding powr_powr by (simp add:ac_simps) also have "... \ 2 powr (80 * (2 + 9 + 12 * ln (1 / \)) ^ 3)" using \_gt_0 \_lt_1 by (intro powr_mono mult_left_mono power_mono add_mono 17 add_nonneg_nonneg) auto - also have "... = 2 powr (80 * (11 + 12 * ln (1 / \)) ^ 3)" - by simp + also have "... = 2 powr (80 * (11 + 12 * ln (1 / \)) ^ 3)" by simp also have "... \ 2 powr (5^3 * (11 + 12 * ln (1 / \)) ^ 3)" - using \_gt_0 \_lt_1 - by (intro powr_mono mult_right_mono) (auto intro!:add_nonneg_nonneg) + using \_gt_0 \_lt_1 by (intro powr_mono mult_right_mono) (auto intro!:add_nonneg_nonneg) also have "... = 2 powr ((55 + 60 * ln (1 / \))^3)" unfolding power_mult_distrib[symmetric] by simp finally have 18:"16^((l - 1) * nat\ln \ / ln (19/20)\) \ 2 powr ((55 + 60 * ln (1 / \))^3)" by simp - have "?L = real (size \) * 16 ^ ((l - 1) * nat \ln \ / ln (19 / 20)\)" - unfolding \.size by simp + have "?L = real (pro_size \) * 16 ^ ((l - 1) * nat \ln \ / ln (19 / 20)\)" + unfolding expander_pro_size[OF \] by simp also have "... \ 2 powr (4*log 2 n+48*(log 2 (1/\)+16)^2)*2 powr ((55 + 60 * ln (1 / \))^3)" by (intro mult_mono 18 19) simp_all also have "... = 2 powr (4 * log 2 n + 48 * (log 2 (1 / \) + 16)^2 + (55 + 60 * ln (1 / \))^3)" unfolding powr_add[symmetric] by simp finally show ?thesis by simp qed end unbundle no_intro_cong_syntax end \ No newline at end of file diff --git a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Outer_Algorithm.thy b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Outer_Algorithm.thy --- a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Outer_Algorithm.thy +++ b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Outer_Algorithm.thy @@ -1,810 +1,807 @@ section \Outer Algorithm\label{sec:outer_algorithm}\ text \This section introduces the final solution with optimal size space usage. Internally it relies on the inner algorithm described in Section~\ref{sec:inner_algorithm}, dependending on the paramaters $n$, $\varepsilon$ and $\delta$ it either uses the inner algorithm directly or if $\varepsilon^{-1}$ is larger than $\ln n$ it runs $\frac{\varepsilon^{-1}}{\ln \ln n}$ copies of the inner algorithm (with the modified failure probability $\frac{1}{\ln n}$) using an expander to select its seeds. The theorems below verify that the probability that the relative accuracy of the median of the copies is too large is below $\varepsilon$.\ theory Distributed_Distinct_Elements_Outer_Algorithm imports Distributed_Distinct_Elements_Accuracy Prefix_Free_Code_Combinators.Prefix_Free_Code_Combinators Frequency_Moments.Landau_Ext Landau_Symbols.Landau_More begin unbundle intro_cong_syntax text \The following are non-asymptotic hard bounds on the space usage for the sketches and seeds repsectively. The end of this section contains a proof that the sum is asymptotically in $\mathcal O(\ln( \varepsilon^{-1}) \delta^{-1} + \ln n)$.\ definition "state_space_usage = (\(n,\,\). 2^40 * (ln(1/\)+1)/ \^2 + log 2 (log 2 n + 3))" definition "seed_space_usage = (\(n,\,\). 2^30+2^23*ln n+48*(log 2(1/\)+16)\<^sup>2+336*ln (1/\))" locale outer_algorithm = fixes n :: nat fixes \ :: real fixes \ :: real assumes n_gt_0: "n > 0" assumes \_gt_0: "\ > 0" and \_lt_1: "\ < 1" assumes \_gt_0: "\ > 0" and \_lt_1: "\ < 1" begin definition n\<^sub>0 where "n\<^sub>0 = max (real n) (exp (exp 5))" definition stage_two where "stage_two = (\ < (1/ln n\<^sub>0))" definition \\<^sub>i :: real where "\\<^sub>i = (if stage_two then (1/ln n\<^sub>0) else \)" definition m :: nat where "m = (if stage_two then nat \4 * ln (1/ \)/ln (ln n\<^sub>0)\ else 1)" definition \ where "\ = (if stage_two then (1/ln n\<^sub>0) else 1)" lemma m_lbound: assumes "stage_two" shows "m \ 4 * ln (1/ \)/ln(ln n\<^sub>0)" proof - have "m = real (nat \4 * ln (1 / \) / ln (ln n\<^sub>0)\)" using assms unfolding m_def by simp also have "... \ 4 * ln (1 / \) / ln (ln n\<^sub>0)" by linarith finally show ?thesis by simp qed lemma n_lbound: "n\<^sub>0 \ exp (exp 5)" "ln n\<^sub>0 \ exp 5" "5 \ ln (ln n\<^sub>0)" "ln n\<^sub>0 > 1" "n\<^sub>0 > 1" proof - show 0:"n\<^sub>0 \ exp (exp 5)" unfolding n\<^sub>0_def by simp have "(1::real) \ exp (exp 5)" by (approximation 5) hence "n\<^sub>0 \ 1" using 0 by argo thus 1:"ln n\<^sub>0 \ exp 5" using 0 by (intro iffD2[OF ln_ge_iff]) auto moreover have "1 < exp (5::real)" by (approximation 5) ultimately show 2:"ln n\<^sub>0 > 1" by argo show "5 \ ln (ln n\<^sub>0)" using 1 2 by (subst ln_ge_iff) simp have "(1::real) < exp (exp 5)" by (approximation 5) thus "n\<^sub>0 > 1" using 0 by argo qed lemma \1_gt_0: "0 < \\<^sub>i" using n_lbound(4) \_gt_0 unfolding \\<^sub>i_def by (cases "stage_two") simp_all lemma \1_lt_1: "\\<^sub>i < 1" using n_lbound(4) \_lt_1 unfolding \\<^sub>i_def by (cases "stage_two") simp_all lemma m_gt_0_aux: assumes "stage_two" shows "1 \ ln (1 / \) / ln (ln n\<^sub>0)" proof - have "ln n\<^sub>0 \ 1 / \" using n_lbound(4) using assms unfolding pos_le_divide_eq[OF \_gt_0] stage_two_def by (simp add:divide_simps ac_simps) hence "ln (ln n\<^sub>0) \ ln (1 / \)" using n_lbound(4) \_gt_0 by (intro iffD2[OF ln_le_cancel_iff] divide_pos_pos) auto thus "1 \ ln (1 / \) / ln (ln n\<^sub>0)" using n_lbound(3) by (subst pos_le_divide_eq) auto qed lemma m_gt_0: "m > 0" proof (cases "stage_two") case True have "0 < 4 * ln (1/ \)/ln(ln n\<^sub>0)" using m_gt_0_aux[OF True] by simp also have "... \ m" using m_lbound[OF True] by simp finally have "0 < real m" by simp then show ?thesis by simp next case False then show ?thesis unfolding m_def by simp qed lemma \_gt_0: "\ > 0" using n_lbound(4) unfolding \_def by (cases "stage_two") auto lemma \_le_1: "\ \ 1" using n_lbound(4) unfolding \_def by (cases "stage_two") simp_all sublocale I: inner_algorithm "n" "\\<^sub>i" "\" unfolding inner_algorithm_def using n_gt_0 \_gt_0 \_lt_1 \1_gt_0 \1_lt_1 by auto abbreviation \ where "\ \ \ m \ I.\" -sublocale \: expander_sample_space m \ I.\ - unfolding expander_sample_space_def using I.\.sample_space \_gt_0 m_gt_0 by auto +lemma \: "m > 0" "\ > 0" using \_gt_0 m_gt_0 by auto type_synonym state = "inner_algorithm.state list" fun single :: "nat \ nat \ state" where - "single \ x = map (\j. I.single (select \ \ j) x) [0.. x = map (\j. I.single (pro_select \ \ j) x) [0.. state \ state" where "merge x y = map (\(x,y). I.merge x y) (zip x y)" fun estimate :: "state \ real" where "estimate x = median m (\i. I.estimate (x ! i))" definition \ :: "nat \ nat set \ state" - where "\ \ A = map (\i. I.\ (select \ \ i) A) [0.. \ A = map (\i. I.\ (pro_select \ \ i) A) [0..The following three theorems verify the correctness of the algorithm. The term @{term "\"} is a mathematical description of the sketch for a given subset, while @{term "single"}, @{term "merge"} are the actual functions that compute the sketches.\ theorem merge_result: "merge (\ \ A) (\ \ B) = \ \ (A \ B)" (is "?L = ?R") proof - have 0: "zip [0..x. (x,x)) [0..x. I.merge (I.\ (select \ \ x) A) (I.\ (select \ \ x) B)) [0..x. I.merge (I.\ (pro_select \ \ x) A) (I.\ (pro_select \ \ x) B)) [0.._def by (simp add:zip_map_map 0 comp_def case_prod_beta) - also have "... = map (\x. I.\ (select \ \ x) (A \ B)) [0...range) auto + also have "... = map (\x. I.\ (pro_select \ \ x) (A \ B)) [0..]) also have "... = ?R" unfolding \_def by simp finally show ?thesis by simp qed theorem single_result: "single \ x = \ \ {x}" (is "?L = ?R") proof - - have "?L = map (\j. I.single (select \ \ j) x) [0..j. I.single (pro_select \ \ j) x) [0.._def by (intro map_cong I.single_result \.range) auto + unfolding \_def by (intro map_cong I.single_result expander_pro_range[OF \]) auto finally show ?thesis by simp qed theorem estimate_result: assumes "A \ {.. {}" - defines "p \ (pmf_of_set {..})" + defines "p \ (pmf_of_set {..})" shows "measure p {\. \estimate (\ \ A)- real (card A)\ > \ * real (card A)} \ \" (is "?L \ ?R") proof (cases "stage_two") case True define I where "I = {x. \x - real (card A)\ \ \ * real (card A)}" have int_I: "interval I" unfolding interval_def I_def by auto define \ where "\ = measure I.\ {\. I.estimate (I.\ \ A) \ I}" have 0:"\ + \ > 0" unfolding \_def by (intro add_nonneg_pos \_gt_0) auto have "\ \ \\<^sub>i" unfolding \_def I_def using I.estimate_result[OF assms(1,2)] by (simp add: not_le del:I.estimate.simps) also have "... = 1/ln n\<^sub>0" using True unfolding \\<^sub>i_def by simp finally have "\ \ 1/ln n\<^sub>0" by simp hence "\ + \ \ 1/ln n\<^sub>0 + 1/ln n\<^sub>0" unfolding \_def using True by (intro add_mono) auto also have "... = 2/ln n\<^sub>0" by simp finally have 1:"\ + \ \ 2 / ln n\<^sub>0" by simp hence 2:"ln n\<^sub>0 \ 2 / (\ + \)" using 0 n_lbound by (simp add:field_simps) have "\ + \ \ 2/ln n\<^sub>0" by (intro 1) also have "... \ 2/exp 5" using n_lbound by (intro divide_left_mono) simp_all also have "... \ 1/2" by (approximation 5) finally have 3:"\ + \ \ 1/2" by simp have 4: "2 * ln 2 + 8 * exp (- 1) \ (5::real)" by (approximation 5) have "?L = measure p {\. median m (\i. I.estimate (\ \ A ! i)) \ I}" unfolding I_def by (simp add:not_le) also have "... \ - measure p {\. real (card {i \ {.. (select \ \ i) A) \ I})\ real m/2}" + measure p {\. real (card {i \ {.. (pro_select \ \ i) A) \ I})\ real m/2}" proof (rule pmf_mono) fix \ assume "\ \ set_pmf p" assume a:"\ \ {\. median m (\i. I.estimate (\ \ A ! i)) \ I}" have "real m = 2 * real m - real m" by simp also have "... \ 2 * real m - 2 * card {i. i < m \ I.estimate (\ \ A ! i) \ I}" using median_est[OF int_I, where n="m"] a by (intro diff_left_mono Nat.of_nat_mono) (auto simp add:not_less[symmetric] simp del:I.estimate.simps) also have "... = 2 * (real (card {.. I.estimate (\ \ A ! i) \ I})" by (simp del:I.estimate.simps) also have "... = 2 * real (card {.. I.estimate (\ \ A ! i) \ I})" by (intro_cong "[\\<^sub>2 (*)]" more:of_nat_diff[symmetric] card_mono) (auto simp del:I.estimate.simps) also have "... = 2 * real (card ({.. I.estimate (\ \ A ! i) \ I}))" by (intro_cong "[\\<^sub>2 (*), \\<^sub>1 of_nat]" more:card_Diff_subset[symmetric]) (auto simp del:I.estimate.simps) also have "... = 2 * real (card {i\{.. \ A ! i) \ I})" by (intro_cong "[\\<^sub>2 (*), \\<^sub>1 of_nat, \\<^sub>1 card]") (auto simp del:I.estimate.simps) - also have "... = 2 * real (card {i \ {.. (select \ \ i) A) \ I})" + also have "... = 2 * real (card {i \ {.. (pro_select \ \ i) A) \ I})" unfolding \_def by (intro_cong "[\\<^sub>2 (*), \\<^sub>1 of_nat, \\<^sub>1 card]" more:restr_Collect_cong) (simp del:I.estimate.simps) - finally have "real m \ 2 * real (card {i \ {.. (select \ \ i) A) \ I})" + finally have "real m \ 2 * real (card {i \ {.. (pro_select \ \ i) A) \ I})" by simp - thus "\ \ {\. real m / 2 \ real (card {i \ {.. (select \ \ i) A) \ I})}" + thus "\ \ {\. real m / 2 \ real (card {i \ {.. (pro_select \ \ i) A) \ I})}" by simp qed also have "...=measure \{\. real(card {i \ {.. (\ i) A) \ I})\(1/2)*real m}" - unfolding sample_pmf_alt[OF \.sample_space] p_def by (simp del:I.estimate.simps) + unfolding sample_pro_alt p_def by (simp del:I.estimate.simps) also have "... \ exp (-real m * ((1/2) * ln (1/ (\ + \)) - 2*exp (-1)))" - using 3 m_gt_0 \_gt_0 unfolding \_def by (intro \.tail_bound) force+ + using 3 m_gt_0 \_gt_0 unfolding \_def by (intro walk_tail_bound) force+ also have "... \ exp (-real m * ((1/2) * ln (ln n\<^sub>0 / 2) - 2*exp (-1)))" using 0 2 3 n_lbound by (intro iffD2[OF exp_le_cancel_iff] mult_right_mono mult_left_mono_neg[where c="-real m"] diff_mono mult_left_mono iffD2[OF ln_le_cancel_iff]) (simp_all) also have "... = exp (-real m * (ln (ln n\<^sub>0) / 2 - (ln 2/2 + 2*exp (-1))))" using n_lbound by (subst ln_div) (simp_all add:algebra_simps) also have "... \ exp (-real m * (ln (ln n\<^sub>0) / 2 - (ln (ln (exp(exp 5))) / 4)))" using 4 by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono_neg[where c="-real m"] diff_mono) simp_all also have "... \ exp (-real m * (ln (ln n\<^sub>0) / 2 - (ln (ln n\<^sub>0) / 4)))" using n_lbound by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono_neg[where c="-real m"] diff_mono) simp_all also have "... = exp (- real m * (ln (ln n\<^sub>0)/ 4) )" by (simp add:algebra_simps) also have "... \ exp (- (4 * ln (1/ \)/ln(ln n\<^sub>0)) * (ln (ln n\<^sub>0)/4))" using m_lbound[OF True] n_lbound by (intro iffD2[OF exp_le_cancel_iff] mult_right_mono divide_nonneg_pos) simp_all also have "... = exp (- ln (1/ \))" using n_lbound by simp also have "... = \" using \_gt_0 by (subst ln_inverse[symmetric]) auto finally show ?thesis by simp next case False have m_eq: "m = 1" unfolding m_def using False by simp hence "?L = measure p {\. \ * real (card A) < \I.estimate (\ \ A ! 0) - real (card A)\}" unfolding estimate.simps m_eq median_def by simp - also have "... = measure p {\. \*real(card A)<\I.estimate (I.\ (select \ \ 0) A)-real(card A)\}" + also have "... = measure p {\. \*card A<\I.estimate (I.\ (pro_select \ \ 0) A)-real(card A)\}" unfolding \_def m_eq by (simp del: I.estimate.simps) also have "... = measure \ {\. \*real(card A) < \I.estimate (I.\ (\ 0) A)-real(card A)\}" - unfolding sample_pmf_alt[OF \.sample_space] p_def by (simp del:I.estimate.simps) + unfolding sample_pro_alt p_def by (simp del:I.estimate.simps) also have "...= measure (map_pmf (\\. \ 0) \) {\. \*real(card A) < \I.estimate (I.\ \ A)-real(card A)\}" by simp also have "... = measure I.\ {\. \*real(card A) < \I.estimate (I.\ \ A)-real(card A)\}" - using m_eq by (subst \.uniform_property) auto + using m_eq by (subst expander_uniform_property[OF \]) auto also have "... \ \\<^sub>i" by (intro I.estimate_result[OF assms(1,2)]) also have "... = ?R" unfolding \\<^sub>i_def using False by simp finally show ?thesis by simp qed text \The function @{term "encode_state"} can represent states as bit strings. This enables verification of the space usage.\ definition encode_state where "encode_state = Lf\<^sub>e I.encode_state m" lemma encode_state: "is_encoding encode_state" unfolding encode_state_def by (intro fixed_list_encoding I.encode_state) lemma state_bit_count: "bit_count (encode_state (\ \ A)) \ state_space_usage (real n, \, \)" (is "?L \ ?R") proof - have 0: "length (\ \ A) = m" unfolding \_def by simp have "?L = (\x\\ \ A. bit_count (I.encode_state x))" using 0 unfolding encode_state_def fixed_list_bit_count by simp - also have "... = (\x\[0.. (select \ \ x) A)))" + also have "... = (\x\[0.. (pro_select \ \ x) A)))" unfolding \_def by (simp add:comp_def) also have "... \ (\x\[0..\<^sub>i)+ 1)/\\<^sup>2 + log 2 (log 2 (real n) + 3)))" - using I.state_bit_count by (intro sum_list_mono I.state_bit_count \.range) + using I.state_bit_count by (intro sum_list_mono I.state_bit_count expander_pro_range[OF \]) also have "... = ereal ( real m * (2^36 *(ln (1/\\<^sub>i)+ 1)/\\<^sup>2 + log 2 (log 2 (real n) + 3)))" unfolding sum_list_triv_ereal by simp also have "... \ 2^40 * (ln(1/\)+1)/ \^2 + log 2 (log 2 n + 3)" (is "?L1 \ ?R1") proof (cases "stage_two") case True have "\4*ln (1/\)/ln(ln n\<^sub>0)\ \ 4*ln (1/\)/ln(ln n\<^sub>0) + 1" by simp also have "... \ 4*ln (1/\)/ln(ln n\<^sub>0) + ln (1/\)/ln(ln n\<^sub>0)" using m_gt_0_aux[OF True] by (intro add_mono) auto also have "... = 5 * ln (1/\)/ln(ln n\<^sub>0)" by simp finally have 3: "\4*ln (1/\)/ln(ln n\<^sub>0)\ \ 5 * ln (1/\)/ln(ln n\<^sub>0)" by simp have 4: "0 \ log 2 (log 2 (real n) + 3)" using n_gt_0 by (intro iffD2[OF zero_le_log_cancel_iff] add_nonneg_pos) auto have 5: "1 / ln 2 + 3 / exp 5 \ exp (1::real)" "1.2 / ln 2 \ (2::real)" by (approximation 5)+ have "log 2(log 2 (real n)+3) \ log 2 (log 2 n\<^sub>0 + 3)" using n_gt_0 by (intro iffD2[OF log_le_cancel_iff] add_mono add_nonneg_pos iffD2[OF zero_le_log_cancel_iff]) (simp_all add:n\<^sub>0_def) also have "... = ln (ln n\<^sub>0 / ln 2 + 3) / ln 2" unfolding log_def by simp also have "... \ ln (ln n\<^sub>0/ln 2 + (3 / exp 5) * ln n\<^sub>0) / ln 2" using n_lbound by (intro divide_right_mono iffD2[OF ln_le_cancel_iff] add_mono add_nonneg_pos) (simp_all add:divide_simps) also have "... = ln ( ln n\<^sub>0 * (1 /ln 2 + 3/exp 5)) / ln 2" by (simp add:algebra_simps) also have "... \ ln ( ln n\<^sub>0 * exp 1) / ln 2" using n_lbound by (intro divide_right_mono iffD2[OF ln_le_cancel_iff] add_mono mult_left_mono 5 Rings.mult_pos_pos add_pos_nonneg) auto also have "... = (ln (ln n\<^sub>0) + 1) / ln 2" using n_lbound by (subst ln_mult) simp_all also have "... \ (ln (ln n\<^sub>0) + 0.2 * ln (ln n\<^sub>0)) / ln 2" using n_lbound by (intro divide_right_mono add_mono) auto also have "... = (1.2/ ln 2) * ln (ln n\<^sub>0)" by simp also have "... \ 2 * ln (ln n\<^sub>0)" using n_lbound by (intro mult_right_mono 5) simp finally have "log 2(log 2 (real n)+3) \ 2 * ln (ln n\<^sub>0)" by simp hence 6: "log 2(log 2 (real n)+3)/ln(ln n\<^sub>0) \ 2" using n_lbound by (subst pos_divide_le_eq) simp_all have "?L1 = real(nat \4*ln (1/\)/ln(ln n\<^sub>0)\)*(2^36*(ln (ln n\<^sub>0)+1)/\^2+log 2(log 2 (real n)+3))" using True unfolding m_def \\<^sub>i_def by simp also have "... = \4*ln (1/\)/ln(ln n\<^sub>0)\*(2^36*(ln (ln n\<^sub>0)+1)/\^2+log 2(log 2 (real n)+3))" using m_gt_0_aux[OF True] by (subst of_nat_nat) simp_all also have "... \ (5*ln (1/\)/ln(ln n\<^sub>0)) *(2^36*(ln (ln n\<^sub>0)+1)/\^2+log 2(log 2 (real n)+3))" using n_lbound(3) \_gt_0 4 by (intro ereal_mono mult_right_mono add_nonneg_nonneg divide_nonneg_pos mult_nonneg_nonneg 3) simp_all also have "... \ (5 * ln (1/\)/ln(ln n\<^sub>0))*((2^36+2^36)*ln (ln n\<^sub>0)/\^2+log 2(log 2 (real n)+3))" using n_lbound \_gt_0 \_lt_1 by (intro ereal_mono mult_left_mono add_mono divide_right_mono divide_nonneg_pos) auto also have "... = 5*(2^37)* ln (1/\)/ \^2 + (5*ln (1/\)) * (log 2(log 2 (real n)+3)/ln(ln n\<^sub>0))" using n_lbound by (simp add:algebra_simps) also have "... \ 5*(2^37)* ln (1/\)/ \^2 + (5*ln(1/ \)) * 2" using \_gt_0 \_lt_1 by (intro add_mono ereal_mono order.refl mult_left_mono 6) auto also have "... = 5*(2^37)* ln (1/\)/ \^2 + 5*2*ln(1/ \) / 1" by simp also have "... \ 5*(2^37)* ln (1/\)/ \^2 + 5*2*ln(1/ \) / \^2" using \_gt_0 \_lt_1 \_gt_0 \_lt_1 by (intro add_mono ereal_mono divide_left_mono Rings.mult_pos_pos power_le_one) auto also have "... = (5*(2^37+2))* (ln (1/\)+0)/ \^2 + 0" by (simp add:algebra_simps) also have "... \ 2^40 * (ln (1 / \)+1) / \^2 + log 2 (log 2 (real n) + 3)" using \_gt_0 \_lt_1 \_gt_0 \_lt_1 n_gt_0 by (intro add_mono ereal_mono divide_right_mono mult_right_mono iffD2[OF zero_le_log_cancel_iff] add_nonneg_pos) auto finally show ?thesis by simp next case False have "?L1 = 2^36 *(ln (1/\)+ 1)/\\<^sup>2 + log 2 (log 2 (real n) + 3)" using False unfolding \\<^sub>i_def m_def by simp also have "... \ ?R1" using \_gt_0 \_lt_1 \_gt_0 \_lt_1 by (intro ereal_mono add_mono divide_right_mono mult_right_mono add_nonneg_nonneg) auto finally show ?thesis by simp qed finally show ?thesis unfolding state_space_usage_def by simp qed text \Encoding function for the seeds which are just natural numbers smaller than -@{term "size \"}.\ +@{term "pro_size \"}.\ definition encode_seed - where "encode_seed = Nb\<^sub>e (size \)" + where "encode_seed = Nb\<^sub>e (pro_size \)" lemma encode_seed: "is_encoding encode_seed" unfolding encode_seed_def by (intro bounded_nat_encoding) lemma random_bit_count: - assumes "\ < size \" + assumes "\ < pro_size \" shows "bit_count (encode_seed \) \ seed_space_usage (real n, \, \)" (is "?L \ ?R") proof - - have 0: "size \ > 0" - using \.sample_space unfolding sample_space_def by simp - have 1: "size I.\ > 0" - using I.\.sample_space unfolding sample_space_def by simp + have 0: "pro_size \ > 0" by (intro pro_size_gt_0) + have 1: "pro_size I.\ > 0" by (intro pro_size_gt_0) have "(55+60*ln (ln n\<^sub>0))^3 \ (180+60*ln (ln n\<^sub>0))^3" using n_lbound by (intro power_mono add_mono) auto also have "... = 180^3 * (1+ln (ln n\<^sub>0)/real 3)^3" unfolding power_mult_distrib[symmetric] by simp also have "... \ 180^3 * exp (ln (ln n\<^sub>0))" using n_lbound by (intro mult_left_mono exp_ge_one_plus_x_over_n_power_n) auto also have "... = 180^3 * ln n\<^sub>0" using n_lbound by (subst exp_ln) auto also have "... \ 180^3 * max (ln n) (ln (exp (exp 5)))" using n_gt_0 unfolding n\<^sub>0_def by (subst ln_max_swap) auto also have "... \ 180^3 * (ln n + exp 5)" using n_gt_0 unfolding ln_exp by (intro mult_left_mono) auto finally have 2:"(55+60*ln (ln n\<^sub>0))^3 \ 180^3 * ln n + 180^3*exp 5" by simp have 3:"(1::real)+180^3*exp 5 \ 2^30" "(4::real)/ln 2 + 180^3 \ 2^23" by (approximation 10)+ - have "?L = ereal (real (floorlog 2 (size \ - 1)))" + have "?L = ereal (real (floorlog 2 (pro_size \ - 1)))" using assms unfolding encode_seed_def bounded_nat_bit_count by simp - also have "... \ ereal (real (floorlog 2 (size \)))" + also have "... \ ereal (real (floorlog 2 (pro_size \)))" by (intro ereal_mono Nat.of_nat_mono floorlog_mono) auto - also have "... = ereal (1 + of_int \log 2 (real (sample_space.size \))\)" + also have "... = ereal (1 + of_int \log 2 (real (pro_size \))\)" using 0 unfolding floorlog_def by simp - also have "... \ ereal (1 + log 2 (real (size \)))" + also have "... \ ereal (1 + log 2 (real (pro_size \)))" by (intro add_mono ereal_mono) auto - also have "... = 1 + log 2 (real (size I.\) * (2^4) ^ ((m - 1) * nat \ln \ / ln 0.95\))" - unfolding \.size by simp - also have "... = 1 + log 2 (real (size I.\) * 2^ (4 * (m - 1) * nat \ln \ / ln 0.95\))" + also have "... = 1 + log 2 (real (pro_size I.\) * (2^4) ^ ((m - 1) * nat \ln \ / ln 0.95\))" + unfolding expander_pro_size[OF \] by simp + also have "... = 1 + log 2 (real (pro_size I.\) * 2^ (4 * (m - 1) * nat \ln \ / ln 0.95\))" unfolding power_mult by simp - also have "... = 1 + log 2 (real (size I.\)) + (4*(m-1)* nat\ln \ / ln 0.95\)" + also have "... = 1 + log 2 (real (pro_size I.\)) + (4*(m-1)* nat\ln \ / ln 0.95\)" using 1 by (subst log_mult) simp_all also have "... \ 1+log 2(2 powr (4*log 2 n + 48 * (log 2 (1/\)+16)\<^sup>2+ (55+60*ln (1/\\<^sub>i))^3))+ (4*(m-1)* nat\ln \ / ln 0.95\)" using 1 by (intro ereal_mono add_mono iffD2[OF log_le_cancel_iff] I.random_bit_count) auto also have "...=1+4*log 2 n+48*(log 2(1/\)+16)\<^sup>2+(55+60*ln (1/\\<^sub>i))^3+(4*(m-1)*nat\ln \/ln 0.95\)" by (subst log_powr_cancel) auto also have "... \ 2^30 + 2^23*ln n+48*(log 2(1/\)+16)\<^sup>2 + 336*ln (1/\)" (is "?L1 \ ?R1") proof (cases "stage_two") case True have "-1 < (0::real)" by simp also have "... \ ln \ / ln 0.95" using \_gt_0 \_le_1 by (intro divide_nonpos_neg) auto finally have 4: "- 1 < ln \ / ln 0.95" by simp have 5: "- 1 / ln 0.95 \ (20::real)" by (approximation 10) have "(4*(m-1)*nat\ln \/ln 0.95\) = 4 * (real m-1) * of_int \ln \/ln 0.95\" using 4 m_gt_0 unfolding of_nat_mult by (subst of_nat_nat) auto also have "... \ 4 * (real m-1) * (ln \/ln 0.95 + 1)" using m_gt_0 by (intro mult_left_mono) auto also have "... = 4 * (real m-1) * (-ln (ln n\<^sub>0)/ln 0.95 + 1)" using n_lbound True unfolding \_def by (subst ln_inverse[symmetric]) (simp_all add:inverse_eq_divide) also have "... = 4 * (real m - 1 ) * (ln (ln n\<^sub>0) * (-1/ln 0.95) + 1)" by simp also have "... \ 4 * (real m - 1 ) * (ln (ln n\<^sub>0) * 20 + 1)" using n_lbound m_gt_0 by (intro mult_left_mono add_mono 5) auto also have "... = 4 * (real (nat \4 * ln (1 / \) / ln (ln n\<^sub>0)\)-1) * (ln (ln n\<^sub>0) * 20 + 1)" using True unfolding m_def by simp also have "... = 4 * (real_of_int \4 * ln (1 / \) / ln (ln n\<^sub>0)\-1) * (ln (ln n\<^sub>0) * 20 + 1)" using m_gt_0_aux[OF True] by (subst of_nat_nat) simp_all also have "... \ 4 * (4 * ln (1 / \) / ln (ln n\<^sub>0)) * (ln (ln n\<^sub>0) * 20 + 1)" using n_lbound by (intro mult_left_mono mult_right_mono) auto also have "... \ 4 * (4 * ln (1 / \) / ln (ln n\<^sub>0)) * (ln (ln n\<^sub>0) * 20 + ln (ln n\<^sub>0))" using \_gt_0 \_lt_1 n_lbound by (intro mult_left_mono mult_right_mono add_mono divide_nonneg_pos Rings.mult_nonneg_nonneg) simp_all also have "... = 336 * ln (1 / \)" using n_lbound by simp finally have 6: "4 * (m-1) * nat \ln \/ln 0.95\ \ 336 * ln (1/\)" by simp have "?L1 =1+4*log 2 n+48*(log 2(1/\)+16)\<^sup>2+(55+60*ln (ln n\<^sub>0))^3+(4*(m-1)*nat\ln \/ln 0.95\)" using True unfolding \\<^sub>i_def by simp also have "... \ 1+4*log 2 n+48*(log 2(1/\)+16)\<^sup>2+(180^3 * ln n + 180^3*exp 5) + 336 * ln (1/\)" by (intro add_mono 6 2 ereal_mono order.refl) also have "... = (1+180^3*exp 5)+ (4/ln 2 + 180^3)*ln n+48*(log 2(1/\)+16)\<^sup>2+ 336 * ln (1/\)" by (simp add:log_def algebra_simps) also have "... \ 2^30 + 2^23*ln n+48*(log 2(1/\)+16)\<^sup>2+ 336 * ln (1/\)" using n_gt_0 by (intro add_mono ereal_mono 3 order.refl mult_right_mono) auto finally show ?thesis by simp next case False hence "1 / \ \ ln n\<^sub>0" using \_gt_0 n_lbound unfolding stage_two_def not_less by (simp add:divide_simps ac_simps) hence 7: "ln (1 / \) \ ln (ln n\<^sub>0)" using n_lbound \_gt_0 \_lt_1 by (intro iffD2[OF ln_le_cancel_iff]) auto have 8: "0 \ 336*ln (1/\) " using \_gt_0 \_lt_1 by auto have "?L1 = 1 + 4 * log 2 (real n) + 48 * (log 2 (1 / \) + 16)\<^sup>2 + (55 + 60 * ln (1 / \)) ^ 3" using False unfolding \\<^sub>i_def m_def by simp also have "... \ 1 + 4 * log 2 (real n) + 48 * (log 2 (1 / \) + 16)\<^sup>2 + (55 + 60 * ln (ln n\<^sub>0))^3" using \_gt_0 \_lt_1 by (intro add_mono order.refl ereal_mono power_mono mult_left_mono add_nonneg_nonneg 7) auto also have "... \ 1+4*log 2(real n)+48*(log 2 (1 / \)+16)\<^sup>2+(180^3*ln (real n) + 180 ^ 3 * exp 5)" by (intro add_mono ereal_mono 2 order.refl) also have "... = (1+180^3*exp 5)+ (4/ln 2 + 180^3)*ln n+48*(log 2(1/\)+16)\<^sup>2+ 0" by (simp add:log_def algebra_simps) also have "... \ 2^30 + 2^23*ln n+48*(log 2(1/\)+16)\<^sup>2 + 336*ln (1/\)" using n_gt_0 by (intro add_mono ereal_mono 3 order.refl mult_right_mono 8) auto finally show ?thesis by simp qed also have "... = seed_space_usage (real n, \, \)" unfolding seed_space_usage_def by simp finally show ?thesis by simp qed text \The following is an alternative form expressing the correctness and space usage theorems. If @{term "x"} is expression formed by @{term "single"} and @{term "merge"} operations. Then @{term "x"} requires @{term "state_space_usage (real n, \, \)"} bits to encode and @{term "estimate x"} approximates the count of the distinct universe elements in the expression. For example: @{term "estimate (merge (single \ 1) (merge (single \ 5) (single \ 1)))"} approximates the cardinality of @{term "{1::nat, 5, 1}"} i.e. $2$.\ datatype sketch_tree = Single nat | Merge sketch_tree sketch_tree fun eval :: "nat \ sketch_tree \ state" where "eval \ (Single x) = single \ x" | "eval \ (Merge x y) = merge (eval \ x) (eval \ y)" fun sketch_tree_set :: "sketch_tree \ nat set" where "sketch_tree_set (Single x) = {x}" | "sketch_tree_set (Merge x y) = sketch_tree_set x \ sketch_tree_set y" theorem correctness: fixes X assumes "sketch_tree_set t \ {.. pmf_of_set {..}" + defines "p \ pmf_of_set {..}" defines "X \ real (card (sketch_tree_set t))" shows "measure p {\. \estimate (eval \ t) - X\ > \ * X} \ \" (is "?L \ ?R") proof - define A where "A = sketch_tree_set t" have X_eq: "X = real (card A)" unfolding X_def A_def by simp have 0:"eval \ t = \ \ A" for \ unfolding A_def using single_result merge_result by (induction t) (auto simp del:merge.simps single.simps) have 1: "A \ {.. {}" unfolding A_def by (induction t) auto show ?thesis unfolding 0 X_eq p_def by (intro estimate_result 1 2) qed theorem space_usage: - assumes "\ < size \" + assumes "\ < pro_size \" shows "bit_count (encode_state (eval \ t)) \ state_space_usage (real n, \, \)" (is "?A") "bit_count (encode_seed \) \ seed_space_usage (real n, \, \)" (is "?B") proof- define A where "A = sketch_tree_set t" have 0:"eval \ t = \ \ A" for \ unfolding A_def using single_result merge_result by (induction t) (auto simp del:merge.simps single.simps) show ?A unfolding 0 by (intro state_bit_count) show ?B using random_bit_count[OF assms] by simp qed end text \The functions @{term "state_space_usage"} and @{term "seed_space_usage"} are exact bounds on the space usage for the state and the seed. The following establishes asymptotic bounds with respect to the limit $n, \delta^{-1}, \varepsilon^{-1} \rightarrow \infty$.\ context begin text \Some local notation to ease proofs about the asymptotic space usage of the algorithm:\ private definition n_of :: "real \ real \ real \ real" where "n_of = (\(n, \, \). n)" private definition \_of :: "real \ real \ real \ real" where "\_of = (\(n, \, \). \)" private definition \_of :: "real \ real \ real \ real" where "\_of = (\(n, \, \). \)" private abbreviation F :: "(real \ real \ real) filter" where "F \ (at_top \\<^sub>F at_right 0 \\<^sub>F at_right 0)" private lemma var_simps: "n_of = fst" "\_of = (\x. fst (snd x))" "\_of = (\x. snd (snd x))" unfolding n_of_def \_of_def \_of_def by (auto simp add:case_prod_beta) private lemma evt_n: "eventually (\x. n_of x \ n) F" unfolding var_simps by (intro eventually_prod1' eventually_prod2' eventually_ge_at_top) (simp add:prod_filter_eq_bot) private lemma evt_n_1: "\\<^sub>F x in F. 0 \ ln (n_of x)" by (intro eventually_mono[OF evt_n[of "1"]] ln_ge_zero) simp private lemma evt_n_2: "\\<^sub>F x in F. 0 \ ln (ln (n_of x))" using order_less_le_trans[OF exp_gt_zero] by (intro eventually_mono[OF evt_n[of "exp 1"]] ln_ge_zero iffD2[OF ln_ge_iff]) auto private lemma evt_\: "eventually (\x. 1/\_of x \ \ \ \_of x > 0) F" unfolding var_simps by (intro eventually_prod1' eventually_prod2' eventually_conj real_inv_at_right_0_inf eventually_at_right_less) (simp_all add:prod_filter_eq_bot) private lemma evt_\: "eventually (\x. 1/\_of x \ \ \ \_of x > 0) F" unfolding var_simps by (intro eventually_prod1' eventually_prod2' eventually_conj real_inv_at_right_0_inf eventually_at_right_less) (simp_all add:prod_filter_eq_bot) private lemma evt_\_1: "\\<^sub>F x in F. 0 \ ln (1 / \_of x)" by (intro eventually_mono[OF evt_\[of "1"]] ln_ge_zero) simp theorem asymptotic_state_space_complexity: "state_space_usage \ O[F](\(n, \, \). ln (1/\)/\^2 + ln (ln n))" (is "_ \ O[?F](?rhs)") proof - have 0:"(\x. 1) \ O[?F](\x. ln (1 / \_of x))" using order_less_le_trans[OF exp_gt_zero] by (intro landau_o.big_mono eventually_mono[OF evt_\[of "exp 1"]]) (auto intro!: iffD2[OF ln_ge_iff] simp add:abs_ge_iff) have 1:"(\x. 1) \ O[?F](\x. ln (n_of x))" using order_less_le_trans[OF exp_gt_zero] by (intro landau_o.big_mono eventually_mono[OF evt_n[of "exp 1"]]) (auto intro!:iffD2[OF ln_ge_iff] simp add:abs_ge_iff) have "(\x. ((ln (1/\_of x)+1)* (1/\_of x)\<^sup>2))\ O[?F](\x. ln(1/\_of x)* (1/\_of x)\<^sup>2)" by (intro landau_o.mult sum_in_bigo 0) simp_all hence 2: "(\x. 2^40*((ln (1/\_of x)+1)* (1/\_of x)\<^sup>2))\ O[?F](\x. ln(1/\_of x)* (1/\_of x)\<^sup>2)" unfolding cmult_in_bigo_iff by simp have 3: "(1::real) \ exp 2" by (approximation 5) have "(\x. ln (n_of x) / ln 2 + 3) \ O[?F](\x. ln (n_of x))" using 1 by (intro sum_in_bigo) simp_all hence "(\x. ln (ln (n_of x) / ln 2 + 3)) \ O[?F](\x. ln (ln (n_of x)))" using order_less_le_trans[OF exp_gt_zero] order_trans[OF 3] by (intro landau_ln_2[where a="2"] eventually_mono[OF evt_n[of "exp 2"]]) (auto intro!:iffD2[OF ln_ge_iff] add_nonneg_nonneg divide_nonneg_pos) hence 4: "(\x. log 2 (log 2 (n_of x) + 3))\ O[?F](\x. ln(ln(n_of x)))" unfolding log_def by simp have 5: "\\<^sub>F x in ?F. 0 \ ln (1 / \_of x) * (1 / \_of x)\<^sup>2" by (intro eventually_mono[OF eventually_conj[OF evt_\_1 evt_\[of "1"]]]) auto have "state_space_usage = (\x. state_space_usage (n_of x, \_of x, \_of x))" by (simp add:case_prod_beta' n_of_def \_of_def \_of_def) also have "... = (\x. 2 ^ 40 * ((ln (1 / (\_of x)) + 1)* (1/\_of x)\<^sup>2) + log 2 (log 2 (n_of x)+3))" unfolding state_space_usage_def by (simp add:divide_simps) also have "... \ O[?F](\x. ln (1/\_of x)* (1/\_of x)\<^sup>2 + ln (ln (n_of x)))" by (intro landau_sum 2 4 5 evt_n_2) also have "... = O[?F](?rhs)" by (simp add:case_prod_beta' n_of_def \_of_def \_of_def divide_simps) finally show ?thesis by simp qed theorem asymptotic_seed_space_complexity: "seed_space_usage \ O[F](\(n, \, \). ln (1/\)+ln (1/\)^2 + ln n)" (is "_ \ O[?F](?rhs)") proof - have 0: "\\<^sub>F x in ?F. 0 \ (ln (1 / \_of x))\<^sup>2" by simp have 1: "\\<^sub>F x in ?F. 0 \ ln (1 / \_of x) + (ln (1 / \_of x))\<^sup>2" by (intro eventually_mono[OF eventually_conj[OF evt_\_1 0]] add_nonneg_nonneg) auto have 2: "(\x. 1) \ O[?F](\x. ln (1 / \_of x))" using order_less_le_trans[OF exp_gt_zero] by (intro landau_o.big_mono eventually_mono[OF evt_\[of "exp 1"]]) (auto intro!:iffD2[OF ln_ge_iff] simp add:abs_ge_iff) have "(\x. 1) \ O[at_top \\<^sub>F at_right 0 \\<^sub>F at_right 0](\x. ln (n_of x))" using order_less_le_trans[OF exp_gt_zero] by (intro landau_o.big_mono eventually_mono[OF evt_n[of "exp 1"]]) (auto intro!:iffD2[OF ln_ge_iff] simp add:abs_ge_iff) hence 3: "(\x. 1) \ O[?F](\x. ln (1 / \_of x) + (ln (1 / \_of x))\<^sup>2 + ln (n_of x))" by (intro landau_sum_2 1 evt_n_1 0 evt_\_1) simp have 4: "(\x. ln (n_of x)) \ O[?F](\x. ln (1 / \_of x) + (ln (1 / \_of x))\<^sup>2 + ln (n_of x))" by (intro landau_sum_2 1 evt_n_1) simp have "(\x. log 2 (1 / \_of x) + 16) \ O[?F](\x. ln (1 / \_of x))" using 2 unfolding log_def by (intro sum_in_bigo) simp_all hence 5: "(\x. (log 2 (1 / \_of x) + 16)\<^sup>2) \ O[?F](\x. ln (1/\_of x)+(ln (1/\_of x))\<^sup>2)" using 0 unfolding power2_eq_square by (intro landau_sum_2 landau_o.mult evt_\_1) simp_all have 6: "(\x. (log 2 (1 / \_of x) + 16)\<^sup>2) \ O[?F](\x. ln (1/\_of x)+(ln (1/\_of x))\<^sup>2+ln (n_of x))" by (intro landau_sum_1[OF _ _ 5] 1 evt_n_1) have 7: "(\x. ln (1/\_of x)) \ O[?F](\x. ln (1/\_of x)+(ln (1/\_of x))\<^sup>2+ln (n_of x))" by (intro landau_sum_1 1 evt_\_1 0 evt_n_1) simp have "seed_space_usage = (\x. seed_space_usage (n_of x, \_of x, \_of x))" by (simp add:case_prod_beta' n_of_def \_of_def \_of_def) also have "... = (\x. 2^30+2^23*ln (n_of x)+48*(log 2 (1/(\_of x))+16)\<^sup>2 + 336 * ln (1 / \_of x))" unfolding seed_space_usage_def by (simp add:divide_simps) also have "... \ O[?F](\x. ln (1/\_of x)+ln (1/\_of x)^2 + ln (n_of x))" using 3 4 6 7 by (intro sum_in_bigo) simp_all also have "... = O[?F](?rhs)" by (simp add:case_prod_beta' n_of_def \_of_def \_of_def) finally show ?thesis by simp qed definition "space_usage x = state_space_usage x + seed_space_usage x" theorem asymptotic_space_complexity: "space_usage \ O[at_top \\<^sub>F at_right 0 \\<^sub>F at_right 0](\(n, \, \). ln (1/\)/\^2 + ln n)" proof - let ?f1 = "(\x. ln (1/\_of x)*(1/\_of x^2)+ln (ln (n_of x)))" let ?f2 = "(\x. ln(1/\_of x)+ln(1/\_of x)^2+ln (n_of x))" have 0: "\\<^sub>F x in F. 0 \ (1 / (\_of x)\<^sup>2)" unfolding var_simps by (intro eventually_prod1' eventually_prod2' eventually_inv) (simp_all add:prod_filter_eq_bot eventually_nonzero_simps) have 1: "\\<^sub>F x in F. 0 \ ln (1 / \_of x) * (1 / (\_of x)\<^sup>2)" by (intro eventually_mono[OF eventually_conj[OF evt_\_1 0]] mult_nonneg_nonneg) auto have 2: "\\<^sub>F x in F. 0 \ ln (1 / \_of x) * (1 / (\_of x)\<^sup>2) + ln (ln (n_of x))" by (intro eventually_mono[OF eventually_conj[OF 1 evt_n_2]] add_nonneg_nonneg) auto have 3: "\\<^sub>F x in F. 0 \ ln (1 / (\_of x)\<^sup>2)" unfolding power_one_over[symmetric] by (intro eventually_mono[OF evt_\[of "1"]] ln_ge_zero) simp have 4: "\\<^sub>F x in F. 0 \ ln (1 / \_of x) + (ln (1 / \_of x))\<^sup>2 + ln (n_of x)" by (intro eventually_mono[OF eventually_conj[OF evt_n_1 eventually_conj[OF evt_\_1 3]]] add_nonneg_nonneg) auto have 5: "(\_. 1) \ O[F](\x. 1 / (\_of x)\<^sup>2)" unfolding var_simps by (intro bigo_prod_1 bigo_prod_2 bigo_inv) (simp_all add:power_divide prod_filter_eq_bot) have 6: "(\_. 1) \ O[F](\x. ln (1 / \_of x))" unfolding var_simps by (intro bigo_prod_1 bigo_prod_2 bigo_inv) (simp_all add:prod_filter_eq_bot) have 7: "state_space_usage \ O[F](\x. ln (1 / \_of x) * (1 / (\_of x)\<^sup>2) + ln (ln (n_of x)))" using asymptotic_state_space_complexity unfolding \_of_def \_of_def n_of_def by (simp add:case_prod_beta') have 8: "seed_space_usage \ O[F](\x. ln (1 / \_of x) + (ln (1 / \_of x))\<^sup>2 + ln (n_of x))" using asymptotic_seed_space_complexity unfolding \_of_def \_of_def n_of_def by (simp add:case_prod_beta') have 9: "(\x. ln (n_of x)) \ O[F](\x. ln (1 / \_of x) * (1 / (\_of x)\<^sup>2) + ln (n_of x))" by (intro landau_sum_2 evt_n_1 1) simp have "(\x. (ln (1 / \_of x))\<^sup>2) \ O[F](\x. 1 / \_of x^2)" unfolding var_simps by (intro bigo_prod_1 bigo_prod_2 bigo_inv) (simp_all add:power_divide prod_filter_eq_bot) hence 10: "(\x. (ln (1 / \_of x))\<^sup>2) \ O[F](\x. ln (1 / \_of x) * (1 / \_of x^2) + ln (n_of x))" by (intro landau_sum_1 evt_n_1 1 landau_o.big_mult_1' 6) have 11: "(\x. ln (1 / \_of x)) \ O[F](\x. ln (1 / \_of x) * (1 / \_of x^2) + ln (n_of x))" by (intro landau_sum_1 evt_n_1 1 landau_o.big_mult_1 5) simp have 12: "(\x. ln (1/\_of x) * (1/\_of x^2)) \ O[F](\x. ln (1/\_of x)*(1/\_of x^2)+ln (n_of x))" by (intro landau_sum_1 1 evt_n_1) simp have "(\x. ln (ln (n_of x))) \ O[F](\x. ln (n_of x))" unfolding var_simps by (intro bigo_prod_1 bigo_prod_2) (simp_all add:prod_filter_eq_bot) hence 13: "(\x. ln (ln (n_of x))) \ O[F](\x. ln (1 / \_of x) * (1 / \_of x^2) + ln (n_of x))" by (intro landau_sum_2 evt_n_1 1) have "space_usage = (\x. state_space_usage x + seed_space_usage x)" unfolding space_usage_def by simp also have "... \ O[F](\x. ?f1 x + ?f2 x)" by (intro landau_sum 2 4 7 8) also have "... \ O[F](\x. ln (1 / \_of x) * (1/\_of x^2) + ln (n_of x))" by (intro landau_o.big.subsetI sum_in_bigo 9 10 11 12 13) also have "... = O[F](\(n, \, \). ln (1/\)/\^2 + ln n)" unfolding \_of_def \_of_def n_of_def by (simp add:case_prod_beta') finally show ?thesis by simp qed end unbundle no_intro_cong_syntax end diff --git a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Tail_Bounds.thy b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Tail_Bounds.thy --- a/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Tail_Bounds.thy +++ b/thys/Distributed_Distinct_Elements/Distributed_Distinct_Elements_Tail_Bounds.thy @@ -1,761 +1,643 @@ section \Tail Bounds for Expander Walks\ theory Distributed_Distinct_Elements_Tail_Bounds imports Distributed_Distinct_Elements_Preliminary - Expander_Graphs.Expander_Graphs_Definition - Expander_Graphs.Expander_Graphs_Walks + Expander_Graphs.Pseudorandom_Objects_Expander_Walks "HOL-Decision_Procs.Approximation" - Pseudorandom_Combinators begin text \This section introduces tail estimates for random walks in expander graphs, specific to the verification of this algorithm (in particular to two-stage expander graph sampling and obtained tail bounds for subgaussian random variables). They follow from the more fundamental results @{thm [source] regular_graph.kl_chernoff_property} and @{thm [source] regular_graph.uniform_property} which are verified in the AFP entry for expander graphs~\cite{Expander_Graphs-AFP}.\ hide_fact Henstock_Kurzweil_Integration.integral_sum unbundle intro_cong_syntax lemma x_ln_x_min: assumes "x \ (0::real)" shows "x * ln x \ -exp (-1)" proof - define f where "f x = x * ln x" for x :: real define f' where "f' x = ln x + 1" for x :: real have 0:"(f has_real_derivative (f' x)) (at x)" if "x > 0" for x unfolding f_def f'_def using that by (auto intro!: derivative_eq_intros) have "f' x \ 0" if "exp (-1) \ x" for x :: real proof - have "ln x \ -1" using that order_less_le_trans[OF exp_gt_zero] by (intro iffD2[OF ln_ge_iff]) auto thus ?thesis unfolding f'_def by (simp) qed hence "\y. (f has_real_derivative y) (at x) \ 0 \ y" if "x \ exp (-1)" for x :: real using that order_less_le_trans[OF exp_gt_zero] by (intro exI[where x="f' x"] conjI 0) auto hence "f (exp (-1)) \ f x" if "exp(-1) \ x" by (intro DERIV_nonneg_imp_nondecreasing[OF that]) auto hence 2:?thesis if "exp(-1) \ x" unfolding f_def using that by simp have "f' x \ 0" if "x > 0" "x \ exp (-1)" for x :: real proof - have "ln x \ ln (exp (-1))" by (intro iffD2[OF ln_le_cancel_iff] that exp_gt_zero) also have "... = -1" by simp finally have "ln x \ -1" by simp thus ?thesis unfolding f'_def by simp qed hence "\y. (f has_real_derivative y) (at x) \ y \ 0" if "x > 0 " "x \ exp (-1)" for x :: real using that by (intro exI[where x="f' x"] conjI 0) auto hence "f (exp (-1)) \ f x" if "x > 0" "x \ exp(-1)" using that(1) by (intro DERIV_nonpos_imp_nonincreasing[OF that(2)]) auto hence 3:?thesis if "x > 0" "x \ exp(-1)" unfolding f_def using that by simp have ?thesis if "x = 0" using that by simp thus ?thesis using 2 3 assms by fastforce qed theorem (in regular_graph) walk_tail_bound: assumes "l > 0" assumes "S \ verts G" defines "\ \ real (card S) / card (verts G)" assumes "\ < 1" "\ + \\<^sub>a \ \" shows "measure (pmf_of_multiset (walks G l)) {w. real (card {i \ {.. S}) \ \*l} \ exp (- real l * (\ * ln (1/(\+\\<^sub>a)) - 2 * exp(-1)))" (is "?L \ ?R") proof (cases "\ > 0") case True have "0 < \ + \\<^sub>a" by (intro add_pos_nonneg \_ge_0 True) also have "... \ \" using assms(5) by simp finally have \_gt_0: "0 < \" by simp hence \_ge_0: "0 \ \" by simp have "card S \ card (verts G)" by (intro card_mono assms(2)) auto hence \_le_1: "\ \ 1" unfolding \_def by (simp add:divide_simps) have 2: "0 < \ + \\<^sub>a * (1 - \)" using \_le_1 by (intro add_pos_nonneg True mult_nonneg_nonneg \_ge_0) auto have "\ + \\<^sub>a * (1 - \) \ \ + \\<^sub>a * 1" using \_ge_0 True by (intro add_mono mult_left_mono) auto also have "... \ \" using assms(5) by simp also have "... < 1" using assms(4) by simp finally have 4:"\ + \\<^sub>a * (1 - \) < 1" by simp hence 3: "1 \ 1 / (1 - (\ + \\<^sub>a * (1 - \)))" using 2 by (subst pos_le_divide_eq) simp_all have "card S \ n" unfolding n_def by (intro card_mono assms(2)) auto hence 0:"\ \ 1" unfolding \_def n_def[symmetric] using n_gt_0 by simp have "\ * ln (1 / (\ + \\<^sub>a)) - 2*exp (- 1) = \ * ln (1 / (\ + \\<^sub>a*1))+0 -2*exp (- 1)" by simp also have "... \ \ * ln (1 / (\ + \\<^sub>a*(1-\)))+0-2*exp(-1)" using True \_ge_0 \_ge_0 0 2 by (intro diff_right_mono mult_left_mono iffD2[OF ln_le_cancel_iff] divide_pos_pos divide_left_mono add_mono) auto also have "... \ \ * ln (1 / (\ + \\<^sub>a*(1-\)))+(1-\)*ln(1/(1-(\+\\<^sub>a*(1-\))))-2* exp(-1)" using assms(4) 3 by (intro add_mono diff_mono mult_nonneg_nonneg ln_ge_zero) auto also have "... = (-exp(-1))+\*ln(1/(\+\\<^sub>a*(1-\)))+(-exp(-1))+(1-\)*ln(1/(1-(\+\\<^sub>a*(1-\))))" by simp also have "... \ \*ln \+\*ln(1/(\+\\<^sub>a*(1-\)))+(1-\)*ln(1-\)+(1-\)*ln(1/(1-(\+\\<^sub>a*(1-\))))" using assms(4) \_ge_0 by (intro add_mono x_ln_x_min) auto also have "... = \*(ln \+ln(1/(\+\\<^sub>a*(1-\))))+(1-\)*(ln(1-\)+ln(1/(1-(\+\\<^sub>a*(1-\)))))" by (simp add:algebra_simps) also have "... = \ * ln (\*(1/(\+\\<^sub>a*(1-\))))+(1-\)*ln((1-\)*(1/(1-(\+\\<^sub>a*(1-\)))))" using 2 4 assms(4) \_gt_0 by (intro_cong "[\\<^sub>2(+), \\<^sub>2(*)]" more:ln_mult[symmetric] divide_pos_pos) auto also have "... = KL_div \ (\+\\<^sub>a*(1-\))" unfolding KL_div_def by simp finally have 1: "\ * ln (1 / (\ + \\<^sub>a)) - 2 * exp (- 1) \ KL_div \ (\ + \\<^sub>a * (1 - \))" by simp have "\+\\<^sub>a*(1-\) \ \+\\<^sub>a*1" using True by (intro add_mono mult_left_mono \_ge_0) auto also have "... \ \" using assms(5) by simp finally have "\+\\<^sub>a*(1-\) \ \" by simp moreover have "\+\\<^sub>a*(1-\) > 0" using 0 by (intro add_pos_nonneg True mult_nonneg_nonneg \_ge_0) auto ultimately have "\+\\<^sub>a*(1-\) \ {0<..\}" by simp hence "?L \ exp (- real l * KL_div \ (\+\\<^sub>a*(1-\)))" using assms(4) unfolding \_def by (intro kl_chernoff_property assms(1,2)) auto also have "... \ ?R" using assms(1) 1 by simp finally show ?thesis by simp next case False hence "\ \ 0" by simp hence "card S = 0" unfolding \_def n_def[symmetric] using n_gt_0 by (simp add:divide_simps) moreover have "finite S" using finite_subset[OF assms(2) finite_verts] by auto ultimately have 0:"S = {}" by auto have "\ = 0" unfolding \_def 0 by simp hence "\ + \\<^sub>a \0 " using \_ge_0 by simp hence "\ \ 0" using assms(5) by simp hence "\ * real l \ 0" by (intro mult_nonneg_nonneg) auto thus ?thesis using 0 by simp qed theorem (in regular_graph) walk_tail_bound_2: assumes "l > 0" "\\<^sub>a \ \" "\ > 0" assumes "S \ verts G" defines "\ \ real (card S) / card (verts G)" assumes "\ < 1" "\ + \ \ \" shows "measure (pmf_of_multiset (walks G l)) {w. real (card {i \ {.. S}) \ \*l} \ exp (- real l * (\ * ln (1/(\+\)) - 2 * exp(-1)))" (is "?L \ ?R") proof (cases "\ > 0") case True have 0: "0 < \ + \\<^sub>a" by (intro add_pos_nonneg \_ge_0 True) hence "0 < \ + \" using assms(2) by simp hence 1: "0 < (\ + \) * (\ + \\<^sub>a)" using 0 by simp have 3:"\ + \\<^sub>a \ \" using assms(2,7) by simp have 2: "0 \ \" using 3 True \_ge_0 by simp have "?L \ exp (- real l * (\ * ln (1/(\+\\<^sub>a)) - 2 * exp(-1)))" using 3 unfolding \_def by (intro walk_tail_bound assms(1,4,6)) also have "... = exp (- (real l * (\ * ln (1/(\+\\<^sub>a)) - 2 * exp(-1))))" by simp also have "... \ exp (- (real l * (\ * ln (1/(\+\)) - 2 * exp(-1))))" using True assms(2,3) using 0 1 2 by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono diff_mono iffD2[OF ln_le_cancel_iff] divide_left_mono le_imp_neg_le) simp_all also have "... = ?R" by simp finally show ?thesis by simp next case False hence "\ \ 0" by simp hence "card S = 0" unfolding \_def n_def[symmetric] using n_gt_0 by (simp add:divide_simps) moreover have "finite S" using finite_subset[OF assms(4) finite_verts] by auto ultimately have 0:"S = {}" by auto have "\ = 0" unfolding \_def 0 by simp hence "\ + \\<^sub>a \0 " using \_ge_0 by simp hence "\ \ 0" using assms by simp hence "\ * real l \ 0" by (intro mult_nonneg_nonneg) auto thus ?thesis using 0 by simp qed -lemma (in expander_sample_space) tail_bound: +lemma disjI_safe: "(\x \ y) \ x \ y" by auto + +lemma walk_tail_bound: fixes T assumes "l > 0" "\ > 0" - defines "\ \ measure (sample_pmf S) {w. T w}" - assumes "\ < 1" "\ + \ \ \" - shows "measure (\ l \ S) {w. real (card {i \ {.. \*l} + assumes "measure (sample_pro S) {w. T w} \ \" + assumes "\ \ 1" "\ + \ \ \" "\ \ 1" + shows "measure (sample_pro (\ l \ S)) {w. real (card {i \ {.. \*l} \ exp (- real l * (\ * ln (1/(\+\)) - 2 * exp(-1)))" (is "?L \ ?R") proof - - let ?w = "pmf_of_multiset (walks (graph_of e) l)" - define V where "V = {v\ verts (graph_of e). T (select S v)} " + have \_ge_0: "\ \ 0" using assms(3) measure_nonneg order.trans by metis + hence \_gt_0: "\ > 0" using assms(2,5) by auto + hence \_ge_0: "\ \ 0" by simp - have 0: "card {i \ {.. {.. V}" - if "w \ set_pmf (pmf_of_multiset (walks (graph_of e) l))" for w - proof - - have a0: "w \# walks (graph_of e) l" using that E.walks_nonempty by simp - have "w ! i \ verts (graph_of e)" if "i < l" for i - using that E.set_walks_3[OF a0] by auto - thus ?thesis - unfolding V_def - by (intro arg_cong[where f="card"] restr_Collect_cong) auto + have "\ + \ * (1 - \) \ \ + \ * 1" using assms(2,6) \_ge_0 by auto + also have "... \ \" using assms(5) by simp + finally have 1:"\ + \ * (1 - \) \ \" by simp + + have 2: "0 < \ + \ * (1 - \)" + proof (cases "\ = 1") + case True then show ?thesis by simp + next + case False + then show ?thesis using assms(2,6) + by (intro add_nonneg_pos \_ge_0 linordered_semiring_strict_class.mult_pos_pos) auto qed - have 1:"E.\\<^sub>a \ \" - using see_standard(1) unfolding is_expander_def e_def by simp - - have 2: "V \ verts (graph_of e)" - unfolding V_def by simp + have 3: "0 < \ + \" using \_ge_0 assms(2) by simp - have "\ = measure (pmf_of_set {.._def sample_pmf_alt[OF sample_space_S] + have "\ * ln (1 / (\ + \)) - 2*exp (- 1) = \ * ln (1 / (\ + \*1))+0 -2*exp (-1)" by simp + also have "... \ \ * ln (1 / (\ + \*(1-\)))+0-2*exp(-1)" + using 2 3 \_ge_0 \_ge_0 assms(2) by (intro diff_right_mono add_mono mult_left_mono + iffD2[OF ln_le_cancel_iff] divide_left_mono divide_pos_pos) simp_all + also have "... \ \ * ln (1 / (\ + \*(1-\)))+(1-\)*ln(1/(1-(\+\*(1-\))))-2* exp(-1)" + proof (cases "\ < 1") + case True + hence "\ + \ * (1 - \) < 1" using 1 by simp + thus ?thesis using assms(4) 2 + by (intro diff_right_mono add_mono mult_nonneg_nonneg order.refl ln_ge_zero) auto + next + case False + hence "\=1" using assms(4) by simp + thus ?thesis by simp + qed + also have "... = (-exp(-1))+\*ln(1/(\+\*(1-\)))+(-exp(-1))+(1-\)*ln(1/(1-(\+\*(1-\))))" by simp - also have "... = real (card ({v\{.._eq: "\ = real (card V) / card (verts (graph_of e))" + also have "... \ \*ln \+\*ln(1/(\+\*(1-\)))+(1-\)*ln(1-\)+(1-\)*ln(1/(1-(\+\*(1-\))))" + using assms(4) \_ge_0 by (intro add_mono x_ln_x_min) auto + also have "... = \*(ln \+ln(1/(\+\*(1-\))))+(1-\)*(ln(1-\)+ln(1/(1-(\+\*(1-\)))))" + by (simp add:algebra_simps) + also have "... = \ * ln (\*(1/(\+\*(1-\))))+(1-\)*ln((1-\)*(1/(1-(\+\*(1-\)))))" + using 2 1 assms(4) \_gt_0 by (intro arg_cong2[where f="(+)"] iffD2[OF mult_cancel_left] + disjI_safe ln_mult[symmetric] divide_pos_pos) auto + also have "... = KL_div \ (\+\*(1-\))" unfolding KL_div_def by simp + finally have 4: "\ * ln (1 / (\ + \)) - 2 * exp (- 1) \ KL_div \ (\ + \ * (1 - \))" by simp - have "?L = measure ?w {y. \ * real l \ real (card {i \ {.. * real l \ real (card {i \ {.. V})}" - using 0 by (intro measure_pmf_cong) (simp) - also have "... \ ?R" - using assms(5) unfolding \_eq - by (intro E.walk_tail_bound_2 assms(1,2,4) 1 2) auto - finally show ?thesis - by simp + have "?L \ exp (- real l * KL_div \ (\+\*(1-\)))" + using 1 by (intro expander_kl_chernoff_bound assms) + also have "... \ exp (- real l * (\ * ln (1 / (\ + \)) - 2 * exp (- 1)))" + by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono_neg 4) auto + finally show ?thesis by simp qed definition C\<^sub>1 :: real where "C\<^sub>1 = exp 2 + exp 3 + (exp 1 - 1)" -lemma (in regular_graph) deviation_bound: +lemma deviation_bound: fixes f :: "'a \ real" assumes "l > 0" - assumes "\\<^sub>a \ exp (-real l * ln (real l)^3)" - assumes "\x. x \ 20 \ measure (pmf_of_set (verts G)) {v. f v \ x} \ exp (-x * ln x^3)" - shows "measure (pmf_of_multiset (walks G l)) {w. (\i\w. f i) \ C\<^sub>1 * l} \ exp (- real l)" - (is "?L \ ?R") + assumes "\ \ {0<..exp (-real l * ln (real l)^3)}" + assumes "\x. x \ 20 \ measure (sample_pro S) {v. f v \ x} \ exp (-x * ln x^3)" + shows "measure (sample_pro (\ l \ S)) {\. (\i i)) \ C\<^sub>1 * l} \ exp (- real l)" (is "?L \ ?R") proof - - let ?w = "pmf_of_multiset (walks G l)" - let ?p = "pmf_of_set (verts G)" + let ?w = "sample_pro (\ l \ S)" + let ?p = "sample_pro S" let ?a = "real l*(exp 2 + exp 3)" define b :: real where "b = exp 1 - 1" - have b_gt_0: "b > 0" - unfolding b_def by (approximation 5) + have b_gt_0: "b > 0" unfolding b_def by (approximation 5) define L where - "L k = measure ?w {w. exp (real k)*card{i\{..exp(real k)} \ real l/real k^2}" for k - - define k_max where "k_max = max 4 (MAX v \ verts G. nat \ln (f v)\+1)" - - define \ where "\ = exp (-real l * ln (real l)^3)" - - have \\<^sub>a_le_\: "\\<^sub>a \ \" - unfolding \_def using assms(2) by simp + "L k = measure ?w {w. exp (real k)*card{i\{..exp(real k)} \ real l/real k^2}" for k - have \_gt_0: "\ > 0" - unfolding \_def by simp + define k_max where "k_max = max 4 (MAX v \ pro_set S. nat \ln (f v)\+1)" - have k_max_ge_4: "k_max \ 4" - unfolding k_max_def by simp - have k_max_ge_3: "k_max \ 3" - unfolding k_max_def by simp + have k_max_ge_4: "k_max \ 4" unfolding k_max_def by simp + have k_max_ge_3: "k_max \ 3" unfolding k_max_def by simp - have 1:"of_bool(\ln(max x (exp 1))\+1=int k) = - (of_bool(x \ exp (real k-1)) - of_bool(x \ exp k)::real)" + have 1:"of_bool(\ln(max x (exp 1))\+1=int k)=(of_bool(x\exp(real k-1))-of_bool(x \ exp k)::real)" (is "?L1 = ?R1") if "k \ 3" for k x proof - have a1: "real k - 1 \ k" by simp - have "?L1 = of_bool(\ln(max x (exp 1))\=int k-1)" - by simp - also have "... = of_bool(ln(max x (exp 1))\{real k-1..{exp (real k-1)..ln(max x (exp 1))\=int k-1)" by simp + also have "... = of_bool(ln(max x (exp 1))\{real k-1..{exp (real k-1)..{exp (real k-1)..{exp (real k-1).. exp 1") case True then show ?thesis by simp next case False - have "{exp (real k - 1).. {exp (real k - 1)..}" - by auto - also have "... \ {exp 1..}" - using that by simp + have "{exp (real k - 1).. {exp (real k - 1)..}" by auto + also have "... \ {exp 1..}" using that by simp finally have "{exp (real k - 1).. {exp 1..}" by simp - moreover have "x \ {exp 1..}" - using False by simp + moreover have "x \ {exp 1..}" using False by simp ultimately have "x \ {exp (real k - 1)..{exp (real k-1)..{exp (real k-1)..ln (max (f x) (exp 1))\+1} \ {2..k_max}" (is "{?L1} \ ?R2") - if "x \ verts G" for x + if "x \ pro_set S" for x proof (cases "f x \ exp 1") case True - hence "?L1 = nat \ln (f x)\+1" - by simp - also have "... \ (MAX v \ verts G. nat \ln (f v)\+1)" - by (intro Max_ge finite_imageI imageI that) auto - also have "... \ k_max" - unfolding k_max_def by simp - finally have le_0: "?L1 \ k_max" - by simp - have "(1::nat) \ nat \ln (exp (1::real))\" - by simp + hence "?L1 = nat \ln (f x)\+1" by simp + also have "... \ (MAX v \ pro_set S. nat \ln (f v)\+1)" + by (intro Max_ge finite_imageI imageI that finite_pro_set) + also have "... \ k_max" unfolding k_max_def by simp + finally have le_0: "?L1 \ k_max" by simp + have "(1::nat) \ nat \ln (exp (1::real))\" by simp also have "... \ nat \ln (f x)\" using True order_less_le_trans[OF exp_gt_zero] by (intro nat_mono floor_mono iffD2[OF ln_le_cancel_iff]) auto finally have "1 \ nat \ln (f x)\" by simp - hence "?L1 \ 2" - using True by simp - hence "?L1 \ ?R2" - using le_0 by simp + hence "?L1 \ 2" using True by simp + hence "?L1 \ ?R2" using le_0 by simp then show ?thesis by simp next case False - hence "{?L1} = {2}" - by simp - also have "... \ ?R2" - using k_max_ge_3 by simp + hence "{?L1} = {2}" by simp + also have "... \ ?R2" using k_max_ge_3 by simp finally show ?thesis by simp qed - have 2:"(\i\w. f i) \ ?a+b*(\k=3..{..exp k})" - (is "?L1 \ ?R1") if "w \# walks G l" for w + have 2:"(\i ?a+b*(\k=3..{..exp k})" + (is "?L1 \ ?R1") if "w \ pro_set (\ l \ S)" for w proof - - have l_w: "length w = l" - using set_walks that by auto - have s_w: "set w \ verts G" - using set_walks that by auto + have s_w: "w i \ pro_set S" for i + using that expander_pro_range[OF assms(1)] assms(2) + unfolding set_sample_pro[where S="\ l \ S"] by auto - have "?L1 \ (\i\w. exp( ln (max (f i) (exp 1))))" - by (intro sum_list_mono) (simp add:less_max_iff_disj) - also have "... \ (\i\w. exp (of_nat (nat \ln (max (f i) (exp 1))\+1)))" - by (intro sum_list_mono iffD2[OF exp_le_cancel_iff]) linarith - also have "... = (\i\w. (\k=2..k_max. exp k * of_bool (k=nat \ln (max (f i)(exp 1))\+1)))" - using Int_absorb1[OF 0] subsetD[OF s_w] by (intro_cong "[\\<^sub>1 sum_list]" more:map_cong) - (simp add:of_bool_def if_distrib if_distribR sum.If_cases) + have "?L1 \ (\i (\iln (max (f (w i)) (exp 1))\+1)))" + by (intro sum_mono iffD2[OF exp_le_cancel_iff]) linarith + also have "... = (\ik=2..k_max. exp k * of_bool (k=nat \ln (max (f (w i))(exp 1))\+1)))" + using Int_absorb1[OF 0] s_w by (intro sum.cong map_cong refl) + (simp add:of_bool_def if_distrib if_distribR sum.If_cases) also have "...= - (\i\w.(\k\(insert 2{3..k_max}). exp k* of_bool(k=nat\ln(max(f i)(exp 1))\+1)))" + (\ik\(insert 2{3..k_max}). exp k* of_bool(k=nat\ln(max(f (w i))(exp 1))\+1)))" using k_max_ge_3 by (intro_cong "[\\<^sub>1 sum_list]" more:map_cong sum.cong) auto - also have "... = (\i\w. exp 2* of_bool (2=nat \ln (max (f i)(exp 1))\+1) + - (\k=3..k_max. exp k * of_bool (k=nat \ln (max (f i)(exp 1))\+1)))" + also have "... = (\iln (max (f (w i))(exp 1))\+1) + + (\k=3..k_max. exp k * of_bool (k=nat \ln (max (f (w i))(exp 1))\+1)))" by (subst sum.insert) auto - also have "... \ (\i\w. exp 2*1+(\k=3..k_max. exp k* of_bool(k=nat\ln(max(f i)(exp 1))\+1)))" - by (intro sum_list_mono add_mono mult_left_mono) auto - also have "... = (\i\w. exp 2+(\k=3..k_max. exp k* of_bool(\ln(max(f i)(exp 1))\+1=int k)))" + also have "...\(\ik=3..k_max. exp k* of_bool(k=nat\ln(max(f (w i))(exp 1))\+1)))" + by (intro sum_mono add_mono mult_left_mono) auto + also have "...=(\ik=3..k_max. exp k* of_bool(\ln(max(f (w i))(exp 1))\+1=int k)))" by (intro_cong "[\\<^sub>1 sum_list,\\<^sub>1 of_bool, \\<^sub>2(+),\\<^sub>2(*)]" more:map_cong sum.cong) auto also have "... = - (\i\w. exp 2+(\k=3..k_max. exp k*(of_bool(f i\exp (real k-1))-of_bool(f i\exp k))))" + (\ik=3..k_max. exp k*(of_bool(f (w i)\exp (real k-1))-of_bool(f (w i)\exp k))))" by (intro_cong "[\\<^sub>1 sum_list,\\<^sub>1 of_bool, \\<^sub>2(+),\\<^sub>2(*)]" more:map_cong sum.cong 1) auto - also have "... = - (\i\w. exp 2+(\k=2+1..exp(real k-1))-of_bool(f i\exp k))))" - by (intro_cong "[\\<^sub>1 sum_list,\\<^sub>2(+)]" more:map_cong sum.cong) auto - also have "... = - (\i\w. exp 2+(\k=2..exp k)-of_bool(f i\exp (Suc k)))))" + also have "... = (\ik=2+1..exp(real k-1))-of_bool(f (w i)\exp k))))" + by (intro_cong "[\\<^sub>2(+)]" more:map_cong sum.cong) auto + also have "... = (\ik=2..exp k)-of_bool(f (w i)\exp (Suc k)))))" by (subst sum.shift_bounds_nat_ivl) simp - also have "... = (\i\w. exp 2+ (\k=2..exp k))- - (\k=2..exp (k+1))))" + also have "... = (\ik=2..exp k))- + (\k=2..exp (k+1))))" by (simp add:sum_subtractf algebra_simps) - also have "... = (\i\w. exp 2+ (\k=2..exp k))- - (\k=3..exp k)))" + also have "... = (\ik=2..exp k))- + (\k=3..exp k)))" by (subst sum.shift_bounds_nat_ivl[symmetric]) (simp cong:sum.cong) - also have "... = (\i\w. exp 2+ (\k\ insert 2 {3..exp k))- - (\k=3..exp k)))" - using k_max_ge_3 - by (intro_cong "[\\<^sub>1 sum_list, \\<^sub>2 (+), \\<^sub>2 (-)]" more: map_cong sum.cong) auto - also have "... = (\i\w. exp 2+ exp 3 * of_bool (f i \ exp 2) + - (\k=3..exp k))-(\k=3..exp k)))" + also have "... = (\ik\ insert 2 {3..exp k))- + (\k=3..exp k)))" + using k_max_ge_3 by (intro_cong "[\\<^sub>2 (+), \\<^sub>2 (-)]" more: map_cong sum.cong) auto + also have "... = (\i exp 2) + + (\k=3..exp k)) - + (\k=3..exp k)))" by (subst sum.insert) (simp_all add:algebra_simps) - also have "... \ (\i\w. exp 2+exp 3+(\k=3..exp k))- - (\k=3..exp k)))" - by (intro sum_list_mono add_mono diff_mono) auto - also have "... = (\i\w. exp 2+exp 3+(\k=3..exp k))- - (\k\ insert k_max {3..exp k)))" - using k_max_ge_3 by (intro_cong "[\\<^sub>1 sum_list, \\<^sub>2 (+), \\<^sub>2 (-)]" more: map_cong sum.cong) auto - also have "... = (\i\w. exp 2+exp 3+(\k=3..exp k))- - (exp k_max * of_bool (f i\ exp k_max)))" + also have "... \ (\ik=3..exp k))- + (\k=3..exp k)))" + by (intro sum_mono add_mono diff_mono) auto + also have "... = (\ik=3..exp k))- + (\k\ insert k_max {3..exp k)))" + using k_max_ge_3 by (intro_cong "[\\<^sub>2 (+), \\<^sub>2 (-)]" more: map_cong sum.cong) auto + also have "... = (\ik=3..exp k))- + (exp k_max * of_bool (f (w i)\ exp k_max)))" by (subst sum.insert) (auto simp add:sum_subtractf algebra_simps) - also have "...\(\i\w. exp 2+exp 3+(\k=3..exp k))-0)" - by (intro sum_list_mono add_mono diff_mono) auto - also have "... \(\i\w. exp 2+exp 3+ (\k=3..exp k)))" + also have "...\(\ik=3..exp k))-0)" + by (intro sum_mono add_mono diff_mono) auto + also have "... \(\ik=3..exp k)))" by auto - also have "... = (\i\w. exp 2+exp 3+ (\k=3..exp k))))" + also have "... = (\ik=3..exp k))))" by (simp add:exp_add algebra_simps) - also have "... = (\i\w. exp 2+exp 3+b*(\k=3..exp k)))" - unfolding b_def - by (subst sum_distrib_left) simp - also have "... = ?a+b*(\i=0..k=3..exp k)))" - unfolding sum_list_sum_nth by (simp add:l_w sum_distrib_left[symmetric]) + also have "... = (\ik=3..exp k)))" + unfolding b_def by (subst sum_distrib_left) simp + also have "... = ?a+b*(\ik=3..exp k)))" + by (simp add: sum_distrib_left[symmetric]) also have "... = ?R1" by (subst sum.swap) (simp add:ac_simps Int_def) finally show ?thesis by simp qed have 3: "\k\{3.. l/real k^2" if "(\k=3.. real l" for g proof (rule ccontr) assume a3: "\(\k\{3.. l/real k^2)" - hence "g k < l/real k^2" if "k \{3..{3..k=3..k=3.. (\k=3..k=3..k=2+1..<(k_max-1)+1. (-1)/k - (-1) / (real k-1))" by (intro sum.cong arg_cong2[where f="(*)"]) auto also have "... = l * (\k=2..<(k_max-1). (-1)/(Suc k) - (-1) / k)" by (subst sum.shift_bounds_nat_ivl) auto also have "... = l * (1/2 - 1 / real (k_max - 1))" using k_max_ge_3 by (subst sum_Suc_diff') auto - also have "... \ real l * (1 - 0)" - by (intro mult_left_mono diff_mono) auto - also have "... = l" - by simp + also have "... \ real l * (1 - 0)" by (intro mult_left_mono diff_mono) auto + also have "... = l" by simp finally have "(\k=3.. exp(-real l-k+2)" if "k \ 3" for k proof (cases "k \ ln l") case True define \ where "\ = 1 / (real k)\<^sup>2 / exp (real k)" - define S where "S = {v \ verts G. f v \ exp (real k)}" - define \ where "\ = card S / card (verts G)" - - have exp_k_ubound: "exp (real k) \ real l" - using True assms(1) - by (simp add: ln_ge_iff) + define \ where "\ = exp (-exp(real k) * real k^3)" - have "20 \ exp (3::real)" - by (approximation 10) - also have "... \ exp (real k)" - using that by simp - finally have exp_k_lbound: "20 \ exp (real k)" - by simp - - have S_range: "S \ verts G" - unfolding S_def by simp + have exp_k_ubound: "exp (real k) \ real l" using True assms(1) by (simp add: ln_ge_iff) - have "\ = measure (pmf_of_set (verts G)) S" - unfolding \_def using verts_non_empty Int_absorb1[OF S_range] - by (simp add:measure_pmf_of_set) - also have "... = measure (pmf_of_set (verts G)) {v. f v \ exp (real k)}" - unfolding S_def using verts_non_empty by (intro measure_pmf_cong) auto - also have "... \ exp (- exp (real k) * ln (exp (real k)) ^ 3)" + have "20 \ exp (3::real)" by (approximation 10) + also have "... \ exp (real k)" using that by simp + finally have exp_k_lbound: "20 \ exp (real k)" by simp + + have "measure (sample_pro S) {v. f v\exp(real k)} \ exp (-exp(real k) * ln (exp (real k)) ^ 3)" by (intro assms(3) exp_k_lbound) - also have "... = exp (-(exp(real k) * real k^3))" - by simp - finally have \_bound: "\ \ exp (-exp(real k) * real k^3)" by simp + also have "... = exp (-(exp(real k) * real k^3))" by simp + finally have \_bound: "measure (sample_pro S) {v. f v \ exp (real k)} \ \" by (simp add:\_def) have "\+\ \ exp (-exp(real k) * real k^3) + exp (- real l * ln (real l) ^ 3)" - unfolding \_def by (intro add_mono \_bound) auto - also have "... = exp (-(exp(real k) * real k^3)) + exp (- (real l * ln (real l) ^ 3))" - by simp + unfolding \_def using assms by (intro add_mono) auto + also have "... = exp (-(exp(real k) * real k^3)) + exp (- (real l * ln (real l) ^ 3))" by simp also have "... \ exp (-(exp(real k) * real k^3)) + exp (-(exp(real k) * ln(exp (real k))^3))" using assms(1) exp_k_ubound by (intro add_mono iffD2[OF exp_le_cancel_iff] le_imp_neg_le mult_mono power_mono iffD2[OF ln_le_cancel_iff]) simp_all - also have "... = 2 * exp (-exp(real k) * real k^3)" - by simp - finally have \_\_bound: "\+\ \ 2 * exp (-exp(real k) * real k^3)" - by simp + also have "... = 2 * exp (-exp(real k) * real k^3)" by simp + finally have \_\_bound: "\+\ \ 2 * exp (-exp(real k) * real k^3)" by simp - have "\+\ \ 2 * exp (-exp(real k) * real k^3)" - by (intro \_\_bound) - also have "... = exp (-exp(real k) * real k^3 + ln 2)" - unfolding exp_add by simp - also have "... = exp (-(exp(real k) * real k^3 - ln 2))" - by simp + have "\+\ \ 2 * exp (-exp(real k) * real k^3)" by (intro \_\_bound) + also have "... = exp (-exp(real k) * real k^3 + ln 2)" unfolding exp_add by simp + also have "... = exp (-(exp(real k) * real k^3 - ln 2))" by simp also have "... \ exp (-((1+ real k) * real k^3 - ln 2))" using that by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le diff_mono mult_right_mono exp_ge_add_one_self_aux) auto also have "... = exp (-(real k^4 + (real k^3- ln 2)))" by (simp add:power4_eq_xxxx power3_eq_cube algebra_simps) also have "... \ exp (-(real k^4 + (2^3- ln 2)))" using that by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le add_mono diff_mono power_mono) auto also have "... \ exp (-(real k^4 + 0))" by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le add_mono order.refl) (approximation 5) also have "... \ exp (-(real k^3 * real k))" by (simp add:power4_eq_xxxx power3_eq_cube algebra_simps) also have "... \ exp (-(2^3 * real k))" using that by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le mult_right_mono power_mono) auto - also have "... \ exp (-3* real k )" - by (intro iffD2[OF exp_le_cancel_iff]) auto - also have "... = exp (-(real k + 2 * real k) )" - by simp + also have "... \ exp (-3* real k)" by (intro iffD2[OF exp_le_cancel_iff]) auto + also have "... = exp (-(real k + 2 * real k) )" by simp also have "... \ exp (-(real k + 2 * ln k) )" using that by (intro iffD2[OF exp_le_cancel_iff] le_imp_neg_le add_mono mult_left_mono ln_bound) auto - also have "... = exp (-(real k + ln(k^2)) )" - using that by (subst ln_powr[symmetric]) auto + also have "... = exp (-(real k + ln(k^2)))" using that by (subst ln_powr[symmetric]) auto also have "... = \" - using that unfolding \_def exp_minus exp_add inverse_eq_divide - by (simp add:algebra_simps) - finally have \_\_le_\: "\+\\\" - by simp + using that unfolding \_def exp_minus exp_add inverse_eq_divide by (simp add:algebra_simps) + finally have \_\_le_\: "\+\\\" by simp - have "\ \ 0" - unfolding \_def n_def[symmetric] using n_gt_0 - by (intro divide_nonneg_pos) auto - hence \_\_gt_0: "\+\>0" - using \_gt_0 by simp + have "\ \ 0" unfolding \_def by simp + hence \_\_gt_0: "\+\>0" using assms(2) by auto - have "\ = 1 / ((real k)\<^sup>2 * exp (real k))" - unfolding \_def by simp + have "\ = 1 / ((real k)\<^sup>2 * exp (real k))" unfolding \_def by simp also have "... \ 1 / (2^2 * exp 2)" using that by (intro divide_left_mono mult_mono power_mono) (auto) - finally have \_ubound: "\ \ 1 / (4 * exp 2)" - by simp + finally have \_ubound: "\ \ 1 / (4 * exp 2)" by simp - have "\ \ 1 / (4 * exp 2)" - by (intro \_ubound) - also have "... < 1" - by (approximation 5) - finally have \_lt_1: "\ < 1" - by simp + have "\ \ 1 / (4 * exp 2)" by (intro \_ubound) + also have "... < 1" by (approximation 5) + finally have \_lt_1: "\ < 1" by simp - have \_ge_0: "\ \ 0" - using that unfolding \_def by (intro divide_nonneg_pos) auto + have \_ge_0: "\ \ 0" using that unfolding \_def by (intro divide_nonneg_pos) auto + have \_le_1: "\ \ 1" unfolding \_def by simp - have "L k = measure ?w {w. \*l \ real (card {i \ {.. f (w ! i)})}" + have "L k = measure ?w {w. \*l \ real (card {i \ {.. f (w i)})}" unfolding L_def \_def using that by (intro_cong "[\\<^sub>2 measure]" more:Collect_cong) (simp add:field_simps) - also have "... = measure ?w {w. \*l \ real (card {i \ {.. S})}" - proof (rule measure_pmf_cong) - fix x assume "x \ set_pmf ?w" - hence "card {i \ {.. f (x ! i)}=card {i \ {.. S}" - using walks_nonempty set_walks_3[of "x"] nth_mem unfolding S_def - by (intro restr_Collect_cong arg_cong[where f="card"]) force - thus "x\{w. \*l\card{i\{..f (w ! i)}}\x\{w. \*l\card {i \ {.. S}}" - by simp - qed also have "... \ exp (- real l * (\ * ln (1/(\+\)) - 2 * exp(-1)))" - using \_\_le_\ \_lt_1 S_range \\<^sub>a_le_\ \_gt_0 unfolding \_def - by (intro walk_tail_bound_2 assms(1)) auto + using \_lt_1 assms(2) by (intro walk_tail_bound \_bound assms(1) \_\_le_\ \_le_1) auto also have "... = exp ( real l * (\ * ln (\+\) + 2 * exp (-1)))" using \_\_gt_0 by (simp_all add:ln_div algebra_simps) also have "... \ exp ( real l * (\ * ln (2 * exp (-exp(real k) * real k^3)) + 2 * exp(-1)))" using \_\_gt_0 \_\_bound \_ge_0 by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono add_mono iffD2[OF ln_le_cancel_iff]) simp_all also have "... = exp (real l * (\ * (ln 2 - exp (real k) * real k ^ 3) + 2 * exp (- 1)))" by (simp add:ln_mult) also have "... = exp (real l * (\ * ln 2 - real k + 2 * exp (- 1)))" using that unfolding \_def by (simp add:field_simps power2_eq_square power3_eq_cube) also have "... \ exp (real l * (ln 2 / (4 * exp 2) - real k + 2 * exp (-1)))" using \_ubound by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono add_mono diff_mono) (auto simp:divide_simps) also have "... = exp (real l * (ln 2 / (4 * exp 2) + 2 *exp(-1) - real k))" by simp also have "... \ exp (real l * (1 - real k))" by (intro iffD2[OF exp_le_cancel_iff] mult_left_mono diff_mono order.refl of_nat_0_le_iff) (approximation 12) also have "... \ exp (-real l - real k + 2)" proof (intro iffD2[OF exp_le_cancel_iff]) have "1 * (real k-2) \ real l * (real k-2)" using assms(1) that by (intro mult_right_mono) auto - thus "real l * (1 - real k) \ - real l - real k + 2" - by argo + thus "real l * (1 - real k) \ - real l - real k + 2" by argo qed finally show ?thesis by simp next case False hence k_gt_l: "k \ ln l" by simp define \ where "\ = 1 / (real k)\<^sup>2 / exp (real k)" - have "20 \ exp (3::real)" - by (approximation 10) - also have "... \ exp (real k)" - using that by simp - finally have exp_k_lbound: "20 \ exp (real k)" - by simp + have "20 \ exp (3::real)" by (approximation 10) + also have "... \ exp (real k)" using that by simp + finally have exp_k_lbound: "20 \ exp (real k)" by simp - have \_gt_0: "0 < \" - using that unfolding \_def by (intro divide_pos_pos) auto + have \_gt_0: "0 < \" using that unfolding \_def by (intro divide_pos_pos) auto - hence \_l_gt_0: "0 < \ * real l" - using assms(1) by auto + hence \_l_gt_0: "0 < \ * real l" using assms(1) by auto - have "L k = measure ?w {w. \*l \ real (card {i \ {.. f (w ! i)})}" + have "L k = measure ?w {w. \*l \ real (card {i \ {.. f (w i)})}" unfolding L_def \_def using that by (intro_cong "[\\<^sub>2 measure]" more:Collect_cong) (simp add:field_simps) - also have "... \ (\w. real (card {i \ {.. f (w ! i)}) \?w) / (\*l)" - using walks_nonempty \_l_gt_0 - by (intro pmf_markov integrable_measure_pmf_finite) simp_all - also have "... = (\w. (\i f (w ! i)))\?w) / (\*l)" + also have "... \ (\w. real (card {i \ {.. f (w i)}) \?w) / (\*l)" + by (intro pmf_markov \_l_gt_0) simp_all + also have "... = (\w. (\i f (w i)))\?w) / (\*l)" by (intro_cong "[\\<^sub>2 (/)]" more:integral_cong_AE AE_pmfI) (auto simp add:Int_def) - also have "... = (\iw. of_bool (exp(real k) \ f (w ! i))\?w)) / (\*l)" - using walks_nonempty - by (intro_cong "[\\<^sub>2 (/)]" more:integral_sum integrable_measure_pmf_finite) auto - also have "... = (\iv. of_bool (exp(real k) \ f v)\(map_pmf (\w. w!i) ?w))) / (\*l)" + also have "... = (\iw. of_bool (exp(real k) \ f (w i))\?w)) / (\*l)" + by (intro_cong "[\\<^sub>2 (/)]" more:integral_sum integrable_measure_pmf_finite finite_pro_set) + also have "... = (\iv. of_bool (exp(real k) \ f v)\(map_pmf (\w. w i) ?w))) / (\*l)" by simp - also have "... = (\iv. of_bool (exp(real k) \ f v)\?p)) / (\*l)" - by (intro_cong "[\\<^sub>2(/),\\<^sub>2(integral\<^sup>L),\\<^sub>1 measure_pmf]" more:sum.cong uniform_property) auto + also have "... = (\iv. of_bool (exp(real k) \ f v)\?p)) / (\*l)" using assms(1,2) + by (intro_cong "[\\<^sub>2(/),\\<^sub>2(integral\<^sup>L),\\<^sub>1 measure_pmf]" more:sum.cong expander_uniform_property) + simp_all also have "... = (\iv. indicat_real {v. (exp(real k) \ f v)} v\?p)) / (\*l)" by (intro_cong "[\\<^sub>2(/),\\<^sub>2(integral\<^sup>L)]" more:sum.cong) auto - also have "... = (\i exp (real k)})) / (\*l)" - by simp + also have "... = (\i exp (real k)})) / (\*l)" by simp also have "... \ (\i*l)" using \_l_gt_0 by (intro divide_right_mono sum_mono assms(3) exp_k_lbound) auto - also have "... = exp (- exp (real k) * real k ^ 3) / \" - using assms(1) by simp + also have "... = exp (- exp (real k) * real k ^ 3) / \" using assms(1) by simp also have "... = exp (real k + ln (k^2) - exp (real k) * real k ^ 3)" using that unfolding \_def by (simp add:exp_add exp_diff exp_minus algebra_simps inverse_eq_divide) also have "... = exp (real k + 2 * ln k - exp (real k) * real k ^ 3)" using that by (subst ln_powr[symmetric]) auto also have "... \ exp (real k + 2 * real k - exp (ln l) * real k^3)" using that k_gt_l ln_bound by (intro iffD2[OF exp_le_cancel_iff] add_mono diff_mono mult_left_mono mult_right_mono) auto also have "... = exp (3* real k - l * (real k^3-1) -l)" using assms(1) by (subst exp_ln) (auto simp add:algebra_simps) also have "... \ exp (3* real k - 1 * (real k^3-1) -l)" using assms(1) that by (intro iffD2[OF exp_le_cancel_iff] diff_mono mult_right_mono) auto also have "... = exp (3* real k - real k * real k^2-1 -l+2)" by (simp add:power2_eq_square power3_eq_cube) also have "... \ exp (3* real k - real k * 2^2-0 -l+2)" using assms(1) that by (intro iffD2[OF exp_le_cancel_iff] add_mono diff_mono mult_left_mono power_mono) auto - also have "... = exp (- real l - real k + 2)" - by simp + also have "... = exp (- real l - real k + 2)" by simp finally show ?thesis by simp qed have "?L \ measure ?w - {w. ?a+b*(\k=3..{..exp (real k)}) \ C\<^sub>1*l}" - using order_trans[OF _ 2] walks_nonempty by (intro pmf_mono) simp + {w. ?a+b*(\k=3..{..exp (real k)}) \ C\<^sub>1*l}" + using order_trans[OF _ 2] by (intro pmf_mono) simp also have "... = measure ?w - {w. (\k=3..{..exp(real k)})\l}" + {w. (\k=3..{..exp(real k)})\l}" unfolding C\<^sub>1_def b_def[symmetric] using b_gt_0 by (intro_cong "[\\<^sub>2 measure]" more:Collect_cong) (simp add:algebra_simps) also have "... \ measure ?w - {w. (\k\{3..{..exp(real k)} \ real l/real k^2)}" + {w. (\k\{3..{..exp(real k)} \ real l/real k^2)}" using 3 by (intro pmf_mono) simp also have "... = measure ?w - (\k\{3..{..exp(real k)} \ real l/real k^2})" + (\k\{3..{..exp(real k)} \ real l/real k^2})" by (intro_cong "[\\<^sub>2 measure]") auto also have "... \ (\k=3.. (\k=3.. (\k=3..k=0+3..<(k_max-3)+3. exp (- real l - real k + 2))" using k_max_ge_3 by (intro sum.cong) auto also have "... = (\k=0..k exp(-1-real l) * (1-0) / (1-exp (- 1))" - using k_max_ge_3 - by (intro mult_left_mono divide_right_mono diff_mono) auto + using k_max_ge_3 by (intro mult_left_mono divide_right_mono diff_mono) auto also have "... = exp (-real l) * (exp (-1) / (1-exp(-1)))" by (simp add:exp_diff exp_minus inverse_eq_divide) also have "... \ exp (-real l) * 1" by (intro mult_left_mono exp_ge_zero) (approximation 10) - finally show ?thesis - by simp -qed - -lemma (in expander_sample_space) deviation_bound: - fixes f :: "'a \ real" - assumes "l > 0" - assumes "\ \ exp (-real l * ln (real l)^3)" - assumes "\x. x \ 20 \ measure (sample_pmf S) {v. f v \ x} \ exp (-x * ln x^3)" - shows "measure (\ l \ S) {\. (\i i)) \ C\<^sub>1 * l} \ exp (- real l)" (is "?L \ ?R") -proof - - let ?w = "pmf_of_multiset (walks (graph_of e) l)" - - have "E.\\<^sub>a \ \" - using see_standard(1) unfolding is_expander_def e_def by simp - also have "... \ exp (- real l * ln (real l) ^ 3)" - using assms(2) by simp - finally have 0: "E.\\<^sub>a \ exp (- real l * ln (real l) ^ 3)" - by simp - - have 1: "measure (pmf_of_set (verts (graph_of e))) {v. x \ f (select S v)} \ exp (- x*ln x^3)" - (is "?L1 \ ?R1") if "x \ 20" for x - proof - - have "?L1 = measure (map_pmf (select S) (pmf_of_set {.. f v}" - using see_standard(2) unfolding e_def graph_of_def by simp - also have "... = measure (sample_pmf S) {v. x \ f v}" - unfolding sample_pmf_alt[OF sample_space_S] by simp - also have "... \ ?R1" - by (intro assms(3) that) - finally show ?thesis - by simp - qed - - have "?L = measure ?w {w. C\<^sub>1 * real l \ (\i1 * real l \ (\w\ws. f (select S w))}" - using E.walks_nonempty E.set_walks_3 atLeast0LessThan - unfolding sum_list_sum_nth by (intro measure_pmf_cong) simp - also have "... \ ?R" - by (intro E.deviation_bound assms(1) 0 1) finally show ?thesis by simp qed unbundle no_intro_cong_syntax end \ No newline at end of file diff --git a/thys/Distributed_Distinct_Elements/Pseudorandom_Combinators.thy b/thys/Distributed_Distinct_Elements/Pseudorandom_Combinators.thy --- a/thys/Distributed_Distinct_Elements/Pseudorandom_Combinators.thy +++ b/thys/Distributed_Distinct_Elements/Pseudorandom_Combinators.thy @@ -1,788 +1,747 @@ -section \Combinators for Pseudo-random Objects\ +section \Combinators for Pseudorandom Objects\ + +theory Pseudorandom_Combinators + imports + Finite_Fields.Card_Irreducible_Polynomials + Universal_Hash_Families.Carter_Wegman_Hash_Family + Distributed_Distinct_Elements_Preliminary + Universal_Hash_Families.Universal_Hash_Families_More_Product_PMF + Expander_Graphs.Expander_Graphs_Strongly_Explicit +begin + +text \Important Note: A more current version of the framework presented here is available at +@{verbatim Universal_Hash_Families.Pseudorandom_Objects}, +@{verbatim Universal_Hash_Families.Pseudorandom_Objects_Hash_Families} and +@{verbatim Expander_Graphs.Pseudorandom_Objects_Expander_Walks}. This section is left here +to prevent possible merge-conflicts.\ text \This section introduces a combinator library for pseudo-random objects. Each object can be described as a sample space, a function from an initial segment of the natural numbers that selects a value (or data structure.) Semantically they are multisets with the natural interpretation as a probability space (each element is selected with a probability proportional to its occurence count in the multiset). Operationally the selection procedure describes an algorithm to sample from the space. After general definitions and lemmas basic sample spaces, such as chosing a natural uniformly in an initial segment, a product construction the main pseudo-random objects: hash families and expander graphs are introduced. In both cases the range is itself an arbitrary sample space, such that it is for example possible to construct a pseudo-random object that samples seeds for hash families using an expander walk. The definitions @{term "\"} in Section~\ref{sec:inner_algorithm} and @{term "\"} in Section~\ref{sec:outer_algorithm} are good examples. A nice introduction into such constructions has been published by Goldreich~\cite{goldreich2011}.\ subsection \Definitions and General Lemmas\ -theory Pseudorandom_Combinators - imports - Finite_Fields.Card_Irreducible_Polynomials - Universal_Hash_Families.Carter_Wegman_Hash_Family - Distributed_Distinct_Elements_Preliminary - Universal_Hash_Families.Universal_Hash_Families_More_Product_PMF - Expander_Graphs.Expander_Graphs_Strongly_Explicit -begin - unbundle intro_cong_syntax hide_const (open) Quantum.T hide_const (open) Discrete_Topology.discrete hide_const (open) Isolated.discrete hide_const (open) Polynomial.order no_notation Digraph.dominates ("_ \\ _" [100,100] 40) record 'a sample_space = size :: "nat" sample_space_select :: "nat \ 'a" definition sample_pmf where "sample_pmf S = map_pmf (sample_space_select S) (pmf_of_set {.. size S > 0" definition "select S k = (sample_space_select S (if k < size S then k else 0))" definition "sample_set S = select S ` {.. {}" using assms unfolding sample_space_def by auto lemma sample_pmf_alt: assumes "sample_space S" shows "sample_pmf S = map_pmf (select S) (pmf_of_set {.. sample_set S" using assms unfolding sample_space_def select_def sample_set_def by auto declare [[coercion sample_pmf]] lemma integrable_sample_pmf[simp]: fixes f :: "'a \ 'c::{banach, second_countable_topology}" assumes "sample_space S" shows "integrable (measure_pmf (sample_pmf S)) f" proof - have "finite (set_pmf (pmf_of_set {..Basic sample spaces\ text \Sample space for uniformly selecting a natural number less than a given bound:\ definition nat_sample_space :: "nat \ nat sample_space" ("[_]\<^sub>S") where "nat_sample_space n = \ size = n, select = id \" lemma nat_sample_pmf: "sample_pmf ([x]\<^sub>S) = pmf_of_set {.. 0" shows "sample_space [n]\<^sub>S" using assms unfolding sample_space_def nat_sample_space_def by simp text \Sample space for the product of two sample spaces:\ definition prod_sample_space :: "'a sample_space \ 'b sample_space \ ('a \ 'b) sample_space" (infixr "\\<^sub>S" 65) where "prod_sample_space s t = \ size = size s * size t, select = (\i. (select s (i mod (size s)), select t (i div (size s)))) \" -lemma split_pmf_mod_div': - assumes "a > (0::nat)" - assumes "b > 0" - shows "map_pmf (\x. (x mod a, x div a)) (pmf_of_set {.. {.. b" using that by simp - have "x + a * y < a + a * y" - using that by simp - also have "... = a * (y+1)" - by simp - also have "... \ a * b" - by (intro mult_left_mono a) auto - finally show ?thesis by simp - qed - - hence "bij_betw (\x. (x mod a, x div a)) {.. {..The following aliases are here to prevent possible merge-conflicts. The lemmas have been +moved to @{theory "Universal_Hash_Families.Universal_Hash_Families_More_Product_PMF"}.\ - moreover have "a * b > 0" using assms by simp - hence "{.. {}" by blast - ultimately show "?thesis" - by (intro map_pmf_of_set_bij_betw) auto -qed - -lemma pmf_of_set_prod_eq: - assumes "A \ {}" "finite A" - assumes "B \ {}" "finite B" - shows "pmf_of_set (A \ B) = pair_pmf (pmf_of_set A) (pmf_of_set B)" -proof - - have "indicat_real (A \ B) (i, j) = indicat_real A i * indicat_real B j" for i j - by (cases "i \ A"; cases "j \ B") auto - hence "pmf (pmf_of_set (A \ B)) (i,j) = pmf (pair_pmf (pmf_of_set A) (pmf_of_set B)) (i,j)" - for i j using assms by (simp add:pmf_pair) - thus ?thesis - by (intro pmf_eqI) auto -qed - -lemma split_pmf_mod_div: - assumes "a > (0::nat)" - assumes "b > 0" - shows "map_pmf (\x. (x mod a, x div a)) (pmf_of_set {.. (0::nat)" assumes "b > 0" shows "map_pmf (\x. x mod a) (pmf_of_set {..x. x mod a) (pmf_of_set {.. (\x. (x mod a, x div a))) (pmf_of_set {..\<^sub>S T) = pair_pmf (sample_pmf S) (sample_pmf T)" (is "?L = ?R") proof - have size: "size S * size T > 0" using assms sample_space_def by (metis nat_0_less_mult_iff) hence a:"{.. {}" "finite {..i. (select S (i mod size S), select T (i div size S))) (pmf_of_set {..(x,y). (select S x, select T y)) \ (\i. (i mod size S, i div size S))) (pmf_of_set {..(x,y). (select S x, select T y)) (map_pmf (\i. (i mod size S, i div size S)) (pmf_of_set {..(x,y). (select S x, select T y)) (pair_pmf (pmf_of_set {..\<^sub>S T)" using assms unfolding sample_space_def prod_sample_space_def by simp lemma prod_sample_set: assumes "sample_space S" assumes "sample_space T" shows "sample_set (S \\<^sub>S T) = sample_set S \ sample_set T" (is "?L = ?R") using assms by (simp add:sample_space_alt prod_sample_pmf) subsection \Hash Families\ lemma indep_vars_map_pmf: assumes "prob_space.indep_vars (measure_pmf p) (\_. discrete) (\i \. X' i (f \)) I" shows "prob_space.indep_vars (measure_pmf (map_pmf f p)) (\_. discrete) X' I" proof - have "prob_space.indep_vars (measure_pmf p) (\_. discrete) (\i. X' i \ f) I" using assms by (simp add:comp_def) hence "prob_space.indep_vars (distr (measure_pmf p) discrete f) (\_. discrete) X' I" by (intro prob_space.indep_vars_distr prob_space_measure_pmf) auto thus ?thesis using map_pmf_rep_eq by metis qed lemma k_wise_indep_vars_map_pmf: assumes "prob_space.k_wise_indep_vars (measure_pmf p) k (\_. discrete) (\i \. X' i (f \)) I" shows "prob_space.k_wise_indep_vars (measure_pmf (map_pmf f p)) k (\_. discrete) X' I" using assms indep_vars_map_pmf unfolding prob_space.k_wise_indep_vars_def[OF prob_space_measure_pmf] by blast -lemma (in prob_space) k_wise_indep_subset: - assumes "J \ I" - assumes "k_wise_indep_vars k M' X' I" - shows "k_wise_indep_vars k M' X' J" - using assms unfolding k_wise_indep_vars_def by simp - lemma (in prob_space) k_wise_indep_vars_reindex: assumes "inj_on f I" assumes "k_wise_indep_vars k M' X' (f ` I)" shows "k_wise_indep_vars k (M' \ f) (\k \. X' (f k) \) I" proof - have "indep_vars (M' \ f) (\k. X' (f k)) J" if "finite J" "card J \ k" "J \ I" for J proof - have "f ` J \ f ` I" using that by auto moreover have "card (f ` J) \ k" using card_image_le[OF that(1)] that(2) order.trans by auto moreover have "finite (f ` J)" using that by auto ultimately have "indep_vars M' X' (f ` J)" using assms(2) unfolding k_wise_indep_vars_def by simp thus ?thesis using that assms(1) inj_on_subset by (intro indep_vars_reindex) qed thus ?thesis unfolding k_wise_indep_vars_def by simp qed definition GF :: "nat \ int set list set ring" where "GF n = (SOME F. finite_field F \ order F = n)" definition is_prime_power :: "nat \ bool" where "is_prime_power n \ (\p k. Factorial_Ring.prime p \ k > 0 \ n = p^k)" lemma assumes "is_prime_power n" shows GF: "finite_field (GF n)" "order (GF n) = n" proof - obtain p k where p_k: "Factorial_Ring.prime p" "k > 0" "n = p^k" using assms unfolding is_prime_power_def by blast have a:"\(F :: int set list set ring). finite_field F \ order F = n" using existence[OF p_k(2,1)] p_k(3) by simp show "finite_field (GF n)" "order (GF n) = n" unfolding GF_def using someI_ex[OF a] by auto qed lemma is_prime_power: "Factorial_Ring.prime p \ k > 0 \ is_prime_power (p^k)" unfolding is_prime_power_def by auto definition split_prime_power :: "nat \ (nat \ nat)" where "split_prime_power n = (THE (p, k). p^k = n \ Factorial_Ring.prime p \ k > 0)" lemma split_prime_power: assumes "Factorial_Ring.prime p" assumes "k > 0" shows "split_prime_power (p^k) = (p,k)" proof - have "q = p \ l = k" if "q^l = p^k" "Factorial_Ring.prime q" "l > 0" for q l proof - have "q dvd p^k" using that by (metis dvd_power) hence "q dvd p" using prime_dvd_power that by auto moreover have "p dvd q^l" using that assms(2) by (metis dvd_power) hence "p dvd q" using prime_dvd_power that assms by blast ultimately have a:"p = q" by auto hence "l = k" using that prime_power_inj by auto thus ?thesis using a by simp qed thus ?thesis unfolding split_prime_power_def using assms by (intro the_equality) auto qed definition \ :: "nat \ nat \ 'a sample_space \ (nat \ 'a) sample_space" where "\ k d R = ( let (p,n) = split_prime_power (size R); m = (LEAST j. d \ p^j \ j \ n); f = from_nat_into (carrier (GF (p^m))); f' = to_nat_on (carrier (GF (p^m))); g = from_nat_into (bounded_degree_polynomials (GF (p^m)) k) in \ size = p^(m*k), select = (\i x. select R ((f' (ring.hash (GF (p^m)) (f x) (g i))) mod p^n))\)" locale hash_sample_space = fixes k d p n :: nat fixes R :: "'a sample_space" assumes p_prime: "Factorial_Ring.prime p" assumes size_R: "size R = p ^ n" assumes k_gt_0: "k > 0" assumes n_gt_0: "n > 0" begin abbreviation S where "S \ \ k d R" lemma p_n_def: "(p,n) = split_prime_power (size R)" unfolding size_R by (intro split_prime_power[symmetric] n_gt_0 p_prime) definition m where "m = (LEAST j. d \ p^j \ j \ n)" definition f where "f = from_nat_into (carrier (GF (p^m)))" definition f' where "f' = to_nat_on (carrier (GF (p^m)))" lemma n_lt_m: "n \ m" and d_lt_p_m: "d \ p^m" proof - define j :: nat where "j = max n d" have "d \ 2^d" by simp also have "... \ 2^j" unfolding j_def by (intro iffD2[OF power_increasing_iff]) auto also have "... \ p^j" using p_prime prime_ge_2_nat by (intro power_mono) auto finally have "d \ p^j" by simp moreover have "n \ j" unfolding j_def by simp ultimately have "d \ p^m \ m \ n" unfolding m_def by (intro LeastI[where P="\x. d \ p^ x \ x \ n" and k="j"]) auto thus "n \ m" "d \ p^m" by auto qed lemma is_field: "finite_field (GF (p^m))" (is "?A") and field_order: "order (GF(p^m)) = p^m" (is "?B") proof - have "is_prime_power (p^m)" using n_gt_0 n_lt_m by (intro is_prime_power p_prime) auto thus "?A" "?B" using GF by auto qed interpretation cw: carter_wegman_hash_family "GF (p^m)" "k" using finite_field_def is_field finite_field_axioms_def by (intro carter_wegman_hash_familyI k_gt_0) auto lemma field_size: "cw.field_size = p^m" using field_order unfolding Coset.order_def by simp lemma f_bij: "bij_betw f {.. 0" by (metis p_prime gr0I not_prime_0 power_not_zero) lemma p_m_gt_0: "p^m > 0" by (metis p_prime gr0I not_prime_0 power_not_zero) lemma S_eq: "S = \ size = p^(m*k), sample_space_select = (\ i x. select R (f' (cw.hash (f x) (g i)) mod p^n )) \" unfolding \_def by (simp add:p_n_def[symmetric] m_def[symmetric] f_def[symmetric] g_def f'_def Let_def cw.space_def) lemma \_size: "size S > 0" unfolding S_eq using p_m_gt_0 k_gt_0 by simp lemma sample_space: "sample_space S" using \_size unfolding sample_space_def by simp lemma sample_space_R: "sample_space R" using size_R p_n_gt_0 unfolding sample_space_def by auto lemma range: "range (select S i) \ sample_set R" proof - define \ where "\ = select S i" have "\ x \ sample_set R" for x proof - have "\ \ sample_set S" unfolding \_def by (intro select_range sample_space) then obtain j where \_alt: "\ = (\x. select R (f' (cw.hash (f x) (g j)) mod p^n))" "j < p^(m*k)" unfolding sample_set_alt[OF sample_space] unfolding S_eq by auto thus "\ x \ sample_set R" unfolding \_alt by (intro select_range sample_space_R) qed thus ?thesis unfolding \_def by auto qed lemma cw_space: "map_pmf g (pmf_of_set {.. 0" using card_gt_0_iff cw.finite_space cw.non_empty_bounded_degree_polynomials by blast show ?thesis unfolding g_def using card_cw_space card_cw_space_gt_0 bij_betw_from_nat_into_finite[where S="cw.space"] by (intro map_pmf_of_set_bij_betw) auto qed lemma single: assumes "x < d" shows "map_pmf (\\. \ x) (sample_pmf S) = sample_pmf R" (is "?L = ?R") proof - have f_x_carr: "f x \ carrier (GF (p^m))" using assms d_lt_p_m by (intro bij_betw_apply[OF f_bij]) auto have "pmf (map_pmf (cw.hash (f x)) (pmf_of_set cw.space)) i = pmf (pmf_of_set (carrier (GF (p ^ m)))) i" (is "?L1 = ?R1") for i proof - have "?L1 = cw.prob (cw.hash (f x) -` {i})" unfolding cw.M_def by (simp add:pmf_map) also have "... = real (card ({i} \ carrier (GF (p ^ m)))) / real cw.field_size" using cw.prob_range[OF f_x_carr, where A="{i}" ] by (simp add:vimage_def) also have "... = ?R1" by (cases "i \ carrier (GF (p^m))", auto) finally show ?thesis by simp qed hence b: "map_pmf (cw.hash (f x)) (pmf_of_set cw.space) = pmf_of_set (carrier (GF (p^m)))" by (intro pmf_eqI) simp have c: "map_pmf f' (pmf_of_set (carrier (GF (p^m)))) = pmf_of_set {.. m" "p > 0" using n_lt_m p_prime prime_gt_0_nat by auto hence d: "map_pmf (\x. x mod p^n) (pmf_of_set {..\. \ x) \ (sample_space_select S)) (pmf_of_set {..\. sample_space_select S \ x) (pmf_of_set {.. (\x. x mod p^n) \ f' \ (cw.hash (f x)) \ g) (pmf_of_set {.._. discrete) (\i \. \ i) {.._. discrete) cw.hash (f ` {.._. discrete) (\i \. select R (f' (cw.hash i \) mod p^n)) (f ` {.._. discrete) (\i \. select R (f' (cw.hash (f i) \) mod p ^ n)) {.. map_pmf g) (pmf_of_set {.._. discrete) (\i \. \ i) {..i x. ?h (g i) x) (pmf_of_set {.._. discrete) (\i \. \ i) {.. 0" defines m_altdef: "m \ max n (nat \log p d\)" shows "size S = p^(m*k)" proof - have "real d = p powr (log p d)" using assms prime_gt_1_nat[OF p_prime] by (intro powr_log_cancel[symmetric]) auto also have "... \ p powr (nat \log p d\)" using prime_gt_1_nat[OF p_prime] by (intro powr_mono) linarith+ also have "... = p^ (nat \log p d\)" using prime_gt_1_nat[OF p_prime] by (subst powr_realpow) auto also have "... \ p^m" using prime_gt_1_nat[OF p_prime] unfolding m_altdef by (intro power_increasing Nat.of_nat_mono) auto finally have "d \ p ^ m" by simp moreover have "n \ m" unfolding m_altdef by simp moreover have "m \ y" if "d \ p ^ y" "n \ y" for y proof - have "log p d \ log p (p ^ y)" using assms prime_gt_1_nat[OF p_prime] by (intro iffD2[OF log_le_cancel_iff] that(1) Nat.of_nat_mono) auto also have "... = log p (p powr (real y))" using prime_gt_1_nat[OF p_prime] by (subst powr_realpow) auto also have "... = y" using prime_gt_1_nat[OF p_prime] by (intro log_powr_cancel) auto finally have "log p d \ y" by simp hence "nat \log p d\ \ y" by simp thus "m \ y" using that(2) unfolding m_altdef by simp qed ultimately have m_eq: "m = (LEAST j. d \ p ^ j \ n \ j)" by (intro Least_equality[symmetric]) auto show ?thesis unfolding S_eq m_def m_eq by simp qed end text \Sample space with a geometric distribution\ fun count_zeros :: "nat \ nat \ nat" where "count_zeros 0 k = 0" | "count_zeros (Suc n) k = (if odd k then 0 else 1 + count_zeros n (k div 2))" lemma count_zeros_iff: "j \ n \ count_zeros n k \ j \ 2^j dvd k" proof (induction j arbitrary: n k) case 0 then show ?case by simp next case (Suc j) then obtain n' where n_def: "n = Suc n'" using Suc_le_D by presburger show ?case using Suc unfolding n_def by auto qed lemma count_zeros_max: "count_zeros n k \ n" by (induction n arbitrary: k) auto definition \ :: "nat \ nat sample_space" where "\ n = \ size = 2^n, sample_space_select = count_zeros n \" lemma \_sample_space[simp]: "sample_space (\ n)" unfolding sample_space_def \_def by simp lemma \_range: "sample_set (\ n) \ {..n}" using count_zeros_max unfolding sample_set_alt[OF \_sample_space] unfolding \_def by auto lemma \_prob: "measure (sample_pmf (\ n)) {\. \ \ j} = of_bool (j \ n) / 2^j" (is "?L = ?R") proof (cases "j \ n") case True have a:"{..<(2^n)::nat} \ {}" by (simp add: lessThan_empty_iff) have b:"finite {..<(2^n)::nat}" by simp define f :: "nat \ nat" where "f = (\x. x * 2^j)" have d:"inj_on f {..<2^(n-j)}" unfolding f_def by (intro inj_onI) simp have e:"2^j > (0::nat)" by simp have "y \ f ` {..< 2^(n-j)} \ y \ {x. x < 2^n \ 2^j dvd x}" for y :: nat proof - have "y \ f ` {..< 2^(n-j)} \ (\x. x < 2 ^ (n - j) \ y = 2 ^ j * x)" unfolding f_def by auto also have "... \ (\x. 2^j * x < 2^j * 2 ^ (n-j) \ y = 2 ^ j * x)" using e by simp also have "... \ (\x. 2^j * x < 2^n \ y = 2 ^ j * x)" using True by (subst power_add[symmetric]) simp also have "... \ (\x. y < 2^n \ y = x * 2 ^ j)" by (metis Groups.mult_ac(2)) also have "... \ y \ {x. x < 2^n \ 2^j dvd x}" by auto finally show ?thesis by simp qed hence c:"f ` {..< 2^(n-j)} = {x. x < 2^n \ 2^j dvd x}" by auto have "?L = measure (pmf_of_set {..<2^n}) {\. count_zeros n \ \ j}" unfolding sample_pmf_def \_def by simp also have "... = real (card {x::nat. x < 2^n \ 2^j dvd x}) / 2^n" by (simp add: measure_pmf_of_set[OF a b] count_zeros_iff[OF True]) (simp add:lessThan_def Collect_conj_eq) also have "... = real (card (f ` {..<2^(n-j)})) / 2^n" by (simp add:c) also have "... = real (card ({..<(2^(n-j)::nat)})) / 2^n" by (simp add: card_image[OF d]) also have "... = ?R" using True by (simp add:frac_eq_eq power_add[symmetric]) finally show ?thesis by simp next case False have "set_pmf (sample_pmf (\ n)) \ {..n}" unfolding sample_space_alt[OF \_sample_space, symmetric] using \_range by simp hence "?L = measure (sample_pmf (\ n)) {}" using False by (intro measure_pmf_cong) auto also have "... = ?R" using False by simp finally show ?thesis by simp qed lemma \_prob_single: "measure (sample_pmf (\ n)) {j} \ 1 / 2^j" (is "?L \ ?R") proof - have "?L = measure (sample_pmf (\ n)) ({j..}-{j+1..})" by (intro measure_pmf_cong) auto also have "... = measure (sample_pmf (\ n)) {j..} - measure (sample_pmf (\ n)) {j+1..}" by (intro measure_Diff) auto also have "... = measure (sample_pmf (\ n)) {\. \ \ j}-measure (sample_pmf (\ n)) {\. \ \ (j+1)}" by (intro arg_cong2[where f="(-)"] measure_pmf_cong) auto also have "... = of_bool (j \ n) * 1 / 2 ^ j - of_bool (j + 1 \ n) / 2 ^ (j + 1)" unfolding \_prob by simp also have "... \ 1/2^j - 0" by (intro diff_mono) auto also have "... = ?R" by simp finally show ?thesis by simp qed subsection \Expander Walks\ definition \ :: "nat \ real \ 'a sample_space \ (nat \ 'a) sample_space" where "\ l \ S = (let e = see_standard (size S) \ in \ size = see_size e * see_degree e^(l-1), sample_space_select = (\i j. select S (see_sample_walk e (l-1) i ! j)) \) " locale expander_sample_space = fixes l :: nat fixes \ :: real fixes S :: "'a sample_space" assumes l_gt_0: "l > 0" assumes \_gt_0: "\ > 0" assumes sample_space_S: "sample_space S" begin definition e where "e = see_standard (size S) \" lemma size_S_gt_0: "size S > 0" using sample_space_S unfolding sample_space_def by simp lemma \_alt: "(\ l \ S) = \ size = see_size e * see_degree e^(l-1), sample_space_select = (\i j. select S (see_sample_walk e (l-1) i ! j)) \" unfolding \_def e_def[symmetric] by (simp add:Let_def) lemmas see_standard = see_standard[OF size_S_gt_0 \_gt_0] sublocale E: regular_graph "graph_of e" using see_standard(1) unfolding is_expander_def e_def by auto lemma e_deg_gt_0: "see_degree e > 0" unfolding e_def see_standard by simp lemma e_size_gt_0: "see_size e > 0" unfolding e_def see_standard using size_S_gt_0 by simp lemma sample_space: "sample_space (\ l \ S)" unfolding sample_space_def \_alt using e_size_gt_0 e_deg_gt_0 by simp lemma range: "select (\ l \ S) i j \ sample_set S" proof - define \ where "\ = select (\ l \ S) i" have "\ \ sample_set (\ l \ S)" unfolding \_def by (intro select_range sample_space) then obtain k where "\ = sample_space_select (\ l \ S) k" using sample_set_alt[OF sample_space] by auto hence "\ j \ sample_set S" unfolding \_alt using select_range[OF sample_space_S] by simp thus ?thesis unfolding \_def by simp qed lemma sample_set: "sample_set (\ l \ S) \ (UNIV \ sample_set S)" proof (rule subsetI) fix x assume "x \ sample_set (\ l \ S)" then obtain i where "x = select (\ l \ S) i" unfolding sample_set_def by auto thus "x \ UNIV \ sample_set S" using range by auto qed lemma walks: defines "R \ map_pmf (\xs i. select S (xs ! i)) (pmf_of_multiset (walks (graph_of e) l))" shows "sample_pmf (\ l \ S) = R" proof - let ?S = "{.. ?S" using e_size_gt_0 e_deg_gt_0 l_gt_0 by auto hence "?S \ {}" by blast hence "?T = pmf_of_multiset {#see_sample_walk e (l-1) i. i \# mset_set ?S#}" by (subst map_pmf_of_set) simp_all also have "... = pmf_of_multiset (walks' (graph_of e) (l-1))" by (subst see_sample_walk) auto also have "... = pmf_of_multiset (walks (graph_of e) l)" unfolding walks_def using l_gt_0 by (cases l, simp_all) finally have 0:"?T = pmf_of_multiset (walks (graph_of e) l)" by simp have "sample_pmf (\ l \ S) = map_pmf (\xs j. select S (xs ! j)) ?T" unfolding map_pmf_comp sample_pmf_def \_alt by simp also have "... = R" unfolding 0 R_def by simp finally show ?thesis by simp qed lemma uniform_property: assumes "i < l" shows "map_pmf (\w. w i) (\ l \ S) = sample_pmf S" (is "?L = ?R") proof - have "?L = map_pmf (select S) (map_pmf (\xs. (xs ! i)) (pmf_of_multiset (walks (graph_of e) l)))" unfolding walks by (simp add: map_pmf_comp) also have "... = map_pmf (select S) (pmf_of_set (verts (graph_of e)))" unfolding E.uniform_property[OF assms] by simp also have "... = ?R" unfolding sample_pmf_alt[OF sample_space_S] e_def graph_of_def using see_standard by simp finally show ?thesis by simp qed lemma size: "size (\ l \ S) = size S * (16 ^ ((l-1) * nat \ln \ / ln (19 / 20)\))" (is "?L = ?R") proof - have "?L = see_size e * see_degree e ^ (l - 1)" unfolding \_alt by simp also have "... = size S * (16 ^ nat \ln \ / ln (19 / 20)\) ^ (l - 1)" using see_standard unfolding e_def by simp also have "... = size S * (16 ^ ((l-1) * nat \ln \ / ln (19 / 20)\))" unfolding power_mult[symmetric] by (simp add:ac_simps) finally show ?thesis by simp qed end end \ No newline at end of file diff --git a/thys/Expander_Graphs/Constructive_Chernoff_Bound.thy b/thys/Expander_Graphs/Constructive_Chernoff_Bound.thy --- a/thys/Expander_Graphs/Constructive_Chernoff_Bound.thy +++ b/thys/Expander_Graphs/Constructive_Chernoff_Bound.thy @@ -1,431 +1,539 @@ subsection \Constructive Chernoff Bound\label{sec:constructive_chernoff_bound}\ text \This section formalizes Theorem~5 by Impagliazzo and Kabanets~\cite{impagliazzo2010}. It is a general result with which Chernoff-type tail bounds for various kinds of weakly dependent random variables can be obtained. The results here are general and will be applied in Section~\ref{sec:random_walks} to random walks in expander graphs.\ theory Constructive_Chernoff_Bound imports "HOL-Probability.Probability_Measure" Universal_Hash_Families.Universal_Hash_Families_More_Product_PMF Weighted_Arithmetic_Geometric_Mean.Weighted_Arithmetic_Geometric_Mean begin lemma powr_mono_rev: fixes x :: real assumes "a \ b" and "x > 0" "x \ 1" shows "x powr b \ x powr a" proof - have "x powr b = (1/x) powr (-b)" using assms by (simp add: powr_divide powr_minus_divide) also have "... \ (1/x) powr (-a)" using assms by (intro powr_mono) auto also have "... = x powr a" using assms by (simp add: powr_divide powr_minus_divide) finally show ?thesis by simp qed lemma exp_powr: "(exp x) powr y = exp (x*y)" for x :: real unfolding powr_def by simp lemma integrable_pmf_iff_bounded: fixes f :: "'a \ real" assumes "\x. x \ set_pmf p \ abs (f x) \ C" shows "integrable (measure_pmf p) f" proof - obtain x where "x \ set_pmf p" using set_pmf_not_empty by fast hence "C \ 0" using assms(1) by fastforce hence " (\\<^sup>+ x. ennreal (abs (f x)) \measure_pmf p) \ (\\<^sup>+ x. C \measure_pmf p)" using assms ennreal_le_iff by (intro nn_integral_mono_AE AE_pmfI) auto also have "... = C" by simp also have "... < Orderings.top" by simp finally have "(\\<^sup>+ x. ennreal (abs (f x)) \measure_pmf p) < Orderings.top" by simp thus ?thesis by (intro iffD2[OF integrable_iff_bounded]) auto qed lemma split_pair_pmf: "measure_pmf.prob (pair_pmf A B) S = integral\<^sup>L A (\a. measure_pmf.prob B {b. (a,b) \ S})" (is "?L = ?R") proof - have a:"integrable (measure_pmf A) (\x. measure_pmf.prob B {b. (x, b) \ S})" by (intro integrable_pmf_iff_bounded[where C="1"]) simp have "?L = (\\<^sup>+x. indicator S x \(measure_pmf (pair_pmf A B)))" by (simp add: measure_pmf.emeasure_eq_measure) also have "... = (\\<^sup>+x. (\\<^sup>+y. indicator S (x,y) \B) \A)" by (simp add: nn_integral_pair_pmf') also have "... = (\\<^sup>+x. (\\<^sup>+y. indicator {b. (x,b) \ S} y \B) \A)" by (simp add:indicator_def) also have "... = (\\<^sup>+x. (measure_pmf.prob B {b. (x,b) \ S}) \A)" by (simp add: measure_pmf.emeasure_eq_measure) also have "... = ?R" using a by (subst nn_integral_eq_integral) auto finally show ?thesis by simp qed lemma split_pair_pmf_2: "measure(pair_pmf A B) S = integral\<^sup>L B (\a. measure_pmf.prob A {b. (b,a) \ S})" (is "?L = ?R") proof - have "?L = measure (pair_pmf B A) {\. (snd \, fst \) \ S}" by (subst pair_commute_pmf) (simp add:vimage_def case_prod_beta) also have "... = ?R" unfolding split_pair_pmf by simp finally show ?thesis by simp qed definition KL_div :: "real \ real \ real" where "KL_div p q = p * ln (p/q) + (1-p) * ln ((1-p)/(1-q))" theorem impagliazzo_kabanets_pmf: fixes Y :: "nat \ 'a \ bool" fixes p :: "'a pmf" assumes "n > 0" assumes "\i. i \ {.. \ i \ {0..1}" assumes "\S. S \ {.. measure p {\. (\i \ S. Y i \)} \ (\i \ S. \ i)" defines "\_avg \ (\i\ {.. i)/n" assumes "\ \ {\_avg..1}" assumes "\_avg > 0" shows "measure p {\. real (card {i \ {..}) \ \ * n} \ exp (-real n * KL_div \ \_avg)" (is "?L \ ?R") proof - let ?n = "real n" define q :: real where "q = (if \ = 1 then 1 else (\-\_avg)/(\*(1-\_avg)))" define g where "g \ = card {i. i < n \ \Y i \}" for \ let ?E = "(\\. real (card {i. i < n \ Y i \}) \ \ * n)" let ?\ = "prod_pmf {.._. bernoulli_pmf q)" have q_range:"q \{0..1}" proof (cases "\ < 1") case True then show ?thesis using assms(5,6) unfolding q_def by (auto intro!:divide_nonneg_pos simp add:algebra_simps) next case False hence "\ = 1" using assms(5) by simp then show ?thesis unfolding q_def by simp qed have abs_pos_le_1I: "abs x \ 1" if "x \ 0" "x \ 1" for x :: real using that by auto have \_n_nonneg: "\*?n \ 0" using assms(1,5,6) by simp define r where "r = n - nat \\*n\" have 2:"(1-q) ^ r \ (1-q)^ g \" if "?E \" for \ proof - have "g \ = card ({i. i < n} - {i. i < n \ Y i \})" unfolding g_def by (intro arg_cong[where f="\x. card x"]) auto also have "... = card {i. i < n} - card {i. i < n \ Y i \}" by (subst card_Diff_subset, auto) also have "... \ card {i. i < n} - nat \\*n\" using that \_n_nonneg by (intro diff_le_mono2) simp also have "... = r" unfolding r_def by simp finally have "g \ \ r" by simp thus "(1-q) ^ r \ (1-q) ^ (g \)" using q_range by (intro power_decreasing) auto qed have \_gt_0: "\ > 0" using assms(5,6) by simp have q_lt_1: "q < 1" if "\ < 1" proof - have "\_avg < 1" using assms(5) that by simp hence "(\ - \_avg) / (\ * (1 - \_avg)) < 1" using \_gt_0 assms(6) that by (subst pos_divide_less_eq) (auto simp add:algebra_simps) thus "q < 1" unfolding q_def using that by simp qed have 5: "(\_avg * q + (1-q)) / (1-q) powr (1-\) = exp (- KL_div \ \_avg)" (is "?L1 = ?R1") if "\ < 1" proof - have \_avg_range: "\_avg \ {0<..<1}" using that assms(5,6) by simp have "?L1 = (1 - (1-\_avg) * q) / (1-q) powr (1-\)" by (simp add:algebra_simps) also have "... = (1 - (\-\_avg) / \ ) / (1-q) powr (1-\)" unfolding q_def using that \_gt_0 \_avg_range by simp also have "... = (\_avg / \) / (1-q) powr (1-\)" using \_gt_0 by (simp add:divide_simps) also have "... = (\_avg / \) * (1/(1-q)) powr (1-\)" using q_lt_1[OF that] by (subst powr_divide, simp_all) also have "... = (\_avg / \) * (1/((\*(1-\_avg)-(\-\_avg))/(\*(1-\_avg)))) powr (1-\)" using \_gt_0 \_avg_range unfolding q_def by (simp add:divide_simps) also have "... = (\_avg / \) * ((\ / \_avg) *((1-\_avg)/(1-\))) powr (1-\)" by (simp add:algebra_simps) also have "... = (\_avg / \) * (\ / \_avg) powr (1-\) *((1-\_avg)/(1-\)) powr (1-\)" using \_gt_0 \_avg_range that by (subst powr_mult, auto) also have "... = (\_avg / \) powr 1 * (\_avg / \) powr -(1-\) *((1-\_avg)/(1-\)) powr (1-\)" using \_gt_0 \_avg_range that unfolding powr_minus_divide by (simp add:powr_divide) also have "... = (\_avg / \) powr \ *((1-\_avg)/(1-\)) powr (1-\)" by (subst powr_add[symmetric]) simp also have "... = exp ( ln ((\_avg / \) powr \ *((1-\_avg)/(1-\)) powr (1-\)))" using \_gt_0 \_avg_range that by (intro exp_ln[symmetric] mult_pos_pos) auto also have "... = exp ((ln ((\_avg / \) powr \) + ln (((1 - \_avg) / (1 - \)) powr (1-\))))" using \_gt_0 \_avg_range that by (subst ln_mult) auto also have "... = exp ((\ * ln (\_avg / \) + (1 - \) * ln ((1 - \_avg) / (1 - \))))" using \_gt_0 \_avg_range that by (simp add:ln_powr algebra_simps) also have "... = exp (- (\ * ln (\ / \_avg) + (1 - \) * ln ((1 - \) / (1 - \_avg))))" using \_gt_0 \_avg_range that by (simp add: ln_div algebra_simps) also have "... = ?R1" unfolding KL_div_def by simp finally show ?thesis by simp qed have 3: "(\_avg * q + (1-q)) ^ n / (1-q) ^ r \ exp (- ?n* KL_div \ \_avg)" (is "?L1 \ ?R1") proof (cases "\ < 1") case True have "\ * real n \ 1 * real n" using True by (intro mult_right_mono) auto hence "r = real n - real (nat \\ * real n\)" unfolding r_def by (subst of_nat_diff) auto also have "... = real n - \\ * real n\" using \_n_nonneg by (subst of_nat_nat, auto) also have "... \ ?n - \ * ?n" by (intro diff_mono) auto also have "... = (1-\) *?n" by (simp add:algebra_simps) finally have r_bound: "r \ (1-\)*n" by simp have "?L1 = (\_avg * q + (1-q)) ^ n / (1-q) powr r" using q_lt_1[OF True] assms(1) by (simp add: powr_realpow) also have "... = (\_avg * q + (1-q)) powr n / (1-q) powr r" using q_lt_1[OF True] assms(6) q_range by (subst powr_realpow[symmetric], auto intro!:add_nonneg_pos) also have "... \ (\_avg * q + (1-q)) powr n / (1-q) powr ((1-\)*n)" using q_range q_lt_1[OF True] by (intro divide_left_mono powr_mono_rev r_bound) auto also have "... = (\_avg * q + (1-q)) powr n / ((1-q) powr (1-\)) powr n" unfolding powr_powr by simp also have "... = ((\_avg * q + (1-q)) / (1-q) powr (1-\)) powr n" using assms(6) q_range by (subst powr_divide) auto also have "... = exp (- KL_div \ \_avg) powr real n" unfolding 5[OF True] by simp also have "... = ?R1" unfolding exp_powr by simp finally show ?thesis by simp next case False hence \_eq_1: "\=1" using assms(5) by simp have "?L1 = \_avg ^ n" using \_eq_1 r_def q_def by simp also have "... = exp( - KL_div 1 \_avg) ^ n" unfolding KL_div_def using assms(6) by (simp add:ln_div) also have "... = ?R1" using \_eq_1 by (simp add: powr_realpow[symmetric] exp_powr) finally show ?thesis by simp qed have 4: "(1 - q) ^ r > 0" proof (cases "\ < 1") case True then show ?thesis using q_lt_1[OF True] by simp next case False hence "\=1" using assms(5) by simp hence "r=0" unfolding r_def by simp then show ?thesis by simp qed have "(1-q) ^ r * ?L = (\\. indicator {\. ?E \} \ * (1-q) ^ r \p)" by simp also have "... \ (\\. indicator {\. ?E \} \ * (1-q) ^ g \ \p)" using q_range 2 by (intro integral_mono_AE integrable_pmf_iff_bounded[where C="1"] abs_pos_le_1I mult_le_one power_le_one AE_pmfI) (simp_all split:split_indicator) also have "... = (\\. indicator {\. ?E \} \ * (\i \ {i. i < n \ \Y i \}. (1-q)) \p)" unfolding g_def using q_range by (intro integral_cong_AE AE_pmfI, simp_all add:powr_realpow) also have "... = (\\. indicator {\. ?E \} \ * measure ?\ ({j. j < n \ \Y j \} \ {False}) \p)" using q_range by (subst prob_prod_pmf') (auto simp add:measure_pmf_single) also have "... = (\\. measure ?\ {\. ?E \ \ (\i\{j. j < n \ \Y j \}. \\ i)} \p)" by (intro integral_cong_AE AE_pmfI, simp_all add:Pi_def split:split_indicator) also have "... = (\\. measure ?\ {\. ?E \ \ (\i\{.. i \ Y i \)} \p)" by (intro integral_cong_AE AE_pmfI measure_eq_AE) auto also have "... = measure (pair_pmf p ?\) {\.?E (fst \)\(\i \ {.. i \ Y i (fst \))}" unfolding split_pair_pmf by simp also have "... \ measure (pair_pmf p ?\) {\. (\i \ {j. j < n \ snd \ j}. Y i (fst \))}" by (intro pmf_mono, auto) also have "... = (\\. measure p {\. \i\{j. j< n \ \ j}. Y i \} \ ?\)" unfolding split_pair_pmf_2 by simp also have "... \ (\a. (\i \ {j. j < n \ a j}. \ i) \ ?\)" using assms(2) by (intro integral_mono_AE AE_pmfI assms(3) subsetI prod_le_1 prod_nonneg integrable_pmf_iff_bounded[where C="1"] abs_pos_le_1I) auto also have "... = (\a. (\i \ {.. i^ of_bool(a i)) \ ?\)" unfolding of_bool_def by (intro integral_cong_AE AE_pmfI) (auto simp add:if_distrib prod.If_cases Int_def) also have "... = (\ia. (\ i ^ of_bool a) \(bernoulli_pmf q)))" using assms(2) by (intro expectation_prod_Pi_pmf integrable_pmf_iff_bounded[where C="1"]) auto also have "... = (\i i * q + (1-q))" using q_range by simp also have "... = (root (card {..i i * q + (1-q))) ^ (card {.. ((\i i * q + (1-q))/card{..i i * q)/n + (1-q))^n" using assms(1) by (simp add:sum.distrib divide_simps mult.commute) also have "... = (\_avg * q + (1-q))^n" unfolding \_avg_def by (simp add: sum_distrib_right[symmetric]) finally have "(1-q) ^ r * ?L \ (\_avg * q + (1-q)) ^ n" by simp hence "?L \ (\_avg * q + (1-q)) ^ n / (1-q) ^ r" using 4 by (subst pos_le_divide_eq) (auto simp add:algebra_simps) also have "... \ ?R" by (intro 3) finally show ?thesis by simp qed text \The distribution of a random variable with a countable range is a discrete probability space, i.e., induces a PMF. Using this it is possible to generalize the previous result to arbitrary probability spaces.\ lemma (in prob_space) establish_pmf: fixes f :: "'a \ 'b" assumes rv: "random_variable discrete f" assumes "countable (f ` space M)" shows "distr M discrete f \ {M. prob_space M \ sets M = UNIV \ (AE x in M. measure M {x} \ 0)}" proof - define N where "N = {x \ space M.\ prob (f -` {f x} \ space M) \ 0}" define I where "I = {z \ (f ` space M). prob (f -` {z} \ space M) = 0}" have countable_I: " countable I" unfolding I_def by (intro countable_subset[OF _ assms(2)]) auto have disj: "disjoint_family_on (\y. f -` {y} \ space M) I" unfolding disjoint_family_on_def by auto have N_alt_def: "N = (\y \ I. f -` {y} \ space M)" unfolding N_def I_def by (auto simp add:set_eq_iff) have "emeasure M N = \\<^sup>+ y. emeasure M (f -` {y} \ space M) \count_space I" using rv countable_I unfolding N_alt_def by (subst emeasure_UN_countable) (auto simp add:disjoint_family_on_def) also have "... = \\<^sup>+ y. 0 \count_space I" unfolding I_def using emeasure_eq_measure ennreal_0 by (intro nn_integral_cong) auto also have "... = 0" by simp finally have 0:"emeasure M N = 0" by simp have 1:"N \ events" unfolding N_alt_def using rv by (intro sets.countable_UN'' countable_I) simp have " AE x in M. prob (f -` {f x} \ space M) \ 0" using 0 1 by (subst AE_iff_measurable[OF _ N_def[symmetric]]) hence " AE x in M. measure (distr M discrete f) {f x} \ 0" by (subst measure_distr[OF rv], auto) hence "AE x in distr M discrete f. measure (distr M discrete f) {x} \ 0" by (subst AE_distr_iff[OF rv], auto) thus ?thesis using prob_space_distr rv by auto qed lemma singletons_image_eq: "(\x. {x}) ` T \ Pow T" by auto theorem (in prob_space) impagliazzo_kabanets: fixes Y :: "nat \ 'a \ bool" assumes "n > 0" assumes "\i. i \ {.. random_variable discrete (Y i)" assumes "\i. i \ {.. \ i \ {0..1}" assumes "\S. S \ {.. \

(\ in M. (\i \ S. Y i \)) \ (\i \ S. \ i)" defines "\_avg \ (\i\ {.. i)/n" assumes "\ \ {\_avg..1}" "\_avg > 0" shows "\

(\ in M. real (card {i \ {..}) \ \ * n) \ exp (-real n * KL_div \ \_avg)" (is "?L \ ?R") proof - define f where "f = (\\ i. if i < n then Y i \ else False)" define g where "g = (\\ i. if i < n then \ i else False)" define T where "T = {\. (\i. \ i \ i < n)}" have g_idem: "g \ f = f" unfolding f_def g_def by (simp add:comp_def) have f_range: " f \ space M \ T" unfolding T_def f_def by simp have "T = PiE_dflt {.._. UNIV)" unfolding T_def PiE_dflt_def by auto hence "finite T" using finite_PiE_dflt by auto hence countable_T: "countable T" by (intro countable_finite) moreover have "f ` space M \ T" using f_range by auto ultimately have countable_f: "countable (f ` space M)" using countable_subset by auto have "f -` y \ space M \ events" if t:"y \ (\x. {x}) ` T" for y proof - obtain t where "y = {t}" and t_range: "t \ T" using t by auto hence "f -` y \ space M = {\ \ space M. f \ = t}" by (auto simp add:vimage_def) also have "... = {\ \ space M. (\i < n. Y i \ = t i)}" using t_range unfolding f_def T_def by auto also have "... = (\i \ {.. \ space M. Y i \ = t i})" using assms(1) by auto also have "... \ events" using assms(1,2) by (intro sets.countable_INT) auto finally show ?thesis by simp qed hence "random_variable (count_space T) f" using sigma_sets_singletons[OF countable_T] singletons_image_eq f_range by (intro measurable_sigma_sets[where \="T" and A=" (\x. {x}) ` T"]) simp_all moreover have "g \ measurable discrete (count_space T)" unfolding g_def T_def by simp ultimately have "random_variable discrete (g \ f)" by simp hence rv:"random_variable discrete f" unfolding g_idem by simp define M' :: "(nat \ bool) measure" where "M' = distr M discrete f" define \ where "\ = Abs_pmf M'" have a:"measure_pmf (Abs_pmf M') = M'" unfolding M'_def by (intro Abs_pmf_inverse[OF establish_pmf] rv countable_f) have b:"{i. (i < n \ Y i x) \ i < n} = {i. i < n \ Y i x}" for x by auto have c: "measure \ {\. \i\S. \ i} \ prod \ S" (is "?L1 \ ?R1") if "S \ {.. S \ i < n" for i using that by auto have "?L1 = measure M' {\. \i\S. \ i}" unfolding \_def a by simp also have "... = \

(\ in M. (\i \ S. Y i \))" unfolding M'_def using that d by (subst measure_distr[OF rv]) (auto simp add:f_def Int_commute Int_def) also have "... \ ?R1" using that assms(4) by simp finally show ?thesis by simp qed have "?L = measure M' {\. real (card {i. i < n \ \ i}) \ \ * n}" unfolding M'_def by (subst measure_distr[OF rv]) (auto simp add:f_def algebra_simps Int_commute Int_def b) also have "... = measure_pmf.prob \ {\. real (card {i \ {.. i}) \ \ * n}" unfolding \_def a by simp also have "... \ ?R" using assms(1,3,6,7) c unfolding \_avg_def by (intro impagliazzo_kabanets_pmf) auto finally show ?thesis by simp qed +text \Bounds and properties of @{term "KL_div"}\ + +lemma KL_div_mono_right_aux_1: + assumes "0 \ p" "p \ q" "q \ q'" "q' < 1" + shows "KL_div p q-2*(p-q)^2 \ KL_div p q'-2*(p-q')^2" +proof (cases "p = 0") + case True + define f' :: "real \ real" where "f' = (\x. 1/(1-x) - 4 * x)" + + have deriv: "((\q. ln (1/(1-q)) - 2*q^2) has_real_derivative (f' x)) (at x)" + if "x \ {q..q'}" for x + proof - + have "x \ {0..<1}" using assms that by auto + thus ?thesis unfolding f'_def by (auto intro!: derivative_eq_intros) + qed + + have deriv_nonneg: "f' x \ 0" if "x \ {q..q'}" for x + proof - + have 0:"x \ {0..<1}" using assms that by auto + have "4 * x*(1-x) = 1 - 4*(x-1/2)^2" by (simp add:power2_eq_square field_simps) + also have "... \ 1" by simp + finally have "4*x*(1-x) \ 1" by simp + hence "1/(1-x) \ 4*x" using 0 by (simp add: pos_le_divide_eq) + thus ?thesis unfolding f'_def by auto + qed + + have "ln (1 / (1 - q)) - 2 * q^2 \ ln (1 / (1 - q')) - 2 * q'^2" + using deriv deriv_nonneg by (intro DERIV_nonneg_imp_nondecreasing[OF assms(3)]) auto + thus ?thesis using True unfolding KL_div_def by simp +next + case False + hence p_gt_0: "p > 0" using assms by auto + + define f' :: "real \ real" where "f' = (\x. (1-p)/(1-x) - p/x + 4 * (p-x))" + + have deriv: "((\q. KL_div p q - 2*(p-q)^2) has_real_derivative (f' x)) (at x)" if "x \ {q..q'}" + for x + proof - + have "0 < p /x" " 0 < (1 - p) / (1 - x)" using that assms p_gt_0 by auto + thus ?thesis unfolding KL_div_def f'_def by (auto intro!: derivative_eq_intros) + qed + + have f'_part_nonneg: "(1/(x*(1-x)) - 4) \ 0" if "x \ {0<..<1}" for x :: real + proof - + have "4 * x * (1-x) = 1 - 4 * (x-1/2)^2" by (simp add:power2_eq_square algebra_simps) + also have "... \ 1" by simp + finally have "4 * x * (1-x) \ 1" by simp + hence "1/(x*(1-x)) \ 4" using that by (subst pos_le_divide_eq) auto + thus ?thesis by simp + qed + + have f'_alt: "f' x = (x-p)*(1/(x*(1-x)) - 4)" if "x \ {0<..<1}" for x + proof - + have "f' x = (x-p)/(x*(1-x)) + 4 * (p-x)" using that unfolding f'_def by (simp add:field_simps) + also have "... = (x-p)*(1/(x*(1-x)) - 4)" by (simp add:algebra_simps) + finally show ?thesis by simp + qed + + have deriv_nonneg: "f' x \ 0" if "x \ {q..q'}" for x + proof - + have "x \ {0<..<1}" using assms that p_gt_0 by auto + have "f' x =(x-p)*(1/(x*(1-x)) - 4)" using that assms p_gt_0 by (subst f'_alt) auto + also have "... \ 0" using that f'_part_nonneg assms p_gt_0 by (intro mult_nonneg_nonneg) auto + finally show ?thesis by simp + qed + + show ?thesis using deriv deriv_nonneg + by (intro DERIV_nonneg_imp_nondecreasing[OF assms(3)]) auto +qed + +lemma KL_div_swap: "KL_div (1-p) (1-q) = KL_div p q" + unfolding KL_div_def by auto + +lemma KL_div_mono_right_aux_2: + assumes "0 < q'" "q' \ q" "q \ p" "p \ 1" + shows "KL_div p q-2*(p-q)^2 \ KL_div p q'-2*(p-q')^2" +proof - + have "KL_div (1-p) (1-q)-2*((1-p)-(1-q))^2 \ KL_div (1-p) (1-q')-2*((1-p)-(1-q'))^2" + using assms by (intro KL_div_mono_right_aux_1) auto + thus ?thesis unfolding KL_div_swap by (auto simp:algebra_simps power2_commute) +qed + +lemma KL_div_mono_right_aux: + assumes "(0 \ p \ p \ q \ q \ q' \ q' < 1) \ (0 < q' \ q' \ q \ q \ p \ p \ 1)" + shows "KL_div p q-2*(p-q)^2 \ KL_div p q'-2*(p-q')^2" + using KL_div_mono_right_aux_1 KL_div_mono_right_aux_2 assms by auto + +lemma KL_div_mono_right: + assumes "(0 \ p \ p \ q \ q \ q' \ q' < 1) \ (0 < q' \ q' \ q \ q \ p \ p \ 1)" + shows "KL_div p q \ KL_div p q'" (is "?L \ ?R") +proof - + consider (a) "0 \ p" "p \ q" "q \ q'" "q' < 1" | (b) "0 < q'" "q' \ q" "q \ p" "p \ 1" + using assms by auto + hence 0: "(p - q)\<^sup>2 \ (p - q')\<^sup>2" + proof (cases) + case a + hence "(q-p)^2 \ (q' - p)^2" by auto + thus ?thesis by (simp add: power2_commute) + next + case b thus ?thesis by simp + qed + have "?L = (KL_div p q - 2*(p-q)^2) + 2 * (p-q)^2" by simp + also have "... \ (KL_div p q' - 2*(p-q')^2) + 2 * (p-q')^2" + by (intro add_mono KL_div_mono_right_aux assms mult_left_mono 0) auto + also have "... = ?R" by simp + finally show ?thesis by simp +qed + end \ No newline at end of file diff --git a/thys/Expander_Graphs/Expander_Graphs_Strongly_Explicit.thy b/thys/Expander_Graphs/Expander_Graphs_Strongly_Explicit.thy --- a/thys/Expander_Graphs/Expander_Graphs_Strongly_Explicit.thy +++ b/thys/Expander_Graphs/Expander_Graphs_Strongly_Explicit.thy @@ -1,1079 +1,1078 @@ section \Strongly Explicit Expander Graphs\label{sec:see}\ text \In some applications, representing an expander graph using a data structure (for example as an adjacency lists) would be prohibitive. For such cases strongly explicit expander graphs (SEE) are relevant. These are expander graphs, which can be represented implicitly using a function that computes for each vertex its neighbors in space and time logarithmic w.r.t. to the size of the graph. An application can for example sample a random walk, from a SEE using such a function efficiently. An example of such a graph is the Margulis construction from Section~\ref{sec:margulis}. This section presents the latter as a SEE but also shows that two graph operations that preserve the SEE property, in particular the graph power construction from Section~\ref{sec:graph_power} and a compression scheme introduced by Murtagh et al.~\cite[Theorem~20]{murtagh2019}. Combining all of the above it is possible to construct -strongly explicit expander graphs of \emph{every size} and spectral gap, which is formalized in -Subsection~\ref{sec:see_standard}.\ +strongly explicit expander graphs of \emph{every size} and spectral gap.\ theory Expander_Graphs_Strongly_Explicit imports Expander_Graphs_Power_Construction Expander_Graphs_MGG begin unbundle intro_cong_syntax no_notation Digraph.dominates ("_ \\ _" [100,100] 40) record strongly_explicit_expander = see_size :: nat see_degree :: nat see_step :: "nat \ nat \ nat" definition graph_of :: "strongly_explicit_expander \ (nat, (nat,nat) arc) pre_digraph" where "graph_of e = \ verts = {..(v, i). Arc v (see_step e i v) i) ` ({.. {.." definition "is_expander e \\<^sub>a \ regular_graph (graph_of e) \ regular_graph.\\<^sub>a (graph_of e) \ \\<^sub>a" lemma is_expander_mono: assumes "is_expander e a" "a \ b" shows "is_expander e b" using assms unfolding is_expander_def by auto lemma graph_of_finI: assumes "see_step e \ ({.. ({.. {.. verts ?G \ tail ?G a \ verts ?G" if "a \ arcs ?G" for a using assms that unfolding graph_of_def by (auto simp add:Pi_def) hence 0: "wf_digraph ?G" unfolding wf_digraph_def by auto have 1: "finite (verts ?G)" unfolding graph_of_def by simp have 2: "finite (arcs ?G)" unfolding graph_of_def by simp show ?thesis using 0 1 2 unfolding fin_digraph_def fin_digraph_axioms_def by auto qed lemma edges_graph_of: "edges(graph_of e)={#(v,see_step e i v). (v,i)\#mset_set ({..{..(v, i). Arc v (see_step e i v) i) ` ({.. {..# mset_set ( {.. {..# mset_set ({.. {..# mset_set ({.. {.. verts (graph_of e)" shows "out_degree (graph_of e) v = see_degree e" (is "?L = ?R") proof - let ?d = "see_degree e" let ?n = "see_size e" have 0: "v < ?n" using assms unfolding graph_of_def by simp have "?L = card {a. (\x\{..y\{.. arc_tail a = v}" unfolding out_degree_def out_arcs_def graph_of_def by (simp add:image_iff) also have "... = card {a. (\y\{..y. Arc v (see_step e y v) y) ` {..v \ verts ?G. {x. fst x = v \ is_arc_walk ?G v (snd x) \ length (snd x) = n})" unfolding arc_walks_def by (intro arg_cong[where f="card"]) auto also have "... = (\v \ verts ?G. card {x. fst x=v\is_arc_walk ?G v (snd x)\length (snd x) = n})" using is_arc_walk_set[where G="?G"] by (intro card_UN_disjoint ballI finite_cartesian_product subsetI finite_lists_length_eq finite_subset[where B="verts ?G \ {x. set x \ arcs ?G \ length x = n}"]) force+ also have "... = (\v \ verts ?G. out_degree (graph_power ?G n) v)" unfolding out_degree_def graph_power_def out_arcs_def arc_walks_def by (intro sum.cong arg_cong[where f="card"]) auto also have "... = (\v \ verts ?G. see_degree e^n)" by (intro sum.cong graph_power_out_degree' out_degree_see refl) (simp_all add: graph_power_def) also have "... = ?R" by (simp add:graph_of_def) finally show ?thesis by simp qed lemma regular_graph_degree_eq_see_degree: assumes "regular_graph (graph_of e)" shows "regular_graph.d (graph_of e) = see_degree e" (is "?L = ?R") proof - interpret regular_graph "graph_of e" using assms(1) by simp obtain v where v_set: "v \ verts (graph_of e)" using verts_non_empty by auto hence "?L = out_degree (graph_of e) v" using v_set reg by auto also have "... = see_degree e" by (intro out_degree_see v_set) finally show ?thesis by simp qed text \The following introduces the compression scheme, described in \cite[Theorem 20]{murtagh2019}.\ fun see_compress :: "nat \ strongly_explicit_expander \ strongly_explicit_expander" where "see_compress m e = \ see_size = m, see_degree = see_degree e * 2 , see_step = (\k v. if k < see_degree e then (see_step e k v) mod m else (if v+m < see_size e then (see_step e (k-see_degree e) (v+m)) mod m else v)) \" lemma edges_of_compress: fixes e m assumes "2*m \ see_size e" "m \ see_size e" defines "A \ {# (x mod m, y mod m). (x,y) \# edges (graph_of e)#}" defines "B \ repeat_mset (see_degree e) {# (x,x). x \# (mset_set {see_size e - m.. v \ v < ?n \ v - m = v mod m" for v using assms by (simp add: le_mod_geq) let ?M = "mset_set ({..{..<2*?d})" define M1 where "M1 = mset_set ({.. {.. {?d..<2*?d})" define M3 where "M3 = mset_set ({?n-m.. {?d..<2*?d})" have "M2 = mset_set ((\(x,y). (x-m,y+?d)) ` ({m.. {..(x,y). (x-m,y+?d)) (mset_set ({m.. {..(x,y). (x-m,y+?d)) (mset_set ({m.. {..{.. {..{?d..<2*?d} \ {?n-m..{?d..<2*?d})" using assms(1,2) by (intro arg_cong[where f="mset_set"]) auto also have "... = mset_set ({..{.. {..{?d..<2*?d}) + M3" unfolding M3_def by (intro mset_set_Union) auto also have "... = M1 + M2 + M3" unfolding M1_def M2_def by (intro arg_cong2[where f="(+)"] mset_set_Union) auto finally have 0:"mset_set ({.. {..<2*?d}) = M1 + M2 + M3" by simp have 1:"{#(v,?c i v). (v,i)\#M1#}={#(v mod m,?s i v mod m). (v,i)\#mset_set ({..{..#M2#}={#(fst x-m,?c(snd x+?d)(fst x-m)).x\#mset_set({m..{..#mset_set ({m..{..#mset_set ({m..{..#M2#}={#(v mod m,?s i v mod m). (v,i)\#mset_set ({m..{..#M3#} = {#(v,v). (v,i) \# mset_set ({?n-m.. {?d..<2*?d})#}" unfolding M3_def by (intro image_mset_cong) auto also have "... = concat_mset {#{#(x, x). xa \# mset_set {?d..<2 * ?d}#}. x \# mset_set {?n - m..# mset_set {?n - m..#M3#}=B" by simp have "A = {#(fst x mod m, ?s (snd x) (fst x) mod m). x \# mset_set ({.. {..#mset_set({..{..#mset_set({..{..# ?M #}" unfolding edges_graph_of by (simp add:ac_simps) also have "... = {#(v,?c i v). (v,i)\#M1#}+{#(v,?c i v). (v,i)\#M2#}+{#(v,?c i v). (v,i)\#M3#}" unfolding 0 image_mset_union by simp also have "...={#(v mod m,?s i v mod m). (v,i)\#mset_set({..{..{m..{..\<^sub>2 (+), \\<^sub>2 image_mset]" more: mset_set_Union[symmetric]) auto also have "...={#(v mod m,?s i v mod m). (v,i)\#mset_set({..{..\<^sub>2 (+), \\<^sub>2 image_mset, \\<^sub>1 mset_set]") auto also have "... = A + B" unfolding 4 by simp finally show ?thesis by simp qed lemma see_compress_sym: assumes "2*m \ see_size e" "m \ see_size e" assumes "symmetric_multi_graph (graph_of e)" shows "symmetric_multi_graph (graph_of (see_compress m e))" proof - let ?c = "see_compress m e" let ?d = "see_degree e" let ?G = "graph_of e" let ?H = "graph_of (see_compress m e)" interpret G:"fin_digraph" "?G" by (intro symmetric_multi_graphD2[OF assms(3)]) interpret H:"fin_digraph" "?H" by (intro graph_of_finI) simp have deg_compres: "see_degree ?c = 2 * see_degree e" by simp have 1: "card (arcs_betw ?H v w) = card (arcs_betw ?H w v)" (is "?L = ?R") if "v \ verts ?H" "w \ verts ?H" for v w proof - define b where "b =count {#(x, x). x \# mset_set {see_size e - m..# mset_set {see_size e - m..# edges (graph_of e)#} (v, w) + ?d * b" unfolding edges_of_compress[OF assms(1,2)] b_def by simp also have "... = count {#(snd e mod m, fst e mod m). e \# edges (graph_of e)#} (v, w) + ?d * b" by (subst G.edges_sym[OF assms(3),symmetric]) (simp add:image_mset.compositionality comp_def case_prod_beta) also have "... = count {#(x mod m, y mod m). (x,y) \# edges (graph_of e)#} (w, v) + ?d * b" unfolding count_mset_exp by (simp add:image_mset_filter_mset_swap[symmetric] ac_simps case_prod_beta) also have "... = count (edges ?H) (w,v)" unfolding edges_of_compress[OF assms(1,2)] b_alt_def by simp also have "... = ?R" unfolding H.count_edges by simp finally show ?thesis by simp qed show ?thesis using 1 H.fin_digraph_axioms unfolding symmetric_multi_graph_def by auto qed lemma see_compress: assumes "is_expander e \\<^sub>a" assumes "2*m \ see_size e" "m \ see_size e" shows "is_expander (see_compress m e) (\\<^sub>a/2 + 1/2)" proof - let ?H = "graph_of (see_compress m e)" let ?G = "graph_of e" let ?d = "see_degree e" let ?n = "see_size e" interpret G:regular_graph "graph_of e" using assms(1) is_expander_def by simp have d_eq: "?d = G.d" using regular_graph_degree_eq_see_degree[OF G.regular_graph_axioms] by simp have n_eq: "G.n = ?n" unfolding G.n_def by (simp add:graph_of_def) have n_gt_1: "?n > 0" using G.n_gt_0 n_eq by auto have "symmetric_multi_graph (graph_of (see_compress m e))" by (intro see_compress_sym assms(2,3) G.sym) moreover have "see_size e > 0" using G.verts_non_empty unfolding graph_of_def by auto hence "m > 0" using assms(2) by simp hence "verts (graph_of (see_compress m e)) \ {}" unfolding graph_of_def by auto moreover have 1:"0 < see_degree e" using d_eq G.d_gt_0 by auto hence "0 < see_degree (see_compress m e)" by simp ultimately have 0:"regular_graph ?H" by (intro regular_graphI[where d="see_degree (see_compress m e)"] out_degree_see) auto interpret H:regular_graph ?H using 0 by auto have "\\a\arcs ?H. f (head ?H a) * f (tail ?H a)\ \ (real G.d * G.\\<^sub>a + G.d) * (H.g_norm f)\<^sup>2" (is "?L \ ?R") if "H.g_inner f (\_. 1) = 0" for f proof - define f' where "f' x = f (x mod m)" for x let ?L1 = "G.g_norm f'^2 + \\x=?n-m.." let ?L2 = "G.g_inner f' (\_.1)^2/ G.n + \\x=?n-m.." have "?L1 = (\x\x=?n-m.." unfolding G.g_norm_sq G.g_inner_def f'_def by (simp add:graph_of_def power2_eq_square) also have "... = (\x\{0.. {m..x=?n-m..\<^sub>2 (+)]" more:sum.cong abs_of_nonneg sum_nonneg) auto also have "...=(\x=0..x=m..x=?n-m..\<^sub>2 (+)]" more:sum.union_disjoint) auto also have "... = (\x=0..x=0..x=?n-m..\<^sub>2 (+)]" more: sum.reindex_bij_betw bij_betwI[where g="(\x. x+m)"]) (auto simp add:le_mod_geq) also have "... = (\x=0..x=0..x=?n-m..x=0..x=0..x=?n-m..x=0..x\{0..{?n-m..xxx\{..{m..x=?n-m..\<^sub>2 (+), \\<^sub>2 (/), \\<^sub>2 (power)]" more: sum.cong abs_of_nonneg sum_nonneg) (auto simp add:graph_of_def) also have "...=((\xx=m..x=?n-m..\<^sub>2 (+), \\<^sub>2 (/), \\<^sub>2 (power)]" more:sum.union_disjoint) auto also have "...=((\xx=0..x=?n-m..\<^sub>2 (+), \\<^sub>2 (/), \\<^sub>2 (power)]" more:sum.reindex_bij_betw bij_betwI[where g="(\x. x+m)"]) (auto simp add:le_mod_geq) also have "...=(H.g_inner f (\_. 1) +(\xx=?n-m..\<^sub>2 (+), \\<^sub>2 (/), \\<^sub>2 (power)]" more: sum.cong) (auto simp:graph_of_def) also have "...=(\xx=?n-m.. (\xf x\ * \1\)^2/G.n + (\x=?n-m.. (L2_set f {.._. 1) {..x=?n-m..x x=?n-m..\<^sub>2 (+), \\<^sub>2 (/),\\<^sub>2 (*)]" more:real_sqrt_pow2 sum_nonneg) auto also have "... = (\x x=?n-m.. (\x x=?n-m..x\{..{?n-m.. H.g_norm f^2" by simp have "?L = \\(u, v)\#edges ?H. f v * f u\" unfolding edges_def arc_to_ends_def sum_unfold_sum_mset by (simp add:image_mset.compositionality comp_def del:see_compress.simps) also have "...=\(\x \# edges ?G.f(snd x mod m)*f(fst x mod m))+(\x=?n-m.." unfolding edges_of_compress[OF assms(2,3)] sum_unfold_sum_mset by (simp add:image_mset.compositionality sum_mset_repeat comp_def case_prod_beta power2_eq_square del:see_compress.simps) also have "...=\(\(u,v) \# edges ?G.f(u mod m)*f(v mod m))+(\x=?n-m.." by (intro_cong "[\\<^sub>1 abs, \\<^sub>2 (+), \\<^sub>1 sum_mset]" more:image_mset_cong) (simp_all add:case_prod_beta) also have "... \ \\(u,v) \# edges ?G.f(u mod m)*f(v mod m)\+\\x=?n-m.. " by (intro abs_triangle_ineq) also have "... = ?d * (\\(u,v) \# edges ?G.f(v mod m)*f(u mod m)\/G.d+\\x=?n-m..)" unfolding d_eq using G.d_gt_0 by (simp add:divide_simps ac_simps sum_distrib_left[symmetric] abs_mult) also have "... = ?d * (\G.g_inner f' (G.g_step f')\ + \\x=?n-m..)" unfolding G.g_inner_step_eq sum_unfold_sum_mset edges_def arc_to_ends_def f'_def by (simp add:image_mset.compositionality comp_def del:see_compress.simps) also have "...\ ?d * ((G.\\<^sub>a * G.g_norm f'^2 + (1-G.\\<^sub>a)*G.g_inner f' (\_.1)^2/ G.n) + \\x=?n-m..)" by (intro add_mono G.expansionD3 mult_left_mono) auto also have "... = ?d * (G.\\<^sub>a * ?L1 + (1 - G.\\<^sub>a) * ?L2)" by (simp add:algebra_simps) also have "... \ ?d * (G.\\<^sub>a * (2 * H.g_norm f^2) + (1-G.\\<^sub>a) * H.g_norm f^2)" unfolding 2 using G.\_ge_0 G.\_le_1 by (intro mult_left_mono add_mono 3) auto also have "... = ?R" unfolding d_eq[symmetric] by (simp add:algebra_simps) finally show ?thesis by simp qed hence "H.\\<^sub>a \ (G.d*G.\\<^sub>a+G.d)/H.d" using G.d_gt_0 G.\_ge_0 by (intro H.expander_intro) (auto simp del:see_compress.simps) also have "... = (see_degree e * G.\\<^sub>a + see_degree e) / (2* see_degree e)" unfolding d_eq[symmetric] regular_graph_degree_eq_see_degree[OF H.regular_graph_axioms] by simp also have "... = G.\\<^sub>a/2 + 1/2" using 1 by (simp add:field_simps) also have "... \ \\<^sub>a/2 + 1/2" using assms(1) unfolding is_expander_def by simp finally have "H.\\<^sub>a \ \\<^sub>a/2 + 1/2" by simp thus ?thesis unfolding is_expander_def using 0 by simp qed text \The graph power of a strongly explicit expander graph is itself a strongly explicit expander graph.\ fun to_digits :: "nat \ nat \ nat \ nat list" where "to_digits _ 0 _ = []" | "to_digits b (Suc l) k = (k mod b)# to_digits b l (k div b)" fun from_digits :: "nat \ nat list \ nat" where "from_digits b [] = 0" | "from_digits b (x#xs) = x + b * from_digits b xs" lemma to_from_digits: assumes "length xs = n" "set xs \ {.. {.. 0") case True have "from_digits b xs \ b^length xs - 1" using assms(2) proof (induction xs) case Nil then show ?case by simp next case (Cons a xs) have "from_digits b (a # xs) = a + b * from_digits b xs" by simp also have "... \ (b-1) + b * from_digits b xs" using Cons by (intro add_mono) auto also have "... \ (b-1) + b * (b^length xs-1)" using Cons(2) by (intro add_mono mult_left_mono Cons(1)) auto also have "... = b^length (a#xs) - 1" using True by (simp add:algebra_simps) finally show "from_digits b (a # xs) \ b^length (a#xs) - 1" by simp qed also have "... < b^n" using True assms(1) by simp finally show ?thesis by simp next case False hence "b = 0" by simp hence "xs = []" using assms(2) by simp thus ?thesis using assms(1) by simp qed lemma from_digits_inj: "inj_on (from_digits b) {xs. set xs \ {.. length xs = n}" by (intro inj_on_inverseI[where g="to_digits b n"] to_from_digits) auto fun see_power :: "nat \ strongly_explicit_expander \ strongly_explicit_expander" where "see_power l e = \ see_size = see_size e, see_degree = see_degree e^l , see_step = (\k v. foldl (\y x. see_step e x y) v (to_digits (see_degree e) l k)) \" lemma graph_power_iso_see_power: assumes "fin_digraph (graph_of e)" shows "digraph_iso (graph_power (graph_of e) n) (graph_of (see_power n e))" proof - let ?G = "graph_of e" let ?P = "graph_power (graph_of e) n" let ?H = "graph_of (see_power n e)" let ?d = "see_degree e" let ?n = "see_size e" interpret fin_digraph "(graph_of e)" using assms by auto interpret P:fin_digraph ?P by (intro graph_power_fin) define \ where "\ = (\(u,v). Arc u (arc_walk_head ?G (u, v)) (from_digits ?d (map arc_label v)))" define iso where "iso = \ iso_verts = id, iso_arcs = \, iso_head = arc_head, iso_tail = arc_tail \" have "xs = ys" if "length xs = length ys" "map arc_label xs = map arc_label ys" "is_arc_walk ?G u xs \ is_arc_walk ?G u ys \ u \ verts ?G" for xs ys u using that proof (induction xs ys arbitrary: u rule:list_induct2) case Nil then show ?case by simp next case (Cons x xs y ys) have "arc_label x = arc_label y" "u \ verts ?G" "x \ out_arcs ?G u" "y \ out_arcs ?G u" using Cons by auto hence a:"x = y" unfolding graph_of_def by auto moreover have "head ?G y \ verts ?G" using Cons by auto ultimately have "xs = ys" using Cons(3,4) by (intro Cons(2)[of "head ?G y"]) auto thus ?case using a by auto qed hence 5:"inj_on (\(u,v). (u, map arc_label v)) (arc_walks ?G n)" unfolding arc_walks_def by (intro inj_onI) auto have 3:"set (map arc_label (snd xs)) \ {.. arc_walks ?G n" for xs proof - show "length (snd xs) = n" using subsetD[OF is_arc_walk_set[where G="?G"]] that unfolding arc_walks_def by auto have "set (snd xs) \ arcs ?G" using subsetD[OF is_arc_walk_set[where G="?G"]] that unfolding arc_walks_def by auto thus "set (map arc_label (snd xs)) \ {..(u,v). (u, from_digits ?d (map arc_label v))) (arc_walks ?G n)" using inj_onD[OF 5] inj_onD[OF from_digits_inj] by (intro inj_onI) auto hence "inj_on \ (arc_walks ?G n)" unfolding inj_on_def \_def by auto hence "inj_on (iso_arcs iso) (arcs (graph_power (graph_of e) n))" unfolding iso_def graph_power_def by simp moreover have "inj_on (iso_verts iso) (verts (graph_power (graph_of e) n))" unfolding iso_def by simp moreover have "iso_verts iso (tail ?P a) = iso_tail iso (iso_arcs iso a)" "iso_verts iso (head ?P a) = iso_head iso (iso_arcs iso a)" if "a \ arcs ?P" for a unfolding \_def iso_def graph_power_def by (simp_all add:case_prod_beta) ultimately have 0:"P.digraph_isomorphism iso" unfolding P.digraph_isomorphism_def by (intro conjI ballI P.wf_digraph_axioms) auto have "card((\(u, v).(u,from_digits ?d (map arc_label v)))`arc_walks ?G n)=card(arc_walks ?G n)" by (intro card_image 7) also have "... = ?d^n * ?n" by (intro card_arc_walks_see fin_digraph_axioms) finally have "card((\(u, v).(u,from_digits ?d (map arc_label v)))`arc_walks ?G n) = ?d^n * ?n" by simp moreover have "fst v \ {.. arc_walks ?G n" for v using that unfolding arc_walks_def graph_of_def by auto moreover have "from_digits ?d (map arc_label (snd v)) < ?d ^ n" if "v \ arc_walks ?G n" for v using 3[OF that] by (intro from_digits_range) auto ultimately have 2: "{..{..(u,v). (u, from_digits ?d (map arc_label v))) ` arc_walks ?G n" by (intro card_subset_eq[symmetric]) auto have "foldl (\y x. see_step e x y) u (map arc_label w) = arc_walk_head ?G (u,w)" if "is_arc_walk ?G u w" "u \ verts ?G" for u w using that proof (induction w rule:rev_induct) case Nil then show ?case by (simp add:arc_walk_head_def) next case (snoc x xs) hence "x \ arcs ?G" by (simp add:is_arc_walk_snoc) hence "see_step e (arc_label x) (tail ?G x) = (head ?G x)" unfolding graph_of_def by (auto simp add:image_iff) also have "... = arc_walk_head (graph_of e) (u, xs @ [x])" unfolding arc_walk_head_def by simp finally have "see_step e (arc_label x) (tail ?G x) = arc_walk_head (graph_of e) (u, xs @ [x])" by simp thus ?case using snoc by (simp add:is_arc_walk_snoc) qed hence 4: "foldl (\y x. see_step e x y) (fst x) (map arc_label (snd x)) = arc_walk_head ?G x" if "x \ arc_walks (graph_of e) n" for x using that unfolding arc_walks_def by (simp add:case_prod_beta) have "arcs ?H = (\(v, i). Arc v (see_step (see_power n e) i v) i) ` ({..{..(v,w). Arc v (see_step (see_power n e) (from_digits ?d (map arc_label w)) v) (from_digits ?d (map arc_label w))) ` arc_walks ?G n" unfolding 2 image_image by (simp del:see_power.simps add: case_prod_beta comp_def) also have "... = (\(v,w). Arc v (foldl (\y x. see_step e x y) v (map arc_label w)) (from_digits ?d (map arc_label w))) ` arc_walks ?G n" using 3 by (intro image_cong refl) (simp add:case_prod_beta to_from_digits) also have "... = \ ` arc_walks ?G n" unfolding \_def using 4 by (simp add:case_prod_beta) also have "... = iso_arcs iso ` arcs ?P" unfolding iso_def graph_power_def by simp finally have "arcs ?H = iso_arcs iso ` arcs ?P" by simp moreover have "verts ?H = iso_verts iso ` verts ?P" unfolding iso_def graph_of_def graph_power_def by simp moreover have "tail ?H = iso_tail iso" unfolding iso_def graph_of_def by simp moreover have "head ?H = iso_head iso" unfolding iso_def graph_of_def by simp ultimately have 1:"?H = app_iso iso ?P" unfolding app_iso_def by (intro pre_digraph.equality) (simp_all del:see_power.simps) show ?thesis using 0 1 unfolding digraph_iso_def by auto qed lemma see_power: assumes "is_expander e \\<^sub>a" shows "is_expander (see_power n e) (\\<^sub>a^n)" proof - interpret G: "regular_graph" "graph_of e" using assms unfolding is_expander_def by auto interpret H:"regular_graph" "graph_power (graph_of e) n" by (intro G.graph_power_regular) have 0:"digraph_iso (graph_power (graph_of e) n) (graph_of (see_power n e))" by (intro graph_power_iso_see_power) auto have "regular_graph.\\<^sub>a (graph_of (see_power n e)) = H.\\<^sub>a" using H.regular_graph_iso_expansion[OF 0] by auto also have "... \ G.\\<^sub>a^n" by (intro G.graph_power_expansion) also have "... \ \\<^sub>a^n" using assms(1) unfolding is_expander_def by (intro power_mono G.\_ge_0) auto finally have "regular_graph.\\<^sub>a (graph_of (see_power n e)) \ \\<^sub>a^n" by simp moreover have "regular_graph (graph_of (see_power n e))" using H.regular_graph_iso[OF 0] by auto ultimately show ?thesis unfolding is_expander_def by auto qed text \The Margulis Construction from Section~\ref{sec:margulis} is a strongly explicit expander graph.\ definition mgg_vert :: "nat \ nat \ (int \ int)" where "mgg_vert n x = (x mod n, x div n)" definition mgg_vert_inv :: "nat \ (int \ int) \ nat" where "mgg_vert_inv n x = nat (fst x) + nat (snd x) * n" lemma mgg_vert_inv: assumes "n > 0" "x \ {0..{0.. (nat \ int)" where "mgg_arc k = (k mod 4, if k \ 4 then (-1) else 1)" definition mgg_arc_inv :: "(nat \ int) \ nat" where "mgg_arc_inv x = (nat (fst x) + 4 * of_bool (snd x < 0))" lemma mgg_arc_inv: assumes "x \ {..<4}\{-1,1}" shows "mgg_arc (mgg_arc_inv x) = x" using assms unfolding mgg_arc_def mgg_arc_inv_def by auto definition see_mgg :: "nat \ strongly_explicit_expander" where "see_mgg n = \ see_size = n^2, see_degree = 8, see_step = (\i v. mgg_vert_inv n (mgg_graph_step n (mgg_vert n v) (mgg_arc i))) \" lemma mgg_graph_iso: assumes "n > 0" shows "digraph_iso (mgg_graph n) (graph_of (see_mgg n))" proof - let ?v = "mgg_vert n" let ?vi = "mgg_vert_inv n" let ?a = "mgg_arc" let ?ai = "mgg_arc_inv" let ?G = "graph_of (see_mgg n)" let ?s = "mgg_graph_step n" define \ where "\ a = Arc (?vi (arc_tail a)) (?vi (arc_head a)) (?ai (arc_label a))" for a define iso where "iso = \ iso_verts = mgg_vert_inv n, iso_arcs = \, iso_head = arc_head, iso_tail = arc_tail \" interpret M: margulis_gaber_galil n using assms by unfold_locales have inj_vi: "inj_on ?vi (verts M.G)" unfolding mgg_graph_def mgg_vert_inv_def by (intro inj_on_inverseI[where g="mgg_vert n"]) (auto simp:mgg_vert_def) have "card (?vi ` verts M.G) = card (verts M.G)" by (intro card_image inj_vi) moreover have "card (verts M.G) = n\<^sup>2" unfolding mgg_graph_def by (auto simp:power2_eq_square) moreover have "mgg_vert_inv n x \ {..2}" if "x \ verts M.G" for x proof - have "mgg_vert_inv n x = nat (fst x) + nat (snd x) * n" unfolding mgg_vert_inv_def by simp also have "... \ (n-1) + (n-1) * n" using that unfolding mgg_graph_def by (intro add_mono mult_right_mono) auto also have "... = n * n - 1" using assms by (simp add:algebra_simps) also have "... < n^2" using assms by (simp add: power2_eq_square) finally have "mgg_vert_inv n x < n^2" by simp thus ?thesis by simp qed ultimately have 0:"{.. {-1,1})" unfolding mgg_arc_inv_def by (intro inj_onI) auto have "card (?ai ` ({..<4} \ {- 1, 1})) = card ({..<4::nat} \ {-1,1::int})" by (intro card_image inj_ai) hence 1:"{..<8} = ?ai ` ({..<4} \ {-1,1})" by (intro card_subset_eq[symmetric] image_subsetI) (auto simp add:mgg_arc_inv_def) have "arcs ?G = (\(v, i). Arc v (?vi (?s (?v v) (?a i))) i) ` ({..2} \ {..<8})" by (simp add:see_mgg_def graph_of_def) also have "... = (\(v, i). Arc (?vi v) (?vi (?s (?v (?vi v)) (?a (?ai i)))) (?ai i)) ` (verts M.G \ ({..<4} \ {-1,1}))" unfolding 0 1 mgg_arc_inv by (auto simp add:image_iff) also have "... = (\(v, i). Arc (?vi v) (?vi (?s v i)) (?ai i)) ` (verts M.G \ ({..<4} \ {-1,1}))" using mgg_vert_inv[OF assms] mgg_arc_inv unfolding mgg_graph_def by (intro image_cong) auto also have "... = (\ \ (\(t, l). Arc t (?s t l) l)) ` (verts M.G \ ({..<4} \ {-1,1}))" unfolding \_def by (intro image_cong refl) ( simp add:comp_def case_prod_beta ) also have "... = \ ` arcs M.G" unfolding mgg_graph_def by (simp add:image_image) also have "... = iso_arcs iso ` arcs (mgg_graph n)" unfolding iso_def by simp finally have "arcs (graph_of (see_mgg n)) = iso_arcs iso ` arcs (mgg_graph n)" by simp moreover have "verts ?G = iso_verts iso ` verts (mgg_graph n)" unfolding iso_def graph_of_def see_mgg_def using 0 by simp moreover have "tail ?G = iso_tail iso" unfolding iso_def graph_of_def by simp moreover have "head ?G = iso_head iso" unfolding iso_def graph_of_def by simp ultimately have 0:"?G = app_iso iso (mgg_graph n)" unfolding app_iso_def by (intro pre_digraph.equality) simp_all have "inj_on \ (arcs M.G)" proof (rule inj_onI) fix x y assume assms': "x \ arcs M.G" "y \ arcs M.G" "\ x = \ y" have "?vi (head M.G x) = ?vi (head M.G y)" using assms'(3) unfolding \_def mgg_graph_def by auto hence "head M.G x = head M.G y" using assms'(1,2) by (intro inj_onD[OF inj_vi]) auto hence "arc_head x = arc_head y" unfolding mgg_graph_def by simp moreover have "?vi (tail M.G x) = ?vi (tail M.G y)" using assms'(3) unfolding \_def mgg_graph_def by auto hence "tail M.G x = tail M.G y" using assms'(1,2) by (intro inj_onD[OF inj_vi]) auto hence "arc_tail x = arc_tail y" unfolding mgg_graph_def by simp moreover have "?ai (arc_label x) = ?ai (arc_label y)" using assms'(3) unfolding \_def by auto hence "arc_label x = arc_label y" using assms'(1,2) unfolding mgg_graph_def by (intro inj_onD[OF inj_ai]) (auto simp del:mgg_graph_step.simps) ultimately show "x = y" by (intro arc.expand) auto qed hence "inj_on (iso_arcs iso) (arcs M.G)" unfolding iso_def by simp moreover have "inj_on (iso_verts iso) (verts M.G)" using inj_vi unfolding iso_def by simp moreover have "iso_verts iso (tail M.G a) = iso_tail iso (iso_arcs iso a)" "iso_verts iso (head M.G a) = iso_head iso (iso_arcs iso a)" if "a \ arcs M.G" for a unfolding iso_def \_def mgg_graph_def by auto ultimately have 1:"M.digraph_isomorphism iso" unfolding M.digraph_isomorphism_def by (intro conjI ballI M.wf_digraph_axioms) auto show ?thesis unfolding digraph_iso_def using 0 1 by auto qed lemma see_mgg: assumes "n > 0" shows "is_expander (see_mgg n) (5* sqrt 2 / 8)" proof - interpret G: "margulis_gaber_galil" "n" using assms by unfold_locales auto note 0 = mgg_graph_iso[OF assms] have "regular_graph.\\<^sub>a (graph_of (see_mgg n)) = G.\\<^sub>a" using G.regular_graph_iso_expansion[OF 0] by auto also have "... \ (5* sqrt 2 / 8)" using G.mgg_numerical_radius unfolding G.MGG_bound_def by simp finally have "regular_graph.\\<^sub>a (graph_of (see_mgg n)) \ (5* sqrt 2 / 8)" by simp moreover have "regular_graph (graph_of (see_mgg n))" using G.regular_graph_iso[OF 0] by auto ultimately show ?thesis unfolding is_expander_def by auto qed text \Using all of the above it is possible to construct strongly explicit expanders of every size and spectral gap with asymptotically optimal degree.\ definition see_standard_aux where "see_standard_aux n = see_compress n (see_mgg (nat \sqrt n\))" lemma see_standard_aux: assumes "n > 0" shows "is_expander (see_standard_aux n) ((8+5 * sqrt 2) / 16)" (is "?A") "see_degree (see_standard_aux n) = 16" (is "?B") "see_size (see_standard_aux n) = n" (is "?C") proof - have 2:"sqrt (real n) > -1" by (rule less_le_trans[where y="0"]) auto have 0:"real n \ of_int \sqrt (real n)\^2" by (simp add:sqrt_le_D) consider (a) "n = 1" | (b) "n \ 2 \ n \ 4" | (c) "n \ 5 \ n \ 9" | (d) "n \ 10" using assms by linarith hence 1:"of_int \sqrt (real n)\^2 \ 2 * real n" proof (cases) case a then show ?thesis by simp next case b hence "real_of_int \sqrt (real n)\^2 \ of_int \sqrt (real 4)\^2" using 2 by (intro power_mono iffD2[OF of_int_le_iff] ceiling_mono iffD2[OF real_sqrt_le_iff]) auto also have "... = 2 * real 2" by simp also have "... \ 2 * real n" using b by (intro mult_left_mono) auto finally show ?thesis by simp next case c hence "real_of_int \sqrt (real n)\^2 \ of_int \sqrt (real 9)\^2" using 2 by (intro power_mono iffD2[OF of_int_le_iff] ceiling_mono iffD2[OF real_sqrt_le_iff]) auto also have "... = 9" by simp also have "... \ 2 * real 5" by simp also have "... \ 2 * real n" using c by (intro mult_left_mono) auto finally show ?thesis by simp next case d have "real_of_int \sqrt (real n)\^2 \ (sqrt (real n)+1)^2" using 2 by (intro power_mono) auto also have "... = real n + sqrt (4 * real n + 0) + 1" using real_sqrt_pow2 by (simp add:power2_eq_square algebra_simps real_sqrt_mult) also have "... \ real n + sqrt (4 * real n + (real n * (real n - 6) + 1)) + 1" using d by (intro add_mono iffD2[OF real_sqrt_le_iff]) auto also have "... = real n + sqrt ((real n-1)^2) + 1" by (intro_cong "[\\<^sub>2 (+), \\<^sub>1 sqrt]") (auto simp add:power2_eq_square algebra_simps) also have "... = 2 * real n" using d by simp finally show ?thesis by simp qed have "real (nat \sqrt (real n)\^2) = of_int \sqrt (real n)\^2" unfolding of_nat_power using 2 by (simp add:not_less) also have "... \ {real n..2 * real n}" using 0 1 by auto also have "... = {real n..real (2*n)}" by simp finally have "real (nat \sqrt (real n)\^2) \ {real n..real (2*n)}" by simp hence "nat \sqrt (real n)\^2 \ {n..2*n}" by (simp del:of_nat_mult) hence "see_size (see_mgg (nat \sqrt (real n)\)) \ {n..2*n}" by (simp add:see_mgg_def) moreover have "sqrt (real n) > 0" using assms by simp hence "0 < nat \sqrt (real n)\" by simp ultimately have "is_expander (see_standard_aux n) ((5* sqrt 2 / 8)/2 + 1/2)" unfolding see_standard_aux_def by (intro see_compress see_mgg) auto thus ?A by (auto simp add:field_simps) show ?B unfolding see_standard_aux_def by (simp add:see_mgg_def) show ?C unfolding see_standard_aux_def by simp qed definition see_standard_power where "see_standard_power x = (if x \ (0::real) then 0 else nat \ln x / ln 0.95\)" lemma see_standard_power: assumes "\\<^sub>a > 0" shows "0.95^(see_standard_power \\<^sub>a) \ \\<^sub>a" (is "?L \ ?R") proof (cases "\\<^sub>a \ 1") case True hence "0 \ ln \\<^sub>a / ln 0.95" using assms by (intro divide_nonpos_neg) auto hence 1:"0 \ \ln \\<^sub>a / ln 0.95\" by simp have "?L = 0.95^nat \ln \\<^sub>a / ln 0.95\" using assms unfolding see_standard_power_def by simp also have "... = 0.95 powr (of_nat (nat (\ln \\<^sub>a / ln 0.95\)))" by (subst powr_realpow) auto also have "... = 0.95 powr \ln \\<^sub>a / ln 0.95\" using 1 by (subst of_nat_nat) auto also have "... \ 0.95 powr (ln \\<^sub>a / ln 0.95)" by (intro powr_mono_rev) auto also have "... = ?R" using assms unfolding powr_def by simp finally show ?thesis by simp next case False hence "ln \\<^sub>a / ln 0.95 \ 0" by (subst neg_divide_le_eq) auto hence "see_standard_power \\<^sub>a = 0" unfolding see_standard_power_def by simp then show ?thesis using False by simp qed lemma see_standard_power_eval[code]: "see_standard_power x = (if x \ 0 \ x \ 1 then 0 else (1+see_standard_power (x/0.95)))" proof (cases "x \ 0 \ x \ 1") case True have "ln x / ln (19 / 20) \ 0" if "x > 0" proof - have "x \ 1" using that True by auto thus ?thesis by (intro divide_nonneg_neg) auto qed then show ?thesis using True unfolding see_standard_power_def by simp next case False hence x_range: "x > 0" "x < 1" by auto have "ln (x / 0.95) < ln (1/0.95)" using x_range by (intro iffD2[OF ln_less_cancel_iff]) auto also have "... = - ln 0.95" by (subst ln_div) auto finally have "ln (x / 0.95) < - ln 0.95" by simp hence 0: "-1 < ln (x / 0.95) / ln 0.95" by (subst neg_less_divide_eq) auto have "see_standard_power x = nat \ln x / ln 0.95\" using x_range unfolding see_standard_power_def by simp also have "... = nat \ln (x/0.95) / ln 0.95 + 1\" by (subst ln_div[OF x_range(1)]) (simp_all add:field_simps ) also have "... = nat (\ln (x/0.95) / ln 0.95\+1)" by (intro arg_cong[where f="nat"]) simp also have "... = 1 + nat \ln (x/0.95) / ln 0.95\" using 0 by (subst nat_add_distrib) auto also have "... = (if x \ 0 \ 1 \ x then 0 else 1 + see_standard_power (x/0.95))" unfolding see_standard_power_def using x_range by auto finally show ?thesis by simp qed definition see_standard :: "nat \ real \ strongly_explicit_expander" where "see_standard n \\<^sub>a = see_power (see_standard_power \\<^sub>a) (see_standard_aux n)" theorem see_standard: assumes "n > 0" "\\<^sub>a > 0" shows "is_expander (see_standard n \\<^sub>a) \\<^sub>a" and "see_size (see_standard n \\<^sub>a) = n" and "see_degree (see_standard n \\<^sub>a) = 16 ^ (nat \ln \\<^sub>a / ln 0.95\)" (is "?C") proof - have 0:"is_expander (see_standard_aux n) 0.95" by (intro see_standard_aux(1)[OF assms(1)] is_expander_mono[where a="(8+5 * sqrt 2) / 16"]) (approximation 10) show "is_expander (see_standard n \\<^sub>a) \\<^sub>a" unfolding see_standard_def by (intro see_power 0 is_expander_mono[where a="0.95^(see_standard_power \\<^sub>a)"] see_standard_power assms(2)) show "see_size (see_standard n \\<^sub>a) = n" unfolding see_standard_def using see_standard_aux[OF assms(1)] by simp have "see_degree (see_standard n \\<^sub>a) = 16 ^ (see_standard_power \\<^sub>a)" unfolding see_standard_def using see_standard_aux[OF assms(1)] by simp also have "... = 16 ^ (nat \ln \\<^sub>a / ln 0.95\)" unfolding see_standard_power_def using assms(2) by simp finally show ?C by simp qed fun see_sample_walk :: "strongly_explicit_expander \ nat \ nat \ nat list" where "see_sample_walk e 0 x = [x]" | "see_sample_walk e (Suc l) x = (let w = see_sample_walk e l (x div (see_degree e)) in w@[see_step e (x mod (see_degree e)) (last w)])" theorem see_sample_walk: fixes e l assumes "fin_digraph (graph_of e)" defines "r \ see_size e * see_degree e ^l" shows "{# see_sample_walk e l k. k \# mset_set {.. {j * ?d..<(j + 1) * ?d} = {}" if "i \ j" for i j using that index_div_eq by blast have 2:"vertices_from ?G x = {# see_step e i x. i \# mset_set {.. verts ?G" for x proof - have "x < ?n" using that unfolding graph_of_def by simp hence 1:"out_arcs ?G x = (\i. Arc x (see_step e i x) i) ` {..# mset_set (out_arcs ?G x) #}" unfolding verts_from_alt by (simp add:graph_of_def) also have "... = {# arc_head a. a \# {# Arc x (see_step e i x) i. i \# mset_set {..ww < r. card {w * ?d..<(w + 1) *?d})" using 1 by (intro card_UN_disjoint) auto also have "... = r * ?d" by simp finally have "card (\w ?d * r" if "z < r" for z proof - have "?d + z * ?d = ?d * (z + 1)" by simp also have "... \ ?d * r" using that by (intro mult_left_mono) auto finally show ?thesis by simp qed ultimately have 0: "(\w# mset_set {..# mset_set {..# mset_set (\w (\w. {w * ?d..<(w + 1) * ?d})) (mset_set {..#mset_set {w*?d..<(w+1)*?d}#}. w\#mset_set {..#mset_set ((+)(w*?d)`{..#mset_set {..\<^sub>1 concat_mset, \\<^sub>2 image_mset, \\<^sub>1 mset_set]" more:ext) (simp add: atLeast0LessThan[symmetric]) also have "... = concat_mset {#{#?w (l+1) i. i\#image_mset ((+) (w*?d)) (mset_set {..#mset_set {..\<^sub>1 concat_mset, \\<^sub>2 image_mset]" more:image_mset_cong image_mset_mset_set[symmetric] inj_onI) auto also have "... = concat_mset {#{#?w (l+1) (w*?d+i).i\#mset_set {..#mset_set {..#mset_set {..#mset_set {..\<^sub>1 concat_mset]" more:image_mset_cong) (simp add:Let_def) also have "... = concat_mset {#{#w@[see_step e i (last w)].i\#mset_set {..#walks' ?G l#}" unfolding r_def Suc[symmetric] image_mset.compositionality comp_def by simp also have "... = concat_mset {#{#w@[x].x\#{# see_step e i (last w). i\#mset_set {..# walks' ?G l#}" unfolding image_mset.compositionality comp_def by simp also have "... = concat_mset {#{#w@[x].x\#vertices_from ?G (last w)#}. w \# walks' ?G l#}" using last_in_set set_walks_2(1,2) by (intro_cong "[\\<^sub>1 concat_mset, \\<^sub>2 image_mset]" more:image_mset_cong 2[symmetric]) blast also have "... = walks' (graph_of e) (l+1)" by (simp add:image_mset.compositionality comp_def) finally show ?case by simp qed unbundle no_intro_cong_syntax end diff --git a/thys/Expander_Graphs/Pseudorandom_Objects_Expander_Walks.thy b/thys/Expander_Graphs/Pseudorandom_Objects_Expander_Walks.thy new file mode 100644 --- /dev/null +++ b/thys/Expander_Graphs/Pseudorandom_Objects_Expander_Walks.thy @@ -0,0 +1,210 @@ +section \Expander Walks as Pseudorandom Objects\ + +theory Pseudorandom_Objects_Expander_Walks + imports + Universal_Hash_Families.Pseudorandom_Objects + Expander_Graphs.Expander_Graphs_Strongly_Explicit +begin + +hide_const (open) Quantum.T + +definition expander_pro :: + "nat \ real \ ('a,'b) pseudorandom_object_scheme \ (nat \ 'a) pseudorandom_object" + where "expander_pro l \ S = ( + let e = see_standard (pro_size S) \ in + \ pro_last = see_size e * see_degree e^(l-1) - 1, + pro_select = (\i j. pro_select S (see_sample_walk e (l-1) i ! j mod pro_size S)) \ + )" + +context + fixes l :: nat + fixes \ :: real + fixes S :: "('a,'b) pseudorandom_object_scheme" + assumes l_gt_0: "l > 0" + assumes \_gt_0: "\ > 0" +begin + +private definition e where "e = see_standard (pro_size S) \" + +private lemma expander_pro_alt: "expander_pro l \ S = \ pro_last = see_size e * see_degree e^(l-1) - 1, + pro_select = (\i j. pro_select S (see_sample_walk e (l-1) i ! j mod pro_size S)) \" + unfolding expander_pro_def e_def[symmetric] by (auto simp:Let_def) + +private lemmas see_standard = see_standard [OF pro_size_gt_0[where S="S"] \_gt_0] + +interpretation E: regular_graph "graph_of e" + using see_standard(1) unfolding is_expander_def e_def by auto + +private lemma e_deg_gt_0: "see_degree e > 0" + unfolding e_def see_standard by simp + +private lemma e_size_gt_0: "see_size e > 0" + unfolding e_def using see_standard pro_size_gt_0 by simp + +private lemma expander_sample_size: "pro_size (expander_pro l \ S) = see_size e * see_degree e^(l-1)" + using e_deg_gt_0 e_size_gt_0 unfolding expander_pro_alt pro_size_def by simp + +private lemma sample_pro_expander_walks: + defines "R \ map_pmf (\xs i. pro_select S (xs ! i mod pro_size S)) + (pmf_of_multiset (walks (graph_of e) l))" + shows "sample_pro (expander_pro l \ S) = R" +proof - + let ?S = "{.. ?S" + using e_size_gt_0 e_deg_gt_0 by auto + hence "?S \ {}" + by blast + hence "?T = pmf_of_multiset {#see_sample_walk e (l-1) i. i \# mset_set ?S#}" + by (subst map_pmf_of_set) simp_all + also have "... = pmf_of_multiset (walks' (graph_of e) (l-1))" + by (subst see_sample_walk) auto + also have "... = pmf_of_multiset (walks (graph_of e) l)" + unfolding walks_def using l_gt_0 by (cases l, simp_all) + finally have 0:"?T = pmf_of_multiset (walks (graph_of e) l)" + by simp + + have "sample_pro (expander_pro l \ S) = map_pmf (\xs j. pro_select S (xs ! j mod pro_size S)) ?T" + unfolding expander_sample_size sample_pro_alt unfolding map_pmf_comp expander_pro_alt by simp + also have "... = R" unfolding 0 R_def by simp + finally show ?thesis by simp +qed + +lemma expander_uniform_property: + assumes "i < l" + shows "map_pmf (\w. w i) (sample_pro (expander_pro l \ S)) = sample_pro S" (is "?L = ?R") +proof - + have "?L = map_pmf (\x. pro_select S (x mod pro_size S)) (map_pmf (\xs. (xs ! i)) (pmf_of_multiset (walks (graph_of e) l)))" + unfolding sample_pro_expander_walks by (simp add: map_pmf_comp) + also have "... = map_pmf (\x. pro_select S (x mod pro_size S)) (pmf_of_set (verts (graph_of e)))" + unfolding E.uniform_property[OF assms] by simp + also have "... = ?R" + using pro_size_gt_0 unfolding sample_pro_alt + by (intro map_pmf_cong) (simp_all add:e_def graph_of_def see_standard select_def) + finally show ?thesis + by simp +qed + +lemma expander_kl_chernoff_bound: + assumes "measure (sample_pro S) {w. T w} \ \" + assumes "\ \ 1" "\ + \ * (1-\) \ \" "\ \ 1" + shows "measure (sample_pro (expander_pro l \ S)) {w. real (card {i \ {.. \*l} + \ exp (- real l * KL_div \ (\ + \*(1-\)))" (is "?L \ ?R") +proof (cases "measure (sample_pro S) {w. T w} > 0") + case True + let ?w = "pmf_of_multiset (walks (graph_of e) l)" + define V where "V = {v\ verts (graph_of e). T (pro_select S v)} " + define \ where "\ = measure (sample_pro S) {w. T w}" + + have \_gt_0: "\ > 0" unfolding \_def using True by simp + have \_le_1: "\ \ 1" unfolding \_def by simp + have \_le_\: "\ \ \" unfolding \_def using assms(1) by simp + + have 0: "card {i \ {.. {.. V}" + if "w \ set_pmf (pmf_of_multiset (walks (graph_of e) l))" for w + proof - + have a0: "w \# walks (graph_of e) l" using that E.walks_nonempty by simp + have a1:"w ! i \ verts (graph_of e)" if "i < l" for i + using that E.set_walks_3[OF a0] by auto + moreover have "w ! i mod pro_size S = w ! i" if "i < l" for i + using a1[OF that] see_standard(2) e_def by (simp add:graph_of_def) + ultimately show ?thesis + unfolding V_def + by (intro arg_cong[where f="card"] restr_Collect_cong) auto + qed + + have 1:"E.\\<^sub>a \ \" + using see_standard(1) unfolding is_expander_def e_def by simp + + have 2: "V \ verts (graph_of e)" + unfolding V_def by simp + + have "\ = measure (pmf_of_set {.._def sample_pro_alt by simp + also have "... = real (card ({v\{.._eq: "\ = real (card V) / card (verts (graph_of e))" + by simp + + have 3: "0 < \ + E.\\<^sub>a * (1 - \)" + using \_le_1 by (intro add_pos_nonneg \_gt_0 mult_nonneg_nonneg E.\_ge_0) auto + + have "\ + E.\\<^sub>a * (1 - \) = \ * (1 - E.\\<^sub>a) + E.\\<^sub>a" by (simp add:algebra_simps) + also have "... \ \ * (1- E.\\<^sub>a) + E.\\<^sub>a" using E.\_le_1 + by (intro add_mono mult_right_mono \_le_\) auto + also have "... = \ + E.\\<^sub>a * (1 - \)" by (simp add:algebra_simps) + also have "... \ \ + \ * (1 - \)" using assms(4) by (intro add_mono mult_right_mono 1) auto + finally have 4: "\ + E.\\<^sub>a * (1 - \) \ \ + \ * (1 - \)" by simp + + have 5: "\ + E.\\<^sub>a*(1-\) \ \" using 4 assms(3) by simp + + have "?L = measure ?w {y. \ * real l \ real (card {i \ {.. * real l \ real (card {i \ {.. V})}" + using 0 by (intro measure_pmf_cong) (simp) + also have "... \ exp (- real l * KL_div \ (\ + E.\\<^sub>a*(1-\)) )" + using assms(2) 3 5 unfolding \_eq by (intro E.kl_chernoff_property l_gt_0 2) auto + also have "... \ exp (- real l * KL_div \ (\ + \*(1-\)))" + using l_gt_0 by (intro iffD2[OF exp_le_cancel_iff] iffD2[OF mult_le_cancel_left_neg] + KL_div_mono_right[OF disjI2] conjI 3 4 assms(2,3)) auto + finally show ?thesis by simp +next + case False + hence 0:"measure (sample_pro S) {w. T w} = 0" using zero_less_measure_iff by blast + hence 1:"T w = False" if "w \ pro_set S" for w using that measure_pmf_posI by force + + have "\ + \ * (1-\) > 0" + proof (cases "\ = 0") + case True then show ?thesis using \_gt_0 by auto + next + case False + then show ?thesis using assms(1,4) 0 \_gt_0 + by (intro add_pos_nonneg mult_nonneg_nonneg) simp_all + qed + hence "\ > 0" using assms(3) by auto + hence 2:"\*real l > 0" using l_gt_0 by simp + + let ?w = "pmf_of_multiset (walks (graph_of e) l)" + + have "?L = measure ?w {y. \*real l\ card {i \ {.. ?R" by simp + finally show ?thesis by simp +qed + +lemma expander_pro_size: + "pro_size (expander_pro l \ S) = pro_size S * (16 ^ ((l-1) * nat \ln \ / ln (19 / 20)\))" + (is "?L = ?R") +proof - + have "?L = see_size e * see_degree e ^ (l - 1)" + unfolding expander_sample_size by simp + also have "... = pro_size S * (16 ^ nat \ln \ / ln (19 / 20)\) ^ (l - 1)" + using see_standard unfolding e_def by simp + also have "... = pro_size S * (16 ^ ((l-1) * nat \ln \ / ln (19 / 20)\))" + unfolding power_mult[symmetric] by (simp add:ac_simps) + finally show ?thesis + by simp +qed + +lemma expander_pro_range: "pro_select (expander_pro l \ S) i j \ pro_set S" + unfolding expander_pro_alt by (simp add:pro_select_in_set) + +end + +bundle expander_pseudorandom_object_notation +begin +notation expander_pro ("\") +end + +bundle no_expander_pseudorandom_object_notation +begin +no_notation expander_pro ("\") +end + +unbundle expander_pseudorandom_object_notation + +end \ No newline at end of file diff --git a/thys/Expander_Graphs/ROOT b/thys/Expander_Graphs/ROOT --- a/thys/Expander_Graphs/ROOT +++ b/thys/Expander_Graphs/ROOT @@ -1,26 +1,27 @@ chapter AFP session Expander_Graphs = "HOL-Probability" + options [timeout = 1200] sessions Graph_Theory Perron_Frobenius Commuting_Hermitian Weighted_Arithmetic_Geometric_Mean Universal_Hash_Families theories Constructive_Chernoff_Bound Expander_Graphs_Algebra Expander_Graphs_Cheeger_Inequality Expander_Graphs_Definition Expander_Graphs_Eigenvalues Expander_Graphs_MGG Expander_Graphs_Multiset_Extras Expander_Graphs_Power_Construction Expander_Graphs_Strongly_Explicit Expander_Graphs_TTS Expander_Graphs_Walks Extra_Congruence_Method + Pseudorandom_Objects_Expander_Walks document_files "root.tex" "root.bib" diff --git a/thys/Finite_Fields/Find_Irreducible_Poly.thy b/thys/Finite_Fields/Find_Irreducible_Poly.thy --- a/thys/Finite_Fields/Find_Irreducible_Poly.thy +++ b/thys/Finite_Fields/Find_Irreducible_Poly.thy @@ -1,794 +1,799 @@ section \Algorithms for finding irreducible polynomials\ theory Find_Irreducible_Poly imports Finite_Fields_Poly_Factor_Ring_Code Rabin_Irreducibility_Test_Code Probabilistic_While.While_SPMF Card_Irreducible_Polynomials Executable_Randomized_Algorithms.Randomized_Algorithm "HOL-Library.Log_Nat" begin hide_const (open) Numeral_Type.mod_ring hide_const (open) Polynomial.degree hide_const (open) Polynomial.order text \Enumeration of the monic polynomials in lexicographic order.\ definition enum_monic_poly :: "('a,'b) idx_ring_enum_scheme \ nat \ nat \ 'a list" where "enum_monic_poly A d i = 1\<^sub>C\<^bsub>A\<^esub>#[ idx_enum A (nth_digit i j (idx_size A)). j \ rev [0..C R" "enum\<^sub>C R" shows "bij_betw (enum_monic_poly R d) {.. degree f = d}" proof - let ?f = " (\x. 1\<^sub>C\<^bsub>R\<^esub> # map (\j. idx_enum R (x j)) (rev [ 0..C_def by auto have 1:"enum_monic_poly R d = ?f \ (\v. \x\{..x. 1\<^sub>C\<^bsub>R\<^esub> # map x (rev [ 0.. (\x. \i\{..x. \\<^bsub>ring_of R\<^esub>#map x (rev [0..x. \\<^bsub>ring_of R\<^esub>#x) \rev\ (\x. map x [0..\<^bsub>?R\<^esub>) {x. set x\carrier ?R\length x=d} {f. monic_poly ?R f \ degree f=d}" using list.collapse unfolding monic_poly_def univ_poly_carrier[symmetric] polynomial_def by (intro bij_betwI[where g="tl"]) (fastforce intro:in_set_tlD)+ have rev_bij: "bij_betw rev {x. set x \ carrier ?R \ length x = d} {x. set x \ carrier ?R \ length x = d}" by (intro bij_betwI[where g="rev"]) auto have "bij_betw (\x. \\<^bsub>?R\<^esub>#map x (rev [ 0..\<^sub>E carrier ?R) {f. monic_poly ?R f\degree f=d}" unfolding 3 by (intro bij_betw_trans[OF lists_bij] bij_betw_trans[OF rev_bij] ap_bij) hence "bij_betw ?f ({..\<^sub>E {.. degree f = d}" unfolding 2 by (intro bij_betw_trans[OF lift_bij_betw[OF select_bij]]) (simp add:fo) thus ?thesis unfolding 1 by (intro bij_betw_trans[OF nth_digit_bij]) qed lemma measure_bind_pmf: "measure (bind_pmf m f) s = (\x. measure (f x) s \m)" (is "?L = ?R") proof - have "ennreal ?L = emeasure (bind_pmf m f) s" unfolding measure_pmf.emeasure_eq_measure by simp also have "... = (\\<^sup>+x. emeasure (f x) s \m)" unfolding emeasure_bind_pmf by simp also have "... = (\\<^sup>+x. measure (f x) s \m)" unfolding measure_pmf.emeasure_eq_measure by simp also have "... = ennreal ?R" by (intro nn_integral_eq_integral measure_pmf.integrable_const_bound[where B="1"] AE_pmfI) auto finally have "ennreal ?L = ennreal ?R" by simp thus ?thesis by (intro iffD1[OF ennreal_inj]) simp_all qed lemma powr_mono_rev: fixes x :: real assumes "a \ b" and "x > 0" "x \ 1" shows "x powr b \ x powr a" proof - have "x powr b = (1/x) powr (-b)" using assms by (simp add: powr_divide powr_minus_divide) also have "... \ (1/x) powr (-a)" using assms by (intro powr_mono) auto also have "... = x powr a" using assms by (simp add: powr_divide powr_minus_divide) finally show ?thesis by simp qed abbreviation tick_spmf :: "('a \ nat) spmf \ ('a \ nat) spmf" where "tick_spmf \ map_spmf (\(x,c). (x,c+1))" text \Finds an irreducible polynomial in the finite field @{term "mod_ring p"} with given degree n:\ partial_function (spmf) sample_irreducible_poly :: "nat \ nat \ (nat list \ nat) spmf" where "sample_irreducible_poly p n = do { k \ spmf_of_set {..The following is a deterministic version. It returns the lexicographically minimal monic irreducible polynomial. Note that contrary to the randomized algorithm, the run time of the deterministic algorithm may be exponential (w.r.t. to the size of the field and degree of the polynomial).\ fun find_irreducible_poly :: "nat \ nat \ nat list" where "find_irreducible_poly p n = (let f = enum_monic_poly (mod_ring p) n in f (while ((\k. \rabin_test (mod_ring p) (f k))) (\x. x + 1) 0))" definition cost :: "('a \ nat) option \ enat" where "cost x = (case x of None \ \ | Some (_,r) \ enat r)" lemma cost_tick: "cost (map_option (\(x, c). (x, Suc c)) c) = eSuc (cost c)" by (cases c) (auto simp:cost_def eSuc_enat) context fixes n p :: nat assumes p_prime: "Factorial_Ring.prime p" assumes n_gt_0: "n > 0" begin private definition S where "S = {f. monic_poly (ring_of (mod_ring p)) f \ degree f = n }" private definition T where "T = {f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n}" lemmas field_c = mod_ring_is_field_c[OF p_prime] lemmas enum_c = mod_ring_is_enum_c[where n="p"] interpretation finite_field "ring_of (mod_ring p)" unfolding finite_field_def finite_field_axioms_def by (intro mod_ring_is_field conjI mod_ring_finite p_prime) private lemmas field_ops = field_cD[OF field_c] private lemma S_fin: "finite S" unfolding S_def using enum_monic_poly[OF field_c enum_c, where d="n"] bij_betw_finite by auto private lemma T_sub_S: "T \ S" unfolding S_def T_def monic_irreducible_poly_def by auto private lemma T_card_gt_0: "real (card T) > 0" proof - have "0 < real (order (ring_of (mod_ring p))) ^ n / (2 * real n)" using n_gt_0 finite_field_min_order by (intro divide_pos_pos) (simp_all) also have "... \ real (card T)" unfolding T_def by (intro card_irred_gt_0 n_gt_0) finally show "real (card T) > 0" by auto qed private lemma S_card_gt_0: "real (card S) > 0" proof - have "0 < card T" using T_card_gt_0 by simp also have "... \ card S" by (intro card_mono T_sub_S S_fin) finally have "0 < card S" by simp thus ?thesis by simp qed private lemma S_ne: "S \ {}" using S_card_gt_0 by auto private lemma sample_irreducible_poly_step_aux: "do { k \ spmf_of_set {.. spmf_of_set S; if monic_irreducible_poly (ring_of (mod_ring p)) poly then return_spmf (poly,c) else x }" (is "?L = ?R") proof - have "order (ring_of (mod_ring p)) = p" unfolding Finite_Fields_Mod_Ring_Code.mod_ring_def Coset.order_def ring_of_def by simp hence 0:"spmf_of_set S = map_spmf (enum_monic_poly (mod_ring p) n) (spmf_of_set {.. spmf_of_set S; if rabin_test (mod_ring p) f then return_spmf (f,c) else x}" unfolding 0 bind_map_spmf by (simp add:Let_def comp_def) also have "... = ?R" using set_spmf_of_set_finite[OF S_fin] by (intro bind_spmf_cong refl if_cong rabin_test field_c enum_c) (simp add:S_def) finally show ?thesis by simp qed private lemma sample_irreducible_poly_step: "sample_irreducible_poly p n = do { poly \ spmf_of_set S; if monic_irreducible_poly (ring_of (mod_ring p)) poly then return_spmf (poly,1) else tick_spmf (sample_irreducible_poly p n) }" by (subst sample_irreducible_poly.simps) (simp add:sample_irreducible_poly_step_aux) private lemma sample_irreducible_poly_aux_1: "ord_spmf (=) (map_spmf fst (sample_irreducible_poly p n)) (spmf_of_set T)" proof (induction rule:sample_irreducible_poly.fixp_induct) case 1 thus ?case by simp next case 2 thus ?case by simp next case (3 rec) let ?f = "monic_irreducible_poly (ring_of (mod_ring p))" have "real (card (S\-{x. ?f x})) = real (card (S - T))" unfolding S_def T_def by (intro arg_cong[where f="card"] arg_cong[where f="of_nat"]) (auto) also have "... = real (card S - card T)" by (intro arg_cong[where f="of_nat"] card_Diff_subset T_sub_S finite_subset[OF T_sub_S S_fin]) also have "... = real (card S) - card T" by (intro of_nat_diff card_mono S_fin T_sub_S) finally have 0:"real (card (S\-{x. ?f x})) = real (card S) - card T" by simp have S_card_gt_0: "real (card S) > 0" using S_ne S_fin by auto have "do {f \ spmf_of_set S;if ?f f then return_spmf f else spmf_of_set T} = spmf_of_set T" (is "?L = ?R") proof (rule spmf_eqI) fix i have "spmf ?L i = spmf (pmf_of_set S \(\x. if ?f x then return_spmf x else spmf_of_set T)) i" unfolding spmf_of_pmf_pmf_of_set[OF S_fin S_ne, symmetric] spmf_of_pmf_def by (simp add:bind_spmf_def bind_map_pmf) also have "... = (\x. (if ?f x then of_bool (x=i) else spmf (spmf_of_set T) i) \pmf_of_set S)" unfolding pmf_bind if_distrib if_distribR pmf_return_spmf indicator_def by (simp cong:if_cong) also have "... = (\x \ S. (if ?f x then of_bool (x = i) else spmf (spmf_of_set T) i))/card S" by (subst integral_pmf_of_set[OF S_ne S_fin]) simp also have "... = (of_bool (i \ T) + spmf (spmf_of_set T) i*real (card (S\-{x. ?f x})))/card S" using S_fin S_ne by (subst sum.If_cases[OF S_fin]) (simp add:of_bool_def T_def monic_irreducible_poly_def S_def) also have "... = (of_bool (i \ T)*(1 + real (card (S\-{x. ?f x}))/real (card T)))/card S" unfolding spmf_of_set indicator_def by (simp add:algebra_simps) also have "... = (of_bool (i \ T)*(real (card S)/real (card T)))/card S" using T_card_gt_0 unfolding 0 by (simp add:field_simps) also have "... = of_bool (i \ T)/real (card T)" using S_card_gt_0 by (simp add:field_simps) also have "... = spmf ?R i" unfolding spmf_of_set by simp finally show "spmf ?L i = spmf ?R i" by simp qed hence "ord_spmf (=) (spmf_of_set S \ (\x. if ?f x then return_spmf x else spmf_of_set T)) (spmf_of_set T)" by simp moreover have "ord_spmf (=) (do { poly \ spmf_of_set S; if ?f poly then return_spmf poly else map_spmf fst (rec p n)}) (do { poly \ spmf_of_set S; if ?f poly then return_spmf poly else spmf_of_set T})" using 3 by (intro bind_spmf_mono') simp_all ultimately have "ord_spmf (=) (spmf_of_set S \ (\x. if ?f x then return_spmf x else map_spmf fst (rec p n))) (spmf_of_set T)" using spmf.leq_trans by force thus ?case unfolding sample_irreducible_poly_step_aux map_spmf_bind_spmf by (simp add:comp_def if_distribR if_distrib spmf.map_comp case_prod_beta cong:if_cong) qed lemma cost_sample_irreducible_poly: "(\\<^sup>+x. cost x \sample_irreducible_poly p n) \ 2*real n" (is "?L \ ?R") proof - let ?f = "monic_irreducible_poly (ring_of (mod_ring p))" let ?a = "(\t. measure (sample_irreducible_poly p n) {\. enat t < cost \})" let ?b = "(\t. measure (sample_irreducible_poly p n) {\. enat t \ cost \})" define \ where "\ = measure (pmf_of_set S) {x. ?f x}" have \_le_1: "\ \ 1" unfolding \_def by simp have "1 / (2* real n) = (card S / (2 * real n)) / card S" using S_card_gt_0 by (simp add:algebra_simps) also have "... = (real (order (ring_of (mod_ring p)))^n / (2 * real n)) / card S" unfolding S_def bij_betw_same_card[OF enum_monic_poly[OF field_c enum_c, where d="n"],symmetric] by simp also have "... \ card T / card S" unfolding T_def by (intro divide_right_mono card_irred_gt_0 n_gt_0) auto also have "... = \" unfolding \_def measure_pmf_of_set[OF S_ne S_fin] by (intro arg_cong2[where f="(/)"] refl arg_cong[where f="of_nat"] arg_cong[where f="card"]) (auto simp: S_def T_def monic_irreducible_poly_def) finally have \_lb: "1/ (2*real n) \ \" by simp have "0 < 1/ (2*real n)" using n_gt_0 by simp also have "... \ \" using \_lb by simp finally have \_gt_0: "\ > 0" by simp have a_step_aux: "norm (a * b) \ 1" if "norm a \ 1" "norm b \ 1" for a b :: real using that by (simp add:abs_mult mult_le_one) have b_eval: "?b t = (\x. (if ?f x then of_bool(t \ 1) else measure (sample_irreducible_poly p n) {\. enat t \ eSuc (cost \)}) \pmf_of_set S)" (is "?L1 = ?R1") for t proof - have "?b t = measure (bind_spmf (spmf_of_set S) (\x. if ?f x then return_spmf (x,1) else tick_spmf (sample_irreducible_poly p n))) {\. enat t \ cost \}" by (subst sample_irreducible_poly_step) simp also have "... = measure (bind_pmf (pmf_of_set S) (\x. if ?f x then return_spmf (x,1) else tick_spmf (sample_irreducible_poly p n))) {\. enat t \ cost \}" unfolding spmf_of_pmf_pmf_of_set[OF S_fin S_ne, symmetric] by (simp add:spmf_of_pmf_def bind_map_pmf bind_spmf_def) also have "... = (\x. (if ?f x then of_bool(t \ 1) else measure (tick_spmf (sample_irreducible_poly p n)) {\. enat t \ cost \}) \pmf_of_set S)" unfolding measure_bind_pmf if_distrib if_distribR emeasure_return_pmf by (simp add:indicator_def cost_def comp_def cong:if_cong) also have "... = ?R1" unfolding measure_map_pmf vimage_def by (intro arg_cong2[where f="integral\<^sup>L"] refl ext if_cong arg_cong2[where f="measure"]) (auto simp add:vimage_def cost_tick eSuc_enat[symmetric]) finally show ?thesis by simp qed have b_eval_2: "?b t = 1 - (1-\)^t" for t proof (induction t) case 0 have "?b 0 = 0" unfolding b_eval by (simp add:enat_0 cong:if_cong ) thus ?case by simp next case (Suc t) have "?b (Suc t) = (\x. (if ?f x then 1 else ?b t) \pmf_of_set S)" unfolding b_eval[of "Suc t"] by (intro arg_cong2[where f="integral\<^sup>L"] if_cong arg_cong2[where f="measure"]) (auto simp add: eSuc_enat[symmetric]) also have "... = (\x. indicator {x. ?f x} x + ?b t * indicator {x. \?f x} x \pmf_of_set S)" by (intro Bochner_Integration.integral_cong) (auto simp:algebra_simps) also have "... = (\x. indicator {x. ?f x} x \pmf_of_set S) + (\x. ?b t * indicator {x. \?f x} x \pmf_of_set S)" by (intro Bochner_Integration.integral_add measure_pmf.integrable_const_bound[where B="1"] AE_pmfI a_step_aux) auto also have "... = \ + ?b t * measure (pmf_of_set S) {x. \?f x}" unfolding \_def by simp also have "... = \ + (1-\) * ?b t" unfolding \_def by (subst measure_pmf.prob_compl[symmetric]) (auto simp:Compl_eq_Diff_UNIV Collect_neg_eq) also have "... = 1 - (1-\)^Suc t" unfolding Suc by (simp add:algebra_simps) finally show ?case by simp qed hence a_eval: "?a t = (1-\)^t" for t proof - have "?a t = 1 - ?b t" by (simp add: measure_pmf.prob_compl[symmetric] Compl_eq_Diff_UNIV[symmetric] Collect_neg_eq[symmetric] not_le) also have "... = (1-\)^t" unfolding b_eval_2 by simp finally show ?thesis by simp qed have "?L = (\t. emeasure (sample_irreducible_poly p n) {\. enat t < cost \})" by (subst nn_integral_enat_function) simp_all also have "... = (\t. ennreal (?a t))" unfolding measure_pmf.emeasure_eq_measure by simp also have "... = (\t. ennreal ((1-\)^t))" unfolding a_eval by (intro arg_cong[where f="suminf"] ext) (simp add: \_def ennreal_mult') also have "... = ennreal (1 / (1-(1-\)))" using \_le_1 \_gt_0 by (intro arg_cong2[where f="(*)"] refl suminf_ennreal_eq geometric_sums) auto also have "... = ennreal (1 / \)" using \_le_1 \_gt_0 by auto also have "... \ ?R" using \_lb n_gt_0 \_gt_0 by (intro ennreal_leI) (simp add:field_simps) finally show ?thesis by simp qed private lemma weight_sample_irreducible_poly: "weight_spmf (sample_irreducible_poly p n) = 1" (is "?L = ?R") proof (rule ccontr) assume "?L \ 1" hence "?L < 1" using less_eq_real_def weight_spmf_le_1 by blast hence "(\::ennreal) = \ * ennreal (1-?L)" by simp also have "... = \ * ennreal (pmf (sample_irreducible_poly p n) None)" unfolding pmf_None_eq_weight_spmf[symmetric] by simp also have "... = (\\<^sup>+x. \ * indicator {None} x \sample_irreducible_poly p n)" by (simp add:emeasure_pmf_single) also have "... \ (\\<^sup>+x. cost x \sample_irreducible_poly p n)" unfolding cost_def by (intro nn_integral_mono) (auto simp:indicator_def) also have "... \ 2*real n" by (intro cost_sample_irreducible_poly) finally have "(\::ennreal) \ 2 * real n" by simp thus "False" using linorder_not_le by fastforce qed lemma sample_irreducible_poly_result: "map_spmf fst (sample_irreducible_poly p n) = spmf_of_set {f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n}" (is "?L = ?R") proof - have "?L = spmf_of_set T" using weight_sample_irreducible_poly by (intro eq_iff_ord_spmf sample_irreducible_poly_aux_1) (auto intro:weight_spmf_le_1) thus ?thesis unfolding T_def by simp qed lemma find_irreducible_poly_result: defines "res \ find_irreducible_poly p n" shows "monic_irreducible_poly (ring_of (mod_ring p)) res" "degree res = n" proof - let ?f = "enum_monic_poly (mod_ring p) n" have ex:"\k. ?f k \ T \ k < order (ring_of (mod_ring p))^n" proof (rule ccontr) assume "\k. ?f k \ T \ k < order (ring_of (mod_ring p)) ^ n" hence "?f ` {.. T = {}" by auto hence "S \ T = {}" unfolding S_def using bij_betw_imp_surj_on[OF enum_monic_poly[OF field_c enum_c]] by auto hence "T = {}" using T_sub_S by auto thus "False" using T_card_gt_0 by simp qed then obtain k :: nat where k_def: "?f k \ T" "\j T" using exists_least_iff[where P="\x. ?f x \ T"] by auto have k_ub: "k < order (ring_of (mod_ring p))^n" using ex k_def(2) by (meson dual_order.strict_trans1 not_less) have a: "monic_irreducible_poly (ring_of (mod_ring p)) (?f k)" using k_def(1) unfolding T_def by simp have b: "monic_poly (ring_of (mod_ring p)) (?f j)" "degree (?f j) = n" if "j \ k" for j proof - have "j < order (ring_of (mod_ring p)) ^n" using k_ub that by simp hence "?f j \ S" unfolding S_def using bij_betw_apply[OF enum_monic_poly[OF field_c enum_c]] by auto thus "monic_poly (ring_of (mod_ring p)) (?f j)" "degree (?f j) = n" unfolding S_def by auto qed have c: "\monic_irreducible_poly (ring_of (mod_ring p)) (?f j)" if " j < k" for j using b[of "j"] that k_def(2) unfolding T_def by auto have 2: "while ((\k. \rabin_test (mod_ring p) (?f k))) (\x. x + 1) (k-j) = k" if "j \ k" for j using that proof (induction j) case 0 have "rabin_test (mod_ring p) (?f k)" by (intro iffD2[OF rabin_test] a b field_c enum_c) auto thus ?case by (subst while_unfold) simp next case (Suc j) hence "\rabin_test (mod_ring p) (?f (k-Suc j))" using b c by (subst rabin_test[OF field_c enum_c]) auto moreover have "Suc (Suc (k - Suc j)) = Suc (k-j)" using Suc by simp ultimately show ?case using Suc(1) by (subst while_unfold) simp qed have 3:"while ((\k. \rabin_test (mod_ring p) (?f k))) (\x. x + 1) 0 = k" using 2[of "k"] by simp have "?f k \ T" using a b unfolding T_def by auto hence "res \ T" unfolding res_def find_irreducible_poly.simps Let_def 3 by simp thus "monic_irreducible_poly (ring_of (mod_ring p)) res" "degree res = n" unfolding T_def by auto qed lemma monic_irred_poly_set_nonempty_finite: "{f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n} \ {}" (is "?R1") "finite {f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n}" (is "?R2") proof - have "card T > 0" using T_card_gt_0 by auto hence "T \ {}" "finite T" using card_ge_0_finite by auto thus ?R1 ?R2 unfolding T_def by auto qed end text \Returns @{term "m"} @{term "e"} such that @{term "n = m^e"}, where @{term "e"} is maximal.\ definition split_power :: "nat \ nat \ nat" where "split_power n = ( let e = last (filter (\x. is_nth_power_nat x n) (1#[2..k. n > 1 \ k>e \ \is_nth_power k n" proof - define es where "es = filter (\x. is_nth_power_nat x n) (1#[2.. 1" for x proof (rule ccontr) assume a:"\(x < m)" obtain y where n_def:"n = y^x" using that0 is_nth_power_def is_nth_power_nat_def by auto have "y \ 0" using that(2) unfolding n_def by (metis (mono_tags) nat_power_eq_Suc_0_iff not_less0 power_0_left power_inject_exp) moreover have "y \ 1" using that(2) unfolding n_def by auto ultimately have y_ge_2: "y \ 2" by simp have "n < 2^floorlog 2 n" using that floorlog_bounds by simp also have "... \ 2^x" using a unfolding m_def by (intro power_increasing) auto also have "... \ y^x" using y_ge_2 by (intro power_mono) auto also have "... = n" using n_def by auto finally show "False" by simp qed have 1: "m = 2" if "\(n > 1)" proof - have "floorlog 2 n \ 2" using that by (intro floorlog_leI) auto thus ?thesis unfolding m_def by auto qed have 2: "n = 1" if "is_nth_power_nat 0 n" using that by (simp add: is_nth_power_nat_code) have "set es = {x \ insert 1 {2.. 0 \ x < m \ is_nth_power_nat x n}" unfolding m_def by auto also have "... = {x. is_nth_power_nat x n \ (n > 1 \ x = 1)}" using 0 1 2 zero_neq_one by (intro Collect_cong iffI conjI) fastforce+ finally have set_es: "set es = {x. is_nth_power_nat x n \ (n > 1 \ x = 1)}" by simp have "is_nth_power_nat 1 n" unfolding is_nth_power_nat_def by simp hence es_ne: "es \ []" unfolding es_def by auto have sorted: "sorted es" unfolding es_def by (intro sorted_wrt_filter) simp have e_def: "e = last es" and x_def: "x = nth_root_nat e n" using assms unfolding es_def split_power_def by (simp_all add:Let_def) hence e_in_set_es: "e \ set es" unfolding e_def using es_ne by (intro last_in_set) auto have e_max: "x \ e" if that1:"x \ set es" for x proof - obtain k where "k < length es" "x = es ! k" using that1 by (metis in_set_conv_nth) moreover have "e = es ! (length es -1)" unfolding e_def using es_ne last_conv_nth by auto ultimately show ?thesis using sorted_nth_mono[OF sorted] es_ne by simp qed have 3:"is_nth_power_nat e n \ (1 < n \ e = 1)" using e_in_set_es unfolding set_es by simp hence "e > 0" using 2 zero_neq_one by fast thus "n = x^e" using 3 unfolding x_def using nth_root_nat_nth_power by (metis is_nth_power_nat_code nth_root_nat_naive_code power_eq_0_iff) show "\is_nth_power k n" if "n > 1" "k > e" for k proof (rule ccontr) assume "\(\is_nth_power k n)" hence "k \ set es" using that unfolding set_es is_nth_power_nat_def by auto hence "k \ e" using e_max by auto thus "False" using that(2) by auto qed qed definition not_perfect_power :: "nat \ bool" where "not_perfect_power n = (n > 1 \ (\x k. n = x ^ k \ k = 1))" lemma is_nth_power_from_multiplicities: assumes "n > (0::nat)" assumes "\p. Factorial_Ring.prime p \ k dvd (multiplicity p n)" shows "is_nth_power k n" proof - have "n = (\p \ prime_factors n. p^multiplicity p n)" using assms(1) by (simp add: prod_prime_factors) also have "... = (\p \ prime_factors n. p^((multiplicity p n div k)*k))" by (intro prod.cong arg_cong2[where f="power"] dvd_div_mult_self[symmetric] refl assms(2)) auto also have "... = (\p \ prime_factors n. p^(multiplicity p n div k))^k" unfolding power_mult prod_power_distrib[symmetric] by simp finally have "n = (\p \ prime_factors n. p^(multiplicity p n div k))^k" by simp thus ?thesis by (intro is_nth_powerI) simp qed lemma power_inj_aux: assumes "not_perfect_power a" "not_perfect_power b" assumes "n > 0" "m > n" assumes "a ^ n = b ^ m" shows "False" proof - define s where "s = gcd n m" define u where "u = n div gcd n m" define t where "t = m div gcd n m" have a_nz: "a \ 0" and b_nz: "b \ 0" using assms(1,2) unfolding not_perfect_power_def by auto have "gcd n m \ 0" using assms (3,4) by simp then obtain t u where n_def: "n = t * s" and m_def: "m = u * s" and cp: "coprime t u" using gcd_coprime_exists unfolding s_def t_def u_def by blast have s_gt_0: "s > 0" and t_gt_0: "t > 0" and u_gt_t: "u > t" using assms(3,4) unfolding n_def m_def by auto have "(a ^ t) ^ s = (b ^ u) ^ s" using assms(5) unfolding n_def m_def power_mult by simp hence 0: "a^t = b^u" using s_gt_0 by (metis nth_root_nat_nth_power) have "u dvd multiplicity p a" if "Factorial_Ring.prime p" for p proof - have "prime_elem p" using that by simp hence "t * multiplicity p a = u * multiplicity p b" using 0 a_nz b_nz by (subst (1 2) prime_elem_multiplicity_power_distrib[symmetric]) auto hence "u dvd t * multiplicity p a" by simp thus ?thesis using cp coprime_commute coprime_dvd_mult_right_iff by blast qed hence "is_nth_power u a" using a_nz by (intro is_nth_power_from_multiplicities) auto moreover have "u > 1" using u_gt_t t_gt_0 by auto ultimately show "False" using assms(1) unfolding not_perfect_power_def is_nth_power_def by auto qed text \Generalization of @{thm [source] prime_power_inj'}\ lemma power_inj: assumes "not_perfect_power a" "not_perfect_power b" assumes "n > 0" "m > 0" assumes "a ^ n = b ^ m" shows "a = b \ n = m" proof - consider (a) "n < m" | (b) "m < n" | (c) "n = m" by linarith thus ?thesis proof (cases) case a thus ?thesis using assms power_inj_aux by auto next case b thus ?thesis using assms power_inj_aux[OF assms(2,1,4) b] by auto next case c thus ?thesis using assms by (simp add: power_eq_iff_eq_base) qed qed lemma split_power_base_not_perfect: assumes "n > 1" shows "not_perfect_power (fst (split_power n))" proof (rule ccontr) obtain b e where be_def: "(b,e) = split_power n" by (metis surj_pair) have n_def:"n = b ^ e" and e_max: "\k. e < k \ \ is_nth_power k n" using assms split_power_result[OF be_def] by auto have e_gt_0: "e > 0" using assms unfolding n_def by (cases e) auto assume "\not_perfect_power (fst (split_power n))" hence "\not_perfect_power b" unfolding be_def[symmetric] by simp moreover have b_gt_1: "b > 1" using assms unfolding n_def by (metis less_one nat_neq_iff nat_power_eq_Suc_0_iff power_0_left) ultimately obtain k b' where "k \ 1" and b_def: "b = b'^k" unfolding not_perfect_power_def by auto hence k_gt_1: "k > 1" using b_gt_1 nat_neq_iff by force have "n = b'^(k*e)" unfolding power_mult n_def b_def by auto moreover have "k*e > e" using k_gt_1 e_gt_0 by simp hence "\is_nth_power (k*e) n" using e_max by auto ultimately show "False" unfolding is_nth_power_def by auto qed lemma prime_not_perfect: assumes "Factorial_Ring.prime p" shows "not_perfect_power p" proof - have "k=1" if "p = x^k" for x k using assms unfolding that by (simp add:prime_power_iff) thus ?thesis using prime_gt_1_nat[OF assms] unfolding not_perfect_power_def by auto qed lemma split_power_prime: assumes "Factorial_Ring.prime p" "n > 0" shows "split_power (p^n) = (p,n)" proof - obtain x e where xe:"(x,e) = split_power (p^n)" by (metis surj_pair) have "1 < p^1" using prime_gt_1_nat[OF assms(1)] by simp also have "... \ p^n" using assms(2) prime_gt_0_nat[OF assms(1)] by (intro power_increasing) auto finally have 0:"p^n > 1" by simp have "not_perfect_power x" using split_power_base_not_perfect[OF 0] unfolding xe[symmetric] by simp moreover have "not_perfect_power p" by (rule prime_not_perfect[OF assms(1)]) moreover have 1:"p^n = x^e" using split_power_result[OF xe] by simp moreover have "e > 0" using 0 1 by (cases e) auto ultimately have "p=x \ n = e" by (intro power_inj assms(2)) thus ?thesis using xe by simp qed definition "is_prime_power n = (\p k. Factorial_Ring.prime p \ k > 0 \ n = p^k)" +lemma is_prime_powerI: + assumes "prime p" "k > 0" + shows "is_prime_power (p ^ k)" + unfolding is_prime_power_def using assms by auto + definition GF where "GF n = ( let (p,k) = split_power n; f = find_irreducible_poly p k in poly_mod_ring (mod_ring p) f)" definition GF\<^sub>R where "GF\<^sub>R n = do { let (p,k) = split_power n; f \ sample_irreducible_poly p k; return_spmf (poly_mod_ring (mod_ring p) (fst f)) }" lemma GF_in_GF_R: assumes "is_prime_power n" shows "GF n \ set_spmf (GF\<^sub>R n)" proof- obtain p k where n_def: "n = p^k" and p_prime: "prime p" and k_gt_0: "k > 0" using assms unfolding is_prime_power_def by blast have pk_def: "(p,k) = split_power n" unfolding n_def using split_power_prime[OF p_prime k_gt_0] by auto let ?S = "{f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = k}" have S_fin: "finite ?S" by (intro monic_irred_poly_set_nonempty_finite p_prime k_gt_0) have "find_irreducible_poly p k \ ?S" using find_irreducible_poly_result[OF p_prime k_gt_0] by auto also have "... = set_spmf (map_spmf fst (sample_irreducible_poly p k))" unfolding sample_irreducible_poly_result[OF p_prime k_gt_0] set_spmf_of_set_finite[OF S_fin] by simp finally have 0: "find_irreducible_poly p k \ set_spmf(map_spmf fst (sample_irreducible_poly p k))" by simp have "GF n = poly_mod_ring (mod_ring p) (find_irreducible_poly p k)" unfolding GF_def pk_def[symmetric] by (simp del:find_irreducible_poly.simps) also have "... \ set_spmf (map_spmf fst (sample_irreducible_poly p k)) \ (\x. {poly_mod_ring (mod_ring p) x})" using 0 by force also have "... = set_spmf (GF\<^sub>R n)" unfolding GF\<^sub>R_def pk_def[symmetric] by (simp add:set_bind_spmf comp_def bind_image) finally show ?thesis by simp qed lemma galois_field_random_1: assumes "is_prime_power n" shows "\\. \ \ set_spmf (GF\<^sub>R n) \ enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n" and "lossless_spmf (GF\<^sub>R n)" proof - let ?pred = "\\. enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n" obtain p k where n_def: "n = p^k" and p_prime: "prime p" and k_gt_0: "k > 0" using assms unfolding is_prime_power_def by blast let ?r = "(\f. poly_mod_ring (mod_ring p) f)" let ?S = "{f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = k}" have fc: "field\<^sub>C (mod_ring p)" by (intro mod_ring_is_field_c p_prime) have ec: "enum\<^sub>C (mod_ring p)" by (intro mod_ring_is_enum_c) have S_fin: "finite ?S" by (intro monic_irred_poly_set_nonempty_finite p_prime k_gt_0) have S_ne: "?S \ {}" by (intro monic_irred_poly_set_nonempty_finite p_prime k_gt_0) have pk_def: "(p,k) = split_power n" unfolding n_def using split_power_prime[OF p_prime k_gt_0] by auto have cond: "?pred (?r x)" if "x \ ?S" for x proof - have "order (ring_of (poly_mod_ring (mod_ring p) x)) = idx_size (poly_mod_ring (mod_ring p) x)" using enum_cD[OF enum_c_poly_mod_ring[OF ec field_c_imp_ring[OF fc]]] by simp also have "... = p^(degree x)" by (simp add:poly_mod_ring_def Finite_Fields_Mod_Ring_Code.mod_ring_def) also have "... = n" unfolding n_def using that by simp finally have "order (ring_of (poly_mod_ring (mod_ring p) x)) = n" by simp thus ?thesis using that by (intro conjI enum_c_poly_mod_ring field_c_poly_mod_ring ec field_c_imp_ring fc) auto qed have "GF\<^sub>R n = bind_spmf (map_spmf fst (sample_irreducible_poly p k)) (\x. return_spmf (?r x))" unfolding GF\<^sub>R_def pk_def[symmetric] map_spmf_conv_bind_spmf by simp also have "... = spmf_of_set ?S \ (\f. return_spmf ((?r f)))" unfolding sample_irreducible_poly_result[OF p_prime k_gt_0] by (simp) also have "... = pmf_of_set ?S \ (\f. return_spmf (?r f))" unfolding spmf_of_pmf_pmf_of_set[OF S_fin S_ne, symmetric] spmf_of_pmf_def by (simp add:bind_spmf_def bind_map_pmf) finally have 0:"GF\<^sub>R n = map_pmf (Some \ ?r) (pmf_of_set ?S) " by (simp add:comp_def map_pmf_def) show "enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n" if "\ \ set_spmf (GF\<^sub>R n)" for \ proof - have "Some \ \ set_pmf (GF\<^sub>R n)" unfolding in_set_spmf[symmetric] by (rule that) also have "... = (Some \ ?r) ` ?S" unfolding 0 set_map_pmf set_pmf_of_set[OF S_ne S_fin] by simp finally have "Some \ \ (Some \ ?r) ` ?S" by simp hence "\ \ ?r ` ?S" by auto then obtain x where x:"x \ ?S" and \_def:"\ = ?r x" by auto show ?thesis unfolding \_def by (intro cond x) qed have "None \ set_pmf(GF\<^sub>R n)" unfolding 0 set_map_pmf set_pmf_of_set[OF S_ne S_fin] by auto thus "lossless_spmf (GF\<^sub>R n)" using lossless_iff_set_pmf_None by blast qed lemma galois_field: assumes "is_prime_power n" shows "enum\<^sub>C (GF n)" "field\<^sub>C (GF n)" "order (ring_of (GF n)) = n" using galois_field_random_1(1)[OF assms(1) GF_in_GF_R[OF assms(1)]] by auto lemma lossless_imp_spmf_of_pmf: assumes "lossless_spmf M" shows "spmf_of_pmf (map_pmf the M) = M" proof - have "spmf_of_pmf (map_pmf the M) = map_pmf (Some \ the) M" unfolding spmf_of_pmf_def by (simp add: pmf.map_comp) also have "... = map_pmf id M" using assms unfolding lossless_iff_set_pmf_None by (intro map_pmf_cong refl) (metis id_apply o_apply option.collapse) also have "... = M" by simp finally show ?thesis by simp qed lemma galois_field_random_2: assumes "is_prime_power n" shows "map_spmf (\\. enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n) (GF\<^sub>R n) = return_spmf True" (is "?L = _") proof - have "?L = map_spmf (\\. True) (GF\<^sub>R n)" using galois_field_random_1[OF assms] by (intro map_spmf_cong refl) auto also have "... = map_pmf (\\. Some True) (GF\<^sub>R n)" by (subst lossless_imp_spmf_of_pmf[OF galois_field_random_1(2)[OF assms],symmetric]) simp also have "... = return_spmf True" unfolding map_pmf_def by simp finally show ?thesis by simp qed lemma bind_galois_field_cong: assumes "is_prime_power n" assumes "\\. enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n \ f \ = g \" shows "bind_spmf (GF\<^sub>R n) f = bind_spmf (GF\<^sub>R n) g" using galois_field_random_1(1)[OF assms(1)] by (intro bind_spmf_cong refl assms(2)) auto end \ No newline at end of file diff --git a/thys/Universal_Hash_Families/Pseudorandom_Objects.thy b/thys/Universal_Hash_Families/Pseudorandom_Objects.thy new file mode 100644 --- /dev/null +++ b/thys/Universal_Hash_Families/Pseudorandom_Objects.thy @@ -0,0 +1,252 @@ +section \Pseudorandom Objects\ + +theory Pseudorandom_Objects + imports Universal_Hash_Families_More_Product_PMF +begin + +text \This section introduces a combinator library for pseudorandom objects~\cite{vadhan2012}. +These can be thought of as PRNGs but with rigorous mathematical properties, which can be used to +in algorithms to reduce their randomness usage. + +Such an object represents a non-empty multiset, with an efficient mechanism to sample from +it. They have a natural interpretation as a probability space (each element is selected with a +probability proportional to its occurrence count in the multiset). + +The following section will introduce a construction of k-independent hash families as a pseudorandom +object. The AFP entry @{verbatim Expander_Graphs} then follows up with expander walks as +pseudorandom objects.\ + +record 'a pseudorandom_object = + pro_last :: nat + pro_select :: "nat \ 'a" + +definition pro_size where "pro_size S = pro_last S + 1" +definition sample_pro where "sample_pro S = map_pmf (pro_select S) (pmf_of_set {0..pro_last S})" + +declare [[coercion sample_pro]] + +abbreviation pro_set where "pro_set S \ set_pmf (sample_pro S)" + +lemma sample_pro_alt: "sample_pro S = map_pmf (pro_select S) (pmf_of_set {.. 0" + unfolding pro_size_def by auto + +lemma set_sample_pro: "pro_set S = pro_select S ` {.. pro_set S" + unfolding set_sample_pro by (intro imageI) (simp add:pro_size_gt_0) + +lemma finite_pro_set: "finite (pro_set S)" + unfolding set_sample_pro by (intro finite_imageI) auto + +lemma integrable_sample_pro[simp]: + fixes f :: "'a \ 'c::{banach, second_countable_topology}" + shows "integrable (measure_pmf (sample_pro S)) f" + by (intro integrable_measure_pmf_finite finite_pro_set) + +(* List sample space *) + +definition list_pro :: "'a list \ 'a pseudorandom_object" where + "list_pro ls = \ pro_last = length ls - 1, pro_select = (!) ls \" + +lemma list_pro: + assumes "xs \ []" + shows "sample_pro (list_pro xs) = pmf_of_multiset (mset xs)" (is "?L = ?R") +proof - + have "?L = map_pmf ((!) xs) (pmf_of_set {.. []" "distinct xs" + shows "sample_pro (list_pro xs) = pmf_of_set (set xs)" (is "?L = ?R") +proof - + have "?L = map_pmf ((!) xs) (pmf_of_set {.. []" + shows "pro_size (list_pro xs) = length xs" + using assms unfolding pro_size_def list_pro_def by auto + +lemma list_pro_set: + assumes "xs \ []" + shows "pro_set (list_pro xs) = set xs" +proof - + have "(!) xs ` {.. nat pseudorandom_object" where + "nat_pro n = \ pro_last = n-1, pro_select = id \" + +lemma nat_pro_size: + assumes "n > 0" + shows"pro_size (nat_pro n) = n" + using assms unfolding nat_pro_def pro_size_def by auto + +lemma nat_pro: + assumes "n > 0" + shows "sample_pro (nat_pro n) = pmf_of_set {.. 0" + shows "pro_set (nat_pro n) = {.. nat \ nat" where + "count_zeros 0 k = 0" | + "count_zeros (Suc n) k = (if odd k then 0 else 1 + count_zeros n (k div 2))" + +lemma count_zeros_iff: "j \ n \ count_zeros n k \ j \ 2^j dvd k" +proof (induction j arbitrary: n k) + case 0 + then show ?case by simp +next + case (Suc j) + then obtain n' where n_def: "n = Suc n'" using Suc_le_D by presburger + show ?case using Suc unfolding n_def by auto +qed + +lemma count_zeros_max: + "count_zeros n k \ n" + by (induction n arbitrary: k) auto + +definition geom_pro :: "nat \ nat pseudorandom_object" where + "geom_pro n = \ pro_last = 2^n - 1, pro_select = count_zeros n \" + +lemma geom_pro_size: "pro_size (geom_pro n) = 2^n" + unfolding geom_pro_def pro_size_def by simp + +lemma geom_pro_range: "pro_set (geom_pro n) \ {..n}" + using count_zeros_max unfolding sample_pro_alt unfolding geom_pro_def by auto + +lemma geom_pro_prob: + "measure (sample_pro (geom_pro n)) {\. \ \ j} = of_bool (j \ n) / 2^j" (is "?L = ?R") +proof (cases "j \ n") + case True + have a:"{..<(2^n)::nat} \ {}" + by (simp add: lessThan_empty_iff) + have b:"finite {..<(2^n)::nat}" by simp + + define f :: "nat \ nat" where "f = (\x. x * 2^j)" + have d:"inj_on f {..<2^(n-j)}" unfolding f_def by (intro inj_onI) simp + + have e:"2^j > (0::nat)" by simp + + have "y \ f ` {..< 2^(n-j)} \ y \ {x. x < 2^n \ 2^j dvd x}" for y :: nat + proof - + have "y \ f ` {..< 2^(n-j)} \ (\x. x < 2 ^ (n - j) \ y = 2 ^ j * x)" + unfolding f_def by auto + also have "... \ (\x. 2^j * x < 2^j * 2 ^ (n-j) \ y = 2 ^ j * x)" + using e by simp + also have "... \ (\x. 2^j * x < 2^n \ y = 2 ^ j * x)" + using True by (subst power_add[symmetric]) simp + also have "... \ (\x. y < 2^n \ y = x * 2 ^ j)" + by (metis Groups.mult_ac(2)) + also have "... \ y \ {x. x < 2^n \ 2^j dvd x}" by auto + finally show ?thesis by simp + qed + + hence c:"f ` {..< 2^(n-j)} = {x. x < 2^n \ 2^j dvd x}" by auto + + have "?L = measure (pmf_of_set {..<2^n}) {\. count_zeros n \ \ j}" + unfolding sample_pro_alt geom_pro_size by (simp add:geom_pro_def) + also have "... = real (card {x::nat. x < 2^n \ 2^j dvd x}) / 2^n" + by (simp add: measure_pmf_of_set[OF a b] count_zeros_iff[OF True]) + (simp add:lessThan_def Collect_conj_eq) + also have "... = real (card (f ` {..<2^(n-j)})) / 2^n" + by (simp add:c) + also have "... = real (card ({..<(2^(n-j)::nat)})) / 2^n" + by (simp add: card_image[OF d]) + also have "... = ?R" + using True by (simp add:frac_eq_eq power_add[symmetric]) + finally show ?thesis by simp +next + case False + have "set_pmf (sample_pro (geom_pro n)) \ {..n}" + using geom_pro_range by simp + hence "?L = measure (sample_pro (geom_pro n)) {}" + using False by (intro measure_pmf_cong) auto + also have "... = ?R" + using False by simp + finally show ?thesis + by simp +qed + +lemma geom_pro_prob_single: + "measure (sample_pro (geom_pro n)) {j} \ 1 / 2^j" (is "?L \ ?R") +proof - + have "?L = measure (sample_pro (geom_pro n)) ({j..}-{j+1..})" + by (intro measure_pmf_cong) auto + also have "... = measure (sample_pro (geom_pro n)) {j..} - measure (sample_pro (geom_pro n)) {j+1..}" + by (intro measure_Diff) auto + also have "... = measure (sample_pro (geom_pro n)) {\. \ \ j}-measure (sample_pro (geom_pro n)) {\. \ \ (j+1)}" + by (intro arg_cong2[where f="(-)"] measure_pmf_cong) auto + also have "... = of_bool (j \ n) * 1 / 2 ^ j - of_bool (j + 1 \ n) / 2 ^ (j + 1)" + unfolding geom_pro_prob by simp + also have "... \ 1/2^j - 0" + by (intro diff_mono) auto + also have "... = ?R" by simp + finally show ?thesis by simp +qed + +(* Pair sample space *) + +definition prod_pro :: + "'a pseudorandom_object \ 'b pseudorandom_object \ ('a \ 'b) pseudorandom_object" + where + "prod_pro P Q = + \ pro_last = pro_size P * pro_size Q - 1, + pro_select = (\k. (pro_select P (k mod pro_size P), pro_select Q (k div pro_size P))) \" + +lemma prod_pro_size: + "pro_size (prod_pro P Q) = pro_size P * pro_size Q" + unfolding prod_pro_def by (subst pro_size_def) (simp add:pro_size_gt_0) + +lemma prod_pro: + "sample_pro (prod_pro P Q) = pair_pmf (sample_pro P) (sample_pro Q)" (is "?L = ?R") +proof - + let ?p = "pro_size P" + let ?q = "pro_size Q" + have "?L = map_pmf (\k. (pro_select P (k mod ?p),pro_select Q (k div ?p))) (pmf_of_set{..k. (k mod ?p, k div ?p)) (pmf_of_set{.. pro_set Q" + unfolding prod_pro set_pair_pmf by simp + +end \ No newline at end of file diff --git a/thys/Universal_Hash_Families/Pseudorandom_Objects_Hash_Families.thy b/thys/Universal_Hash_Families/Pseudorandom_Objects_Hash_Families.thy new file mode 100644 --- /dev/null +++ b/thys/Universal_Hash_Families/Pseudorandom_Objects_Hash_Families.thy @@ -0,0 +1,527 @@ +section \K-Independent Hash Families as Pseudorandom Objects\ + +theory Pseudorandom_Objects_Hash_Families + imports + Pseudorandom_Objects + Finite_Fields.Find_Irreducible_Poly + Carter_Wegman_Hash_Family + Universal_Hash_Families_More_Product_PMF +begin + +hide_const (open) Numeral_Type.mod_ring +hide_const (open) Divisibility.prime +hide_const (open) Isolated.discrete + +definition hash_space' :: + "('a,'b) idx_ring_enum_scheme \ nat \ ('c,'d) pseudorandom_object_scheme + \ (nat \ 'c) pseudorandom_object" + where "hash_space' R k S = ( + \ + pro_last = idx_size R ^k-1, + pro_select = (\x i. + pro_select S + (idx_enum_inv R (poly_eval R (poly_enum R k x) (idx_enum R i)) mod pro_size S)) + \)" + +lemma prod_pmf_of_set: + assumes "finite A" "finite B" "A \ {}" "B \ {}" + shows "pmf_of_set (A \ B) = pair_pmf (pmf_of_set A) (pmf_of_set B)" (is "?L = ?R") +proof (rule pmf_eqI) + fix x + have "pmf ?L x = indicator (A \ B) x / real (card (A \ B))" + using assms by (intro pmf_of_set) auto + also have "... = (indicator A (fst x) / real (card A)) * (indicator B (snd x) / real (card B))" + unfolding card_cartesian_product of_nat_mult by (simp add: indicator_times) + also have "... = pmf (pmf_of_set A) (fst x) * pmf (pmf_of_set B) (snd x)" + by (intro arg_cong2[where f="(*)"] pmf_of_set[symmetric] assms) + also have "... = pmf ?R x" + unfolding pmf_pair[symmetric] by auto + finally show "pmf ?L x = pmf ?R x" by simp +qed + +lemma hash_prob_single': + assumes "field F" "finite (carrier F)" + assumes "x \ carrier F" + assumes "1 \ n" + shows "measure (pmf_of_set (bounded_degree_polynomials F n)) {\. ring.hash F x \ = y} = + of_bool (y\ carrier F)/(real (card (carrier F)))" (is "?L = ?R") +proof (cases "y \ carrier F") + case True + have "?L = \

(\ in pmf_of_set (bounded_degree_polynomials F n). ring.hash F x \ = y)" by simp + also have "... = 1 / (real (card (carrier F)))" by (intro hash_prob_single assms conjI True) + also have "... = ?R" using True by simp + finally show ?thesis by simp +next + case False + interpret field "F" using assms by simp + have fin_carr: "finite (carrier F)" using assms by simp + note S = non_empty_bounded_degree_polynomials fin_degree_bounded[OF fin_carr] + let ?S = "bounded_degree_polynomials F n" + + have "hash x f \ y" if "f \ ?S" for f + proof - + have "hash x f \ carrier F" + using that unfolding hash_def bounded_degree_polynomials_def + by (intro eval_in_carrier assms) (simp add: polynomial_incl univ_poly_carrier) + thus ?thesis using False by auto + qed + hence "?L = measure (pmf_of_set (bounded_degree_polynomials F n)) {}" + using S by (intro measure_eq_AE AE_pmfI) simp_all + also have "... = ?R" using False by simp + finally show ?thesis by simp +qed + +lemma hash_k_wise_indep': + assumes "field F \ finite (carrier F)" + assumes "1 \ n" + shows "prob_space.k_wise_indep_vars (pmf_of_set (bounded_degree_polynomials F n)) n + (\_. discrete) (ring.hash F) (carrier F)" + by (intro prob_space.k_wise_indep_vars_compose[OF _ hash_k_wise_indep[OF assms]] + prob_space_measure_pmf) auto + +lemma hash_space': + fixes R :: "('a,'b) idx_ring_enum_scheme" + assumes "enum\<^sub>C R" "field\<^sub>C R" + assumes "pro_size S dvd order (ring_of R)" + assumes "I \ {.. k" + shows "map_pmf (\f. (\i\I. f i)) (sample_pro (hash_space' R k S)) = prod_pmf I (\_. sample_pro S)" + (is "?L = ?R") +proof (cases "I = {}") + case False + let ?b = "idx_size R" + let ?s = "pro_size S" + let ?t = "?b div ?s" + let ?g = "\x i. poly_eval R (poly_enum R k x) (idx_enum R i)" + let ?f = "\x. pro_select S (idx_enum_inv R x mod ?s)" + let ?R_pmf = "pmf_of_set (carrier (ring_of R))" + let ?S = "{xs \ carrier (poly_ring (ring_of R)). length xs \ k}" + let ?T = "pmf_of_set (bounded_degree_polynomials (ring_of R) k)" + + interpret field "ring_of R" using assms(2) unfolding field\<^sub>C_def by auto + + have ring_c: "ring\<^sub>C R" using field_c_imp_ring assms(2) by auto + note enum_c = enum_cD[OF assms(1)] + + have fin_carr: "finite (carrier (ring_of R))" using enum_c by simp + + have "0 < card I" using False assms(4) card_gt_0_iff finite_nat_iff_bounded by blast + also have "... \ k" using assms(5) by simp + finally have k_gt_0: "k > 0" by simp + have b_gt_0: "?b > 0" unfolding enum_c(2) using fin_carr order_gt_0_iff_finite by blast + hence t_gt_0: "?t > 0" using enum_c(2) assms(3) dvd_div_gt0 by simp + have b_k_gt_0: "?b ^ k > 0" using b_gt_0 by simp + + have fin_I: "finite I" using assms(4) finite_subset by auto + + have inj: "inj_on (idx_enum R) I" + using assms(4) unfolding enum_c(2) + by (intro inj_on_subset[OF bij_betw_imp_inj_on[OF enum_c(3)]]) + have "card (idx_enum R ` I) \ k" + using assms(5) unfolding card_image[OF inj] by auto + + hence "prob_space.indep_vars ?T (\_. discrete) hash (idx_enum R ` I)" + using assms(4) k_gt_0 fin_I bij_betw_apply[OF enum_c(3)] enum_c(2) + by (intro prob_space.k_wise_indep_vars_subset[OF _ hash_k_wise_indep'] + prob_space_measure_pmf conjI fin_carr field_axioms) auto + hence "prob_space.indep_vars ?T ((\_. discrete) \ idx_enum R) (\x \. eval \ (idx_enum R x)) I" + using inj unfolding hash_def + by (intro prob_space.indep_vars_reindex prob_space_measure_pmf) auto + hence indep: "prob_space.indep_vars ?T (\_. discrete) (\x \. eval \ (idx_enum R x)) I" + by (simp add:comp_def) + + have 0: "pmf (map_pmf (\x. \i\I. eval x (idx_enum R i)) ?T) \ = pmf (prod_pmf I (\_. ?R_pmf)) \" + (is "?L1 = ?R1") for \ + proof (cases "\ \ extensional I") + case True + have "?L1 = measure ?T {x. (\i\I. eval x (idx_enum R i)) = \}" + by (simp add:pmf_map vimage_def) + also have "... = measure ?T {x. (\i\I. eval x (idx_enum R i) = \ i)}" + using True unfolding restrict_def extensional_def + by (intro arg_cong2[where f="measure"] refl Collect_cong) auto + also have "... = (\i\I. measure ?T {x. eval x (idx_enum R i) = \ i})" + by (intro prob_space.split_indep_events[where I="I" and p="?T"] prob_space_measure_pmf + fin_I refl prob_space.indep_vars_compose2[OF _ indep]) auto + also have "... = (\i\I. measure ?T {x. hash (idx_enum R i) x = \ i})" + unfolding hash_def by simp + also have "... = (\i\I. of_bool( \ i \ carrier (ring_of R))/real (card (carrier (ring_of R))))" + using k_gt_0 assms(4) by (intro prod.cong refl hash_prob_single' + bij_betw_apply[OF enum_c(3)] fin_carr field_axioms) (auto simp:enum_c) + also have "... = (\i\I. pmf (pmf_of_set (carrier (ring_of R))) (\ i))" + using fin_carr carrier_not_empty by (simp add:indicator_def) + also have "... = ?R1" + using True unfolding pmf_prod_pmf[OF fin_I] by simp + finally show ?thesis by simp + next + case False + have "?L1 = 0" using False unfolding pmf_eq_0_set_pmf set_map_pmf by auto + moreover have "?R1 = 0" + using False unfolding pmf_eq_0_set_pmf set_prod_pmf[OF fin_I] PiE_def by simp + ultimately show ?thesis by simp + qed + + have "map_pmf (\x. \i\I. ?g x i) (pmf_of_set {..x. \i\I. poly_eval R x (idx_enum R i)) (map_pmf (poly_enum R k) (pmf_of_set {..x. \i\I. poly_eval R x (idx_enum R i)) (pmf_of_set ?S)" + using b_k_gt_0 by (intro arg_cong2[where f="map_pmf"] refl map_pmf_of_set_bij_betw + bij_betw_poly_enum assms(1,2) field_c_imp_ring) blast+ + also have "... = map_pmf (\x. \i\I. poly_eval R x (idx_enum R i)) ?T" + using k_gt_0 unfolding bounded_degree_polynomials_def + by (intro map_pmf_cong refl arg_cong[where f="pmf_of_set"] restrict_ext ring_c) auto + also have "... = map_pmf (\x. \i\I. eval x (idx_enum R i)) ?T" + using non_empty_bounded_degree_polynomials fin_degree_bounded[OF fin_carr] assms(4) + by (intro map_pmf_cong poly_eval refl restrict_ext ring_c bij_betw_apply[OF enum_c(3)]) + (auto simp add:bounded_degree_polynomials_def ring_of_poly[OF ring_c] enum_c(2)) + also have "... = prod_pmf I (\_. ?R_pmf)" (is "?L1 = ?R1") + by (intro pmf_eqI 0) + finally have 0: "map_pmf (\x. \i\I. ?g x i) (pmf_of_set {.._. ?R_pmf)" + by simp + + have 1: "map_pmf (\x. x mod ?s) (pmf_of_set {..x. (x mod ?s, x div ?s)) (pmf_of_set {.. {..x. pro_select S (x mod ?s)) (map_pmf (idx_enum_inv R) ?R_pmf)" + by (simp add:map_pmf_comp) + also have "... = map_pmf (\x. pro_select S (x mod ?s)) (pmf_of_set {..x. x mod ?s) (pmf_of_set {..x. \i\I. ?f (?g x i)) (pmf_of_set {..f. \i\I. ?f (f i)) (map_pmf (\x. \i\I. ?g x i) (pmf_of_set {.._. map_pmf ?f (pmf_of_set (carrier (ring_of R))))" unfolding 0 + by (simp add:map_pmf_def Pi_pmf_bind_return[OF fin_I, where d'="undefined"] restrict_def) + also have "... = ?R" unfolding 2 by simp + finally show ?thesis by simp +next + case True + have "?L = map_pmf (\f i. undefined) (sample_pro (hash_space' R k S))" + using True by (intro map_pmf_cong refl) auto + also have "... = return_pmf (\f. undefined)" unfolding map_pmf_const by simp + also have "... = ?R" using True by simp + finally show "?L = ?R" by simp +qed + +lemma hash_space'_range: + "pro_select (hash_space' R k S) i j \ pro_set S" + unfolding hash_space'_def by (simp add: pro_select_in_set) + +definition hash_pro :: + "nat \ nat \ ('a,'b) pseudorandom_object_scheme \ (nat \ 'a) pseudorandom_object" + where "hash_pro k d S = ( + let (p,j) = split_power (pro_size S); + l = max j (floorlog p (d-1)) + in hash_space' (GF (p^l)) k S)" + +definition hash_pro_spmf :: + "nat \ nat \ ('a,'b) pseudorandom_object_scheme \ (nat \ 'a) pseudorandom_object spmf" + where "hash_pro_spmf k d S = + do { + let (p,j) = split_power (pro_size S); + let l = max j (floorlog p (d-1)); + R \ GF\<^sub>R (p^l); + return_spmf (hash_space' R k S) + }" + +definition hash_pro_pmf :: + "nat \ nat \ ('a,'b) pseudorandom_object_scheme \ (nat \ 'a) pseudorandom_object pmf" + where "hash_pro_pmf k d S = map_pmf the (hash_pro_spmf k d S)" + +syntax + "_FLIPBIND" :: "('a \ 'b) \ 'c \ 'b" (infixr "=<<" 54) + +translations + "_FLIPBIND f g" => "g \ f" + +context + fixes S + fixes d :: nat + fixes k :: nat + assumes size_prime_power: "is_prime_power (pro_size S)" +begin + +private definition p where "p = fst (split_power (pro_size S))" +private definition j where "j = snd (split_power (pro_size S))" +private definition l where "l = max j (floorlog p (d-1))" + +private lemma split_power: "(p,j) = split_power (pro_size S)" + using p_def j_def by auto + +private lemma hash_sample_space_alt: "hash_pro k d S = hash_space' (GF (p^l)) k S" + unfolding hash_pro_def split_power[symmetric] by (simp add:j_def l_def Let_def) + +private lemma p_prime : "prime p" and j_gt_0: "j > 0" +proof - + obtain q r where 0:"pro_size S = q^r" and q_prime: "prime q" and r_gt_0: "r > 0" + using size_prime_power is_prime_power_def by blast + + have "(p,j) = split_power (q^r)" unfolding split_power 0 by simp + also have "... = (q,r)" by (intro split_power_prime q_prime r_gt_0) + finally have "(p,j) = (q,r)" by simp + thus "prime p" "j > 0" using q_prime r_gt_0 by auto +qed + +private lemma l_gt_0: "l > 0" + unfolding l_def using j_gt_0 by simp + +private lemma prime_power: "is_prime_power (p^l)" + using p_prime l_gt_0 unfolding is_prime_power_def by auto + +lemma hash_in_hash_pro_spmf: "hash_pro k d S \ set_spmf (hash_pro_spmf k d S)" + using GF_in_GF_R[OF prime_power] + unfolding hash_pro_def hash_pro_spmf_def split_power[symmetric] l_def by (auto simp add:set_bind_spmf) + +lemma lossless_hash_pro_spmf: "lossless_spmf (hash_pro_spmf k d S)" +proof - + have "lossless_spmf (GF\<^sub>R (p^l))" by (intro galois_field_random_1 prime_power) + thus ?thesis unfolding hash_pro_spmf_def split_power[symmetric] l_def by simp +qed + +lemma hashp_eq_hash_pro_spmf: "set_pmf (hash_pro_pmf k d S) = set_spmf (hash_pro_spmf k d S)" + unfolding hash_pro_pmf_def using lossless_imp_spmf_of_pmf[OF lossless_hash_pro_spmf] + by (metis set_spmf_spmf_of_pmf) + +lemma hashp_in_hash_pro_spmf: + assumes "x \ set_pmf (hash_pro_pmf k d S)" + shows "x \ set_spmf (hash_pro_spmf k d S)" + using hashp_eq_hash_pro_spmf assms by auto + +lemma hash_pro_in_hash_pro_pmf: "hash_pro k d S \ set_pmf (hash_pro_pmf k d S)" + unfolding hashp_eq_hash_pro_spmf by (intro hash_in_hash_pro_spmf) + +lemma hash_pro_spmf_distr: + assumes "s \ set_spmf (hash_pro_spmf k d S)" + assumes "I \ {.. k" + shows "map_pmf (\f. (\i\I. f i)) (sample_pro s) = prod_pmf I (\_. sample_pro S)" +proof - + have "(d-1) < p^floorlog p (d-1)" + using floorlog_leD prime_gt_1_nat[OF p_prime] by simp + hence "d \ p^floorlog p (d-1)" by (cases d) auto + also have "... \ p^l" + using prime_gt_0_nat[OF p_prime] unfolding l_def by (intro power_increasing) auto + finally have 0: "d \ p^l" by simp + + obtain R where R_in: "R \ set_spmf (GF\<^sub>R (p^l))" and s_def: "s = hash_space' R k S" + using assms(1) unfolding hash_pro_spmf_def split_power[symmetric] l_def + by (auto simp add:set_bind_spmf) + have 1: "order (ring_of R) = p ^ l" + using galois_field_random_1(1)[OF prime_power R_in] by auto + have "I \ {.. {.. {.. l" unfolding l_def by auto + hence "pro_size S dvd order (ring_of R)" + unfolding 1 split_power_result[OF split_power] by (intro le_imp_power_dvd) + ultimately show ?thesis + using galois_field_random_1(1)[OF prime_power R_in] assms(3) + unfolding s_def by (intro hash_space') simp_all +qed + +lemma hash_pro_spmf_component: + assumes "s \ set_spmf (hash_pro_spmf k d S)" + assumes "i < d" "k > 0" + shows "map_pmf (\f. f i) (sample_pro s) = sample_pro S" (is "?L = ?R") +proof - + have "?L = map_pmf (\f. f i) (map_pmf (\f. (\i\{i}. f i)) (sample_pro s))" + using assms(1) unfolding map_pmf_comp by (intro map_pmf_cong refl) auto + also have "... = map_pmf (\f. f i) (prod_pmf {i} (\_. sample_pro S))" + using assms by (subst hash_pro_spmf_distr[OF assms(1)]) auto + also have "... = ?R" by (subst Pi_pmf_component) auto + finally show ?thesis by simp +qed + +lemma hash_pro_spmf_indep: + assumes "s \ set_spmf (hash_pro_spmf k d S)" + assumes "I \ {.. k" + shows "prob_space.indep_vars (sample_pro s) (\_. discrete) (\i \. \ i) I" +proof (rule measure_pmf.indep_vars_pmf[OF refl]) + fix x J + assume a:"J \ I" + have 0:"J \ {.. card I" using finite_subset[OF assms(2)] by (intro card_mono a) auto + also have "... \ k" using assms(3) by simp + finally have 1: " card J \ k" by simp + let ?s = "sample_pro s" + + have 2: "0 < k" if "x \ J" for x + proof - + have "0 < card J" using 0 that card_gt_0_iff finite_nat_iff_bounded by auto + also have "... \ k" using 1 by simp + finally show ?thesis by simp + qed + + have "measure ?s {\. \j\J. \ j = x j} = measure (map_pmf (\\. \j\J. \ j)?s) {\. \j\J. \ j = x j}" + by auto + also have "... = measure (prod_pmf J (\_. sample_pro S)) (Pi J (\j. {x j}))" + unfolding hash_pro_spmf_distr[OF assms(1) 0 1] by (intro arg_cong2[where f="measure"]) (auto simp:Pi_def) + also have "... = (\j\J. measure (sample_pro S) {x j})" + using finite_subset[OF a] finite_subset[OF assms(2)] by (intro measure_Pi_pmf_Pi) auto + also have "... = (\j\J. measure (map_pmf (\\. \ j) ?s) {x j})" + using 0 1 2 by (intro prod.cong arg_cong2[where f="measure"] refl + arg_cong[where f="measure_pmf"] hash_pro_spmf_component[OF assms(1), symmetric]) auto + also have "... = (\j\J. measure ?s {\. \ j = x j})" by (simp add:vimage_def) + finally show "measure ?s {\. \j\J. \ j = x j} = (\j\J. measure_pmf.prob ?s {\. \ j = x j})" + by simp +qed + +lemma hash_pro_spmf_k_indep: + assumes "s \ set_spmf (hash_pro_spmf k d S)" + shows "prob_space.k_wise_indep_vars (sample_pro s) k (\_. discrete) (\i \. \ i) {.. set_spmf (hash_pro_spmf k d S)" + shows "pro_size s = (p^l)^k" (is "?L = ?R") +proof - + obtain R where R_in: "R \ set_spmf (GF\<^sub>R (p^l))" and s_def: "s = hash_space' R k S" + using assms(1) unfolding hash_pro_spmf_def split_power[symmetric] l_def + by (auto simp add:set_bind_spmf) + have 1: "order (ring_of R) = p ^ l" and ec: "enum\<^sub>C R" + using galois_field_random_1(1)[OF prime_power R_in] by auto + + have "?L = idx_size R ^ k - 1 + 1" + unfolding s_def pro_size_def hash_space'_def by simp + also have "... = ((p^l)^k - 1) + 1" + using 1 enum_cD(2)[OF ec] by simp + also have "... = (p^l)^k" using prime_gt_0_nat[OF p_prime] by simp + finally show ?thesis by simp +qed + +lemma floorlog_alt_def: + "floorlog b a = (if 1 < b then nat \log (real b) (real a+1)\ else 0)" +proof (cases "a > 0 \ 1 < b") + case True + have 1:"log (real b) (real a + 1) > 0" using True by (subst zero_less_log_cancel_iff) auto + + have "a < real a + 1" by simp + also have "... = b powr (log b (real a + 1))" using True by simp + also have "... \ b powr (\log b (real a + 1)\)" + using True by (intro iffD2[OF powr_le_cancel_iff]) auto + also have "... = b powr (real (nat \log b (real a + 1)\))" + using 1 by (intro arg_cong2[where f="(powr)"] refl) linarith + also have "... = b ^ nat \log (real b) (real a + 1)\" using True by (subst powr_realpow) auto + finally have "a < b ^ nat \log (real b) (real a + 1)\" by simp + hence 0:"floorlog b a \ nat \log (real b) (real a+1)\" using True by (intro floorlog_leI) auto + + have "b ^ (nat \log b (real a + 1)\ - 1) = b powr (real (nat \log b (real a + 1)\ - 1))" + using True by (subst powr_realpow) auto + also have "... = b powr (\log b (real a + 1)\ - 1)" + using 1 by (intro arg_cong2[where f="(powr)"] refl) linarith + also have "... < b powr (log b (real a + 1))" using True by (intro powr_less_mono) linarith+ + also have "... = real (a + 1)" using True by simp + finally have "b ^ (nat \log (real b) (real a + 1)\ - 1) < a + 1" by linarith + hence "b ^ (nat \log (real b) (real a + 1)\ - 1) \ a" by simp + hence "floorlog b a \ nat \log (real b) (real a+1)\" using True by (intro floorlog_geI) auto + hence "floorlog b a = nat \log (real b) (real a+1)\" using 0 by linarith + also have "... = (if 1 < b then nat \log (real b) (real a+1)\ else 0)" using True by simp + finally show ?thesis by simp +next + case False + hence a_eq_0: "a = 0 \ \(1 < b)" by simp + thus ?thesis unfolding floorlog_def by auto +qed + +lemma hash_pro_spmf_size: + assumes "s \ set_spmf (hash_pro_spmf k d S)" + assumes "(p',j') = split_power (pro_size S)" + shows "pro_size s = (p'^(max j' (floorlog p' (d-1))))^k" + unfolding hash_pro_spmf_size_aux[OF assms(1)] l_def p_def j_def using assms(2) + by (metis fst_conv snd_conv) + +lemma hash_pro_spmf_size': + assumes "s \ set_spmf (hash_pro_spmf k d S)" "d > 0" + assumes "(p',j') = split_power (pro_size S)" + shows "pro_size s = (p'^(k*max j' (nat \log p' d\)))" +proof - + have "pro_size s = (p^(max j (floorlog p (d-1))))^k" + unfolding hash_pro_spmf_size_aux[OF assms(1)] l_def by simp + also have "... = (p^(max j (nat \log p (real (d-1)+1)\)))^k" + using prime_gt_1_nat[OF p_prime] by (simp add:floorlog_alt_def) + also have "... = (p^(max j (nat \log p d\)))^k" using assms(2) by (subst of_nat_diff) auto + also have "... = p^(k*max j (nat \log p d\))" by (simp add:ac_simps power_mult[symmetric]) + also have "... = p'^(k*max j' (nat \log p' d\))" + using assms(3) p_def j_def by (metis fst_conv snd_conv) + finally show ?thesis by simp +qed + +lemma hash_pro_spmf_size_prime_power: + assumes "s \ set_spmf (hash_pro_spmf k d S)" + assumes "k > 0" + shows "is_prime_power (pro_size s)" + unfolding hash_pro_spmf_size_aux[OF assms(1)] power_mult[symmetric] is_prime_power_def + using p_prime mult_pos_pos[OF l_gt_0 assms(2)] by blast + +lemma hash_pro_smpf_range: + assumes "s \ set_spmf (hash_pro_spmf k d S)" + shows "pro_select s i q \ pro_set S" +proof - + obtain R where R_in: "R \ set_spmf (GF\<^sub>R (p^l))" and s_def: "s = hash_space' R k S" + using assms(1) unfolding hash_pro_spmf_def split_power[symmetric] l_def + by (auto simp add:set_bind_spmf) + thus ?thesis + unfolding s_def using hash_space'_range by auto +qed + +lemmas hash_pro_size' = hash_pro_spmf_size'[OF hash_in_hash_pro_spmf] +lemmas hash_pro_size = hash_pro_spmf_size[OF hash_in_hash_pro_spmf] +lemmas hash_pro_size_prime_power = hash_pro_spmf_size_prime_power[OF hash_in_hash_pro_spmf] +lemmas hash_pro_distr = hash_pro_spmf_distr[OF hash_in_hash_pro_spmf] +lemmas hash_pro_component = hash_pro_spmf_component[OF hash_in_hash_pro_spmf] +lemmas hash_pro_indep = hash_pro_spmf_indep[OF hash_in_hash_pro_spmf] +lemmas hash_pro_k_indep = hash_pro_spmf_k_indep[OF hash_in_hash_pro_spmf] +lemmas hash_pro_range = hash_pro_smpf_range[OF hash_in_hash_pro_spmf] + +lemmas hash_pro_pmf_size' = hash_pro_spmf_size'[OF hashp_in_hash_pro_spmf] +lemmas hash_pro_pmf_size = hash_pro_spmf_size[OF hashp_in_hash_pro_spmf] +lemmas hash_pro_pmf_size_prime_power = hash_pro_spmf_size_prime_power[OF hashp_in_hash_pro_spmf] +lemmas hash_pro_pmf_distr = hash_pro_spmf_distr[OF hashp_in_hash_pro_spmf] +lemmas hash_pro_pmf_component = hash_pro_spmf_component[OF hashp_in_hash_pro_spmf] +lemmas hash_pro_pmf_indep = hash_pro_spmf_indep[OF hashp_in_hash_pro_spmf] +lemmas hash_pro_pmf_k_indep = hash_pro_spmf_k_indep[OF hashp_in_hash_pro_spmf] +lemmas hash_pro_pmf_range = hash_pro_smpf_range[OF hashp_in_hash_pro_spmf] + +end + +bundle pseudorandom_object_notation +begin +notation hash_pro ("\") +notation hash_pro_spmf ("\\<^sub>S") +notation hash_pro_pmf ("\\<^sub>P") +notation list_pro ("\") +notation nat_pro ("\") +notation geom_pro ("\") +notation prod_pro (infixr "\\<^sub>P" 65) +end + +bundle no_pseudorandom_object_notation +begin +no_notation hash_pro ("\") +no_notation hash_pro_spmf ("\\<^sub>S") +no_notation hash_pro_pmf ("\\<^sub>P") +no_notation list_pro ("\") +no_notation nat_pro ("\") +no_notation geom_pro ("\") +no_notation prod_pro (infixr "\\<^sub>P" 65) +end + +unbundle pseudorandom_object_notation + +end \ No newline at end of file diff --git a/thys/Universal_Hash_Families/ROOT b/thys/Universal_Hash_Families/ROOT --- a/thys/Universal_Hash_Families/ROOT +++ b/thys/Universal_Hash_Families/ROOT @@ -1,18 +1,20 @@ chapter AFP session Universal_Hash_Families = "HOL-Probability" + options [timeout = 600] sessions "HOL-Algebra" Concentration_Inequalities Finite_Fields Interpolation_Polynomials_HOL_Algebra theories Universal_Hash_Families Universal_Hash_Families_More_Independent_Families Carter_Wegman_Hash_Family Universal_Hash_Families_More_Finite_Fields Universal_Hash_Families_More_Product_PMF + Pseudorandom_Objects + Pseudorandom_Objects_Hash_Families document_files "root.tex" "root.bib" diff --git a/thys/Universal_Hash_Families/Universal_Hash_Families.thy b/thys/Universal_Hash_Families/Universal_Hash_Families.thy --- a/thys/Universal_Hash_Families/Universal_Hash_Families.thy +++ b/thys/Universal_Hash_Families/Universal_Hash_Families.thy @@ -1,81 +1,87 @@ section \Introduction and Definition\ theory Universal_Hash_Families imports "HOL-Probability.Independent_Family" begin text \Universal hash families are commonly used in randomized algorithms and data structures to randomize the input of algorithms, such that probabilistic methods can be employed without requiring any assumptions about the input distribution. If we regard a family of hash functions from a domain $D$ to a finite range $R$ as a uniform probability space, then the family is $k$-universal if: \begin{itemize} \item For each $x \in D$ the evaluation of the functions at $x$ forms a uniformly distributed random variable on $R$. \item The evaluation random variables for $k$ or fewer distinct domain elements form an independent family of random variables. \end{itemize} This definition closely follows the definition from Vadhan~\<^cite>\\\textsection 3.5.5\ in "vadhan2012"\, with the minor modification that independence is required not only for exactly $k$, but also for \emph{fewer} than $k$ distinct domain elements. The correction is due to the fact that in the corner case where $D$ has fewer than $k$ elements, the second part of their definition becomes void. In the formalization this helps avoid an unnecessary assumption in the theorems. The following definition introduces the notion of $k$-wise independent random variables:\ definition (in prob_space) k_wise_indep_vars where "k_wise_indep_vars k M' X I = (\J \ I. card J \ k \ finite J \ indep_vars M' X J)" lemma (in prob_space) k_wise_indep_vars_subset: assumes "k_wise_indep_vars k M' X I" assumes "J \ I" assumes "finite J" assumes "card J \ k" shows "indep_vars M' X J" using assms by (simp add:k_wise_indep_vars_def) +lemma (in prob_space) k_wise_indep_subset: + assumes "J \ I" + assumes "k_wise_indep_vars k M' X' I" + shows "k_wise_indep_vars k M' X' J" + using assms unfolding k_wise_indep_vars_def by simp + text \Similarly for a finite non-empty set $A$ the predicate @{term "uniform_on X A"} indicates that the random variable is uniformly distributed on $A$:\ definition (in prob_space) "uniform_on X A = ( distr M (count_space UNIV) X = uniform_measure (count_space UNIV) A \ A \ {} \ finite A \ random_variable (count_space UNIV) X)" lemma (in prob_space) uniform_onD: assumes "uniform_on X A" shows "prob {\ \ space M. X \ \ B} = card (A \ B) / card A" proof - have "prob {\ \ space M. X \ \ B} = prob (X -` B \ space M)" by (subst Int_commute, simp add:vimage_def Int_def) also have "... = measure (distr M (count_space UNIV) X) B" using assms by (subst measure_distr, auto simp:uniform_on_def) also have "... = measure (uniform_measure (count_space UNIV) A) B" using assms by (simp add:uniform_on_def) also have "... = card (A \ B) / card A" using assms by (subst measure_uniform_measure, auto simp:uniform_on_def)+ finally show ?thesis by simp qed text \With the two previous definitions it is possible to define the $k$-universality condition for a family of hash functions from $D$ to $R$:\ definition (in prob_space) "k_universal k X D R = ( k_wise_indep_vars k (\_. count_space UNIV) X D \ (\i \ D. uniform_on (X i) R))" text \Note: The definition is slightly more generic then the informal specification from above. This is because usually a family is formed by a single function with a variable seed parameter. Instead of choosing a random function from a probability space, a random seed is chosen from the probability space which parameterizes the hash function. The following section contains some preliminary results about independent families of random variables. Section~\ref{sec:carter_wegman} introduces the Carter-Wegman hash family, which is an explicit construction of $k$-universal families for arbitrary $k$ using polynomials over finite fields. The last section contains a proof that the factor ring of the integers modulo a prime ideal is a finite field, followed by an isomorphic construction of prime fields over an initial segment of the natural numbers.\ end diff --git a/thys/Universal_Hash_Families/Universal_Hash_Families_More_Product_PMF.thy b/thys/Universal_Hash_Families/Universal_Hash_Families_More_Product_PMF.thy --- a/thys/Universal_Hash_Families/Universal_Hash_Families_More_Product_PMF.thy +++ b/thys/Universal_Hash_Families/Universal_Hash_Families_More_Product_PMF.thy @@ -1,229 +1,257 @@ section \Indexed Products of Probability Mass Functions\ theory Universal_Hash_Families_More_Product_PMF imports "HOL-Probability.Product_PMF" Concentration_Inequalities.Concentration_Inequalities_Preliminary + Finite_Fields.Finite_Fields_More_Bijections Universal_Hash_Families_More_Independent_Families begin hide_const (open) Isolated.discrete text \This section introduces a restricted version of @{term "Pi_pmf"} where the default value is @{term "undefined"} and contains some additional results about that case in addition to @{theory "HOL-Probability.Product_PMF"}\ abbreviation prod_pmf where "prod_pmf I M \ Pi_pmf I undefined M" lemma measure_pmf_cong: assumes "\x. x \ set_pmf p \ x \ P \ x \ Q" shows "measure (measure_pmf p) P = measure (measure_pmf p) Q" using assms by (intro finite_measure.finite_measure_eq_AE AE_pmfI) auto lemma pmf_mono: assumes "\x. x \ set_pmf p \ x \ P \ x \ Q" shows "measure (measure_pmf p) P \ measure (measure_pmf p) Q" proof - have "measure (measure_pmf p) P = measure (measure_pmf p) (P \ (set_pmf p))" by (intro measure_pmf_cong) auto also have "... \ measure (measure_pmf p) Q" using assms by (intro finite_measure.finite_measure_mono) auto finally show ?thesis by simp qed lemma pmf_prod_pmf: assumes "finite I" shows "pmf (prod_pmf I M) x = (if x \ extensional I then \i \ I. (pmf (M i)) (x i) else 0)" by (simp add: pmf_Pi[OF assms(1)] extensional_def) lemma PiE_defaut_undefined_eq: "PiE_dflt I undefined M = PiE I M" by (simp add:PiE_dflt_def PiE_def extensional_def Pi_def set_eq_iff) blast lemma set_prod_pmf: assumes "finite I" shows "set_pmf (prod_pmf I M) = PiE I (set_pmf \ M)" by (simp add:set_Pi_pmf[OF assms] PiE_defaut_undefined_eq) text \A more general version of @{thm [source] "measure_Pi_pmf_Pi"}.\ lemma prob_prod_pmf': assumes "finite I" assumes "J \ I" shows "measure (measure_pmf (Pi_pmf I d M)) (Pi J A) = (\ i \ J. measure (M i) (A i))" proof - have a:"Pi J A = Pi I (\i. if i \ J then A i else UNIV)" using assms by (simp add:Pi_def set_eq_iff, blast) show ?thesis using assms by (simp add:if_distrib a measure_Pi_pmf_Pi[OF assms(1)] prod.If_cases[OF assms(1)] Int_absorb1) qed lemma prob_prod_pmf_slice: assumes "finite I" assumes "i \ I" shows "measure (measure_pmf (prod_pmf I M)) {\. P (\ i)} = measure (M i) {\. P \}" using prob_prod_pmf'[OF assms(1), where J="{i}" and M="M" and A="\_. Collect P"] by (simp add:assms Pi_def) definition restrict_dfl where "restrict_dfl f A d = (\x. if x \ A then f x else d)" lemma pi_pmf_decompose: assumes "finite I" shows "Pi_pmf I d M = map_pmf (\\. restrict_dfl (\i. \ (f i) i) I d) (Pi_pmf (f ` I) (\_. d) (\j. Pi_pmf (f -` {j} \ I) d M))" proof - have fin_F_I:"finite (f ` I)" using assms by blast have "finite I \ ?thesis" using fin_F_I proof (induction "f ` I" arbitrary: I rule:finite_induct) case empty then show ?case by (simp add:restrict_dfl_def) next case (insert x F) have a: "(f -` {x} \ I) \ (f -` F \ I) = I" using insert(4) by blast have b: "F = f ` (f -` F \ I) " using insert(2,4) by (auto simp add:set_eq_iff image_def vimage_def) have c: "finite (f -` F \ I)" using insert by blast have d: "\j. j \ F \ (f -` {j} \ (f -` F \ I)) = (f -` {j} \ I)" using insert(4) by blast have " Pi_pmf I d M = Pi_pmf ((f -` {x} \ I) \ (f -` F \ I)) d M" by (simp add:a) also have "... = map_pmf (\(g, h) i. if i \ f -` {x} \ I then g i else h i) (pair_pmf (Pi_pmf (f -` {x} \ I) d M) (Pi_pmf (f -` F \ I) d M))" using insert by (subst Pi_pmf_union) auto also have "... = map_pmf (\(g,h) i. if f i = x \ i \ I then g i else if f i \ F \ i \ I then h (f i) i else d) (pair_pmf (Pi_pmf (f -` {x} \ I) d M) (Pi_pmf F (\_. d) (\j. Pi_pmf (f -` {j} \ (f -` F \ I)) d M)))" by (simp add:insert(3)[OF b c] map_pmf_comp case_prod_beta' apsnd_def map_prod_def pair_map_pmf2 b[symmetric] restrict_dfl_def) (metis fst_conv snd_conv) also have "... = map_pmf (\(g,h) i. if i \ I then (h(x := g)) (f i) i else d) (pair_pmf (Pi_pmf (f -` {x} \ I) d M) (Pi_pmf F (\_. d) (\j. Pi_pmf (f -` {j} \ I) d M)))" using insert(4) d by (intro arg_cong2[where f="map_pmf"] ext) (auto simp add:case_prod_beta' cong:Pi_pmf_cong) also have "... = map_pmf (\\ i. if i \ I then \ (f i) i else d) (Pi_pmf (insert x F) (\_. d) (\j. Pi_pmf (f -` {j} \ I) d M))" by (simp add:Pi_pmf_insert[OF insert(1,2)] map_pmf_comp case_prod_beta') finally show ?case by (simp add:insert(4) restrict_dfl_def) qed thus ?thesis using assms by blast qed lemma restrict_dfl_iter: "restrict_dfl (restrict_dfl f I d) J d = restrict_dfl f (I \ J) d" by (rule ext, simp add:restrict_dfl_def) lemma indep_vars_restrict': assumes "finite I" shows "prob_space.indep_vars (Pi_pmf I d M) (\_. discrete) (\i \. restrict_dfl \ (f -` {i} \ I) d) (f ` I)" proof - let ?Q = "(Pi_pmf (f ` I) (\_. d) (\i. Pi_pmf (I \ f -` {i}) d M))" have a:"prob_space.indep_vars ?Q (\_. discrete) (\i \. \ i) (f ` I)" using assms by (intro indep_vars_Pi_pmf, blast) have b: "AE x in measure_pmf ?Q. \i\f ` I. x i = restrict_dfl (\i. x (f i) i) (I \ f -` {i}) d" using assms by (auto simp add:PiE_dflt_def restrict_dfl_def AE_measure_pmf_iff set_Pi_pmf comp_def Int_commute) have "prob_space.indep_vars ?Q (\_. discrete) (\i x. restrict_dfl (\i. x (f i) i) (I \ f -` {i}) d) (f ` I)" by (rule prob_space.indep_vars_cong_AE[OF prob_space_measure_pmf b a], simp) thus ?thesis using prob_space_measure_pmf by (auto intro!:prob_space.indep_vars_distr simp:pi_pmf_decompose[OF assms, where f="f"] map_pmf_rep_eq comp_def restrict_dfl_iter Int_commute) qed lemma indep_vars_restrict_intro': assumes "finite I" assumes "\i \. i \ J \ X' i \ = X' i (restrict_dfl \ (f -` {i} \ I) d)" assumes "J = f ` I" assumes "\\ i. i \ J \ X' i \ \ space (M' i)" shows "prob_space.indep_vars (measure_pmf (Pi_pmf I d p)) M' (\i \. X' i \) J" proof - define M where "M \ measure_pmf (Pi_pmf I d p)" interpret prob_space "M" using M_def prob_space_measure_pmf by blast have "indep_vars (\_. discrete) (\i x. restrict_dfl x (f -` {i} \ I) d) (f ` I)" unfolding M_def by (rule indep_vars_restrict'[OF assms(1)]) hence "indep_vars M' (\i \. X' i (restrict_dfl \ ( f -` {i} \ I) d)) (f ` I)" using assms(4) by (intro indep_vars_compose2[where Y="X'" and N="M'" and M'="\_. discrete"]) (auto simp:assms(3)) hence "indep_vars M' (\i \. X' i \) (f ` I)" using assms(2)[symmetric] by (simp add:assms(3) cong:indep_vars_cong) thus ?thesis unfolding M_def using assms(3) by simp qed lemma fixes f :: "'b \ ('c :: {second_countable_topology,banach,real_normed_field})" assumes "finite I" assumes "i \ I" assumes "integrable (measure_pmf (M i)) f" shows integrable_Pi_pmf_slice: "integrable (Pi_pmf I d M) (\x. f (x i))" and expectation_Pi_pmf_slice: "integral\<^sup>L (Pi_pmf I d M) (\x. f (x i)) = integral\<^sup>L (M i) f" proof - have a:"distr (Pi_pmf I d M) (M i) (\\. \ i) = distr (Pi_pmf I d M) discrete (\\. \ i)" by (rule distr_cong, auto) have b: "measure_pmf.random_variable (M i) borel f" using assms(3) by simp have c:"integrable (distr (Pi_pmf I d M) (M i) (\\. \ i)) f" using assms(1,2,3) by (subst a, subst map_pmf_rep_eq[symmetric], subst Pi_pmf_component, auto) show "integrable (Pi_pmf I d M) (\x. f (x i))" by (rule integrable_distr[where f="f" and M'="M i"]) (auto intro: c) have "integral\<^sup>L (Pi_pmf I d M) (\x. f (x i)) = integral\<^sup>L (distr (Pi_pmf I d M) (M i) (\\. \ i)) f" using b by (intro integral_distr[symmetric], auto) also have "... = integral\<^sup>L (map_pmf (\\. \ i) (Pi_pmf I d M)) f" by (subst a, subst map_pmf_rep_eq[symmetric], simp) also have "... = integral\<^sup>L (M i) f" using assms(1,2) by (simp add: Pi_pmf_component) finally show "integral\<^sup>L (Pi_pmf I d M) (\x. f (x i)) = integral\<^sup>L (M i) f" by simp qed text \This is an improved version of @{thm [source] "expectation_prod_Pi_pmf"}. It works for general normed fields instead of non-negative real functions .\ lemma expectation_prod_Pi_pmf: fixes f :: "'a \ 'b \ ('c :: {second_countable_topology,banach,real_normed_field})" assumes "finite I" assumes "\i. i \ I \ integrable (measure_pmf (M i)) (f i)" shows "integral\<^sup>L (Pi_pmf I d M) (\x. (\i \ I. f i (x i))) = (\ i \ I. integral\<^sup>L (M i) (f i))" proof - have a: "prob_space.indep_vars (measure_pmf (Pi_pmf I d M)) (\_. borel) (\i \. f i (\ i)) I" by (intro prob_space.indep_vars_compose2[where Y="f" and M'="\_. discrete"] prob_space_measure_pmf indep_vars_Pi_pmf assms(1)) auto have "integral\<^sup>L (Pi_pmf I d M) (\x. (\i \ I. f i (x i))) = (\ i \ I. integral\<^sup>L (Pi_pmf I d M) (\x. f i (x i)))" by (intro prob_space.indep_vars_lebesgue_integral prob_space_measure_pmf assms(1,2) a integrable_Pi_pmf_slice) auto also have "... = (\ i \ I. integral\<^sup>L (M i) (f i))" by (intro prod.cong expectation_Pi_pmf_slice assms(1,2)) auto finally show ?thesis by simp qed lemma variance_prod_pmf_slice: fixes f :: "'a \ real" assumes "i \ I" "finite I" assumes "integrable (measure_pmf (M i)) (\\. f \^2)" shows "prob_space.variance (Pi_pmf I d M) (\\. f (\ i)) = prob_space.variance (M i) f" proof - have a:"integrable (measure_pmf (M i)) f" using assms(3) measure_pmf.square_integrable_imp_integrable by auto have b:" integrable (measure_pmf (Pi_pmf I d M)) (\x. (f (x i))\<^sup>2)" by (rule integrable_Pi_pmf_slice[OF assms(2) assms(1)], metis assms(3)) have c:" integrable (measure_pmf (Pi_pmf I d M)) (\x. (f (x i)))" by (rule integrable_Pi_pmf_slice[OF assms(2) assms(1)], metis a) have "measure_pmf.expectation (Pi_pmf I d M) (\x. (f (x i))\<^sup>2) - (measure_pmf.expectation (Pi_pmf I d M) (\x. f (x i)))\<^sup>2 = measure_pmf.expectation (M i) (\x. (f x)\<^sup>2) - (measure_pmf.expectation (M i) f)\<^sup>2" using assms a b c by ((subst expectation_Pi_pmf_slice[OF assms(2,1)])?, simp)+ thus ?thesis using assms a b c by (simp add: measure_pmf.variance_eq) qed lemma Pi_pmf_bind_return: assumes "finite I" shows "Pi_pmf I d (\i. M i \ (\x. return_pmf (f i x))) = Pi_pmf I d' M \ (\x. return_pmf (\i. if i \ I then f i (x i) else d))" using assms by (simp add: Pi_pmf_bind[where d'="d'"]) +lemma pmf_of_set_prod_eq: + assumes "A \ {}" "finite A" + assumes "B \ {}" "finite B" + shows "pmf_of_set (A \ B) = pair_pmf (pmf_of_set A) (pmf_of_set B)" +proof - + have "indicat_real (A \ B) (i, j) = indicat_real A i * indicat_real B j" for i j + by (cases "i \ A"; cases "j \ B") auto + hence "pmf (pmf_of_set (A \ B)) (i,j) = pmf (pair_pmf (pmf_of_set A) (pmf_of_set B)) (i,j)" + for i j using assms by (simp add:pmf_pair) + thus ?thesis + by (intro pmf_eqI) auto +qed + +lemma split_pmf_mod_div': + assumes "a > (0::nat)" + assumes "b > 0" + shows "map_pmf (\x. (x mod a, x div a)) (pmf_of_set {.. {.. (0::nat)" + assumes "b > 0" + shows "map_pmf (\x. (x mod a, x div a)) (pmf_of_set {..