diff --git a/thys/Hermite_Lindemann/Algebraic_Integer_Divisibility.thy b/thys/Hermite_Lindemann/Algebraic_Integer_Divisibility.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/Algebraic_Integer_Divisibility.thy @@ -0,0 +1,221 @@ +(* + File: Algebraic_Integer_Divisibility.thy + Author: Manuel Eberl, TU München +*) +section \Divisibility of algebraic integers\ +theory Algebraic_Integer_Divisibility + imports "Algebraic_Numbers.Algebraic_Numbers" +begin + +text \ + In this section, we define a notion of divisibility of algebraic integers: \y\ is divisible + by \x\ if \y / x\ is an algebraic integer (or if \x\ and \y\ are both zero). + + Technically, the definition does not require \x\ and \y\ to be algebraic integers themselves, + but we will always use it that way (in fact, in our case \x\ will always be a rational integer). +\ + +definition alg_dvd :: "'a :: field \ 'a \ bool" (infix "alg'_dvd" 50) where + "x alg_dvd y \ (x = 0 \ y = 0) \ algebraic_int (y / x)" + +lemma alg_dvd_imp_algebraic_int: + fixes x y :: "'a :: field_char_0" + shows "x alg_dvd y \ algebraic_int x \ algebraic_int y" + using algebraic_int_times[of "y / x" x] by (auto simp: alg_dvd_def) + +lemma alg_dvd_0_left_iff [simp]: "0 alg_dvd x \ x = 0" + by (auto simp: alg_dvd_def) + +lemma alg_dvd_0_right [iff]: "x alg_dvd 0" + by (auto simp: alg_dvd_def) + +lemma one_alg_dvd_iff [simp]: "1 alg_dvd x \ algebraic_int x" + by (auto simp: alg_dvd_def) + +lemma alg_dvd_of_int [intro]: + assumes "x dvd y" + shows "of_int x alg_dvd of_int y" +proof (cases "of_int x = (0 :: 'a)") + case False + from assms obtain z where z: "y = x * z" + by (elim dvdE) + have "algebraic_int (of_int z)" + by auto + also have "of_int z = of_int y / (of_int x :: 'a)" + using False by (simp add: z field_simps) + finally show ?thesis + using False by (simp add: alg_dvd_def) +qed (use assms in \auto simp: alg_dvd_def\) + +lemma alg_dvd_of_nat [intro]: + assumes "x dvd y" + shows "of_nat x alg_dvd of_nat y" + using alg_dvd_of_int[of "int x" "int y"] assms by simp + +lemma alg_dvd_of_int_iff [simp]: + "(of_int x :: 'a :: field_char_0) alg_dvd of_int y \ x dvd y" +proof + assume "(of_int x :: 'a) alg_dvd of_int y" + hence "of_int y / (of_int x :: 'a) \ \" and nz: "of_int x = (0::'a) \ of_int y = (0::'a)" + by (auto simp: alg_dvd_def dest!: rational_algebraic_int_is_int) + then obtain n where "of_int y / of_int x = (of_int n :: 'a)" + by (elim Ints_cases) + hence "of_int y = (of_int (x * n) :: 'a)" + unfolding of_int_mult using nz by (auto simp: field_simps) + hence "y = x * n" + by (subst (asm) of_int_eq_iff) + thus "x dvd y" + by auto +qed blast + +lemma alg_dvd_of_nat_iff [simp]: + "(of_nat x :: 'a :: field_char_0) alg_dvd of_nat y \ x dvd y" +proof - + have "(of_int (int x) :: 'a) alg_dvd of_int (int y) \ x dvd y" + by (subst alg_dvd_of_int_iff) auto + thus ?thesis unfolding of_int_of_nat_eq . +qed + +lemma alg_dvd_add [intro]: + fixes x y z :: "'a :: field_char_0" + shows "x alg_dvd y \ x alg_dvd z \ x alg_dvd (y + z)" + unfolding alg_dvd_def by (auto simp: add_divide_distrib) + +lemma alg_dvd_uminus_right [intro]: "x alg_dvd y \ x alg_dvd -y" + by (auto simp: alg_dvd_def) + +lemma alg_dvd_uminus_right_iff [simp]: "x alg_dvd -y \ x alg_dvd y" + using alg_dvd_uminus_right[of x y] alg_dvd_uminus_right[of x "-y"] by auto + +lemma alg_dvd_diff [intro]: + fixes x y z :: "'a :: field_char_0" + shows "x alg_dvd y \ x alg_dvd z \ x alg_dvd (y - z)" + unfolding alg_dvd_def by (auto simp: diff_divide_distrib) + +lemma alg_dvd_triv_left [intro]: "algebraic_int y \ x alg_dvd x * y" + by (auto simp: alg_dvd_def) + +lemma alg_dvd_triv_right [intro]: "algebraic_int x \ y alg_dvd x * y" + by (auto simp: alg_dvd_def) + +lemma alg_dvd_triv_left_iff: "x alg_dvd x * y \ x = 0 \ algebraic_int y" + by (auto simp: alg_dvd_def) + +lemma alg_dvd_triv_right_iff: "y alg_dvd x * y \ y = 0 \ algebraic_int x" + by (auto simp: alg_dvd_def) + +lemma alg_dvd_triv_left_iff' [simp]: "x \ 0 \ x alg_dvd x * y \ algebraic_int y" + by (simp add: alg_dvd_triv_left_iff) + +lemma alg_dvd_triv_right_iff' [simp]: "y \ 0 \ y alg_dvd x * y \ algebraic_int x" + by (simp add: alg_dvd_triv_right_iff) + +lemma alg_dvd_trans [trans]: + fixes x y z :: "'a :: field_char_0" + shows "x alg_dvd y \ y alg_dvd z \ x alg_dvd z" + using algebraic_int_times[of "y / x" "z / y"] by (auto simp: alg_dvd_def) + +lemma alg_dvd_mono [simp]: + fixes a b c d :: "'a :: field_char_0" + shows "a alg_dvd c \ b alg_dvd d \ (a * b) alg_dvd (c * d)" + using algebraic_int_times[of "c / a" "d / b"] by (auto simp: alg_dvd_def) + +lemma alg_dvd_mult [simp]: + fixes a b c :: "'a :: field_char_0" + shows "a alg_dvd c \ algebraic_int b \ a alg_dvd (b * c)" + using alg_dvd_mono[of a c 1 b] by (auto simp: mult.commute) + +lemma alg_dvd_mult2 [simp]: + fixes a b c :: "'a :: field_char_0" + shows "a alg_dvd b \ algebraic_int c \ a alg_dvd (b * c)" + using alg_dvd_mult[of a b c] by (simp add: mult.commute) + +text \ + A crucial theorem: if an integer \x\ divides a rational number \y\, then \y\ is in fact + also an integer, and that integer is a multiple of \x\. +\ +lemma alg_dvd_int_rat: + fixes y :: "'a :: field_char_0" + assumes "of_int x alg_dvd y" and "y \ \" + shows "\n. y = of_int n \ x dvd n" +proof (cases "x = 0") + case False + have "y / of_int x \ \" + by (intro rational_algebraic_int_is_int) (use assms in \auto simp: alg_dvd_def\) + then obtain n where n: "of_int n = y / (of_int x :: 'a)" + by (elim Ints_cases) auto + hence "y = of_int (n * x)" + using False by (simp add: field_simps) + thus ?thesis by (intro exI[of _ "x * n"]) auto +qed (use assms in auto) + +lemma prod_alg_dvd_prod: + fixes f :: "'a \ 'b :: field_char_0" + assumes "\x. x \ A \ f x alg_dvd g x" + shows "prod f A alg_dvd prod g A" + using assms by (induction A rule: infinite_finite_induct) auto + +lemma alg_dvd_sum: + fixes f :: "'a \ 'b :: field_char_0" + assumes "\x. x \ A \ y alg_dvd f x" + shows "y alg_dvd sum f A" + using assms by (induction A rule: infinite_finite_induct) auto + +lemma not_alg_dvd_sum: + fixes f :: "'a \ 'b :: field_char_0" + assumes "\x. x \ A-{x'} \ y alg_dvd f x" + assumes "\y alg_dvd f x'" + assumes "x' \ A" "finite A" + shows "\y alg_dvd sum f A" +proof + assume *: "y alg_dvd sum f A" + have "y alg_dvd sum f A - sum f (A - {x'})" + using \x' \ A\ by (intro alg_dvd_diff[OF * alg_dvd_sum] assms) auto + also have "\ = sum f (A - (A - {x'}))" + using assms by (subst sum_diff) auto + also have "A - (A - {x'}) = {x'}" + using assms by auto + finally show False using assms by simp +qed + +lemma fact_dvd_pochhammer: + assumes "m \ n + 1" + shows "fact m dvd pochhammer (int n - int m + 1) m" +proof - + have "(real n gchoose m) * fact m = of_int (pochhammer (int n - int m + 1) m)" + by (simp add: gbinomial_pochhammer' pochhammer_of_int [symmetric]) + also have "(real n gchoose m) * fact m = of_int (int (n choose m) * fact m)" + by (simp add: binomial_gbinomial) + finally have "int (n choose m) * fact m = pochhammer (int n - int m + 1) m" + by (subst (asm) of_int_eq_iff) + from this [symmetric] show ?thesis by simp +qed + +lemma coeff_higher_pderiv: + "coeff ((pderiv ^^ m) f) n = pochhammer (of_nat (Suc n)) m * coeff f (n + m)" + by (induction m arbitrary: n) (simp_all add: coeff_pderiv pochhammer_rec algebra_simps) + +lemma fact_alg_dvd_poly_higher_pderiv: + fixes p :: "'a :: field_char_0 poly" + assumes "\i. algebraic_int (poly.coeff p i)" "algebraic_int x" "m \ k" + shows "fact m alg_dvd poly ((pderiv ^^ k) p) x" + unfolding poly_altdef +proof (intro alg_dvd_sum, goal_cases) + case (1 i) + have "(of_int (fact m) :: 'a) alg_dvd (of_int (fact k))" + by (intro alg_dvd_of_int fact_dvd assms) + also have "(of_int (fact k) :: 'a) alg_dvd of_int (pochhammer (int i + 1) k)" + using fact_dvd_pochhammer[of k "i + k"] + by (intro alg_dvd_of_int fact_dvd_pochhammer) (auto simp: algebra_simps) + finally have "fact m alg_dvd (pochhammer (of_nat i + 1) k :: 'a)" + by (simp flip: pochhammer_of_int) + also have "\ alg_dvd pochhammer (of_nat i + 1) k * poly.coeff p (i + k)" + by (rule alg_dvd_triv_left) (rule assms) + also have "\ = poly.coeff ((pderiv ^^ k) p) i" + unfolding coeff_higher_pderiv by (simp add: add_ac flip: pochhammer_of_int) + also have "\ alg_dvd poly.coeff ((pderiv ^^ k) p) i * x ^ i" + by (intro alg_dvd_triv_left algebraic_int_power assms) + finally show ?case . +qed + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/Complex_Lexorder.thy b/thys/Hermite_Lindemann/Complex_Lexorder.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/Complex_Lexorder.thy @@ -0,0 +1,89 @@ +(* + File: Complex_Lexorder.thy + Author: Manuel Eberl, TU München +*) +section \The lexicographic ordering on complex numbers\ +theory Complex_Lexorder + imports Complex_Main "HOL-Library.Multiset" +begin + +text \ + We define a lexicographic order on the complex numbers, comparing first the real parts + and, if they are equal, the imaginary parts. This ordering is of course not compatible with + multiplication, but it is compatible with addition. +\ + +definition less_eq_complex_lex (infix "\\<^sub>\" 50) where + "less_eq_complex_lex x y \ Re x < Re y \ Re x = Re y \ Im x \ Im y" + +definition less_complex_lex (infix "<\<^sub>\" 50) where + "less_complex_lex x y \ Re x < Re y \ Re x = Re y \ Im x < Im y" + +interpretation complex_lex: + linordered_ab_group_add "(+)" 0 "(-)" "uminus" less_eq_complex_lex less_complex_lex + by standard (auto simp: less_eq_complex_lex_def less_complex_lex_def complex_eq_iff) + +lemmas [trans] = + complex_lex.order.trans complex_lex.less_le_trans + complex_lex.less_trans complex_lex.le_less_trans + +lemma (in ordered_comm_monoid_add) sum_mono_complex_lex: + "(\i. i\K \ f i \\<^sub>\ g i) \ (\i\K. f i) \\<^sub>\ (\i\K. g i)" + by (induct K rule: infinite_finite_induct) (use complex_lex.add_mono in auto) + +lemma sum_strict_mono_ex1_complex_lex: + fixes f g :: "'i \ complex" + assumes "finite A" + and "\x\A. f x \\<^sub>\ g x" + and "\a\A. f a <\<^sub>\ g a" + shows "sum f A <\<^sub>\ sum g A" +proof- + from assms(3) obtain a where a: "a \ A" "f a <\<^sub>\ g a" by blast + have "sum f A = sum f ((A - {a}) \ {a})" + by (simp add: insert_absorb[OF \a \ A\]) + also have "\ = sum f (A - {a}) + sum f {a}" + using \finite A\ by (subst sum.union_disjoint) auto + also have "\ \\<^sub>\ sum g (A - {a}) + sum f {a}" + by (intro complex_lex.add_mono sum_mono_complex_lex) (simp_all add: assms) + also have "\ <\<^sub>\ sum g (A - {a}) + sum g {a}" + using a by (intro complex_lex.add_strict_left_mono) auto + also have "\ = sum g ((A - {a}) \ {a})" + using \finite A\ by (subst sum.union_disjoint[symmetric]) auto + also have "\ = sum g A" by (simp add: insert_absorb[OF \a \ A\]) + finally show ?thesis + by simp +qed + +lemma sum_list_mono_complex_lex: + assumes "list_all2 (\\<^sub>\) xs ys" + shows "sum_list xs \\<^sub>\ sum_list ys" + using assms by induction (auto intro: complex_lex.add_mono) + +lemma sum_mset_mono_complex_lex: + assumes "rel_mset (\\<^sub>\) A B" + shows "sum_mset A \\<^sub>\ sum_mset B" + using assms by (auto simp: rel_mset_def sum_mset_sum_list intro: sum_list_mono_complex_lex) + +lemma rel_msetI: + assumes "list_all2 R xs ys" "mset xs = A" "mset ys = B" + shows "rel_mset R A B" + using assms by (auto simp: rel_mset_def) + +lemma mset_replicate [simp]: "mset (replicate n x) = replicate_mset n x" + by (induction n) auto + +lemma rel_mset_replicate_mset_right: + assumes "\x. x \# A \ R x y" "size A = n" + shows "rel_mset R A (replicate_mset n y)" +proof - + obtain xs where [simp]: "A = mset xs" + by (metis ex_mset) + from assms have "\x\set xs. R x y" + by auto + hence "list_all2 R xs (replicate (length xs) y)" + by (induction xs) auto + with assms(2) show ?thesis + by (intro rel_msetI[of R xs "replicate n y"]) auto +qed + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/Hermite_Lindemann.thy b/thys/Hermite_Lindemann/Hermite_Lindemann.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/Hermite_Lindemann.thy @@ -0,0 +1,2558 @@ +(* + File: Hermite_Lindemann.thy + Author: Manuel Eberl, TU München +*) +section \The Hermite--Lindemann--Weierstraß Transcendence Theorem\ +theory Hermite_Lindemann +imports + Pi_Transcendental.Pi_Transcendental + Algebraic_Numbers.Algebraic_Numbers + Algebraic_Integer_Divisibility + Min_Int_Poly + Complex_Lexorder + More_Polynomial_HLW + More_Multivariate_Polynomial_HLW + More_Algebraic_Numbers_HLW + Misc_HLW +begin + +text \ + The Hermite--Lindemann--Weierstraß theorem answers questions about the transcendence of + the exponential function and other related complex functions. It proves that a large number of + combinations of exponentials is always transcendental. + + A first (much weaker) version of the theorem was proven by Hermite. Lindemann and Weierstraß then + successively generalised it shortly afterwards, and finally Baker gave another, arguably more + elegant formulation (which is the one that we will prove, and then derive the traditional version + from it). + + To honour the contributions of all three of these 19th-century mathematicians, I refer to the + theorem as the Hermite--Lindemann--Weierstraß theorem, even though in other literature it is + often called Hermite--Lindemann or Lindemann--Weierstraß. To keep things short, the Isabelle + name of the theorem, however, will omit Weierstraß's name. +\ + +subsection \Main proof\ + +text \ + Following Baker, We first prove the following special form of the theorem: + Let $m > 0$ and $q_1, \ldots, q_m \in\mathbb{Z}[X]$ be irreducible, non-constant, + and pairwise coprime polynomials. Let $\beta_1, \ldots, \beta_m$ be non-zero integers. Then + \[\sum_{i=1}^m \beta_i \sum_{q_i(\alpha) = 0} e^\alpha \neq 0\] + + The difference to the final theorem is that + + \<^enum> The coefficients $\beta_i$ are non-zero integers (as opposed to arbitrary algebraic numbers) + + \<^enum> The exponents $\alpha_i$ occur in full sets of conjugates, and each set has the same + coefficient. + + In a similar fashion to the proofs of the transcendence of \e\ and \\\, we define some number + $J$ depending on the $\alpha_i$ and $\beta_i$ and an arbitrary sufficiently large prime \p\. We + then show that, on one hand, $J$ is an integer multiple of $(p-1)!$, but on the other hand it + is bounded from above by a term of the form $C_1 \cdot C_2^p$. This is then clearly a + contradiction if \p\ is chosen large enough. +\ + +lemma Hermite_Lindemann_aux1: + fixes P :: "int poly set" and \ :: "int poly \ int" + assumes "finite P" and "P \ {}" + assumes distinct: "pairwise Rings.coprime P" + assumes irred: "\p. p \ P \ irreducible p" + assumes nonconstant: "\p. p \ P \ Polynomial.degree p > 0" + assumes \_nz: "\p. p \ P \ \ p \ 0" + defines "Roots \ (\p. {\::complex. poly (of_int_poly p) \ = 0})" + shows "(\p\P. of_int (\ p) * (\\\Roots p. exp \)) \ 0" +proof + note [intro] = \finite P\ + assume sum_eq_0: "(\p\P. of_int (\ p) * (\\\Roots p. exp \)) = 0" + + define Roots' where "Roots' = (\p\P. Roots p)" + have finite_Roots [intro]: "finite (Roots p)" if "p \ P" for p + using nonconstant[of p] that by (auto intro: poly_roots_finite simp: Roots_def) + have [intro]: "finite Roots'" + by (auto simp: Roots'_def) + have [simp]: "0 \ P" + using nonconstant[of 0] by auto + have [simp]: "p \ 0" if "p \ P" for p + using that by auto + + text \ + The polynomials in \<^term>\P\ do not have multiple roots: + \ + have rsquarefree: "rsquarefree (of_int_poly q :: complex poly)" if "q \ P" for q + by (rule irreducible_imp_rsquarefree_of_int_poly) (use that in \auto intro: irred nonconstant\) + + text \ + No two different polynomials in \<^term>\P\ have roots in common: + \ + have disjoint: "disjoint_family_on Roots P" + using distinct + proof (rule pairwise_imp_disjoint_family_on) + fix p q assume P: "p \ P" "q \ P" and "Rings.coprime p q" + hence "Rings.coprime (of_int_poly p :: complex poly) (of_int_poly q)" + by (intro coprime_of_int_polyI) + thus "Roots p \ Roots q = {}" + using poly_eq_0_coprime[of "of_int_poly p" "of_int_poly q :: complex poly"] P + by (auto simp: Roots_def) + qed + + define n_roots :: "int poly \ nat" ("\_") + where "n_roots = (\p. card (Roots p))" + define n where "n = (\p\P. \p)" + have n_altdef: "n = card Roots'" + unfolding n_def Roots'_def n_roots_def using disjoint + by (subst card_UN_disjoint) (auto simp: disjoint_family_on_def) + have Roots_nonempty: "Roots p \ {}" if "p \ P" for p + using nonconstant[OF that] by (auto simp: Roots_def fundamental_theorem_of_algebra constant_degree) + have "Roots' \ {}" + using Roots_nonempty \P \ {}\ by (auto simp: Roots'_def) + have "n > 0" + using \Roots' \ {}\ \finite Roots'\ by (auto simp: n_altdef) + + text \ + We can split each polynomial in \P\ into a product of linear factors: + \ + have of_int_poly_P: + "of_int_poly q = Polynomial.smult (Polynomial.lead_coeff q) (\x\Roots q. [:-x, 1:])" + if "q \ P" for q + using complex_poly_decompose_rsquarefree[OF rsquarefree[OF that]] by (simp add: Roots_def) + + text \ + We let \l\ be an integer such that $l\alpha$ is an algebraic integer for all our roots \\\: + \ + define l where "l = (LCM q\P. Polynomial.lead_coeff q)" + have alg_int: "algebraic_int (of_int l * x)" if "x \ Roots'" for x + proof - + from that obtain q where q: "q \ P" "ipoly q x = 0" + by (auto simp: Roots'_def Roots_def) + show ?thesis + by (rule algebraic_imp_algebraic_int'[of q]) (use q in \auto simp: l_def\) + qed + have "l \ 0" + using \finite P\ by (auto simp: l_def Lcm_0_iff) + moreover have "l \ 0" + unfolding l_def by (rule Lcm_int_greater_eq_0) + ultimately have "l > 0" by linarith + + text \ + We can split the product of all the polynomials in \P\ into linear factors: + \ + define lc_factor where "lc_factor = (\q\P. l ^ Polynomial.degree q div Polynomial.lead_coeff q)" + have lc_factor: "Polynomial.smult (of_int l ^ n) (\\'\Roots'. [:-\',1:]) = + of_int_poly (Polynomial.smult lc_factor (\P))" + proof - + define lc where "lc = (\q. Polynomial.lead_coeff q :: int)" + define d where "d = (Polynomial.degree :: int poly \ nat)" + have "(\q\P. of_int_poly q) = + (\q\P. Polynomial.smult (lc q) (\x\Roots q. [:-x, 1:]) :: complex poly)" + unfolding lc_def by (intro prod.cong of_int_poly_P refl) + also have "\ = Polynomial.smult (\q\P. lc q) (\q\P. (\x\Roots q. [:-x, 1:]))" + by (simp add: prod_smult) + also have "(\q\P. (\x\Roots q. [:-x, 1:])) = (\x\Roots'. [:-x, 1:])" + unfolding Roots'_def using disjoint + by (intro prod.UNION_disjoint [symmetric]) (auto simp: disjoint_family_on_def) + also have "Polynomial.smult (of_int lc_factor) (Polynomial.smult (\q\P. lc q) \) = + Polynomial.smult (\q\P. of_int (l ^ d q div lc q * lc q)) (\x\Roots'. pCons (- x) 1)" + by (simp add: lc_factor_def prod.distrib lc_def d_def) + also have "(\q\P. of_int (l ^ d q div lc q * lc q)) = (\q\P. of_int l ^ d q :: complex)" + proof (intro prod.cong, goal_cases) + case (2 q) + have "lc q dvd l" + unfolding l_def lc_def using 2 by auto + also have "\ dvd l ^ d q" + using 2 nonconstant[of q] by (intro dvd_power) (auto simp: d_def) + finally show ?case by simp + qed auto + also have "\ = l ^ (\q\P. d q)" + by (simp add: power_sum) + also have "(\q\P. d q) = (\q\P. n_roots q)" + proof (intro sum.cong, goal_cases) + case (2 q) + thus ?case using rsquarefree[OF 2] + by (subst (asm) rsquarefree_card_degree) (auto simp: d_def n_roots_def Roots_def) + qed auto + also have "\ = n" + by (simp add: n_def) + finally show ?thesis + by (simp add: of_int_hom.map_poly_hom_smult of_int_poly_hom.hom_prod) + qed + + text \ + We define \R\ to be the radius of the smallest circle around the origin in which all our + roots lie: + \ + define R :: real where "R = Max (norm ` Roots')" + have R_ge: "R \ norm \" if "\ \ Roots'" for \ + unfolding R_def using that by (intro Max_ge) auto + have "R \ 0" + proof - + from \Roots' \ {}\ obtain \ where "\ \ Roots'" + by auto + have "0 \ norm \" + by simp + also have "\ \ R" + by (intro R_ge) fact + finally show "R \ 0" + by simp + qed + + text \ + Now the main part of the proof: for any sufficiently large prime \p\, our assumptions + imply $(p-1)! ^ n \leq C' l^{np} (2R)^{np-1}$ for some constant $C'$: + \ + define C :: "nat \ real" where "C = (\p. l ^ (n * p) * (2*R) ^ (n * p - 1))" + define C' where + "C' = (\x\Roots'. \q\P. real_of_int \\ q\ * (\\\Roots q. cmod \ * exp (cmod \)))" + + text \ + We commence with the proof of the main inequality. + \ + have ineq: "fact (p - 1) ^ n \ C' * C p ^ n" + if p: "prime p" + and p_ineqs: "\q\P. p > \\ q\" + "real p > norm (\\\Roots'. of_int (l^n) * (\x\Roots'-{\}. \ - x))" + for p :: nat + proof - + have "p > 1" + using prime_gt_1_nat[OF p] . + + text \ + We define the polynomial function + \[f_i(X) = l^{np} \frac{\prod_\alpha (X-\alpha)^p}{X - \alpha_i}\] + where the product runs over all roots $\alpha$. + \ + define f_poly :: "complex \ complex poly" where + "f_poly = (\\. Polynomial.smult (l^(n*p)) ((\\'\Roots'. [:-\', 1:]^p) div [:-\, 1:]))" + have f_poly_altdef: "f_poly \ = Polynomial.smult (l^(n*p)) + ((\\'\Roots'. [:-\', 1:]^(if \' = \ then p - 1 else p)))" + if "\ \ Roots'" for \ + proof - + have "(\\'\Roots'. [:-\', 1:] ^ (if \'=\ then p-1 else p)) * [:-\, 1:] = + [:- \, 1:] ^ (p - 1) * (\x\Roots' - {\}. [:- x, 1:] ^ p) * [:- \, 1:]" + using that by (subst prod.If_eq) (auto simp: algebra_simps) + also have "\ = (\x\Roots' - {\}. [:- x, 1:] ^ p) * [:- \, 1:] ^ Suc (p - 1)" + by (simp only: power_Suc mult_ac) + also have "Suc (p - 1) = p" + using \p > 1\ by auto + also have "(\x\Roots' - {\}. [:- x, 1:] ^ p) * [:- \, 1:] ^ p = (\x\Roots'. [:- x, 1:] ^ p)" + using that by (subst prod.remove[of _ \]) auto + finally have eq: "(\\'\Roots'. [:-\', 1:] ^ (if \'=\ then p-1 else p)) * [:-\, 1:] = + (\x\Roots'. [:- x, 1:] ^ p)" . + show ?thesis + unfolding f_poly_def eq[symmetric] by (subst nonzero_mult_div_cancel_right) auto + qed + + define f :: "complex \ complex \ complex" + where "f = (\\ x. l^(n*p) * (\\'\Roots'. (x - \')^(if \' = \ then p - 1 else p)))" + have eval_f: "poly (f_poly \) x = f \ x" if "\ \ Roots'" for \ x + using that by (simp add: f_poly_altdef poly_prod f_def) + have deg_f: "Polynomial.degree (f_poly \) = n * p - 1" if "\ \ Roots'" for \ + proof - + have "Polynomial.degree (f_poly \) = p - 1 + (n - 1) * p" + unfolding f_poly_altdef[OF that] using that \l > 0\ \finite Roots'\ + by (subst prod.If_eq) (auto simp: degree_prod_eq degree_power_eq degree_mult_eq n_altdef) + also have "p - 1 + (n - 1) * p = n * p - 1" + using \n > 0\ \p > 1\ by (cases n) auto + finally show ?thesis . + qed + + text \ + Next, we define the function $I_i(z) = \int_0^z e^{z-t} f_i(t) \text{d}t$, and, + based on that, the numbers $J_i = \sum_{i=1}^m \beta_i \sum_{q_i(x) = 0} I_i(x)$, + and the number $J$, which is the product of all the $J_i$: + \ + define I :: "complex \ complex \ complex" + where "I = (\\ x. lindemann_weierstrass_aux.I (f_poly \) x)" + define J :: "complex \ complex" + where "J = (\\. \q\P. \ q * (\x\Roots q. I \ x))" + + define J' :: complex + where "J' = (\\\Roots'. J \)" + + text \ + Reusing some of the machinery from the proof that \e\ is transcendental, + we find the following equality for $J_i$: + \ + have J_eq: "J \ = -(\q\P. of_int (\ q) * (\x\Roots q. \j)) x))" + if "\ \ Roots'" for \ + proof - + have "n * p \ 1 * 2" + using \n > 0\ \p > 1\ by (intro mult_mono) auto + hence [simp]: "{..n*p-Suc 0} = {.. = (\q\P. \ q * (\x\Roots q. I \ x))" + unfolding J_def .. + also have "\ = (\q\P. of_int (\ q) * (\x\Roots q. exp x * (\j)) 0))) - + (\q\P. of_int (\ q) * (\x\Roots q. \j)) x))" + unfolding I_def lindemann_weierstrass_aux.I_def + by (simp add: deg_f that ring_distribs sum_subtractf sum_distrib_left sum_distrib_right mult_ac) + also have "\ = -(\q\P. of_int (\ q) * (\x\Roots q. \j)) x))" + unfolding sum_distrib_right [symmetric] mult.assoc [symmetric] sum_eq_0 by simp + finally show ?thesis . + qed + + text \ + The next big step is to show that $(p-1)! \mid J_i$ as an algebraic integer (i.e. + $J_i / (p-1)!$ is an algebraic integer), but $p \not\mid J_i$. This is done by brute force: + We show that every summand in the above sum has $p!$ as a factor, except for + the one corresponding to $x = \alpha_i$, $j = p - 1$, which has $(p-1)!$ as a factor but + not \p\. + \ + have J: "fact (p - 1) alg_dvd J \" "\of_nat p alg_dvd J \" if \: "\ \ Roots'" for \ + proof - + define h where "h = (\\' j. poly ((pderiv ^^ j) (f_poly \)) \')" + from \ obtain q where q: "q \ P" "\ \ Roots q" + by (auto simp: Roots'_def) + + have "J \ = -(\(q, \')\Sigma P Roots. \j q) * h \' j)" + unfolding J_eq[OF \] h_def sum_distrib_left by (subst (2) sum.Sigma) auto + also have "\ = -(\((q,\'),i)\Sigma P Roots\{.. q) * h \' i)" + by (subst (2) sum.Sigma [symmetric]) (auto simp: case_prod_unfold) + finally have J_eq': "J \ = - (\((q, \'), i)\Sigma P Roots \ {.. q) * h \' i)" . + + have h_\_pm1_eq: "h \ (p-1) = of_int (l^(n*p)) * fact (p-1) * (\\'\Roots'-{\}. (\-\')^p)" + proof - + have "h \ (p - 1) = of_int (l ^ (n * p)) * + poly ((pderiv ^^ (p-1)) (\\'\Roots'. [:-\',1:] ^ (if \' = \ then p - 1 else p))) \" + unfolding h_def f_poly_altdef[OF \] higher_pderiv_smult poly_smult .. + also have "(\\'\Roots'. [:-\',1:] ^ (if \' = \ then p - 1 else p)) = + [:-\,1:]^(p-1) * (\\'\Roots'-{\}. [:-\',1:]^p)" + using \ by (subst prod.If_eq) auto + also have "poly ((pderiv ^^ (p-1)) \) \ = fact (p - 1) * (\\'\Roots' - {\}. (\ - \') ^ p)" + by (subst poly_higher_pderiv_aux2) (simp_all add: poly_prod) + finally show ?thesis by (simp only: mult.assoc) + qed + + have "fact (p-1) alg_dvd h \ (p-1)" + proof - + have "fact (p-1) alg_dvd fact (p-1) * (of_int (l^p) * (\\'\Roots'-{\}. (l*\-l*\')^p))" + by (intro alg_dvd_triv_left algebraic_int_times[of "of_int (l^p)"] + algebraic_int_prod algebraic_int_power algebraic_int_diff + alg_int \ algebraic_int_of_int) auto + also have "(\\'\Roots'-{\}. (l*\-l*\')^p) = (\\'\Roots'-{\}. of_int l^p * (\-\')^p)" + by (subst power_mult_distrib [symmetric]) (simp_all add: algebra_simps) + also have "\ = of_int (l ^ (p * (n-1))) * (\\'\Roots'-{\}. (\-\')^p)" + using \ by (subst prod.distrib) (auto simp: card_Diff_subset n_altdef simp flip: power_mult) + also have "of_int (l^p) * \ = of_int (l^(p+p*(n-1))) * (\\'\Roots'-{\}. (\-\')^p)" + unfolding mult.assoc [symmetric] power_add [symmetric] of_int_power .. + also have "p + p * (n - 1) = n * p" + using \n > 0\ by (cases n) (auto simp: mult_ac) + also have "fact (p - 1) * (of_int (l^(n*p)) * (\\'\Roots'-{\}. (\-\')^p)) = h \ (p-1)" + unfolding h_\_pm1_eq by (simp add: mult_ac) + finally show ?thesis . + qed + + have "\of_nat p alg_dvd of_int (\ q) * h \ (p-1)" + unfolding h_\_pm1_eq mult.assoc [symmetric] of_int_mult [symmetric] + proof + define r where "r = (\\. of_int (l^n) * (\\'\Roots'-{\}. \-\'))" + have alg_int_r: "algebraic_int (r \)" if "\ \ Roots'" for \ + proof - + have "algebraic_int (of_int l * (\\'\Roots'-{\}. of_int l * \ - of_int l * \'))" + by (intro algebraic_int_times[OF algebraic_int_of_int] algebraic_int_prod + algebraic_int_power algebraic_int_diff alg_int that) auto + also have "\ = of_int l * (\\'\Roots'-{\}. of_int l * (\ - \'))" + by (simp add: algebra_simps flip: power_mult_distrib) + also have "\ = of_int (l^(1 + (n-1))) * (\\'\Roots'-{\}. \ - \')" + using that by (simp add: r_def prod.distrib card_Diff_subset + n_altdef power_add mult_ac flip: power_mult) + also have "1 + (n - 1) = n" + using \n > 0\ by auto + finally show "algebraic_int (r \)" + unfolding r_def . + qed + + have "(\\'\Roots'. r \') \ \" + proof - + obtain Root where Root_bij: "bij_betw Root {..finite Roots'\] unfolding n_altdef atLeast0LessThan by metis + have Root_in_Roots': "Root i \ Roots'" if "i < n" for i + using Root_bij that by (auto simp: bij_betw_def) + + define R :: "complex mpoly" where + "R = (\ij\{.. \" + proof (rule symmetric_poly_of_roots_in_subring) + show "symmetric_mpoly {..\. \"], goal_cases) + case (2 i \) + from \\ permutes {.. have [simp]: "bij \" + by (rule permutes_bij) + have "mpoly_map_vars \ (Const (of_int (l ^ n)) * + (\j\{..j\{.. i) - Var (\ j))" + by simp + also have "(\j\{.. i) - Var (\ j)) = + (\j\{.. i}. Var (\ i) - Var j)" + using 2 permutes_in_image[OF 2(2), of i] + by (intro prod.reindex_bij_betw bij_betw_Diff permutes_imp_bij[OF 2(2)]) + (auto simp: bij_betw_singleton) + finally show ?case by simp + qed + next + show "vars R \ {.. :: complex set)" + by unfold_locales auto + then interpret ring_closed "\ :: complex set" . + show "\m. MPoly_Type.coeff R m \ \" + unfolding R_def + by (intro allI coeff_prod_closed coeff_mult_closed coeff_power_closed) + (auto simp: mpoly_coeff_Const coeff_Var when_def) + next + let ?lc = "of_int (\p\P. Polynomial.lead_coeff p) :: complex" + have "(\q\P. of_int_poly q) = (\q\P. Polynomial.smult + (of_int (Polynomial.lead_coeff q)) (\x\Roots q. [:-x, 1:]))" + by (intro prod.cong of_int_poly_P refl) + also have "\ = Polynomial.smult ?lc (\q\P. \x\Roots q. [:-x, 1:])" + by (simp add: prod_smult) + also have "(\q\P. \x\Roots q. [:-x, 1:]) = (\x\Roots'. [:-x, 1:])" + unfolding Roots'_def using disjoint + by (intro prod.UNION_disjoint [symmetric]) (auto simp: disjoint_family_on_def) + also have "\ = (\iP) = Polynomial.smult ?lc (\i 0" + by (intro prod_nonzeroI) auto + thus "inverse ?lc * ?lc = 1" "inverse ?lc \ \" + by (auto simp: field_simps simp flip: of_int_prod) + qed auto + also have "insertion Root R = (\ij\{.. = (\i\'\Roots'-{Root i}. Root i - \'))" + proof (intro prod.cong, goal_cases) + case (2 i) + hence "(\j\{..\'\Roots'-{Root i}. Root i - \')" + by (intro prod.reindex_bij_betw bij_betw_Diff Root_bij) + (auto intro: Root_in_Roots' simp: bij_betw_singleton) + thus ?case by simp + qed auto + also have "\ = (\\'\Roots'. r \')" + unfolding r_def by (intro prod.reindex_bij_betw Root_bij) + finally show "(\\'\Roots'. r \') \ \" . + qed + moreover have "algebraic_int (\\'\Roots'. r \')" + by (intro algebraic_int_prod alg_int_r) + ultimately have is_int: "(\\'\Roots'. r \') \ \" + using rational_algebraic_int_is_int by blast + then obtain R' where R': "(\\'\Roots'. r \') = of_int R'" + by (elim Ints_cases) + have "(\\'\Roots'. r \') \ 0" + using \l > 0\ by (intro prod_nonzeroI) (auto simp: r_def \finite Roots'\) + with R' have [simp]: "R' \ 0" + by auto + + assume "of_nat p alg_dvd of_int (\ q * l^(n*p)) * fact (p-1) * (\\'\Roots'-{\}. (\-\') ^ p)" + also have "\ = of_int (\ q) * fact (p-1) * r \ ^ p" + by (simp add: r_def mult_ac power_mult_distrib power_mult prod_power_distrib) + also have "\ alg_dvd of_int (\ q) * fact (p-1) * r \ ^ p * (\\'\Roots'-{\}. r \') ^ p" + by (intro alg_dvd_triv_left algebraic_int_prod alg_int_r algebraic_int_power) auto + also have "\ = of_int (\ q) * fact (p-1) * (\\'\Roots'. r \') ^ p" + using \ by (subst (2) prod.remove[of _ "\"]) (auto simp: mult_ac power_mult_distrib) + also have "\ = of_int (\ q * fact (p - 1) * R' ^ p)" + by (simp add: R') + also have "of_nat p = of_int (int p)" + by simp + finally have "int p dvd \ q * fact (p - 1) * R' ^ p" + by (subst (asm) alg_dvd_of_int_iff) + moreover have "prime (int p)" + using \prime p\ by auto + ultimately have "int p dvd \ q \ int p dvd fact (p - 1) \ int p dvd R' ^ p" + by (simp add: prime_dvd_mult_iff) + moreover have "\int p dvd \ q" + proof + assume "int p dvd \ q" + hence "int p \ \\ q\" + using \_nz[of q] dvd_imp_le_int[of "\ q" "int p"] q by auto + with p_ineqs(1) q show False by auto + qed + moreover have "\int p dvd fact (p - 1)" + proof - + have "\p dvd fact (p - 1)" + using \p > 1\ p by (subst prime_dvd_fact_iff) auto + hence "\int p dvd int (fact (p - 1))" + by (subst int_dvd_int_iff) + thus ?thesis unfolding of_nat_fact . + qed + moreover have "\int p dvd R' ^ p" + proof + assume "int p dvd R' ^ p" + hence "int p dvd R'" + using \prime (int p)\ prime_dvd_power by metis + hence "int p \ \R'\" + using \_nz[of q] dvd_imp_le_int[of R' "int p"] q by auto + hence "real p \ real_of_int \R'\" + by linarith + also have "\ = norm (\\\Roots'. r \)" + unfolding R' by simp + finally show False unfolding r_def using p_ineqs(2) + by linarith + qed + ultimately show False + by blast + qed + + have fact_p_dvd: "fact p alg_dvd h \' j" if "\' \ Roots'" "\' \ \ \ j \ p - 1" for \' j + proof (cases "j \ p") + case False + with that have j: "j < (if \' = \ then p - 1 else p)" + by auto + have "h \' j = 0" + unfolding h_def f_poly_altdef[OF \] + by (intro poly_higher_pderiv_aux1'[OF j] dvd_smult dvd_prodI that) auto + thus ?thesis by simp + next + case True + define e where "e = (\x. if x = \ then p - 1 else p)" + define Q where "Q = (\x\Roots'. [:-x, 1:] ^ e x)" + define Q' where "Q' = Polynomial.smult (of_int (l^(n*p+j))) (pcompose Q [:0, 1 / of_int l:])" + have "poly ((pderiv ^^ j) Q) \' / l ^ j = + poly ((pderiv ^^ j) (pcompose Q [:0, 1 / of_int l:])) (l * \')" + using \l > 0\ by (simp add: higher_pderiv_pcompose_linear poly_pcompose field_simps) + + have "sum e Roots' = (n - 1) * p + (p - 1)" + unfolding e_def using \ + by (subst sum.If_eq) (auto simp: card_Diff_subset n_altdef algebra_simps) + also have "\ = n * p - 1" + using \n > 0\ \p > 1\ by (cases n) auto + finally have [simp]: "sum e Roots' = n * p - 1" . + + have "h \' j = of_int (l^(n*p)) * poly ((pderiv ^^ j) Q) \'" + unfolding h_def f_poly_altdef[OF \] higher_pderiv_smult poly_smult e_def Q_def .. + also have "poly ((pderiv ^^ j) Q) \' = + of_int l ^ j * poly ((pderiv ^^ j) (pcompose Q [:0, 1 / of_int l:])) (l * \')" + using \l > 0\ by (simp add: higher_pderiv_pcompose_linear poly_pcompose field_simps) + also have "of_int (l ^ (n * p)) * \ = poly ((pderiv ^^ j) Q') (l * \')" + by (simp add: Q'_def higher_pderiv_smult power_add) + also have "fact p alg_dvd \" + proof (rule fact_alg_dvd_poly_higher_pderiv) + show "j \ p" by fact + show "algebraic_int (of_int l * \')" + by (rule alg_int) fact + interpret alg_int: ring_closed "{x::complex. algebraic_int x}" + by standard auto + show "algebraic_int (poly.coeff Q' i)" for i + proof (cases "i \ Polynomial.degree Q'") + case False + thus ?thesis + by (simp add: coeff_eq_0) + next + case True + hence "i \ n * p - 1" using \l > 0\ + by (simp add: Q'_def degree_prod_eq Q_def degree_power_eq) + also have "n * p > 0" + using \n > 0\ \p > 1\ by auto + hence "n * p - 1 < n * p" + by simp + finally have i: "i < n * p" . + + have "poly.coeff Q' i = of_int l ^ (n * p + j) / of_int l ^ i * poly.coeff Q i" + by (simp add: Q'_def coeff_pcompose_linear field_simps) + also have "of_int l ^ (n * p + j) = (of_int l ^ (n * p + j - i) :: complex) * of_int l ^ i" + unfolding power_add [symmetric] using i by simp + hence "of_int l ^ (n * p + j) / of_int l ^ i = (of_int l ^ (n * p + j - i) :: complex)" + using \l > 0\ by (simp add: field_simps) + also have "\ * poly.coeff Q i = + (\X\{X. X \ (SIGMA x:Roots'. {.. i = n * p - Suc (card X)}. + of_int l ^ (n * p + j - (n * p - Suc (card X))) * ((- 1) ^ card X * prod fst X))" + unfolding Q_def by (subst coeff_prod_linear_factors) (auto simp: sum_distrib_left) + also have "algebraic_int \" + proof (intro algebraic_int_sum, goal_cases) + case (1 X) + hence X: "X \ (SIGMA x:Roots'. {.. card (SIGMA x:Roots'. {.. n * p - 1" + using card_eq by auto + also have "\ < n * p" + using \n * p > 0\ by simp + finally have card_less: "card X < n * p" . + have "algebraic_int ((-1) ^ card X * of_int l ^ (j + 1) * (\x\X. of_int l * fst x))" + using X by (intro algebraic_int_times algebraic_int_prod alg_int) auto + thus ?case + using card_less by (simp add: power_add prod.distrib mult_ac) + qed + finally show ?thesis . + qed + qed + finally show ?thesis . + qed + + have p_dvd: "of_nat p alg_dvd h \' j" if "\' \ Roots'" "\' \ \ \ j \ p - 1" for \' j + proof - + have "of_nat p alg_dvd (of_nat (fact p) :: complex)" + by (intro alg_dvd_of_nat dvd_fact) (use \p > 1\ in auto) + hence "of_nat p alg_dvd (fact p :: complex)" + by simp + also have "\ alg_dvd h \' j" + using that by (intro fact_p_dvd) + finally show ?thesis . + qed + + show "fact (p - 1) alg_dvd J \" + unfolding J_eq' + proof (intro alg_dvd_uminus_right alg_dvd_sum, safe intro!: alg_dvd_mult algebraic_int_of_int) + fix q \' j + assume "q \ P" "\' \ Roots q" "j < n * p" + hence "\' \ Roots'" + by (auto simp: Roots'_def) + show "fact (p - 1) alg_dvd h \' j" + proof (cases "\' = \ \ j = p - 1") + case True + thus ?thesis using \fact (p - 1) alg_dvd h \ (p - 1)\ + by simp + next + case False + have "of_int (fact (p - 1)) alg_dvd (of_int (fact p) :: complex)" + by (intro alg_dvd_of_int fact_dvd) auto + hence "fact (p - 1) alg_dvd (fact p :: complex)" + by simp + also have "\ alg_dvd h \' j" + using False \\' \ Roots'\ by (intro fact_p_dvd) auto + finally show ?thesis . + qed + qed + + show "\of_nat p alg_dvd J \" + unfolding J_eq' alg_dvd_uminus_right_iff + proof (rule not_alg_dvd_sum) + have "p - 1 < 1 * p" + using \p > 1\ by simp + also have "1 * p \ n * p" + using \n > 0\ by (intro mult_right_mono) auto + finally show "((q, \), p - 1) \ Sigma P Roots \ {..n > 0\ by auto + next + fix z assume z: "z \ Sigma P Roots \ {..),p-1)}" + from z have "snd (fst z) \ Roots'" + by (auto simp: Roots'_def) + moreover have "fst (fst z) = q" if "\ \ Roots (fst (fst z))" + proof - + have "\ \ Roots (fst (fst z)) \ Roots q" "q \ P" "fst (fst z) \ P" + using that q z by auto + with disjoint show ?thesis + unfolding disjoint_family_on_def by blast + qed + ultimately have "of_nat p alg_dvd h (snd (fst z)) (snd z)" + using z by (intro p_dvd) auto + thus "of_nat p alg_dvd (case z of (x, xa) \ (case x of (q, \') \ \i. of_int (\ q) * h \' i) xa)" + using z by auto + qed (use \\of_nat p alg_dvd of_int (\ q) * h \ (p-1)\ in auto) + qed + + text \ + Our next goal is to show that $J$ is rational. This is done by repeated applications + of the fundamental theorem of symmetric polynomials, exploiting the fact that $J$ is + symmetric in all the $\alpha_i$ for each set of conjugates. + \ + define g :: "int poly poly" + where "g = synthetic_div (map_poly (\x. [:x:]) + ((Polynomial.smult lc_factor (\P)) ^ p)) [:0, 1:]" + have g: "map_poly (\p. ipoly p \) g = f_poly \" if \: "\ \ Roots'" for \ + proof - + interpret \: comm_ring_hom "\p. ipoly p \" + by standard (auto simp: of_int_hom.poly_map_poly_eval_poly of_int_poly_hom.hom_mult) + define Q :: "int poly" where "Q = (Polynomial.smult lc_factor (\P)) ^ p" + have "f_poly \ = Polynomial.smult (of_int (l^(n*p))) ((\\'\Roots'. [:-\',1:])^p) div [:-\,1:]" + unfolding f_poly_def div_smult_left [symmetric] prod_power_distrib[symmetric] .. + also have "of_int (l^(n*p)) = (of_int l^n)^p" + by (simp add: power_mult) + also have "Polynomial.smult \ ((\\'\Roots'. [:-\',1:])^p) = + (Polynomial.smult (of_int l ^ n) (\\'\Roots'. [:-\',1:])) ^ p" + by (simp only: smult_power) + also have "\ = of_int_poly Q" + by (subst lc_factor) (simp_all add: Q_def of_int_poly_hom.hom_power) + also have "\ div [:-\, 1:] = synthetic_div (of_int_poly Q) \" + unfolding synthetic_div_altdef .. + also have "\ = synthetic_div (map_poly (\p. ipoly p \) (map_poly (\x. [:x:]) Q)) (ipoly [:0, 1:] \)" + by (simp add: map_poly_map_poly o_def) + also have "\ = map_poly (\p. ipoly p \) g" + unfolding g_def Q_def by (rule \.synthetic_div_hom) + finally show ?thesis .. + qed + + obtain Q where Q: "J \ = -(\q\P. of_int (\ q) * eval_poly of_rat (Q q) \)" + if "\ \ Roots'" for \ + proof - + define g' :: "nat \ complex poly poly" + where "g' = (\j. (map_poly of_int_poly ((pderiv ^^ j) g)))" + obtain root :: "int poly \ nat \ complex" + where root: "\q. q \ P \ bij_betw (root q) {..<\q} (Roots q)" + using ex_bij_betw_nat_finite[OF finite_Roots] unfolding n_roots_def atLeast0LessThan + by metis + have "\Q'. map_poly of_rat Q' = (\x\Roots q. poly (g' j) [:x:])" if q: "q \ P" for q j + proof - + define Q :: "nat \ complex poly mpoly" + where "Q = (\j. (\i<\q. mpoly_of_poly i (g' j)))" + define ratpolys :: "complex poly set" where "ratpolys = {p. \i. poly.coeff p i \ \}" + have "insertion ((\x. [:x:]) \ root q) (Q j) \ ratpolys" + proof (rule symmetric_poly_of_roots_in_subring) + show "ring_closed ratpolys" + by standard (auto simp: ratpolys_def intro!: coeff_mult_semiring_closed) + show "\m. MPoly_Type.coeff (Q j) m \ ratpolys" + by (auto simp: Q_def ratpolys_def Polynomial.coeff_sum coeff_mpoly_of_poly when_def g'_def + intro!: sum_in_Rats) + show "vars (Q j) \ {..<\q}" unfolding Q_def + by (intro order.trans[OF vars_sum] UN_least order.trans[OF vars_mpoly_of_poly]) auto + show "symmetric_mpoly {..<\q} (Q j)" unfolding Q_def + by (rule symmetric_mpoly_symmetric_sum[of _ id]) (auto simp: permutes_bij) + interpret coeff_lift_hom: map_poly_idom_hom "\x. [:x:]" + by standard + define lc :: complex where "lc = of_int (Polynomial.lead_coeff q)" + have "of_int_poly q = Polynomial.smult (Polynomial.lead_coeff q) (\x\Roots q. [:-x, 1:])" + by (rule of_int_poly_P) fact + also have "poly_lift \ = Polynomial.smult [:lc:] (\a\Roots q. [:-[:a:], 1:])" + by (simp add: poly_lift_def map_poly_smult coeff_lift_hom.hom_prod lc_def) + also have "(\a\Roots q. [:-[:a:], 1:]) = (\i<\q. [:-[:root q i:], 1:])" + by (intro prod.reindex_bij_betw [symmetric] root q) + also have "\ = (\i<\q. [:- ((\x. [:x:]) \ root q) i, 1:])" + by simp + finally show "poly_lift (Ring_Hom_Poly.of_int_poly q) = Polynomial.smult [:lc:] \" . + have "lc \ 0" + using q by (auto simp: lc_def) + thus "[:inverse lc:] * [:lc:] = 1" + by (simp add: field_simps) + qed (auto simp: ratpolys_def coeff_pCons split: nat.splits) + + also have "insertion ((\x. [:x:]) \ root q) (Q j) = (\i<\q. poly (g' j) [:root q i:])" + by (simp add: Q_def insertion_sum poly_sum) + also have "\ = (\x\Roots q. poly (g' j) [:x:])" + by (intro sum.reindex_bij_betw root q) + finally have "\i. poly.coeff (\x\Roots q. poly (g' j) [:x:]) i \ \" + by (auto simp: ratpolys_def) + thus ?thesis + using ratpolyE by metis + qed + then obtain Q where Q: "\q j. q \ P \ map_poly of_rat (Q q j) = (\x\Roots q. poly (g' j) [:x:])" + by metis + define Q' where "Q' = (\q. \j = - (\q\P. of_int (\ q) * eval_poly of_rat (Q' q) \)" if \: "\ \ Roots'" for \ + proof - + have "J \ = -(\q\P. of_int (\ q) * (\x\Roots q. \j)) x))" + (is "_ = -?S") unfolding J_eq[OF \] .. + also have "?S = (\q\P. of_int (\ q) * eval_poly of_rat (Q' q) \)" + proof (rule sum.cong, goal_cases) + case q: (2 q) + interpret \: idom_hom "\p. ipoly p \" + by standard (auto simp: of_int_hom.poly_map_poly_eval_poly of_int_poly_hom.hom_mult) + + have "(\x\Roots q. \j)) x) = + (\jx\Roots q. poly ((pderiv ^^ j) (f_poly \)) x)" + by (rule sum.swap) + also have "\ = (\j)" + proof (rule sum.cong, goal_cases) + case j: (2 j) + have "(\x\Roots q. poly ((pderiv ^^ j) (f_poly \)) x) = + (\x\Roots q. poly (poly (g' j) [:x:]) \)" + proof (rule sum.cong, goal_cases) + case (2 x) + have "poly ((pderiv ^^ j) (f_poly \)) x = + poly ((pderiv ^^ j) (map_poly (\p. ipoly p \) g)) x" + by (subst g[OF \, symmetric]) (rule refl) + also have "\ = poly (eval_poly ((\p. [:poly p \:]) \ of_int_poly) ((pderiv ^^ j) g) [:0, 1:]) x" + unfolding o_def \.map_poly_higher_pderiv [symmetric] + by (simp only: \.map_poly_eval_poly) + also have "\ = poly (eval_poly (\p. [:poly p \:]) + (map_poly of_int_poly ((pderiv ^^ j) g)) [:0, 1:]) x" + unfolding eval_poly_def by (subst map_poly_map_poly) auto + also have "\ = poly (poly (map_poly of_int_poly ((pderiv ^^ j) g)) [:x:]) \" + by (rule poly_poly_eq [symmetric]) + also have "\ = poly (poly (g' j) [:x:]) \" + by (simp add: g'_def) + finally show ?case . + qed auto + also have "\ = poly (\x\Roots q. poly (g' j) [:x:]) \" + by (simp add: poly_sum) + also have "\ = eval_poly of_rat (Q q j) \" + using q by (simp add: Q eval_poly_def) + finally show ?case . + qed auto + also have "\ = eval_poly of_rat (Q' q) \" + by (simp add: Q'_def of_rat_hom.eval_poly_sum) + finally show ?case by simp + qed auto + finally show "J \ = - (\q\P. of_int (\ q) * eval_poly of_rat (Q' q) \)" . + qed + thus ?thesis using that[of Q'] by metis + qed + + have "J' \ \" + proof - + have "(\\\Roots q. J \) \ \" if q: "q \ P" for q + proof - + obtain root where root: "bij_betw root {..<\q} (Roots q)" + using ex_bij_betw_nat_finite[OF finite_Roots[OF q]] + unfolding atLeast0LessThan n_roots_def by metis + define Q' :: "complex poly" + where "Q' = -(\q\P. Polynomial.smult (of_int (\ q)) (map_poly of_rat (Q q)))" + + have "(\\\Roots q. J \) = (\\\Roots q. -(\q\P. of_int (\ q) * eval_poly of_rat (Q q) \))" + by (intro prod.cong refl Q) (auto simp: Roots'_def q) + also have "\ = (\\\Roots q. poly Q' \)" + by (simp add: Q'_def poly_sum eval_poly_def) + also have "\ = (\i<\q. poly Q' (root i))" + by (intro prod.reindex_bij_betw [symmetric] root) + also have "\ = insertion root (\i<\q. mpoly_of_poly i Q')" + by (simp add: insertion_prod) + also have "\ \ \" + proof (rule symmetric_poly_of_roots_in_subring) + show "ring_closed (\ :: complex set)" + by standard auto + then interpret Q: ring_closed "\ :: complex set" . + show "\m. MPoly_Type.coeff (\i<\q. mpoly_of_poly i Q') m \ \" + by (auto intro!: Q.coeff_prod_closed sum_in_Rats + simp: coeff_mpoly_of_poly when_def Q'_def Polynomial.coeff_sum) + show "symmetric_mpoly {..<\q} (\i<\q. mpoly_of_poly i Q')" + by (intro symmetric_mpoly_symmetric_prod'[of _ id]) (auto simp: permutes_bij) + show "vars (\i<\q. mpoly_of_poly i Q') \ {..<\q}" + by (intro order.trans[OF vars_prod] order.trans[OF vars_mpoly_of_poly] UN_least) auto + define lc where "lc = (of_int (Polynomial.lead_coeff q) :: complex)" + have "of_int_poly q = Polynomial.smult lc (\x\Roots q. [:- x, 1:])" + unfolding lc_def by (rule of_int_poly_P) fact + also have "(\x\Roots q. [:- x, 1:]) = (\i<\q. [:- root i, 1:])" + by (intro prod.reindex_bij_betw [symmetric] root) + finally show "of_int_poly q = Polynomial.smult lc (\i<\q. [:- root i, 1:])" . + have "lc \ 0" + using q by (auto simp: lc_def) + thus "inverse lc * lc = 1" "inverse lc \ \" + by (auto simp: lc_def) + qed auto + finally show ?thesis . + qed + hence "(\q\P. \\\Roots q. J \) \ \" + by (rule prod_in_Rats) + also have "(\q\P. \\\Roots q. J \) = J'" + unfolding Roots'_def J'_def using disjoint + by (intro prod.UNION_disjoint [symmetric]) (auto simp: disjoint_family_on_def) + finally show "J' \ \" . + qed + + text \ + Since \J'\ is clearly an algebraic integer, we now know that it is in fact an integer. + \ + moreover have "algebraic_int J'" + unfolding J'_def + proof (intro algebraic_int_prod) + fix x assume "x \ Roots'" + hence "fact (p - 1) alg_dvd J x" + by (intro J) + thus "algebraic_int (J x)" + by (rule alg_dvd_imp_algebraic_int) auto + qed + ultimately have "J' \ \" + using rational_algebraic_int_is_int by blast + + text \ + It is also non-zero, as none of the $J_i$ have $p$ as a factor and such cannot be zero. + \ + have "J' \ 0" + unfolding J'_def + proof (intro prod_nonzeroI) + fix \ assume "\ \ Roots'" + hence "\of_nat p alg_dvd J \" + using J(2)[of \] by auto + thus "J \ \ 0" + by auto + qed + + text \ + It then clearly follows that $(p-1)!^n \leq J$: + \ + have "fact (p - 1) ^ n alg_dvd J'" + proof - + have "fact (p - 1) ^ n = (\\\Roots'. fact (p - 1))" + by (simp add: n_altdef) + also have "\ alg_dvd J'" + unfolding J'_def by (intro prod_alg_dvd_prod J(1)) + finally show ?thesis . + qed + + have "fact (p - 1) ^ n \ norm J'" + proof - + from \J' \ \\ obtain J'' where [simp]: "J' = of_int J''" + by (elim Ints_cases) + have "of_int (fact (p - 1) ^ n) = (fact (p - 1) ^ n :: complex)" + by simp + also have "\ alg_dvd J'" + by fact + also have "J' = of_int J''" + by fact + finally have "fact (p - 1) ^ n dvd J''" + by (subst (asm) alg_dvd_of_int_iff) + moreover from \J' \ 0\ have "J'' \ 0" + by auto + ultimately have "\J''\ \ \fact (p - 1) ^ n\" + by (intro dvd_imp_le_int) + hence "real_of_int \J''\ \ real_of_int \fact (p - 1) ^ n\" + by linarith + also have "real_of_int \J''\ = norm J'" + by simp + finally show ?thesis + by simp + qed + + text \The standard M-L bound for $I_i(x)$ shows the following inequality:\ + also have "norm J' \ C' * C p ^ n" + proof - + have "norm J' = (\x\Roots'. norm (J x))" + unfolding J'_def prod_norm [symmetric] .. + also have "\ \ (\x\Roots'. \q\P. real_of_int \\ q\ * (\\\Roots q. cmod \ * exp (cmod \) * C p))" + proof (intro prod_mono conjI) + fix x assume x: "x \ Roots'" + show "norm (J x) \ (\q\P. real_of_int \\ q\ * (\\\Roots q. norm \ * exp (norm \) * C p))" + unfolding J_def + proof (intro sum_norm_le) + fix q assume "q \ P" + show "norm (of_int (\ q) * sum (I x) (Roots q)) \ + real_of_int \\ q\ * (\\\Roots q. norm \ * exp (norm \) * C p)" + unfolding norm_mult norm_of_int of_int_abs + proof (intro mult_left_mono sum_norm_le) + fix \ assume "\ \ Roots q" + hence \: "\ \ Roots'" + using \q \ P\ by (auto simp: Roots'_def) + show "norm (I x \) \ norm \ * exp (norm \) * C p" + unfolding I_def + proof (intro lindemann_weierstrass_aux.lindemann_weierstrass_integral_bound) + fix t assume "t \ closed_segment 0 \" + also have "closed_segment 0 \ \ cball 0 R" + using \R \ 0\ R_ge[OF \] by (intro closed_segment_subset) auto + finally have "norm t \ R" by simp + + have norm_diff_le: "norm (t - y) \ 2 * R" if "y \ Roots'" for y + proof - + have "norm (t - y) \ norm t + norm y" + by (meson norm_triangle_ineq4) + also have "\ \ R + R" + by (intro add_mono[OF \norm t \ R\ R_ge] that) + finally show ?thesis by simp + qed + + have "norm (poly (f_poly x) t) = + \real_of_int l\ ^ (n * p) * (\y\Roots'. cmod (t - y) ^ (if y = x then p - 1 else p))" + by (simp add: eval_f x f_def norm_mult norm_power flip: prod_norm) + also have "\ \ \real_of_int l\ ^ (n * p) * (\y\Roots'. (2*R) ^ (if y = x then p - 1 else p))" + by (intro mult_left_mono prod_mono conjI power_mono norm_diff_le) auto + also have "\ = \real_of_int l\^(n*p) * (2^(p-1) * R^(p-1) * (2^p*R^p)^(n-1))" + using x by (subst prod.If_eq) (auto simp: card_Diff_subset n_altdef) + also have "2^(p-1) * R^(p-1) * (2^p*R^p)^(n-1) = (2^((p-1)+p*(n-1))) * (R^((p-1)+p*(n-1)))" + unfolding power_mult power_mult_distrib power_add by (simp add: mult_ac) + also have "(p-1)+p*(n-1) = p*n - 1" + using \n > 0\ \p > 1\ by (cases n) (auto simp: algebra_simps) + also have "2 ^ (p * n - 1) * R ^ (p * n - 1) = (2*R)^(n * p-1)" + unfolding power_mult_distrib by (simp add: mult_ac) + finally show "norm (poly (f_poly x) t) \ C p" + unfolding C_def using \l > 0\ by simp + qed (use \R \ 0\ \l > 0\ in \auto simp: C_def\) + qed auto + qed + qed auto + also have "\ = C' * C p ^ n" + by (simp add: C'_def power_mult_distrib n_altdef flip: sum_distrib_right mult.assoc) + finally show ?thesis . + qed + + text \And with that, we have our inequality:\ + finally show "fact (p - 1) ^ n \ C' * C p ^ n" . + qed + + text \ + Some simple asymptotic estimates show that this is clearly a contradiction, since + the left-hand side grows much faster than the right-hand side and there are infinitely many + sufficiently large primes: + \ + have freq: "frequently prime sequentially" + using frequently_prime_cofinite unfolding cofinite_eq_sequentially . + have ev: "eventually (\p. (\q\P. int p > \\ q\) \ + real p > norm (\\\Roots'. of_int (l^n) * (\\'\Roots'-{\}. (\-\')))) sequentially" + by (intro eventually_ball_finite \finite P\ ballI eventually_conj filterlim_real_sequentially + eventually_compose_filterlim[OF eventually_gt_at_top] filterlim_int_sequentially) + + have "frequently (\p. fact (p - 1) ^ n \ C' * C p ^ n) sequentially" + by (rule frequently_eventually_mono[OF freq ev]) (use ineq in blast) + moreover have "eventually (\p. fact (p - 1) ^ n > C' * C p ^ n) sequentially" + proof (cases "R = 0") + case True + have "eventually (\p. p * n > 1) at_top" using \n > 0\ + by (intro eventually_compose_filterlim[OF eventually_gt_at_top] mult_nat_right_at_top) + thus ?thesis + by eventually_elim (use \n > 0\ True in \auto simp: C_def power_0_left mult_ac\) + next + case False + hence "R > 0" + using \R \ 0\ by auto + define D :: real where "D = (2 * R * \real_of_int l\) ^ n" + have "D > 0" + using \R > 0\ \l > 0\ unfolding D_def by (intro zero_less_power) auto + + have "(\p. C' * C p ^ n) \ O(\p. C p ^ n)" + by simp + also have "(\p. C p ^ n) \ O(\p. ((2 * R * l) ^ (n * p)) ^ n)" + proof (rule landau_o.big_power[OF bigthetaD1]) + have np: "eventually (\p. p * n > 0) at_top" using \n > 0\ + by (intro eventually_compose_filterlim[OF eventually_gt_at_top] mult_nat_right_at_top) + have "eventually (\p. (2 * R) * C p = (2 * R * l) ^ (n * p)) at_top" + using np + proof eventually_elim + case (elim p) + have "2 * R * C p = l ^ (n * p) * (2 * R) ^ (Suc (n * p - 1))" + by (simp add: C_def algebra_simps) + also have "Suc (n * p - 1) = n * p" + using elim by auto + finally show ?case + by (simp add: algebra_simps) + qed + hence "(\p. (2 * R) * C p) \ \(\p. (2 * R * l) ^ (n * p))" + by (intro bigthetaI_cong) + thus "C \ \(\p. (2 * R * l) ^ (n * p))" + using \R > 0\ by simp + qed + also have "\ = O(\p. (D ^ p) ^ n)" + using \l > 0\ by (simp flip: power_mult add: power2_eq_square mult_ac D_def) + also have "(\p. (D ^ p) ^ n) \ o(\p. fact (p - 1) ^ n)" + proof (intro landau_o.small_power) + have "eventually (\p. D ^ p = D * D ^ (p - 1)) at_top" + using eventually_gt_at_top[of 0] + by eventually_elim (use \D > 0\ in \auto simp flip: power_Suc\) + hence "(\p. D ^ p) \ \(\p. D * D ^ (p - 1))" + by (intro bigthetaI_cong) + hence "(\p. D ^ p) \ \(\p. D ^ (p - 1))" + using \D > 0\ by simp + also have "(\p. D ^ (p - 1)) \ o(\p. fact (p - 1))" + by (intro smalloI_tendsto[OF filterlim_compose[OF power_over_fact_tendsto_0]] + filterlim_minus_nat_at_top) auto + finally show "(\p. D ^ p) \ o(\x. fact (x - 1))" . + qed fact+ + finally have smallo: "(\p. C' * C p ^ n) \ o(\p. fact (p - 1) ^ n)" . + have "eventually (\p. \C' * C p ^ n\ \ 1/2 * fact (p - 1) ^ n) at_top" + using landau_o.smallD[OF smallo, of "1/2"] by simp + thus "eventually (\p. C' * C p ^ n < fact (p - 1) ^ n) at_top" + proof eventually_elim + case (elim p) + have "C' * C p ^ n \ \C' * C p ^ n\" + by simp + also have "\ \ 1/2 * fact (p - 1) ^ n" + by fact + also have "\ < fact (p - 1) ^ n" + by simp + finally show ?case . + qed + qed + ultimately have "frequently (\p::nat. False) sequentially" + by (rule frequently_eventually_mono) auto + thus False + by simp +qed + + +subsection \Removing the restriction of full sets of conjugates\ + +text \ + We will now remove the restriction that the $\alpha_i$ must occur in full sets of conjugates + by multiplying the equality with all permutations of roots. +\ +lemma Hermite_Lindemann_aux2: + fixes X :: "complex set" and \ :: "complex \ int" + assumes "finite X" + assumes nz: "\x. x \ X \ \ x \ 0" + assumes alg: "\x. x \ X \ algebraic x" + assumes sum0: "(\x\X. of_int (\ x) * exp x) = 0" + shows "X = {}" +proof (rule ccontr) + assume "X \ {}" + note [intro] = \finite X\ + + text \ + Let \P\ be the smallest integer polynomial whose roots are a superset of \X\: + \ + define P :: "int poly" where "P = \(min_int_poly ` X)" + define Roots :: "complex set" where "Roots = {x. ipoly P x = 0}" + have [simp]: "P \ 0" + using \finite X\ by (auto simp: P_def) + have [intro]: "finite Roots" + unfolding Roots_def by (intro poly_roots_finite) auto + + have "X \ Roots" + proof safe + fix x assume "x \ X" + hence "ipoly (min_int_poly x) x = 0" + by (intro ipoly_min_int_poly alg) + thus "x \ Roots" + using \finite X\ \x \ X\ + by (auto simp: Roots_def P_def of_int_poly_hom.hom_prod poly_prod) + qed + + have "squarefree (of_int_poly P :: complex poly)" + unfolding P_def of_int_poly_hom.hom_prod + proof (rule squarefree_prod_coprime; safe) + fix x assume "x \ X" + thus "squarefree (of_int_poly (min_int_poly x) :: complex poly)" + by (intro squarefree_of_int_polyI) auto + next + fix x y assume xy: "x \ X" "y \ X" "min_int_poly x \ min_int_poly y" + thus "Rings.coprime (of_int_poly (min_int_poly x)) (of_int_poly (min_int_poly y) :: complex poly)" + by (intro coprime_of_int_polyI[OF primes_coprime]) auto + qed + + text \ + Since we will need a numbering of these roots, we obtain one: + \ + define n where "n = card Roots" + obtain Root where Root: "bij_betw Root {..finite Roots\] unfolding n_def atLeast0LessThan by metis + define unRoot :: "complex \ nat" where "unRoot = inv_into {.. Roots" for x + unfolding unRoot_def using Root that by (subst f_inv_into_f) (auto simp: bij_betw_def) + have [simp, intro]: "Root i \ Roots" if "i < n" for i + using Root that by (auto simp: bij_betw_def) + have [simp, intro]: "unRoot x < n" if "x \ Roots" for x + using unRoot that by (auto simp: bij_betw_def) + + text \ + We will also need to convert between permutations of natural numbers less than \n\ and + permutations of the roots: + \ + define convert_perm :: "(nat \ nat) \ (complex \ complex)" where + "convert_perm = (\\ x. if x \ Roots then Root (\ (unRoot x)) else x)" + have bij_convert: "bij_betw convert_perm {\. \ permutes {... \ permutes Roots}" + using bij_betw_permutations[OF Root] unfolding convert_perm_def unRoot_def . + have permutes_convert_perm [intro]: "convert_perm \ permutes Roots" if "\ permutes {.. + using that bij_convert unfolding bij_betw_def by blast + have convert_perm_compose: "convert_perm (\ \ \) = convert_perm \ \ convert_perm \" + if "\ permutes {.. permutes {.. \ + proof (intro ext) + fix x show "convert_perm (\ \ \) x = (convert_perm \ \ convert_perm \) x" + proof (cases "x \ Roots") + case True + thus ?thesis + using permutes_in_image[OF that(2), of "unRoot x"] + by (auto simp: convert_perm_def bij_betw_def) + qed (auto simp: convert_perm_def) + qed + + text \ + We extend the coefficient vector to the new roots by setting their coefficients to 0: + \ + define \' where "\' = (\x. if x \ X then \ x else 0)" + + text \ + We now define the set of all permutations of our roots: + \ + define perms where "perms = {\. \ permutes Roots}" + have [intro]: "finite perms" + unfolding perms_def by (rule finite_permutations) auto + have [simp]: "card perms = fact n" + unfolding perms_def n_def by (intro card_permutations) auto + + text \ + The following is the set of all \n!\-tuples of roots, disregarding permutation of components. + In other words: all multisets of roots with size \n!\. + \ + define Roots_ms :: "complex multiset set" where + "Roots_ms = {X. set_mset X \ Roots \ size X = fact n}" + have [intro]: "finite Roots_ms" + unfolding Roots_ms_def by (rule finite_multisets_of_size) auto + + text \ + Next, the following is the set of \n!\-tuples whose entries are precisely the multiset \X\: + \ + define tuples :: "complex multiset \ ((complex \ complex) \ complex) set" where + "tuples = (\X. {f\perms \\<^sub>E Roots. image_mset f (mset_set perms) = X})" + have fin_tuples [intro]: "finite (tuples X)" for X + unfolding tuples_def by (rule finite_subset[of _ "perms \\<^sub>E Roots", OF _ finite_PiE]) auto + define tuples' :: "(complex multiset \ ((complex \ complex) \ complex)) set" where + "tuples' = (SIGMA X:Roots_ms. tuples X)" + + text \ + The following shows that our \<^term>\tuples\ definition is stable under permutation of + the roots. + \ + have bij_convert': "bij_betw (\f. f \ (\g. \ \ g)) (tuples X) (tuples X)" + if \: "\ permutes Roots" for \ X + proof (rule bij_betwI) + have *: "(\f. f \ (\) \) \ tuples X \ tuples X" if \: "\ permutes Roots" for \ + proof + fix f assume f: "f \ tuples X" + show "f \ (\) \ \ tuples X" + unfolding tuples_def + proof safe + fix \' + assume \': "\' \ perms" + show "(f \ (\) \) \' \ Roots" + using permutes_compose[OF _ \, of \'] \ \' f by (auto simp: perms_def tuples_def) + next + fix \' + assume \': "\' \ perms" + have "\(\ \ \') permutes Roots" + proof + assume "(\ \ \') permutes Roots" + hence "inv_into UNIV \ \ (\ \ \') permutes Roots" + by (rule permutes_compose) (use permutes_inv[OF \] in simp_all) + also have "inv_into UNIV \ \ (\ \ \') = \'" + by (auto simp: fun_eq_iff permutes_inverses[OF \]) + finally show False using \' by (simp add: perms_def) + qed + thus "(f \ (\) \) \' = undefined" + using f by (auto simp: perms_def tuples_def) + next + have "image_mset (f \ (\) \) (mset_set perms) = + image_mset f (image_mset ((\) \) (mset_set perms))" + by (rule multiset.map_comp [symmetric]) + also have "image_mset ((\) \) (mset_set perms) = mset_set perms" + using bij_betw_permutes_compose_left[OF \] + by (subst image_mset_mset_set) (auto simp: bij_betw_def perms_def) + also have "image_mset f \ = X" + using f by (auto simp: tuples_def) + finally show "image_mset (f \ (\) \) (mset_set perms) = X" . + qed + qed + + show "(\f. f \ (\) \) \ tuples X \ tuples X" + by (rule *) fact + show "(\f. f \ (\) (inv_into UNIV \)) \ tuples X \ tuples X" + by (intro * permutes_inv) fact + show "f \ (\) \ \ (\) (inv_into UNIV \) = f" if "f \ tuples X" for f + by (auto simp: fun_eq_iff o_def permutes_inverses[OF \]) + show "f \ (\) (inv_into UNIV \) \ (\) \ = f" if "f \ tuples X" for f + by (auto simp: fun_eq_iff o_def permutes_inverses[OF \]) + qed + + text \ + Next, we define the multiset of of possible exponents that we can get for a given + \n!\-multiset of roots, + \ + define R :: "complex multiset \ complex multiset" where + "R = (\X. image_mset (\f. \\\perms. \ (f \)) (mset_set (tuples X)))" + + text \ + We show that, for each such multiset, there is a content-free integer polynomial that has + exactly these exponents as roots. This shows that they form a full set of conjugates (but + note this polynomial is not necessarily squarefree). + + The proof is yet another application of the fundamental theorem of symmetric polynomials. + \ + obtain Q :: "complex multiset \ int poly" + where Q: "\X. X \ Roots_ms \ poly_roots (of_int_poly (Q X)) = R X" + "\X. X \ Roots_ms \ content (Q X) = 1" + proof - + { + fix X :: "complex multiset" + assume X: "X \ Roots_ms" + define Q :: "complex poly mpoly" where + "Q = (\f\tuples X. Const [:0, 1:] - + (\\ | \ permutes {.. (unRoot (f (convert_perm \))))))" + define Q1 where "Q1 = (\f\tuples X. [:- (\\ | \ permutes Roots. \ (f \)), 1:])" + define ratpolys :: "complex poly set" where "ratpolys = {p. \i. poly.coeff p i \ \}" + + have "insertion (\x. [:Root x:]) Q \ ratpolys" + proof (rule symmetric_poly_of_roots_in_subring[where l = "\x. [:x:]"]) + show "ring_closed ratpolys" + unfolding ratpolys_def by standard (auto intro: coeff_mult_semiring_closed) + then interpret ratpolys: ring_closed ratpolys . + have "pCons 0 1 \ ratpolys " + by (auto simp: ratpolys_def coeff_pCons split: nat.splits) + thus "\m. MPoly_Type.coeff Q m \ ratpolys" + unfolding Q_def + by (intro allI ratpolys.coeff_prod_closed) + (auto intro!: ratpolys.minus_closed ratpolys.sum_closed ratpolys.uminus_closed simp: coeff_Var mpoly_coeff_Const when_def) + next + show "ring_homomorphism (\x::complex. [:x:])" .. + next + have "\ (unRoot (f (convert_perm \))) < n" if "f \ tuples X" "\ permutes {.. + proof - + have "convert_perm \ \ perms" + using bij_convert that(2) by (auto simp: bij_betw_def perms_def) + hence "f (convert_perm \) \ Roots" + using that by (auto simp: tuples_def) + thus ?thesis + using permutes_in_image[OF that(2)] by simp + qed + thus "vars Q \ {.. ratpolys" + by (auto simp: ratpolys_def coeff_pCons lc_def split: nat.splits) + show "\i. [:poly.coeff (of_int_poly P) i:] \ ratpolys" + by (auto simp: ratpolys_def coeff_pCons split: nat.splits) + have "lc \ 0" + by (auto simp: lc_def) + thus "[:inverse lc:] * [:lc:] = 1" + by auto + have "rsquarefree (of_int_poly P :: complex poly)" + using \squarefree (of_int_poly P :: complex poly)\ by (intro squarefree_imp_rsquarefree) + hence "of_int_poly P = Polynomial.smult lc (\x\Roots. [:-x, 1:])" + unfolding lc_def Roots_def of_int_hom.hom_lead_coeff[symmetric] + by (rule complex_poly_decompose_rsquarefree [symmetric]) + also have "(\x\Roots. [:-x, 1:]) = (\ii assume \: "\ permutes {.. Q = (\f\tuples X. Const (pCons 0 1) - (\ \ | \ permutes {.. \ \) (unRoot (f (convert_perm \))))))" + by (simp add: Q_def permutes_bij[OF \]) + also have "\ = (\f\tuples X. Const (pCons 0 1) - (\ \ | \ permutes {.. \ \) (unRoot ((f \ (\\. convert_perm \ \ \)) (convert_perm \))))))" + using \ by (intro prod.reindex_bij_betw [OF bij_convert', symmetric]) auto + also have "\ = Q" + unfolding Q_def + proof (rule prod.cong, goal_cases) + case (2 f) + have "(\ \ | \ permutes {.. \ \) (unRoot ((f \ (\\. convert_perm \ \ \)) (convert_perm \))))) = + (\ \ | \ permutes {.. \ \) (unRoot (f (convert_perm (\ \ \))))))" + using \ by (intro sum.cong refl, subst convert_perm_compose) simp_all + also have "\ = (\ \ | \ permutes {.. (unRoot (f (convert_perm \)))))" + using \ by (rule setum_permutations_compose_left [symmetric]) + finally show ?case by simp + qed auto + finally show "mpoly_map_vars \ Q = Q" . + qed + qed auto + also have "insertion (\x. [:Root x:]) Q = Q1" + unfolding Q_def Q1_def insertion_prod insertion_sum insertion_diff insertion_Const insertion_Var + proof (intro prod.cong, goal_cases) + case f: (2 f) + have "(\\ | \ permutes {.. (unRoot (f (convert_perm \)))):]) = + (\\ | \ permutes {.. (f (convert_perm \)):])" + proof (rule sum.cong, goal_cases) + case (2 \) + have "convert_perm \ permutes Roots" + using bij_convert 2 by (auto simp: bij_betw_def) + hence "f (convert_perm \) \ Roots" + using f by (auto simp: tuples_def perms_def) + thus ?case by (simp add: convert_perm_def) + qed simp_all + also have "\ = (\\ | \ permutes Roots. [:\ (f \):])" + by (rule sum.reindex_bij_betw[OF bij_convert]) + finally show ?case + by (simp flip: pCons_one coeff_lift_hom.hom_sum) + qed simp_all + finally have "Q1 \ ratpolys" + by auto + then obtain Q2 :: "rat poly" where Q2: "Q1 = map_poly of_rat Q2" + unfolding ratpolys_def using ratpolyE[of Q1] by blast + + have "Q1 \ 0" + unfolding Q1_def using fin_tuples[of X] by auto + with Q2 have "Q2 \ 0" + by auto + obtain Q3 :: "int poly" and lc :: rat + where Q3: "Q2 = Polynomial.smult lc (of_int_poly Q3)" and "lc > 0" and "content Q3 = 1" + using rat_to_normalized_int_poly_exists[OF \Q2 \ 0\] by metis + + have "poly_roots (of_int_poly Q3) = poly_roots (map_poly (of_rat \ of_int) Q3)" + by simp + also have "map_poly (of_rat \ of_int) Q3 = map_poly of_rat (map_poly of_int Q3)" + by (subst map_poly_map_poly) auto + also have "poly_roots \ = poly_roots (Polynomial.smult (of_rat lc) \)" + using \lc > 0\ by simp + also have "Polynomial.smult (of_rat lc) (map_poly of_rat (map_poly of_int Q3)) = + map_poly of_rat (Polynomial.smult lc (map_poly of_int Q3))" + by (simp add: of_rat_hom.map_poly_hom_smult) + also have "\ = Q1" + by (simp only: Q3 [symmetric] Q2 [symmetric]) + also have "poly_roots Q1 = R X" + unfolding Q1_def + by (subst poly_roots_prod, force, subst poly_roots_linear) + (auto simp: R_def perms_def sum_mset_image_mset_singleton sum_unfold_sum_mset) + finally have "\Q. poly_roots (of_int_poly Q) = R X \ content Q = 1" + using \content Q3 = 1\ by metis + } + hence "\Q. \X\Roots_ms. poly_roots (of_int_poly (Q X)) = R X \ content (Q X) = 1" + by metis + thus ?thesis using that by metis + qed + + text \ + We can now collect all the $e^{\sum \alpha_i}$ that happen to be equal and let the following + be their coefficients: + \ + define \'' :: "int poly \ int" + where "\'' = (\q. \X\Roots_ms. int (count (prime_factorization (Q X)) q) * (\x\#X. \' x))" + have supp_\'': "{q. \'' q \ 0} \ (\X\Roots_ms. prime_factors (Q X))" + unfolding \''_def using sum.not_neutral_contains_not_neutral by fastforce + + text \ + We have to prove that \\''\ is not zero everywhere. We do this by selecting the nonzero term + with the maximal exponent (w.r.t. the lexicographic ordering on the complex numbers) in every + factor of the product and show that there is no other summand corresponding to these, so + that their non-zero coefficient cannot get cancelled. + \ + have "{q. \'' q \ 0} \ {}" + proof - + define f where "f = restrict (\\. inv_into UNIV \ (complex_lex.Max (\ ` X))) perms" + have f: "f \ perms \ X" + proof + fix \ assume \: "\ \ perms" + have "complex_lex.Max (\ ` X) \ \ ` X" + using \X \ {}\ by (intro complex_lex.Max_in finite_imageI) auto + thus "f \ \ X" + using \ by (auto simp: f_def permutes_inverses[of \ Roots] perms_def) + qed + hence f': "f \ perms \\<^sub>E Roots" + using \X \ Roots\ by (auto simp: f_def PiE_def) + + define Y where "Y = image_mset f (mset_set perms)" + have "Y \ Roots_ms" using f' \finite perms\ + by (auto simp: Roots_ms_def Y_def) + + have "(\\\perms. \ (f \)) \# R Y" + proof - + from f' have "f \ tuples Y" + unfolding tuples_def Y_def by simp + thus ?thesis + unfolding R_def using fin_tuples[of Y] by auto + qed + also have "R Y = poly_roots (of_int_poly (Q Y))" + by (rule Q(1) [symmetric]) fact + also have "\ = (\p\#prime_factorization (Q Y). poly_roots (of_int_poly p))" + by (rule poly_roots_of_int_conv_sum_prime_factors) + finally obtain q where q: "q \ prime_factors (Q Y)" "(\\\perms. \ (f \)) \# poly_roots (of_int_poly q)" + by auto + + have "\'' q = (\X\{Y}. int (count (prime_factorization (Q X)) q) * prod_mset (image_mset \' X))" + unfolding \''_def + proof (intro sum.mono_neutral_right ballI) + fix Y' assume Y': "Y' \ Roots_ms - {Y}" + show "int (count (prime_factorization (Q Y')) q) * \\<^sub># (image_mset \' Y') = 0" + proof (cases "set_mset Y' \ X") + case Y'_subset: True + have "q \ prime_factors (Q Y')" + proof + assume q': "q \ prime_factors (Q Y')" + have "poly_roots (of_int_poly q :: complex poly) \# + poly_roots (of_int_poly (Q Y'))" + using q' by (intro dvd_imp_poly_roots_subset of_int_poly_hom.hom_dvd) auto + with q(2) have "(\\\perms. \ (f \)) \# poly_roots (of_int_poly (Q Y'))" + by (meson mset_subset_eqD) + also have "poly_roots (of_int_poly (Q Y')) = R Y'" + using Q(1)[of Y'] Y' by auto + finally obtain g where g: "g \ tuples Y'" "(\\\perms. \ (f \)) = (\\\perms. \ (g \))" + unfolding R_def using fin_tuples[of Y'] by auto + + moreover have "(\\\perms. \ (g \)) <\<^sub>\ (\\\perms. \ (f \))" + proof (rule sum_strict_mono_ex1_complex_lex) + show le: "\\\perms. \ (g \) \\<^sub>\ \ (f \)" + proof + fix \ assume \: "\ \ perms" + hence \': "\ permutes Roots" + by (auto simp: perms_def) + have "image_mset g (mset_set perms) = Y'" + using g by (auto simp: tuples_def) + also have "set_mset \ \ X" + by fact + finally have "g ` perms \ X" + using \finite perms\ by auto + hence "\ (g \) \\<^sub>\ complex_lex.Max (\ ` X)" + using \finite perms\ \ + by (intro complex_lex.Max.coboundedI finite_imageI imageI) + (auto simp: tuples_def) + also have "\ = \ (f \)" + using \ by (simp add: f_def permutes_inverses[OF \']) + finally show "\ (g \) \\<^sub>\ \ (f \)" . + qed + + have "image_mset g (mset_set perms) \ image_mset f (mset_set perms)" + using Y' g by (auto simp: tuples_def Y_def) + then obtain \ where \: "\ \# mset_set perms" "g \ \ f \" + by (meson multiset.map_cong) + have "\ permutes Roots" + using \ \finite perms\ by (auto simp: perms_def) + have "\ (g \) \ \ (f \)" + using permutes_inj[OF \\ permutes Roots\] \ by (auto simp: inj_def) + moreover have "\ (g \) \\<^sub>\ \ (f \)" + using le \ \finite perms\ by auto + ultimately have "\ (g \) <\<^sub>\ \ (f \)" + by simp + thus "\\\perms. \ (g \) <\<^sub>\ \ (f \)" + using \ \finite perms\ by auto + qed (use \finite perms\ in simp_all) + ultimately show False by simp + qed + thus ?thesis by auto + qed (auto simp: \'_def) + qed (use \Y \ Roots_ms\ in auto) + also have "\ = int (count (prime_factorization (Q Y)) q) * prod_mset (image_mset \' Y)" + by simp + also have "\ \ 0" + using q nz \finite X\ \X \ {}\ \finite perms\ f by (auto simp: \'_def Y_def) + finally show "{q. \'' q \ 0} \ {}" + by auto + qed + + text \ + We are now ready for the final push: we start with the original sum that we know to be zero, + multiply it with the other permutations, and then multiply out the sum. + \ + have "0 = (\x\X. \ x * exp x)" + using sum0 .. + also have "\ = (\x\Roots. \' x * exp x)" + by (intro sum.mono_neutral_cong_left \X \ Roots\) (auto simp: \'_def) + also have "\ dvd (\\\perms. \x\Roots. \' x * exp (\ x))" + by (rule dvd_prodI[OF \finite perms\]) + (use permutes_id[of Roots] in \simp_all add: id_def perms_def\) + also have "\ = (\f\perms \\<^sub>E Roots. \\\perms. \' (f \) * exp (\ (f \)))" + by (rule prod_sum_PiE) auto + also have "\ = (\f\perms \\<^sub>E Roots. (\\\perms. \' (f \)) * exp (\\\perms. \ (f \)))" + using \finite perms\ by (simp add: prod.distrib exp_sum) + also have "\ = (\(X,f)\tuples'. (\\\perms. \' (f \)) * exp (\\\perms. \ (f \)))" + using \finite perms\ + by (intro sum.reindex_bij_witness[of _ snd "\f. (image_mset f (mset_set perms), f)"]) + (auto simp: tuples'_def tuples_def Roots_ms_def PiE_def Pi_def) + also have "\ = (\(X,f)\tuples'. (\x\#X. \' x) * exp (\\\perms. \ (f \)))" + proof (safe intro!: sum.cong) + fix X :: "complex multiset" and f :: "(complex \ complex) \ complex" + assume "(X, f) \ tuples'" + hence X: "X \ Roots_ms" "X = image_mset f (mset_set perms)" and f: "f \ perms \\<^sub>E Roots" + by (auto simp: tuples'_def tuples_def) + have "(\\\perms. \' (f \)) = (\\\#mset_set perms. \' (f \))" + by (meson prod_unfold_prod_mset) + also have "\ = (\x\#X. \' x)" + unfolding X(2) by (simp add: multiset.map_comp o_def) + finally show "(\\\perms. \' (f \)) * exp (\\\perms. \ (f \)) = + (\x\#X. \' x) * exp (\\\perms. \ (f \))" by simp + qed + also have "\ = (\X\Roots_ms. \f\tuples X. (\x\#X. \' x) * exp (\\\perms. \ (f \)))" + unfolding tuples'_def by (intro sum.Sigma [symmetric]) auto + also have "\ = (\X\Roots_ms. of_int (\x\#X. \' x) * (\f\tuples X. exp (\\\perms. \ (f \))))" + by (simp add: sum_distrib_left) + also have "\ = (\X\Roots_ms. of_int (\x\#X. \' x) * (\x\#R X. exp x))" + by (simp only: R_def multiset.map_comp o_def sum_unfold_sum_mset) + also have "\ = (\X\Roots_ms. of_int (\x\#X. \' x) * (\x\#poly_roots (of_int_poly (Q X)). exp x))" + by (intro sum.cong) (simp_all flip: Q) + + text \ + Our problem now is that the polynomials \Q X\ can still contain multiple roots and that their + roots might not be disjoint. We therefore split them all into irreducible factors and collect + equal terms. + \ + also have "\ = (\X\Roots_ms. (\p. of_int (int (count (prime_factorization (Q X)) p) * + (\x\#X. \' x)) * (\x | ipoly p x = 0. exp x)))" + proof (rule sum.cong, goal_cases) + case (2 X) + have "(\x\#poly_roots (of_int_poly (Q X) :: complex poly). exp x) = + (\x \# (\p\#prime_factorization (Q X). poly_roots (of_int_poly p)). exp x)" + by (subst poly_roots_of_int_conv_sum_prime_factors) (rule refl) + also have "\ = (\p\#prime_factorization (Q X). \x\#poly_roots (of_int_poly p). exp x)" + by (rule sum_mset_image_mset_sum_mset_image_mset) + also have "rsquarefree (of_int_poly p :: complex poly)" if "p \ prime_factors (Q X)" for p + proof (rule irreducible_imp_rsquarefree_of_int_poly) + have "prime p" + using that by auto + thus "irreducible p" + by blast + next + show "Polynomial.degree p > 0" + by (intro content_1_imp_nonconstant_prime_factors[OF Q(2) that] 2) + qed + hence "(\p\#prime_factorization (Q X). \x\#poly_roots (of_int_poly p). exp x) = + (\p\#prime_factorization (Q X). \x | ipoly p x = 0. exp (x :: complex))" + unfolding sum_unfold_sum_mset + by (intro arg_cong[of _ _ sum_mset] image_mset_cong sum.cong refl, + subst rsquarefree_poly_roots_eq) auto + also have "\ = (\p. count (prime_factorization (Q X)) p * (\x | ipoly p x = 0. exp (x :: complex)))" + by (rule sum_mset_conv_Sum_any) + also have "of_int (\x\#X. \' x) * \ = + (\p. of_int (int (count (prime_factorization (Q X)) p) * (\x\#X. \' x)) * (\x | ipoly p x = 0. exp x))" + by (subst Sum_any_right_distrib) (auto simp: mult_ac) + finally show ?case by simp + qed auto + also have "\ = (\q. of_int (\'' q) * (\x | ipoly q x = 0. exp x))" + unfolding \''_def of_int_sum + by (subst Sum_any_sum_swap [symmetric]) (auto simp: sum_distrib_right) + also have "\ = (\q | \'' q \ 0. of_int (\'' q) * (\x | ipoly q x = 0. exp x))" + by (intro Sum_any.expand_superset finite_subset[OF supp_\'']) auto + finally have "(\q | \'' q \ 0. of_int (\'' q) * (\x | ipoly q x = 0. exp (x :: complex))) = 0" + by simp + + text \ + We are now in the situation of our the specialised Hermite--Lindemann Theorem we proved + earlier and can easily derive a contradiction. + \ + moreover have "(\q | \'' q \ 0. of_int (\'' q) * (\x | ipoly q x = 0. exp (x :: complex))) \ 0" + proof (rule Hermite_Lindemann_aux1) + show "finite {q. \'' q \ 0}" + by (rule finite_subset[OF supp_\'']) auto + next + show "pairwise Rings.coprime {q. \'' q \ 0}" + proof (rule pairwiseI, clarify) + fix p q assume pq: "p \ q" "\'' p \ 0" "\'' q \ 0" + hence "prime p" "prime q" + using supp_\'' Q(2) by auto + with pq show "Rings.coprime p q" + by (simp add: primes_coprime) + qed + next + fix q :: "int poly" + assume q: "q \ {q. \'' q \ 0}" + also note supp_\'' + finally obtain X where X: "X \ Roots_ms" "q \ prime_factors (Q X)" + by blast + show "irreducible q" + using X by (intro prime_elem_imp_irreducible prime_imp_prime_elem) auto + show "Polynomial.degree q > 0" using X + by (intro content_1_imp_nonconstant_prime_factors[OF Q(2)[of X]]) + qed (use \{x. \'' x \ 0} \ {}\ in auto) + + ultimately show False by contradiction +qed + + +subsection \Removing the restriction to integer coefficients\ + +text \ + Next, we weaken the restriction that the $\beta_i$ must be integers to the restriction + that they must be rationals. This is done simply by multiplying with the least common multiple + of the demoninators. +\ +lemma Hermite_Lindemann_aux3: + fixes X :: "complex set" and \ :: "complex \ rat" + assumes "finite X" + assumes nz: "\x. x \ X \ \ x \ 0" + assumes alg: "\x. x \ X \ algebraic x" + assumes sum0: "(\x\X. of_rat (\ x) * exp x) = 0" + shows "X = {}" +proof - + define l :: int where "l = Lcm ((snd \ quotient_of \ \) ` X)" + have [simp]: "snd (quotient_of r) \ 0" for r + using quotient_of_denom_pos'[of r] by simp + have [simp]: "l \ 0" + using \finite X\ by (auto simp: l_def Lcm_0_iff) + + have "of_int l * \ x \ \" if "x \ X" for x + proof - + define a b where "a = fst (quotient_of (\ x))" and "b = snd (quotient_of (\ x))" + have "b > 0" + using quotient_of_denom_pos'[of "\ x"] by (auto simp: b_def) + have "\ x = of_int a / of_int b" + by (intro quotient_of_div) (auto simp: a_def b_def) + also have "of_int l * \ = of_int (l * a) / of_int b" + using \b > 0\ by (simp add: field_simps) + also have "\ \ \" using that + by (intro of_int_divide_in_Ints) (auto simp: l_def b_def) + finally show ?thesis . + qed + hence "\x\X. \n. of_int n = of_int l * \ x" + using Ints_cases by metis + then obtain \' where \': "of_int (\' x) = of_int l * \ x" if "x \ X" for x + by metis + + show ?thesis + proof (rule Hermite_Lindemann_aux2) + have "0 = of_int l * (\x\X. of_rat (\ x) * exp x :: complex)" + by (simp add: sum0) + also have "\ = (\x\X. of_int (\' x) * exp x)" + unfolding sum_distrib_left + proof (rule sum.cong, goal_cases) + case (2 x) + have "of_int l * of_rat (\ x) = of_rat (of_int l * \ x)" + by (simp add: of_rat_mult) + also have "of_int l * \ x = of_int (\' x)" + using 2 by (rule \' [symmetric]) + finally show ?case by (simp add: mult_ac) + qed simp_all + finally show "\ = 0" .. + next + fix x assume "x \ X" + hence "of_int (\' x) \ (0 :: rat)" using nz + by (subst \') auto + thus "\' x \ 0" + by auto + qed (use alg \finite X\ in auto) +qed + +text \ + Next, we weaken the restriction that the $\beta_i$ must be rational to them being algebraic. + Similarly to before, this is done by multiplying over all possible permutations of the $\beta_i$ + (in some sense) to introduce more symmetry, from which it then follows by the fundamental theorem + of symmetric polynomials that the resulting coefficients are rational. +\ +lemma Hermite_Lindemann_aux4: + fixes \ :: "complex \ complex" + assumes [intro]: "finite X" + assumes alg1: "\x. x \ X \ algebraic x" + assumes alg2: "\x. x \ X \ algebraic (\ x)" + assumes nz: "\x. x \ X \ \ x \ 0" + assumes sum0: "(\x\X. \ x * exp x) = 0" + shows "X = {}" +proof (rule ccontr) + assume X: "X \ {}" + note [intro!] = finite_PiE + + text \ + We now take more or less the same approach as before, except that now we find a polynomial + that has all of the conjugates of the coefficients \\\ as roots. Note that this is a slight + deviation from Baker's proof, who picks one polynomial for each \\\ independently. I did it + this way because, as Bernard~\cite{bernard} observed, it makes the proof a bit easier. + \ + define P :: "int poly" where "P = \((min_int_poly \ \) ` X)" + define Roots :: "complex set" where "Roots = {x. ipoly P x = 0}" + have "0 \ Roots" using \finite X\ alg2 nz + by (auto simp: Roots_def P_def poly_prod) + have [simp]: "P \ 0" + using \finite X\ by (auto simp: P_def) + have [intro]: "finite Roots" + unfolding Roots_def by (intro poly_roots_finite) auto + + have "\ ` X \ Roots" + proof safe + fix x assume "x \ X" + hence "ipoly (min_int_poly (\ x)) (\ x) = 0" + by (intro ipoly_min_int_poly alg2) + thus "\ x \ Roots" + using \finite X\ \x \ X\ + by (auto simp: Roots_def P_def of_int_poly_hom.hom_prod poly_prod) + qed + + have "squarefree (of_int_poly P :: complex poly)" + unfolding P_def of_int_poly_hom.hom_prod o_def + proof (rule squarefree_prod_coprime; safe) + fix x assume "x \ X" + thus "squarefree (of_int_poly (min_int_poly (\ x)) :: complex poly)" + by (intro squarefree_of_int_polyI) auto + next + fix x y assume xy: "x \ X" "y \ X" "min_int_poly (\ x) \ min_int_poly (\ y)" + thus "Rings.coprime (of_int_poly (min_int_poly (\ x))) + (of_int_poly (min_int_poly (\ y)) :: complex poly)" + by (intro coprime_of_int_polyI[OF primes_coprime]) auto + qed + + define n where "n = card Roots" + define m where "m = card X" + have "Roots \ {}" + using \\ ` X \ Roots\ \X \ {}\ by auto + hence "n > 0" "m > 0" + using \finite Roots\ \finite X\ \X \ {}\ by (auto simp: n_def m_def) + have fin1 [simp]: "finite (X \\<^sub>E Roots)" + by auto + have [simp]: "card (X \\<^sub>E Roots) = n ^ m" + by (subst card_PiE) (auto simp: m_def n_def) + + text \ + We again find a bijection between the roots and the natural numbers less than \n\: + \ + obtain Root where Root: "bij_betw Root {..finite Roots\] unfolding n_def atLeast0LessThan by metis + define unRoot :: "complex \ nat" where "unRoot = inv_into {.. Roots" for x + unfolding unRoot_def using Root that by (subst f_inv_into_f) (auto simp: bij_betw_def) + have [simp, intro]: "Root i \ Roots" if "i < n" for i + using Root that by (auto simp: bij_betw_def) + have [simp, intro]: "unRoot x < n" if "x \ Roots" for x + using unRoot that by (auto simp: bij_betw_def) + + text \ + And we again define the set of multisets and tuples that we will get in the expanded product. + \ + define Roots_ms :: "complex multiset set" where + "Roots_ms = {Y. set_mset Y \ X \ size Y = n ^ m}" + have [intro]: "finite Roots_ms" + unfolding Roots_ms_def by (rule finite_multisets_of_size) auto + define tuples :: "complex multiset \ ((complex \ complex) \ complex) set" + where "tuples = (\Y. {f\(X \\<^sub>E Roots) \\<^sub>E X. image_mset f (mset_set (X \\<^sub>E Roots)) = Y})" + have [intro]: "finite (tuples Y)" for Y + unfolding tuples_def by (rule finite_subset[of _ "(X \\<^sub>E Roots) \\<^sub>E X"]) auto + + text \ + We will also need to convert permutations over the natural and over the roots again. + \ + define convert_perm :: "(nat \ nat) \ (complex \ complex)" where + "convert_perm = (\\ x. if x \ Roots then Root (\ (unRoot x)) else x)" + have bij_convert: "bij_betw convert_perm {\. \ permutes {... \ permutes Roots}" + using bij_betw_permutations[OF Root] unfolding convert_perm_def unRoot_def . + have permutes_convert_perm [intro]: "convert_perm \ permutes Roots" if "\ permutes {.. + using that bij_convert unfolding bij_betw_def by blast + + text \ + We also need a small lemma showing that our tuples are stable under permutation of the roots. + \ + have bij_betw_compose_perm: + "bij_betw (\f. restrict (\g. f (restrict (\ \ g) X)) (X \\<^sub>E Roots)) (tuples Y) (tuples Y)" + if \: "\ permutes Roots" and "Y \ Roots_ms" for \ Y + proof (rule bij_betwI) + have *: "(\f. restrict (\g. f (restrict (\ \ g) X)) (X \\<^sub>E Roots)) \ tuples Y \ tuples Y" + if \: "\ permutes Roots" for \ + proof + fix f assume f: "f \ tuples Y" + hence f': "f \ (X \\<^sub>E Roots) \\<^sub>E X" + by (auto simp: tuples_def) + define f' where "f' = (\g. f (restrict (\ \ g) X))" + have "f' \ (X \\<^sub>E Roots) \ X" unfolding f'_def + using f' bij_betw_apply[OF bij_betw_compose_left_perm_PiE[OF \, of X]] by blast + hence "restrict f' (X \\<^sub>E Roots) \ (X \\<^sub>E Roots) \\<^sub>E X" + by simp + moreover have "image_mset (restrict f' (X \\<^sub>E Roots)) (mset_set (X \\<^sub>E Roots)) = Y" + proof - + have "image_mset (restrict f' (X \\<^sub>E Roots)) (mset_set (X \\<^sub>E Roots)) = + image_mset f' (mset_set (X \\<^sub>E Roots))" + by (intro image_mset_cong) auto + also have "\ = image_mset f (image_mset (\g. restrict (\ \ g) X) (mset_set (X \\<^sub>E Roots)))" + unfolding f'_def o_def multiset.map_comp by (simp add: o_def) + also have "image_mset (\g. restrict (\ \ g) X) (mset_set (X \\<^sub>E Roots)) = + mset_set (X \\<^sub>E Roots)" + by (intro bij_betw_image_mset_set bij_betw_compose_left_perm_PiE \) + also have "image_mset f \ = Y" + using f by (simp add: tuples_def) + finally show ?thesis . + qed + ultimately show "restrict f' (X \\<^sub>E Roots) \ tuples Y" + by (auto simp: tuples_def) + qed + show "(\f. restrict (\g. f (restrict (\ \ g) X)) (X \\<^sub>E Roots)) \ tuples Y \ tuples Y" + by (intro * \) + show "(\f. restrict (\g. f (restrict (inv_into UNIV \ \ g) X)) (X \\<^sub>E Roots)) \ tuples Y \ tuples Y" + by (intro * permutes_inv \) + next + have *: "(\g\X \\<^sub>E Roots. (\g\X \\<^sub>E Roots. f (restrict (\ \ g) X)) + (restrict (inv_into UNIV \ \ g) X)) = f" (is "?lhs = _") + if f: "f \ tuples Y" and \: "\ permutes Roots" for f \ + proof + fix g show "?lhs g = f g" + proof (cases "g \ X \\<^sub>E Roots") + case True + have "restrict (\ \ restrict (inv_into UNIV \ \ g) X) X = g" + using True + by (intro ext) (auto simp: permutes_inverses[OF \]) + thus ?thesis using True + by (auto simp: permutes_in_image[OF permutes_inv[OF \]]) + qed (use f in \auto simp: tuples_def\) + qed + show "(\g\X \\<^sub>E Roots. (\g\X \\<^sub>E Roots. f (restrict (\ \ g) X)) + (restrict (inv_into UNIV \ \ g) X)) = f" if "f \ tuples Y" for f + using *[OF that \] . + show "(\g\X \\<^sub>E Roots. (\g\X \\<^sub>E Roots. f (restrict (inv_into UNIV \ \ g) X)) + (restrict (\ \ g) X)) = f" if "f \ tuples Y" for f + using *[OF that permutes_inv[OF \]] permutes_inv_inv[OF \] by simp + qed + + text \ + We show that the coefficients in the expanded new sum are rational -- again using the + fundamental theorem of symmetric polynomials. + \ + define \' :: "complex multiset \ complex" + where "\' = (\Y. \f\tuples Y. \g\X \\<^sub>E Roots. g (f g))" + + have "\' Y \ \" if Y: "Y \ Roots_ms" for Y + proof - + define Q :: "complex mpoly" + where "Q = (\f\tuples Y. \g\X \\<^sub>E Roots. Var (unRoot (g (f g))))" + + have "insertion Root Q \ \" + proof (rule symmetric_poly_of_roots_in_subring) + show "ring_closed (\ :: complex set)" + by standard auto + then interpret ring_closed "\ :: complex set" . + show "\m. coeff Q m \ \" + by (auto simp: Q_def coeff_Var when_def intro!: sum_in_Rats coeff_prod_closed) + next + show "symmetric_mpoly {.. assume \: "\ permutes {..' where "\' = convert_perm (inv_into UNIV \)" + have \': "\' permutes Roots" + unfolding \'_def by (intro permutes_convert_perm permutes_inv \) + have "mpoly_map_vars \ Q = (\f\tuples Y. \g\X \\<^sub>E Roots. Var (\ (unRoot (g (f g)))))" + unfolding Q_def by (simp add: permutes_bij[OF \]) + also have "\ = (\f\tuples Y. \g\X \\<^sub>E Roots. Var (unRoot (g (f (restrict (\' \ g) X)))))" + proof (rule sum.cong, goal_cases) + case (2 f) + have f: "f \ (X \\<^sub>E Roots) \\<^sub>E X" + using 2 by (auto simp: tuples_def) + have "(\g\X \\<^sub>E Roots. Var (\ (unRoot (g (f g))))) = + (\g\X \\<^sub>E Roots. Var (\ (unRoot (restrict (\' \ g) X (f (restrict (\' \ g) X))))))" + using \' by (intro prod.reindex_bij_betw [symmetric] bij_betw_compose_left_perm_PiE) + also have "\ = (\g\X \\<^sub>E Roots. Var (unRoot (g (f (restrict (\' \ g) X)))))" + proof (intro prod.cong refl arg_cong[of _ _ Var]) + fix g assume g: "g \ X \\<^sub>E Roots" + have "restrict (\' \ g) X \ X \\<^sub>E Roots" + using bij_betw_compose_left_perm_PiE[OF \', of X] g unfolding bij_betw_def by blast + hence *: "f (restrict (\' \ g) X) \ X" + by (rule PiE_mem[OF f]) + hence **: "g (f (restrict (\' \ g) X)) \ Roots" + by (rule PiE_mem[OF g]) + + have "unRoot (restrict (\' \ g) X (f (restrict (\' \ g) X))) = + unRoot (Root (inv_into UNIV \ (unRoot (g (f (restrict (\' \ g) X))))))" + using * ** by (subst \'_def) (auto simp: convert_perm_def) + also have "inv_into UNIV \ (unRoot (g (f (restrict (\' \ g) X)))) \ {..]]) auto + hence "unRoot (Root (inv_into UNIV \ (unRoot (g (f (restrict (\' \ g) X)))))) = + inv_into UNIV \ (unRoot (g (f (restrict (\' \ g) X))))" + by (intro unRoot_Root) auto + also have "\ \ = unRoot (g (f (restrict (\' \ g) X)))" + by (rule permutes_inverses[OF \]) + finally show "\ (unRoot (restrict (\' \ g) X (f (restrict (\' \ g) X)))) = + unRoot (g (f (restrict (\' \ g) X)))" . + qed + finally show ?case . + qed simp_all + also have "\ = (\x\tuples Y. \g\X \\<^sub>E Roots. Var (unRoot (g ((\g\X \\<^sub>E Roots. x (restrict (\' \ g) X)) g))))" + by (intro sum.cong prod.cong refl) auto + also have "\ = Q" + unfolding Q_def + by (rule sum.reindex_bij_betw[OF bij_betw_compose_perm]) (use \' Y in simp_all) + finally show "mpoly_map_vars \ Q = Q" . + qed + next + show "vars Q \ {.. 0" + unfolding lc_def by auto + thus "inverse (of_int lc) * (of_int lc :: complex) = 1" and "inverse (of_int lc) \ \" + by auto + have "rsquarefree (of_int_poly P :: complex poly)" + using \squarefree (of_int_poly P :: complex poly)\ by (intro squarefree_imp_rsquarefree) + hence "of_int_poly P = Polynomial.smult (of_int lc) (\x\Roots. [:-x, 1:])" + unfolding lc_def of_int_hom.hom_lead_coeff[symmetric] Roots_def + by (rule complex_poly_decompose_rsquarefree [symmetric]) + also have "(\x\Roots. [:-x, 1:]) = (\iif\tuples Y. \g\X \\<^sub>E Roots. Root (unRoot (g (f g))))" + by (simp add: Q_def insertion_sum insertion_prod) + also have "\ = \' Y" + unfolding \'_def by (intro sum.cong prod.cong refl Root_unRoot) (auto simp: tuples_def) + finally show ?thesis . + qed + hence "\Y\Roots_ms. \x. \' Y = of_rat x" + by (auto elim!: Rats_cases) + then obtain \'' :: "complex multiset \ rat" + where \'': "\Y. Y \ Roots_ms \ \' Y = of_rat (\'' Y)" + by metis + + text \ + We again collect all the terms that happen to have equal exponents and call their + coefficients \\''\: + \ + define \''' :: "complex \ rat" where "\''' = (\\. \Y\Roots_ms. (\'' Y when \\<^sub>#Y = \))" + have supp_\''': "{x. \''' x \ 0} \ sum_mset ` Roots_ms" + by (auto simp: \'''_def when_def elim!: sum.not_neutral_contains_not_neutral split: if_splits) + + text \ + We again start with the sum that we now to be zero and multiply it with all the sums that can + be obtained with different choices for the roots. + \ + have "0 = (\x\X. \ x * exp x)" + using sum0 .. + also have "\ = (\x\X. restrict \ X x * exp x)" + by (intro sum.cong) auto + also have "\ dvd (\f \ X \\<^sub>E Roots. \x\X. f x * exp x)" + by (rule dvd_prodI) (use \\ ` X \ Roots\ in \auto simp: id_def\) + also have "\ = (\f\(X \\<^sub>E Roots) \\<^sub>E X. \g\X \\<^sub>E Roots. g (f g) * exp (f g))" + by (rule prod_sum_PiE) auto + also have "\ = (\f\(X \\<^sub>E Roots) \\<^sub>E X. (\g\X \\<^sub>E Roots. g (f g)) * exp (\g\X \\<^sub>E Roots. f g))" + by (simp add: prod.distrib exp_sum) + also have "\ = (\(Y,f)\Sigma Roots_ms tuples. + (\g\X \\<^sub>E Roots. g (f g)) * exp (\g\X \\<^sub>E Roots. f g))" + by (intro sum.reindex_bij_witness[of _ snd "\f. (image_mset f (mset_set (X \\<^sub>E Roots)), f)"]) + (auto simp: Roots_ms_def tuples_def) + also have "\ = (\(Y,f)\Sigma Roots_ms tuples. (\g\X \\<^sub>E Roots. g (f g)) * exp (\\<^sub>#Y))" + by (intro sum.cong) (auto simp: tuples_def sum_unfold_sum_mset) + also have "\ = (\Y\Roots_ms. \' Y * exp (\\<^sub>#Y))" + unfolding \'_def sum_distrib_right by (rule sum.Sigma [symmetric]) auto + also have "\ = (\Y\Roots_ms. of_rat (\'' Y) * exp (\\<^sub>#Y))" + by (intro sum.cong) (auto simp: \'') + also have "\ = (\Y\Roots_ms. Sum_any (\\. of_rat (\'' Y when \\<^sub># Y = \) * exp \))" + proof (rule sum.cong, goal_cases) + case (2 Y) + have "Sum_any (\\. of_rat (\'' Y when \\<^sub># Y = \) * exp \) = + (\\\{\\<^sub># Y}. of_rat (\'' Y when \\<^sub># Y = \) * exp \)" + by (intro Sum_any.expand_superset) auto + thus ?case by simp + qed auto + also have "\ = Sum_any (\\. of_rat (\''' \) * exp \)" + unfolding \'''_def of_rat_sum sum_distrib_right by (subst Sum_any_sum_swap) auto + also have "\ = (\\ | \''' \ \ 0. of_rat (\''' \) * exp \)" + by (intro Sum_any.expand_superset finite_subset[OF supp_\''']) auto + finally have "(\\ | \''' \ \ 0. of_rat (\''' \) * exp \) = 0" + by auto + + text \ + We are now in the situation of our previous version of the theorem and can apply it to find + that all the coefficients are zero. + \ + have "{\. \''' \ \ 0} = {}" + proof (rule Hermite_Lindemann_aux3) + show "finite {\. \''' \ \ 0}" + by (rule finite_subset[OF supp_\''']) auto + next + show "(\\ | \''' \ \ 0. of_rat (\''' \) * exp \) = 0" + by fact + next + fix \ assume \: "\ \ {\. \''' \ \ 0}" + then obtain Y where Y: "Y \ Roots_ms" "\ = sum_mset Y" + using supp_\''' by auto + thus "algebraic \" using alg1 + by (auto simp: Roots_ms_def) + qed auto + + text \ + However, similarly to before, we can show that the coefficient corresponding to the + term with the lexicographically greatest exponent (which is obtained by picking the + term with the lexicographically greatest term in each of the factors of our big product) + is non-zero. + \ + moreover have "\\. \''' \ \ 0" + proof - + define \_max where "\_max = complex_lex.Max X" + have [simp]: "\_max \ X" + unfolding \_max_def using \X \ {}\ by (intro complex_lex.Max_in) auto + define Y_max :: "complex multiset" where "Y_max = replicate_mset (n ^ m) \_max" + define f_max where "f_max = restrict (\_. \_max) (X \\<^sub>E Roots)" + have [simp]: "Y_max \ Roots_ms" + by (auto simp: Y_max_def Roots_ms_def) + have "tuples Y_max = {f_max}" + proof safe + have "image_mset (\_\X \\<^sub>E Roots. \_max) (mset_set (X \\<^sub>E Roots)) = + image_mset (\_. \_max) (mset_set (X \\<^sub>E Roots))" + by (intro image_mset_cong) auto + thus "f_max \ tuples Y_max" + by (auto simp: f_max_def tuples_def Y_max_def image_mset_const_eq) + next + fix f assume "f \ tuples Y_max" + hence f: "f \ (X \\<^sub>E Roots) \\<^sub>E X" "image_mset f (mset_set (X \\<^sub>E Roots)) = Y_max" + by (auto simp: tuples_def) + hence "\g \# mset_set (X \\<^sub>E Roots). f g = \_max" + by (intro image_mset_eq_replicate_msetD[where n = "n ^ m"]) (auto simp: Y_max_def) + thus "f = f_max" + using f by (auto simp: Y_max_def fun_eq_iff f_max_def) + qed + + have "\''' (of_nat (n ^ m) * \_max) = (\Y\Roots_ms. \'' Y when \\<^sub># Y = of_nat (n ^ m) * \_max)" + unfolding \'''_def Roots_ms_def .. + also have "\\<^sub># Y \ of_nat n ^ m * \_max" if "Y \ Roots_ms" "Y \ Y_max" for Y + proof - + have "\set_mset Y \ {\_max}" + using set_mset_subset_singletonD[of Y "\_max"] that + by (auto simp: Roots_ms_def Y_max_def split: if_splits) + then obtain y where y: "y \# Y" "y \ \_max" + by auto + have "y \ X" "set_mset (Y - {#y#}) \ X" + using y that by (auto simp: Roots_ms_def dest: in_diffD) + hence "y \\<^sub>\ \_max" + using y unfolding \_max_def by (intro complex_lex.Max_ge) auto + with y have "y <\<^sub>\ \_max" + by auto + have *: "Y = {#y#} + (Y - {#y#})" + using y by simp + have "sum_mset Y = y + sum_mset (Y - {#y#})" + by (subst *) auto + also have "\ <\<^sub>\ \_max + sum_mset (Y - {#y#})" + by (intro complex_lex.add_strict_right_mono) fact + also have "\ \\<^sub>\ \_max + sum_mset (replicate_mset (n ^ m - 1) \_max)" + unfolding \_max_def using that y \set_mset (Y - {#y#}) \ X\ + by (intro complex_lex.add_left_mono sum_mset_mono_complex_lex + rel_mset_replicate_mset_right complex_lex.Max_ge) + (auto simp: Roots_ms_def size_Diff_singleton) + also have "\ = of_nat (Suc (n ^ m - 1)) * \_max" + by (simp add: algebra_simps) + also have "Suc (n ^ m - 1) = n ^ m" + using \n > 0\ by simp + finally show ?thesis by simp + qed + hence "(\Y\Roots_ms. \'' Y when \\<^sub># Y = of_nat (n ^ m) * \_max) = (\Y\{Y_max}. \'' Y when \\<^sub># Y = of_nat (n ^ m) * \_max)" + by (intro sum.mono_neutral_right ballI) auto + also have "\ = \'' Y_max" + by (auto simp: when_def Y_max_def) + also have "of_rat \ = \' Y_max" + using \''[of Y_max] by auto + also have "\ = (\g\X \\<^sub>E Roots. g (f_max g))" + by (auto simp: \'_def \tuples Y_max = {f_max}\) + also have "\ = (\g\X \\<^sub>E Roots. g \_max)" + by (intro prod.cong) (auto simp: f_max_def) + also have "\ \ 0" + using \0 \ Roots\ \\_max \ X\ by (intro prod_nonzeroI) (metis PiE_mem) + finally show ?thesis by blast + qed + + ultimately show False by blast +qed + + +subsection \The final theorem\ + +text \ + We now additionally allow some of the $\beta_i$ to be zero: +\ +lemma Hermite_Lindemann': + fixes \ :: "complex \ complex" + assumes "finite X" + assumes "\x. x \ X \ algebraic x" + assumes "\x. x \ X \ algebraic (\ x)" + assumes "(\x\X. \ x * exp x) = 0" + shows "\x\X. \ x = 0" +proof - + have "{x\X. \ x \ 0} = {}" + proof (rule Hermite_Lindemann_aux4) + have "(\x | x \ X \ \ x \ 0. \ x * exp x) = (\x\X. \ x * exp x)" + by (intro sum.mono_neutral_left assms(1)) auto + also have "\ = 0" + by fact + finally show "(\x | x \ X \ \ x \ 0. \ x * exp x) = 0" . + qed (use assms in auto) + thus ?thesis by blast +qed + +text \ + Lastly, we switch to indexed summation in order to obtain a version of the theorem that + is somewhat nicer to use: +\ +theorem Hermite_Lindemann: + fixes \ \ :: "'a \ complex" + assumes "finite I" + assumes "\x. x \ I \ algebraic (\ x)" + assumes "\x. x \ I \ algebraic (\ x)" + assumes "inj_on \ I" + assumes "(\x\I. \ x * exp (\ x)) = 0" + shows "\x\I. \ x = 0" +proof - + define f where "f = inv_into I \" + have [simp]: "f (\ x) = x" if "x \ I" for x + using that by (auto simp: f_def inv_into_f_f[OF assms(4)]) + have "\x\\`I. (\ \ f) x = 0" + proof (rule Hermite_Lindemann') + have "0 = (\x\I. \ x * exp (\ x))" + using assms(5) .. + also have "\ = (\x\I. (\ \ f) (\ x) * exp (\ x))" + by (intro sum.cong) auto + also have "\ = (\x\\`I. (\ \ f) x * exp x)" + using assms(4) by (subst sum.reindex) auto + finally show "(\x\\ ` I. (\ \ f) x * exp x) = 0" .. + qed (use assms in auto) + thus ?thesis by auto +qed + +text \ + The following version using lists instead of sequences is even more convenient to use + in practice: +\ +corollary Hermite_Lindemann_list: + fixes xs :: "(complex \ complex) list" + assumes alg: "\(x,y)\set xs. algebraic x \ algebraic y" + assumes distinct: "distinct (map snd xs)" + assumes sum0: "(\(c,\)\xs. c * exp \) = 0" + shows "\c\(fst ` set xs). c = 0" +proof - + define n where "n = length xs" + have *: "\i\{..i. map snd xs ! i) {.. inj_on (\i. snd (xs ! i)) {..i. snd (xs ! i)) {..(c,\)\xs. c * exp \)" + using sum0 .. + also have "\ = (\i = 0" .. + next + fix i assume i: "i \ {.. set xs" + by (auto simp: n_def) + with alg show "algebraic (fst (xs ! i))" "algebraic (snd (xs ! i))" + by blast+ + qed auto + + show ?thesis + proof (intro ballI, elim imageE) + fix c x assume cx: "c = fst x" "x \ set xs" + then obtain i where "i \ {..The traditional formulation of the theorem\ + +text \ + What we proved above was actually Baker's reformulation of the theorem. Thus, we now also derive + the original one, which uses linear independence and algebraic independence. + + It states that if $\alpha_1, \ldots, \alpha_n$ are algebraic numbers that are linearly + independent over \\\, then $e^{\alpha_1}, \ldots, e^{\alpha_n}$ are algebraically independent + over \\\. +\ + +text \ + Linear independence over the integers is just independence of a set of complex numbers when + viewing the complex numbers as a \\\-module. +\ +definition linearly_independent_over_int :: "'a :: field_char_0 set \ bool" where + "linearly_independent_over_int = module.independent (\r x. of_int r * x)" + +text \ + Algebraic independence over the rationals means that the given set \X\ of numbers fulfils + no non-trivial polynomial equation with rational coefficients, i.e. there is no non-zero + multivariate polynomial with rational coefficients that, when inserting the numbers from \X\, + becomes zero. + + Note that we could easily replace `rational coefficients' with `algebraic coefficients' here + and the proof would still go through without any modifications. +\ +definition algebraically_independent_over_rat :: "nat \ (nat \ 'a :: field_char_0) \ bool" where + "algebraically_independent_over_rat n a \ + (\p. vars p \ {.. (\m. coeff p m \ \) \ insertion a p = 0 \ p = 0)" + +corollary Hermite_Lindemann_original: + fixes n :: nat and \ :: "nat \ complex" + assumes "inj_on \ {..i. i < n \ algebraic (\ i)" + assumes "linearly_independent_over_int (\ ` {..i. exp (\ i))" + unfolding algebraically_independent_over_rat_def +proof safe + fix p assume p: "vars p \ {..m. coeff p m \ \" "insertion (\i. exp (\ i)) p = 0" + define \' where "\' = (\m. \i i)" + define I where "I = {m. coeff p m \ 0}" + + have lookup_eq_0: "lookup m i = 0" if "m \ I" "i \ {.. vars p" + using that coeff_notin_vars[of m p] by (auto simp: I_def) + thus "lookup m i = 0" + using in_keys_iff[of i m] that p(1) by blast + qed + + have "\x\I. coeff p x = 0" + proof (rule Hermite_Lindemann) + show "finite I" + by (auto simp: I_def) + next + show "algebraic (\' m)" if "m \ I" for m + unfolding \'_def using assms(2) by fastforce + next + show "algebraic (coeff p m)" if "m \ I" for m + unfolding \'_def using p(2) by blast + next + show "inj_on \' I" + proof + fix m1 m2 assume m12: "m1 \ I" "m2 \ I" "\' m1 = \' m2" + define lu :: "(nat \\<^sub>0 nat) \ nat \ int" where "lu = (\m i. int (lookup m i))" + interpret int: Modules.module "\r x. of_int r * (x :: complex)" + by standard (auto simp: algebra_simps of_rat_mult of_rat_add) + define idx where "idx = inv_into {.." + + have "lu m1 i = lu m2 i" if "i < n" for i + proof - + have "lu m1 (idx (\ i)) - lu m2 (idx (\ i)) = 0" + proof (rule int.independentD) + show "int.independent (\ ` {..x\\`{..i i)) - lu m2 (idx (\ i))) * \ i)" + using assms(1) by (subst sum.reindex) auto + also have "\ = (\i i)" + by (intro sum.cong) (auto simp: idx_def inv_into_f_f[OF assms(1)]) + also have "\ = 0" + using m12 by (simp add: \'_def ring_distribs of_rat_diff sum_subtractf lu_def) + finally show "(\x\\`{..'_def ring_distribs of_rat_diff sum_subtractf lu_def) + qed (use that in auto) + thus ?thesis + using that by (auto simp: idx_def inv_into_f_f[OF assms(1)]) + qed + hence "lookup m1 i = lookup m2 i" for i + using m12 by (cases "i < n") (auto simp: lu_def lookup_eq_0) + thus "m1 = m2" + by (rule poly_mapping_eqI) + qed + next + have "0 = insertion (\i. exp (\ i)) p" + using p(3) .. + also have "\ = (\m\I. coeff p m * Prod_any (\i. exp (\ i) ^ lookup m i))" + unfolding insertion_altdef by (rule Sum_any.expand_superset) (auto simp: I_def) + also have "\ = (\m\I. coeff p m * exp (\' m))" + proof (intro sum.cong, goal_cases) + case (2 m) + have "Prod_any (\i. exp (\ i) ^ lookup m i) = (\i i) ^ lookup m i)" + using 2 lookup_eq_0[of m] by (intro Prod_any.expand_superset; force) + also have "\ = exp (\' m)" + by (simp add: exp_sum exp_of_nat_mult \'_def) + finally show ?case by simp + qed simp_all + finally show "(\m\I. coeff p m * exp (\' m)) = 0" .. + qed + thus "p = 0" + by (intro mpoly_eqI) (auto simp: I_def) +qed + + +subsection \Simple corollaries\ + +text \ + Now, we derive all the usual obvious corollaries of the theorem in the obvious way. + + First, the exponential of a non-zero algebraic number is transcendental. +\ +corollary algebraic_exp_complex_iff: + assumes "algebraic x" + shows "algebraic (exp x :: complex) \ x = 0" + using Hermite_Lindemann_list[of "[(1, x), (-exp x, 0)]"] assms by auto + +text \ + More generally, any sum of exponentials with algebraic coefficients and exponents is + transcendental if the exponents are all distinct and non-zero and at least one coefficient + is non-zero. +\ +corollary sum_of_exp_transcendentalI: + fixes xs :: "(complex \ complex) list" + assumes "\(x,y)\set xs. algebraic x \ algebraic y \ y \ 0" + assumes "\x\fst`set xs. x \ 0" + assumes distinct: "distinct (map snd xs)" + shows "\algebraic (\(c,\)\xs. c * exp \)" +proof + define S where "S = (\(c,\)\xs. c * exp \)" + assume S: "algebraic S" + have "\c\fst`set ((-S,0) # xs). c = 0" + proof (rule Hermite_Lindemann_list) + show "(\(c, \)\(- S, 0) # xs. c * exp \) = 0" + by (auto simp: S_def) + qed (use S assms in auto) + with assms(2) show False + by auto +qed + +text \ + Any complex logarithm of an algebraic number other than 1 is transcendental + (no matter which branch cut). +\ +corollary transcendental_complex_logarithm: + assumes "algebraic x" "exp y = (x :: complex)" "x \ 1" + shows "\algebraic y" + using algebraic_exp_complex_iff[of y] assms by auto + +text \ + In particular, this holds for the standard branch of the logarithm. +\ +corollary transcendental_Ln: + assumes "algebraic x" "x \ 0" "x \ 1" + shows "\algebraic (Ln x)" + by (rule transcendental_complex_logarithm) (use assms in auto) + +text \ + The transcendence of \e\ and \\\, which I have already formalised directly in other AFP + entries, now follows as a simple corollary. +\ +corollary exp_1_complex_transcendental: "\algebraic (exp 1 :: complex)" + by (subst algebraic_exp_complex_iff) auto + +corollary pi_transcendental: "\algebraic pi" +proof - + have "\algebraic (\ * pi)" + by (rule transcendental_complex_logarithm[of "-1"]) auto + thus ?thesis by simp +qed + + +subsection \Transcendence of the trigonometric and hyperbolic functions\ + +text \ + In a similar fashion, we can also prove the transcendence of all the trigonometric and + hyperbolic functions such as $\sin$, $\tan$, $\sinh$, $\arcsin$, etc. +\ + +lemma transcendental_sinh: + assumes "algebraic z" "z \ 0" + shows "\algebraic (sinh z :: complex)" +proof - + have "\algebraic (\(a,b)\[(1/2, z), (-1/2, -z)]. a * exp b)" + using assms by (intro sum_of_exp_transcendentalI) auto + also have "(\(a,b)\[(1/2, z), (-1/2, -z)]. a * exp b) = sinh z" + by (simp add: sinh_def field_simps scaleR_conv_of_real) + finally show ?thesis . +qed + +lemma transcendental_cosh: + assumes "algebraic z" "z \ 0" + shows "\algebraic (cosh z :: complex)" +proof - + have "\algebraic (\(a,b)\[(1/2, z), (1/2, -z)]. a * exp b)" + using assms by (intro sum_of_exp_transcendentalI) auto + also have "(\(a,b)\[(1/2, z), (1/2, -z)]. a * exp b) = cosh z" + by (simp add: cosh_def field_simps scaleR_conv_of_real) + finally show ?thesis . +qed + +lemma transcendental_sin: + assumes "algebraic z" "z \ 0" + shows "\algebraic (sin z :: complex)" + unfolding sin_conv_sinh using transcendental_sinh[of "\ * z"] assms by simp + +lemma transcendental_cos: + assumes "algebraic z" "z \ 0" + shows "\algebraic (cos z :: complex)" + unfolding cos_conv_cosh using transcendental_cosh[of "\ * z"] assms by simp + +(* TODO: Move? *) +lemma tan_square_neq_neg1: "tan (z :: complex) ^ 2 \ -1" +proof + assume "tan z ^ 2 = -1" + hence "sin z ^ 2 = -(cos z ^ 2)" + by (auto simp: tan_def divide_simps split: if_splits) + also have "cos z ^ 2 = 1 - sin z ^ 2" + by (simp add: cos_squared_eq) + finally show False + by simp +qed + +lemma transcendental_tan: + assumes "algebraic z" "z \ 0" + shows "\algebraic (tan z :: complex)" +proof + assume "algebraic (tan z)" + + have nz1: "real_of_int n + 1 / 2 \ 0" for n + proof - + have "real_of_int (2 * n + 1) / real_of_int 2 \ \" + by (intro fraction_not_in_ints) auto + also have "real_of_int (2 * n + 1) / real_of_int 2 = real_of_int n + 1 / 2" + by simp + finally show "\ \ 0" + by auto + qed + + have nz2: "1 + tan z ^ 2 \ 0" + using tan_square_neq_neg1[of z] by (subst add_eq_0_iff) + + have nz3: "cos z \ 0" + proof + assume "cos z = 0" + then obtain n where "z = complex_of_real (real_of_int n * pi) + complex_of_real pi / 2" + by (subst (asm) cos_eq_0) blast + also have "\ = complex_of_real ((real_of_int n + 1 / 2) * pi)" + by (simp add: ring_distribs) + also have "algebraic \ \ algebraic ((real_of_int n + 1 / 2) * pi)" + by (rule algebraic_of_real_iff) + also have "\algebraic ((real_of_int n + 1 / 2) * pi)" + using nz1[of n] transcendental_pi by simp + finally show False using assms(1) by contradiction + qed + + from nz3 have *: "sin z ^ 2 = tan z ^ 2 * cos z ^ 2" + by (simp add: tan_def field_simps) + also have "cos z ^ 2 = 1 - sin z ^ 2" + by (simp add: cos_squared_eq) + finally have "sin z ^ 2 * (1 + tan z ^ 2) = tan z ^ 2" + by (simp add: algebra_simps) + hence "sin z ^ 2 = tan z ^ 2 / (1 + tan z ^ 2)" + using nz2 by (simp add: field_simps) + also have "algebraic (tan z ^ 2 / (1 + tan z ^ 2))" + using \algebraic (tan z)\ by auto + finally have "algebraic (sin z ^ 2)" . + hence "algebraic (sin z)" + by simp + thus False + using transcendental_sin[OF \algebraic z\ \z \ 0\] by contradiction +qed + +lemma transcendental_cot: + assumes "algebraic z" "z \ 0" + shows "\algebraic (cot z :: complex)" +proof - + have "\algebraic (tan z)" + by (rule transcendental_tan) fact+ + also have "algebraic (tan z) \ algebraic (inverse (tan z))" + by simp + also have "inverse (tan z) = cot z" + by (simp add: cot_def tan_def) + finally show ?thesis . +qed + +lemma transcendental_tanh: + assumes "algebraic z" "z \ 0" "cosh z \ 0" + shows "\algebraic (tanh z :: complex)" + using transcendental_tan[of "\ * z"] assms unfolding tanh_conv_tan by simp + +lemma transcendental_Arcsin: + assumes "algebraic z" "z \ 0" + shows "\algebraic (Arcsin z)" +proof - + have "\ * z + csqrt (1 - z\<^sup>2) \ 0" + using Arcsin_body_lemma by blast + moreover have "\ * z + csqrt (1 - z\<^sup>2) \ 1" + proof + assume "\ * z + csqrt (1 - z\<^sup>2) = 1" + hence "Arcsin z = 0" + by (simp add: Arcsin_def) + hence "sin (Arcsin z) = 0" + by (simp only: sin_zero) + also have "sin (Arcsin z) = z" + by simp + finally show False using \z \ 0\ by simp + qed + ultimately have "\ algebraic (Ln (\ * z + csqrt (1 - z\<^sup>2)))" + using assms by (intro transcendental_Ln) auto + thus ?thesis + by (simp add: Arcsin_def) +qed + +lemma transcendental_Arccos: + assumes "algebraic z" "z \ 1" + shows "\algebraic (Arccos z)" +proof - + have "z + \ * csqrt (1 - z\<^sup>2) \ 0" + using Arccos_body_lemma by blast + moreover have "z + \ * csqrt (1 - z\<^sup>2) \ 1" + proof + assume "z + \ * csqrt (1 - z\<^sup>2) = 1" + hence "Arccos z = 0" + by (simp add: Arccos_def) + hence "cos (Arccos z) = 1" + by (simp only: cos_zero) + also have "cos (Arccos z) = z" + by simp + finally show False using \z \ 1\ by simp + qed + ultimately have "\ algebraic (Ln (z + \ * csqrt (1 - z\<^sup>2)))" + using assms by (intro transcendental_Ln) auto + thus ?thesis + by (simp add: Arccos_def) +qed + +lemma transcendental_Arctan: + assumes "algebraic z" "z \ {0, \, -\}" + shows "\algebraic (Arctan z)" +proof - + have "\ * z \ 1" "1 + \ * z \ 0" + using assms(2) by (auto simp: complex_eq_iff) + hence "\ algebraic (Ln ((1 - \ * z) / (1 + \ * z)))" + using assms by (intro transcendental_Ln) auto + thus ?thesis + by (simp add: Arctan_def) +qed + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/Min_Int_Poly.thy b/thys/Hermite_Lindemann/Min_Int_Poly.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/Min_Int_Poly.thy @@ -0,0 +1,190 @@ +(* + File: Min_Int_Poly.thy + Author: Manuel Eberl, TU München +*) +section \The minimal polynomial of an algebraic number\ +theory Min_Int_Poly +imports + "Algebraic_Numbers.Algebraic_Numbers" + "HOL-Computational_Algebra.Computational_Algebra" + More_Polynomial_HLW +begin + +text \ + Given an algebraic number \x\ in a field, the minimal polynomial is the unique irreducible + integer polynomial with positive leading coefficient that has \x\ as a root. + + Note that we assume characteristic 0 since the material upon which all of this builds also + assumes it. +\ + +(* TODO Move *) + +definition min_int_poly :: "'a :: field_char_0 \ int poly" where + "min_int_poly x = + (if algebraic x then THE p. p represents x \ irreducible p \ Polynomial.lead_coeff p > 0 + else [:0, 1:])" + +lemma + fixes x :: "'a :: {field_char_0, field_gcd}" + shows min_int_poly_represents [intro]: "algebraic x \ min_int_poly x represents x" + and min_int_poly_irreducible [intro]: "irreducible (min_int_poly x)" + and lead_coeff_min_int_poly_pos: "Polynomial.lead_coeff (min_int_poly x) > 0" +proof - + note * = theI'[OF algebraic_imp_represents_unique, of x] + show "min_int_poly x represents x" if "algebraic x" + using *[OF that] by (simp add: that min_int_poly_def) + have "irreducible [:0, 1::int:]" + by (rule irreducible_linear_poly) auto + thus "irreducible (min_int_poly x)" + using * by (auto simp: min_int_poly_def) + show "Polynomial.lead_coeff (min_int_poly x) > 0" + using * by (auto simp: min_int_poly_def) +qed + +lemma + fixes x :: "'a :: {field_char_0, field_gcd}" + shows degree_min_int_poly_pos [intro]: "Polynomial.degree (min_int_poly x) > 0" + and degree_min_int_poly_nonzero [simp]: "Polynomial.degree (min_int_poly x) \ 0" +proof - + show "Polynomial.degree (min_int_poly x) > 0" + proof (cases "algebraic x") + case True + hence "min_int_poly x represents x" + by auto + thus ?thesis by blast + qed (auto simp: min_int_poly_def) + thus "Polynomial.degree (min_int_poly x) \ 0" + by blast +qed + +lemma min_int_poly_squarefree [intro]: + fixes x :: "'a :: {field_char_0, field_gcd}" + shows "squarefree (min_int_poly x)" + by (rule irreducible_imp_squarefree) auto + +lemma min_int_poly_primitive [intro]: + fixes x :: "'a :: {field_char_0, field_gcd}" + shows "primitive (min_int_poly x)" + by (rule irreducible_imp_primitive) auto + +lemma min_int_poly_content [simp]: + fixes x :: "'a :: {field_char_0, field_gcd}" + shows "content (min_int_poly x) = 1" + using min_int_poly_primitive[of x] by (simp add: primitive_def) + +lemma ipoly_min_int_poly [simp]: + "algebraic x \ ipoly (min_int_poly x) (x :: 'a :: {field_gcd, field_char_0}) = 0" + using min_int_poly_represents[of x] by (auto simp: represents_def) + +lemma min_int_poly_nonzero [simp]: + fixes x :: "'a :: {field_char_0, field_gcd}" + shows "min_int_poly x \ 0" + using lead_coeff_min_int_poly_pos[of x] by auto + +lemma min_int_poly_normalize [simp]: + fixes x :: "'a :: {field_char_0, field_gcd}" + shows "normalize (min_int_poly x) = min_int_poly x" + unfolding normalize_poly_def using lead_coeff_min_int_poly_pos[of x] by simp + +lemma min_int_poly_prime_elem [intro]: + fixes x :: "'a :: {field_char_0, field_gcd}" + shows "prime_elem (min_int_poly x)" + using min_int_poly_irreducible[of x] by blast + +lemma min_int_poly_prime [intro]: + fixes x :: "'a :: {field_char_0, field_gcd}" + shows "prime (min_int_poly x)" + using min_int_poly_prime_elem[of x] + by (simp only: prime_normalize_iff [symmetric] min_int_poly_normalize) + +lemma min_int_poly_unique: + fixes x :: "'a :: {field_char_0, field_gcd}" + assumes "p represents x" "irreducible p" "Polynomial.lead_coeff p > 0" + shows "min_int_poly x = p" +proof - + from assms(1) have x: "algebraic x" + using algebraic_iff_represents by blast + thus ?thesis + using the1_equality[OF algebraic_imp_represents_unique[OF x], of p] assms + unfolding min_int_poly_def by auto +qed + +lemma min_int_poly_of_int [simp]: + "min_int_poly (of_int n :: 'a :: {field_char_0, field_gcd}) = [:-of_int n, 1:]" + by (intro min_int_poly_unique irreducible_linear_poly) auto + +lemma min_int_poly_of_nat [simp]: + "min_int_poly (of_nat n :: 'a :: {field_char_0, field_gcd}) = [:-of_nat n, 1:]" + using min_int_poly_of_int[of "int n"] by (simp del: min_int_poly_of_int) + +lemma min_int_poly_0 [simp]: "min_int_poly (0 :: 'a :: {field_char_0, field_gcd}) = [:0, 1:]" + using min_int_poly_of_int[of 0] unfolding of_int_0 by simp + +lemma min_int_poly_1 [simp]: "min_int_poly (1 :: 'a :: {field_char_0, field_gcd}) = [:-1, 1:]" + using min_int_poly_of_int[of 1] unfolding of_int_1 by simp + +lemma poly_min_int_poly_0_eq_0_iff [simp]: + fixes x :: "'a :: {field_char_0, field_gcd}" + assumes "algebraic x" + shows "poly (min_int_poly x) 0 = 0 \ x = 0" +proof + assume *: "poly (min_int_poly x) 0 = 0" + show "x = 0" + proof (rule ccontr) + assume "x \ 0" + hence "poly (min_int_poly x) 0 \ 0" + using assms by (intro represents_irr_non_0) auto + with * show False by contradiction + qed +qed auto + +lemma min_int_poly_conv_Gcd: + fixes x :: "'a :: {field_char_0, field_gcd}" + assumes "algebraic x" + shows "min_int_poly x = Gcd {p. p \ 0 \ p represents x}" +proof (rule sym, rule Gcd_eqI, (safe)?) + fix p assume p: "\q. q \ {p. p \ 0 \ p represents x} \ p dvd q" + show "p dvd min_int_poly x" + using assms by (intro p) auto +next + fix p assume p: "p \ 0" "p represents x" + have "min_int_poly x represents x" + using assms by auto + hence "poly (gcd (of_int_poly (min_int_poly x)) (of_int_poly p)) x = 0" + using p by (intro poly_gcd_eq_0I) auto + hence "ipoly (gcd (min_int_poly x) p) x = 0" + by (subst (asm) gcd_of_int_poly) auto + hence "gcd (min_int_poly x) p represents x" + using p unfolding represents_def by auto + + have "min_int_poly x dvd gcd (min_int_poly x) p \ is_unit (gcd (min_int_poly x) p)" + by (intro irreducibleD') auto + moreover from \gcd (min_int_poly x) p represents x\ have "\is_unit (gcd (min_int_poly x) p)" + by (auto simp: represents_def) + ultimately have "min_int_poly x dvd gcd (min_int_poly x) p" + by blast + also have "\ dvd p" + by blast + finally show "min_int_poly x dvd p" . +qed auto + +lemma min_int_poly_eqI: + fixes x :: "'a :: {field_char_0, field_gcd}" + assumes "p represents x" "irreducible p" "Polynomial.lead_coeff p \ 0" + shows "min_int_poly x = p" +proof - + from assms have [simp]: "p \ 0" + by auto + have "Polynomial.lead_coeff p \ 0" + by auto + with assms(3) have "Polynomial.lead_coeff p > 0" + by linarith + moreover have "algebraic x" + using \p represents x\ by (meson algebraic_iff_represents) + ultimately show ?thesis + unfolding min_int_poly_def + using the1_equality[OF algebraic_imp_represents_unique[OF \algebraic x\], of p] assms by auto +qed + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/Misc_HLW.thy b/thys/Hermite_Lindemann/Misc_HLW.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/Misc_HLW.thy @@ -0,0 +1,231 @@ +(* + File: Misc_HLW.thy + Author: Manuel Eberl, TU München +*) +section \Miscellaneous facts\ +theory Misc_HLW +imports + Complex_Main + "HOL-Library.Multiset" + "HOL-Library.Permutations" + "HOL-Library.FuncSet" + "HOL-Library.Groups_Big_Fun" + "HOL-Library.Poly_Mapping" + "HOL-Library.Landau_Symbols" + "HOL-Computational_Algebra.Computational_Algebra" +begin + +lemma set_mset_subset_singletonD: + assumes "set_mset A \ {x}" + shows "A = replicate_mset (size A) x" + using assms by (induction A) auto + +lemma image_mset_eq_replicate_msetD: + assumes "image_mset f A = replicate_mset n y" + shows "\x\#A. f x = y" +proof - + have "f ` set_mset A = set_mset (image_mset f A)" + by simp + also note assms + finally show ?thesis by (auto split: if_splits) +qed + +lemma bij_betw_permutes_compose_left: + assumes "\ permutes A" + shows "bij_betw (\\. \ \ \) {\. \ permutes A} {\. \ permutes A}" +proof (rule bij_betwI) + show "(\) \ \ {\. \ permutes A} \ {\. \ permutes A}" + by (auto intro: permutes_compose assms) + show "(\) (inv_into UNIV \) \ {\. \ permutes A} \ {\. \ permutes A}" + by (auto intro: permutes_compose assms permutes_inv) +qed (use permutes_inverses[OF assms] in auto) + +lemma bij_betw_compose_left_perm_Pi: + assumes "\ permutes B" + shows "bij_betw (\f. (\ \ f)) (A \ B) (A \ B)" +proof (rule bij_betwI) + have *: "(\f. (\ \ f)) \ (A \ B) \ A \ B" if \: "\ permutes B" for \ + by (auto simp: permutes_in_image[OF \]) + show "(\f. (\ \ f)) \ (A \ B) \ A \ B" + by (rule *) fact + show "(\f. (inv_into UNIV \ \ f)) \ (A \ B) \ A \ B" + by (intro * permutes_inv) fact +qed (auto simp: permutes_inverses[OF assms] fun_eq_iff) + +lemma bij_betw_compose_left_perm_PiE: + assumes "\ permutes B" + shows "bij_betw (\f. restrict (\ \ f) A) (A \\<^sub>E B) (A \\<^sub>E B)" +proof (rule bij_betwI) + have *: "(\f. restrict (\ \ f) A) \ (A \\<^sub>E B) \ A \\<^sub>E B" if \: "\ permutes B" for \ + by (auto simp: permutes_in_image[OF \]) + show "(\f. restrict (\ \ f) A) \ (A \\<^sub>E B) \ A \\<^sub>E B" + by (rule *) fact + show "(\f. restrict (inv_into UNIV \ \ f) A) \ (A \\<^sub>E B) \ A \\<^sub>E B" + by (intro * permutes_inv) fact +qed (auto simp: permutes_inverses[OF assms] fun_eq_iff) + +lemma bij_betw_image_mset_set: + assumes "bij_betw f A B" + shows "image_mset f (mset_set A) = mset_set B" + using assms by (simp add: bij_betw_def image_mset_mset_set) + +lemma finite_multisets_of_size: + assumes "finite A" + shows "finite {X. set_mset X \ A \ size X = n}" +proof (rule finite_subset) + show "{X. set_mset X \ A \ size X = n} \ mset ` {xs. set xs \ A \ length xs = n}" + proof + fix X assume X: "X \ {X. set_mset X \ A \ size X = n}" + obtain xs where [simp]: "X = mset xs" + by (metis ex_mset) + thus "X \ mset ` {xs. set xs \ A \ length xs = n}" + using X by auto + qed +next + show "finite (mset ` {xs. set xs \ A \ length xs = n})" + by (intro finite_imageI finite_lists_length_eq assms) +qed + +lemma sum_mset_image_mset_sum_mset_image_mset: + "sum_mset (image_mset g (sum_mset (image_mset f A))) = + sum_mset (image_mset (\x. sum_mset (image_mset g (f x))) A)" + by (induction A) auto + +lemma sum_mset_image_mset_singleton: "sum_mset (image_mset (\x. {#f x#}) A) = image_mset f A" + by (induction A) auto + +lemma sum_mset_conv_sum: + "sum_mset (image_mset f A) = (\x\set_mset A. of_nat (count A x) * f x)" +proof (induction A rule: full_multiset_induct) + case (less A) + show ?case + proof (cases "A = {#}") + case False + then obtain x where x: "x \# A" + by auto + define n where "n = count A x" + define A' where "A' = filter_mset (\y. y \ x) A" + have A_eq: "A = replicate_mset n x + A'" + by (intro multiset_eqI) (auto simp: A'_def n_def) + have [simp]: "x \# A'" "count A' x = 0" + by (auto simp: A'_def) + have "n \ 0" + using x by (auto simp: n_def) + + have "sum_mset (image_mset f A) = of_nat n * f x + sum_mset (image_mset f A')" + by (simp add: A_eq) + also have "A' \# A" + unfolding A'_def using x by (simp add: filter_mset_eq_conv subset_mset_def) + with less.IH have "sum_mset (image_mset f A') = (\x\set_mset A'. of_nat (count A' x) * f x)" + by simp + also have "\ = (\x\set_mset A'. of_nat (count A x) * f x)" + by (intro sum.cong) (auto simp: A_eq) + also have "of_nat n * f x + \ = (\x\insert x (set_mset A'). of_nat (count A x) * f x)" + by (subst sum.insert) (auto simp: A_eq) + also from \n \ 0\ have "insert x (set_mset A') = set_mset A" + by (auto simp: A_eq) + finally show ?thesis . + qed auto +qed + +lemma sum_mset_conv_Sum_any: + "sum_mset (image_mset f A) = Sum_any (\x. of_nat (count A x) * f x)" +proof - + have "sum_mset (image_mset f A) = (\x\set_mset A. of_nat (count A x) * f x)" + by (rule sum_mset_conv_sum) + also have "\ = Sum_any (\x. of_nat (count A x) * f x)" + proof (rule Sum_any.expand_superset [symmetric]) + show "{x. of_nat (count A x) * f x \ 0} \ set_mset A" + proof + fix x assume "x \ {x. of_nat (count A x) * f x \ 0}" + hence "count A x \ 0" + by (intro notI) auto + thus "x \# A" + by auto + qed + qed auto + finally show ?thesis . +qed + +lemma Sum_any_sum_swap: + assumes "finite A" "\y. finite {x. f x y \ 0}" + shows "Sum_any (\x. sum (f x) A) = (\y\A. Sum_any (\x. f x y))" +proof - + have "Sum_any (\x. sum (f x) A) = Sum_any (\x. Sum_any (\y. f x y when y \ A))" + unfolding when_def by (subst Sum_any.conditionalize) (use assms in simp_all) + also have "\ = Sum_any (\y. Sum_any (\x. f x y when y \ A))" + by (intro Sum_any.swap[of "(\y\A. {x. f x y \ 0}) \ A"] finite_SigmaI finite_UN_I assms) auto + also have "(\y. Sum_any (\x. f x y when y \ A)) = (\y. Sum_any (\x. f x y) when y \ A)" + by (auto simp: when_def) + also have "Sum_any \ = (\y\A. Sum_any (\x. f x y))" + unfolding when_def by (subst Sum_any.conditionalize) (use assms in simp_all) + finally show ?thesis . +qed + +lemma (in landau_pair) big_power: + assumes "f \ L F g" + shows "(\x. f x ^ n) \ L F (\x. g x ^ n)" + using big_prod[of "{.._. f" F "\_. g"] assms by simp + +lemma (in landau_pair) small_power: + assumes "f \ l F g" "n > 0" + shows "(\x. f x ^ n) \ l F (\x. g x ^ n)" + using assms(2,1) + by (induction rule: nat_induct_non_zero) (auto intro!: small.mult) + +lemma pairwise_imp_disjoint_family_on: + assumes "pairwise R A" + assumes "\m n. m \ A \ n \ A \ R m n \ f m \ f n = {}" + shows "disjoint_family_on f A" + using assms + unfolding disjoint_family_on_def pairwise_def by blast + +lemma (in comm_monoid_set) If_eq: + assumes "y \ A" "finite A" + shows "F (\x. g x (if x = y then h1 x else h2 x)) A = f (g y (h1 y)) (F (\x. g x (h2 x)) (A-{y}))" +proof - + have "F (\x. g x (if x = y then h1 x else h2 x)) A = + f (g y (h1 y)) (F (\x. g x (if x = y then h1 x else h2 x)) (A-{y}))" + using assms by (subst remove[of _ y]) auto + also have "F (\x. g x (if x = y then h1 x else h2 x)) (A-{y}) = F (\x. g x (h2 x)) (A-{y})" + by (intro cong) auto + finally show ?thesis by simp +qed + +lemma prod_nonzeroI: + fixes f :: "'a \ 'b :: {semiring_no_zero_divisors, comm_semiring_1}" + assumes "\x. x \ A \ f x \ 0" + shows "prod f A \ 0" + using assms by (induction rule: infinite_finite_induct) auto + +lemma frequently_prime_cofinite: "frequently (prime :: nat \ bool) cofinite" + unfolding INFM_nat_le by (meson bigger_prime less_imp_le) + +lemma frequently_eventually_mono: + assumes "frequently Q F" "eventually P F" "\x. P x \ Q x \ R x" + shows "frequently R F" +proof (rule frequently_mp[OF _ assms(1)]) + show "eventually (\x. Q x \ R x) F" + using assms(2) by eventually_elim (use assms(3) in blast) +qed + +lemma bij_betw_Diff: + assumes "bij_betw f A B" "bij_betw f A' B'" "A' \ A" "B' \ B" + shows "bij_betw f (A - A') (B - B')" + unfolding bij_betw_def +proof + have "inj_on f A" + using assms(1) by (auto simp: bij_betw_def) + thus "inj_on f (A - A')" + by (rule inj_on_subset) auto + have "f ` (A - A') = f ` A - f ` A'" + by (intro inj_on_image_set_diff[OF \inj_on f A\]) (use \A' \ A\ in auto) + also have "\ = B - B'" + using assms(1,2) by (auto simp: bij_betw_def) + finally show "f` (A - A') = B - B'" . +qed + +lemma bij_betw_singleton: "bij_betw f {x} {y} \ f x = y" + by (auto simp: bij_betw_def) + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/More_Algebraic_Numbers_HLW.thy b/thys/Hermite_Lindemann/More_Algebraic_Numbers_HLW.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/More_Algebraic_Numbers_HLW.thy @@ -0,0 +1,245 @@ +(* + File: More_Algebraic_Numbers_HLW.thy + Author: Manuel Eberl, TU München +*) +section \More facts about algebraic numbers\ +theory More_Algebraic_Numbers_HLW + imports "Algebraic_Numbers.Algebraic_Numbers" +begin + +subsection \Miscellaneous\ + +(* TODO: Move! All of this belongs in Algebraic_Numbers *) + +lemma in_Ints_imp_algebraic [simp, intro]: "x \ \ \ algebraic x" + by (intro algebraic_int_imp_algebraic int_imp_algebraic_int) + +lemma in_Rats_imp_algebraic [simp, intro]: "x \ \ \ algebraic x" + by (auto elim!: Rats_cases' intro: algebraic_div) + +lemma algebraic_uminus_iff [simp]: "algebraic (-x) \ algebraic x" + using algebraic_uminus[of x] algebraic_uminus[of "-x"] by auto + +lemma algebraic_0 [simp]: "algebraic (0 :: 'a :: field_char_0)" + and algebraic_1 [simp]: "algebraic (1 :: 'a :: field_char_0)" + by auto + +lemma algebraic_sum [intro]: + "(\x. x \ A \ algebraic (f x)) \ algebraic (sum f A)" + by (induction A rule: infinite_finite_induct) (auto intro!: algebraic_plus) + +lemma algebraic_prod [intro]: + "(\x. x \ A \ algebraic (f x)) \ algebraic (prod f A)" + by (induction A rule: infinite_finite_induct) (auto intro!: algebraic_times) + +lemma algebraic_sum_list [intro]: + "(\x. x \ set xs \ algebraic x) \ algebraic (sum_list xs)" + by (induction xs) (auto intro!: algebraic_plus) + +lemma algebraic_prod_list [intro]: + "(\x. x \ set xs \ algebraic x) \ algebraic (prod_list xs)" + by (induction xs) (auto intro!: algebraic_times) + +lemma algebraic_sum_mset [intro]: + "(\x. x \# A \ algebraic x) \ algebraic (sum_mset A)" + by (induction A) (auto intro!: algebraic_plus) + +lemma algebraic_prod_mset [intro]: + "(\x. x \# A \ algebraic x) \ algebraic (prod_mset A)" + by (induction A) (auto intro!: algebraic_times) + +lemma algebraic_power [intro]: "algebraic x \ algebraic (x ^ n)" + by (induction n) (auto intro: algebraic_times) + +lemma algebraic_csqrt [intro]: "algebraic x \ algebraic (csqrt x)" + by (rule algebraic_nth_root[of 2 x]) auto + +lemma algebraic_csqrt_iff [simp]: "algebraic (csqrt x) \ algebraic x" +proof + assume "algebraic (csqrt x)" + hence "algebraic (csqrt x ^ 2)" + by (rule algebraic_power) + also have "csqrt x ^ 2 = x" + by simp + finally show "algebraic x" . +qed auto + +lemmas [intro] = algebraic_plus algebraic_times algebraic_uminus algebraic_div + +lemma algebraic_power_iff [simp]: + assumes "n > 0" + shows "algebraic (x ^ n) \ algebraic x" + using algebraic_nth_root[of n "x ^ n" x] assms by auto + +lemma algebraic_ii [simp]: "algebraic \" + by (intro algebraic_int_imp_algebraic) auto + +lemma algebraic_int_fact [simp, intro]: "algebraic_int (fact n)" + by (intro int_imp_algebraic_int fact_in_Ints) + +lemma algebraic_minus [intro]: "algebraic x \ algebraic y \ algebraic (x - y)" + using algebraic_plus[of x "-y"] by simp + +lemma algebraic_add_cancel_left [simp]: + assumes "algebraic x" + shows "algebraic (x + y) \ algebraic y" +proof + assume "algebraic (x + y)" + hence "algebraic (x + y - x)" + using assms by (intro algebraic_minus) auto + thus "algebraic y" by simp +qed (auto intro: algebraic_plus assms) + +lemma algebraic_add_cancel_right [simp]: + assumes "algebraic y" + shows "algebraic (x + y) \ algebraic x" + using algebraic_add_cancel_left[of y x] assms + by (simp add: add.commute del: algebraic_add_cancel_left) + +lemma algebraic_diff_cancel_left [simp]: + assumes "algebraic x" + shows "algebraic (x - y) \ algebraic y" + using algebraic_add_cancel_left[of x "-y"] assms by (simp del: algebraic_add_cancel_left) + +lemma algebraic_diff_cancel_right [simp]: + assumes "algebraic y" + shows "algebraic (x - y) \ algebraic x" + using algebraic_add_cancel_right[of "-y" x] assms by (simp del: algebraic_add_cancel_right) + +lemma algebraic_mult_cancel_left [simp]: + assumes "algebraic x" "x \ 0" + shows "algebraic (x * y) \ algebraic y" +proof + assume "algebraic (x * y)" + hence "algebraic (x * y / x)" + using assms by (intro algebraic_div) auto + also have "x * y / x = y" + using assms by auto + finally show "algebraic y" . +qed (auto intro: algebraic_times assms) + +lemma algebraic_mult_cancel_right [simp]: + assumes "algebraic y" "y \ 0" + shows "algebraic (x * y) \ algebraic x" + using algebraic_mult_cancel_left[of y x] assms + by (simp add: mult.commute del: algebraic_mult_cancel_left) + +lemma algebraic_inverse_iff [simp]: "algebraic (inverse y) \ algebraic y" +proof + assume "algebraic (inverse y)" + hence "algebraic (inverse (inverse y))" + by (rule algebraic_inverse) + thus "algebraic y" by simp +qed (auto intro: algebraic_inverse) + +lemma algebraic_divide_cancel_left [simp]: + assumes "algebraic x" "x \ 0" + shows "algebraic (x / y) \ algebraic y" +proof - + have "algebraic (x * inverse y) \ algebraic (inverse y)" + by (intro algebraic_mult_cancel_left assms) + also have "\ \ algebraic y" + by (intro algebraic_inverse_iff) + finally show ?thesis by (simp add: field_simps) +qed + +lemma algebraic_divide_cancel_right [simp]: + assumes "algebraic y" "y \ 0" + shows "algebraic (x / y) \ algebraic x" +proof - + have "algebraic (x * inverse y) \ algebraic x" + using assms by (intro algebraic_mult_cancel_right) auto + thus ?thesis by (simp add: field_simps) +qed + + +subsection \Turning an algebraic number into an algebraic integer\ + +subsection \ + Multiplying an algebraic number with a suitable integer turns it into an algebraic integer. +\ + +lemma algebraic_imp_algebraic_int: + fixes x :: "'a :: field_char_0" + assumes "ipoly p x = 0" "p \ 0" + defines "c \ Polynomial.lead_coeff p" + shows "algebraic_int (of_int c * x)" +proof - + define n where "n = Polynomial.degree p" + define p' where "p' = Abs_poly (\i. if i = n then 1 else c ^ (n - i - 1) * poly.coeff p i)" + have "n > 0" + using assms unfolding n_def by (intro Nat.gr0I) (auto elim!: degree_eq_zeroE) + + have coeff_p': "poly.coeff p' i = + (if i = n then 1 else c ^ (n - i - 1) * poly.coeff p i)" + (is "_ = ?f i") for i unfolding p'_def + proof (subst poly.Abs_poly_inverse) + have "eventually (\i. poly.coeff p i = 0) cofinite" + using MOST_coeff_eq_0 by blast + hence "eventually (\i. ?f i = 0) cofinite" + by eventually_elim (use assms in \auto simp: n_def\) + thus "?f \ {f. eventually (\i. f i = 0) cofinite}" by simp + qed auto + + have deg_p': "Polynomial.degree p' = n" + proof - + from assms have "(\n. \i>n. poly.coeff p' i = 0) = (\n. \i>n. poly.coeff p i = 0)" + by (auto simp: coeff_p' fun_eq_iff n_def) + thus ?thesis + by (simp add: Polynomial.degree_def n_def) + qed + + have lead_coeff_p': "Polynomial.lead_coeff p' = 1" + by (simp add: coeff_p' deg_p') + + have "0 = of_int (c ^ (n - 1)) * (\i\n. of_int (poly.coeff p i) * x ^ i)" + using assms unfolding n_def poly_altdef by simp + also have "\ = (\i\n. of_int (c ^ (n - 1) * poly.coeff p i) * x ^ i)" + by (simp add: sum_distrib_left sum_distrib_right mult_ac) + also have "\ = (\i\n. of_int (poly.coeff p' i) * (of_int c * x) ^ i)" + proof (intro sum.cong, goal_cases) + case (2 i) + have "of_int (poly.coeff p' i) * (of_int c * x) ^ i = + of_int (c ^ i * poly.coeff p' i) * x ^ i" + by (simp add: algebra_simps) + also have "c ^ i * poly.coeff p' i = c ^ (n - 1) * poly.coeff p i" + proof (cases "i = n") + case True + hence "c ^ i * poly.coeff p' i = c ^ n" + by (auto simp: coeff_p' simp flip: power_Suc) + also have "n = Suc (n - 1)" + using \n > 0\ by simp + also have "c ^ \ = c * c ^ (n - 1)" + by simp + finally show ?thesis + using True by (simp add: c_def n_def) + next + case False + thus ?thesis using 2 + by (auto simp: coeff_p' simp flip: power_add) + qed + finally show ?case .. + qed auto + also have "\ = ipoly p' (of_int c * x)" + by (simp add: poly_altdef n_def deg_p') + finally have "ipoly p' (of_int c * x) = 0" .. + + with lead_coeff_p' show ?thesis + unfolding algebraic_int_altdef_ipoly by blast +qed + +lemma algebraic_imp_algebraic_int': + fixes x :: "'a :: field_char_0" + assumes "ipoly p x = 0" "p \ 0" "Polynomial.lead_coeff p dvd c" + shows "algebraic_int (of_int c * x)" +proof - + from assms(3) obtain c' where c_eq: "c = Polynomial.lead_coeff p * c'" + by auto + have "algebraic_int (of_int c' * (of_int (Polynomial.lead_coeff p) * x))" + by (rule algebraic_int_times[OF _ algebraic_imp_algebraic_int]) (use assms in auto) + also have "of_int c' * (of_int (Polynomial.lead_coeff p) * x) = of_int c * x" + by (simp add: c_eq mult_ac) + finally show ?thesis . +qed + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/More_Multivariate_Polynomial_HLW.thy b/thys/Hermite_Lindemann/More_Multivariate_Polynomial_HLW.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/More_Multivariate_Polynomial_HLW.thy @@ -0,0 +1,202 @@ +(* + File: More_Multivariate_Polynomial_HLW.thy + Author: Manuel Eberl, TU München +*) +section \Additional facts about multivariate polynomials\ +theory More_Multivariate_Polynomial_HLW + imports "Power_Sum_Polynomials.Power_Sum_Polynomials_Library" +begin + +subsection \Miscellaneous\ + +lemma Var_altdef: "Var i = monom (Poly_Mapping.single i 1) 1" + by transfer' (simp add: Var\<^sub>0_def) + +lemma Const_conv_monom: "Const c = monom 0 c" + by transfer' (auto simp: Const\<^sub>0_def) + +lemma smult_conv_mult_Const: "smult c p = Const c * p" + by (simp add: smult_conv_mult Const_conv_monom) + +lemma mpoly_map_vars_Var [simp]: "bij f \ mpoly_map_vars f (Var i) = Var (f i)" + unfolding Var_altdef + by (subst mpoly_map_vars_monom) (auto simp: permutep_single bij_imp_bij_inv inv_inv_eq) + +lemma symmetric_mpoly_symmetric_prod': + assumes "\\. \ permutes A \ g \ permutes X" + assumes "\x \. x \ X \ \ permutes A \ mpoly_map_vars \ (f x) = f (g \ x)" + shows "symmetric_mpoly A (\x\X. f x)" + unfolding symmetric_mpoly_def +proof safe + fix \ assume \: "\ permutes A" + have "mpoly_map_vars \ (prod f X) = (\x\X. mpoly_map_vars \ (f x))" + by simp + also have "\ = (\x\X. f (g \ x))" + by (intro prod.cong assms \ refl) + also have "\ = (\x\g \`X. f x)" + using assms(1)[OF \] by (subst prod.reindex) (auto simp: permutes_inj_on) + also have "g \ ` X = X" + using assms(1)[OF \] by (simp add: permutes_image) + finally show "mpoly_map_vars \ (prod f X) = prod f X" . +qed + + + +subsection \Converting a univariate polynomial into a multivariate one\ + +lift_definition mpoly_of_poly_aux :: "nat \ 'a :: zero poly \ (nat \\<^sub>0 nat) \\<^sub>0 'a" is + "\i c m. if Poly_Mapping.keys m \ {i} then c (Poly_Mapping.lookup m i) else 0" +proof goal_cases + case (1 i c) + hence fin: "finite {n. c n \ 0}" + by (metis eventually_cofinite) + show "finite {x. (if keys x \ {i} then c (lookup x i) else 0) \ 0}" + proof (rule finite_subset) + show "finite (Poly_Mapping.single i ` {n. c n \ 0})" + by (intro finite_imageI fin) + next + show "{x. (if keys x \ {i} then c (lookup x i) else 0) \ 0} \ + Poly_Mapping.single i ` {n. c n \ 0}" + proof (safe, split if_splits) + fix x :: "(nat \\<^sub>0 nat)" + assume x: "keys x \ {i}" "c (lookup x i) \ 0" + hence "x = Poly_Mapping.single i (lookup x i)" + by (metis Diff_eq_empty_iff keys_empty_iff lookup_single_eq + remove_key_keys remove_key_single remove_key_sum) + thus "x \ Poly_Mapping.single i ` {n. c n \ 0}" + using x by blast + qed auto + qed +qed + +lift_definition mpoly_of_poly :: "nat \ 'a :: zero poly \ 'a mpoly" is + "mpoly_of_poly_aux" . + +lemma mpoly_of_poly_0 [simp]: "mpoly_of_poly i 0 = 0" + by (transfer', transfer) auto + +lemma coeff_mpoly_of_poly1 [simp]: + "coeff (mpoly_of_poly i p) (Poly_Mapping.single i n) = poly.coeff p n" + by (transfer', transfer') auto + +lemma coeff_mpoly_of_poly2 [simp]: + assumes "\keys x \ {i}" + shows "coeff (mpoly_of_poly i p) x = 0" + using assms by (transfer', transfer') auto + +lemma coeff_mpoly_of_poly: + "coeff (mpoly_of_poly i p) m = + (poly.coeff p (Poly_Mapping.lookup m i) when keys m \ {i})" + by (transfer', transfer') auto + +lemma poly_mapping_single_eq_0_iff [simp]: "Poly_Mapping.single i n = 0 \ n = 0" + by (metis lookup_single_eq single_zero) + +lemma mpoly_of_poly_pCons [simp]: + fixes p :: "'a :: semiring_1 poly" + shows "mpoly_of_poly i (pCons c p) = Const c + Var i * mpoly_of_poly i p" +proof (rule mpoly_eqI) + fix mon :: "nat \\<^sub>0 nat" + define moni :: "nat \\<^sub>0 nat" where "moni = Poly_Mapping.single i 1" + have "coeff (Var i * mpoly_of_poly i p) mon = + (\l. (1 when l = moni) * (\q. coeff (mpoly_of_poly i p) q when mon = moni + q))" + unfolding coeff_mpoly_times prod_fun_def coeff_Var moni_def + by (rule Sum_any.cong) (auto simp: when_def) + also have "\ = (\a. coeff (mpoly_of_poly i p) a when mon = moni + a)" + by (subst Sum_any_left_distrib [symmetric]) simp_all + finally have eq: "coeff (Var i * mpoly_of_poly i p) mon = \" . + + show "coeff (mpoly_of_poly i (pCons c p)) mon = coeff (Const c + Var i * mpoly_of_poly i p) mon" + proof (cases "keys mon \ {i}") + case False + hence [simp]: "mon \ 0" + by auto + obtain j where j: "j \ keys mon" "j \ i" + using False by auto + have "coeff (mpoly_of_poly i p) mon' = 0" if mon_eq: "mon = moni + mon'" for mon' + proof - + have "Poly_Mapping.lookup mon j \ 0" + using j by (meson lookup_eq_zero_in_keys_contradict) + also have "Poly_Mapping.lookup mon j = Poly_Mapping.lookup mon' j" + unfolding mon_eq moni_def using j by (simp add: lookup_add lookup_single) + finally have "j \ keys mon'" + by (meson lookup_not_eq_zero_eq_in_keys) + with j have "\keys mon' \ {i}" + by blast + thus ?thesis by simp + qed + hence "coeff (Var i * mpoly_of_poly i p) mon = 0" + unfolding eq by (intro Sum_any_zeroI) (auto simp: when_def) + thus ?thesis using False + by (simp add: mpoly_coeff_Const) + next + case True + define n where "n = Poly_Mapping.lookup mon i" + have mon_eq: "mon = Poly_Mapping.single i n" + using True unfolding n_def + by (metis Diff_eq_empty_iff add_cancel_right_left keys_empty_iff remove_key_keys remove_key_sum) + have eq': "mon = moni + mon' \ n > 0 \ mon' = Poly_Mapping.single i (n - 1)" for mon' + proof safe + assume eq: "mon = moni + mon'" + thus "n > 0" "mon' = Poly_Mapping.single i (n - 1)" + unfolding moni_def mon_eq using gr0I by (force simp: single_diff)+ + next + assume "n > 0" "mon' = Poly_Mapping.single i (n - 1)" + thus "mon = moni + Poly_Mapping.single i (n - 1)" + unfolding mon_eq moni_def by (subst single_add [symmetric]) auto + qed + have "coeff (Var i * mpoly_of_poly i p) mon = (poly.coeff p (n - 1) when (n > 0))" + unfolding eq eq' by (auto simp: when_def) + thus ?thesis + by (auto simp: mon_eq when_def mpoly_coeff_Const coeff_pCons split: nat.splits) + qed +qed + +lemma mpoly_of_poly_1 [simp]: "mpoly_of_poly i 1 = 1" + unfolding one_pCons mpoly_of_poly_pCons mpoly_of_poly_0 by simp + +lemma mpoly_of_poly_uminus [simp]: "mpoly_of_poly i (-p) = -mpoly_of_poly i p" + by (rule mpoly_eqI) (auto simp: coeff_mpoly_of_poly when_def) + +lemma mpoly_of_poly_add [simp]: "mpoly_of_poly i (p + q) = mpoly_of_poly i p + mpoly_of_poly i q" + by (rule mpoly_eqI) (auto simp: coeff_mpoly_of_poly when_def) + +lemma mpoly_of_poly_diff [simp]: "mpoly_of_poly i (p - q) = mpoly_of_poly i p - mpoly_of_poly i q" + by (rule mpoly_eqI) (auto simp: coeff_mpoly_of_poly when_def) + +lemma mpoly_of_poly_smult [simp]: + "mpoly_of_poly i (Polynomial.smult c p) = smult c (mpoly_of_poly i p)" + by (rule mpoly_eqI) (auto simp: coeff_mpoly_of_poly when_def) + +lemma mpoly_of_poly_mult [simp]: + fixes p q :: "'a :: comm_semiring_1 poly" + shows "mpoly_of_poly i (p * q) = mpoly_of_poly i p * mpoly_of_poly i q" + by (induction p) (auto simp: algebra_simps smult_conv_mult_Const) + +lemma insertion_mpoly_of_poly [simp]: "insertion f (mpoly_of_poly i p) = poly p (f i)" + by (induction p) (auto simp: insertion_add insertion_mult) + +lemma mapping_of_mpoly_of_poly [simp]: "mapping_of (mpoly_of_poly i p) = mpoly_of_poly_aux i p" + by transfer' simp + +lemma vars_mpoly_of_poly: "vars (mpoly_of_poly i p) \ {i}" +proof - + have "x = i" if "xa \ keys (mpoly_of_poly_aux i p)" "x \ keys xa" for x xa + using that + by (meson in_mono lookup_eq_zero_in_keys_contradict mpoly_of_poly_aux.rep_eq singletonD) + thus ?thesis + by (auto simp: vars_def) +qed + +lemma mpoly_map_vars_mpoly_of_poly [simp]: + assumes "bij f" + shows "mpoly_map_vars f (mpoly_of_poly i p) = mpoly_of_poly (f i) p" +proof (rule mpoly_eqI, goal_cases) + case (1 mon) + have "f -` keys mon \ {i} \ keys mon \ {f i}" + using assms by (simp add: vimage_subset_eq) + thus ?case using assms + by (simp add: coeff_mpoly_map_vars coeff_mpoly_of_poly lookup_permutep keys_permutep when_def) +qed + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/More_Polynomial_HLW.thy b/thys/Hermite_Lindemann/More_Polynomial_HLW.thy new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/More_Polynomial_HLW.thy @@ -0,0 +1,518 @@ +(* + File: More_Polynomial_HLW.thy + Author: Manuel Eberl, TU München +*) +section \Auxiliary facts about univariate polynomials\ +theory More_Polynomial_HLW +imports + "HOL-Computational_Algebra.Computational_Algebra" + "Polynomial_Factorization.Gauss_Lemma" + "Power_Sum_Polynomials.Power_Sum_Polynomials_Library" + "Algebraic_Numbers.Algebraic_Numbers" +begin + +instance poly :: ("{idom_divide,normalization_semidom_multiplicative,factorial_ring_gcd, + semiring_gcd_mult_normalize}") factorial_semiring_multiplicative .. + +lemma lead_coeff_prod_mset: + fixes A :: "'a::{comm_semiring_1, semiring_no_zero_divisors} poly multiset" + shows "Polynomial.lead_coeff (prod_mset A) = prod_mset (image_mset Polynomial.lead_coeff A)" + by (induction A) (auto simp: Polynomial.lead_coeff_mult) + +lemma content_normalize [simp]: + fixes p :: "'a :: {factorial_semiring, idom_divide, semiring_gcd, normalization_semidom_multiplicative} poly" + shows "content (normalize p) = content p" +proof (cases "p = 0") + case [simp]: False + have "content p = content (unit_factor p * normalize p)" + by simp + also have "\ = content (unit_factor p) * content (normalize p)" + by (rule content_mult) + also have "content (unit_factor p) = 1" + by (auto simp: unit_factor_poly_def) + finally show ?thesis by simp +qed auto + +lemma rat_to_normalized_int_poly_exists: + fixes p :: "rat poly" + assumes "p \ 0" + obtains q lc where "p = Polynomial.smult lc (of_int_poly q)" "lc > 0" "content q = 1" +proof - + define lc where "lc = fst (rat_to_normalized_int_poly p)" + define q where "q = snd (rat_to_normalized_int_poly p)" + have eq: "rat_to_normalized_int_poly p = (lc, q)" + by (simp add: lc_def q_def) + show ?thesis + using rat_to_normalized_int_poly[OF eq] assms + by (intro that[of lc q]) auto +qed + +lemma irreducible_imp_squarefree: + assumes "irreducible p" + shows "squarefree p" +proof (rule squarefreeI) + fix q assume "q ^ 2 dvd p" + then obtain r where qr: "p = q ^ 2 * r" + by (elim dvdE) + have "q dvd 1 \ q * r dvd 1" + by (intro irreducibleD[OF assms]) (use qr in \simp_all add: power2_eq_square mult_ac\) + thus "q dvd 1" + by (meson dvd_mult_left) +qed + +lemma squarefree_imp_rsquarefree: + fixes p :: "'a :: idom poly" + assumes "squarefree p" + shows "rsquarefree p" + unfolding rsquarefree_def +proof (intro conjI allI) + fix x :: 'a + have "Polynomial.order x p < 2" + proof (rule ccontr) + assume "\(Polynomial.order x p < 2)" + hence "[:-x, 1:] ^ 2 dvd p" + by (subst order_divides) auto + from assms and this have "[:-x, 1:] dvd 1" + by (rule squarefreeD) + hence "Polynomial.degree [:-x, 1:] \ Polynomial.degree (1 :: 'a poly)" + by (rule dvd_imp_degree_le) auto + thus False by simp + qed + thus "Polynomial.order x p = 0 \ Polynomial.order x p = 1" + by linarith +qed (use assms in auto) + +lemma squarefree_imp_coprime_pderiv: + fixes p :: "'a :: {factorial_ring_gcd,semiring_gcd_mult_normalize,semiring_char_0} poly" + assumes "squarefree p" and "content p = 1" + shows "Rings.coprime p (pderiv p)" +proof (rule coprimeI_primes) + fix d assume d: "prime d" "d dvd p" "d dvd pderiv p" + show False + proof (cases "Polynomial.degree d = 0") + case deg: False + obtain q where dq: "p = d * q" + using d by (elim dvdE) + have \d dvd q * pderiv d\ + using d by (simp add: dq pderiv_mult dvd_add_right_iff) + moreover have "\d dvd pderiv d" + proof + assume "d dvd pderiv d" + hence "Polynomial.degree d \ Polynomial.degree (pderiv d)" + using d deg by (intro dvd_imp_degree_le) (auto simp: pderiv_eq_0_iff) + hence "Polynomial.degree d = 0" + by (subst (asm) degree_pderiv) auto + thus False using deg by contradiction + qed + ultimately have "d dvd q" + using d(1) by (simp add: prime_dvd_mult_iff) + hence "d ^ 2 dvd p" + by (auto simp: dq power2_eq_square) + from assms(1) and this have "is_unit d" + by (rule squarefreeD) + thus False using \prime d\ by auto + next + case True + then obtain d' where [simp]: "d = [:d':]" + by (elim degree_eq_zeroE) + from d have "d' dvd content p" + by (simp add: const_poly_dvd_iff_dvd_content) + with assms and prime_imp_prime_elem[OF \prime d\] show False + by (auto simp: prime_elem_const_poly_iff) + qed +qed (use assms in auto) + +lemma irreducible_imp_coprime_pderiv: + fixes p :: "'a :: {idom_divide,semiring_char_0} poly" + assumes "irreducible p" "Polynomial.degree p \ 0" + shows "Rings.coprime p (pderiv p)" +proof (rule Rings.coprimeI) + fix d assume d: "d dvd p" "d dvd pderiv p" + obtain q where dq: "p = d * q" + using d by (elim dvdE) + have "is_unit d \ is_unit q" + using assms dq by (auto simp: irreducible_def) + thus "is_unit d" + proof + assume unit: "is_unit q" + with d have "p dvd pderiv p" + using algebraic_semidom_class.mult_unit_dvd_iff dq by blast + hence "Polynomial.degree p = 0" + by (meson not_dvd_pderiv) + with assms(2) show ?thesis by contradiction + qed +qed + +lemma poly_gcd_eq_0I: + assumes "poly p x = 0" "poly q x = 0" + shows "poly (gcd p q) x = 0" + using assms by (simp add: poly_eq_0_iff_dvd) + +lemma poly_eq_0_coprime: + assumes "Rings.coprime p q" "p \ 0" "q \ 0" + shows "poly p x \ 0 \ poly q x \ 0" +proof - + have False if "poly p x = 0" "poly q x = 0" + proof - + have "[:-x, 1:] dvd p" "[:-x, 1:] dvd q" + using that by (simp_all add: poly_eq_0_iff_dvd) + hence "[:-x, 1:] dvd 1" + using \Rings.coprime p q\ by (meson not_coprimeI) + thus False + by (simp add: is_unit_poly_iff) + qed + thus ?thesis + by blast +qed + +lemma coprime_of_int_polyI: + assumes "Rings.coprime p q" + shows "Rings.coprime (of_int_poly p) (of_int_poly q :: 'a :: {field_char_0,field_gcd} poly)" + using assms gcd_of_int_poly[of p q, where ?'a = 'a] unfolding coprime_iff_gcd_eq_1 by simp + +lemma irreducible_imp_rsquarefree_of_int_poly: + fixes p :: "int poly" + assumes "irreducible p" and "Polynomial.degree p > 0" + shows "rsquarefree (of_int_poly p :: 'a :: {field_gcd, field_char_0} poly)" +proof - + { + fix x :: 'a + assume x: "poly (of_int_poly p) x = 0" "poly (pderiv (of_int_poly p)) x = 0" + define d where "d = gcd (of_int_poly p) (pderiv (of_int_poly p) :: 'a poly)" + have "poly d x = 0" + using x unfolding d_def by (intro poly_gcd_eq_0I) auto + moreover have "d \ 0" + using assms by (auto simp: d_def) + ultimately have "0 < Polynomial.degree d" + by (intro Nat.gr0I) (auto elim!: degree_eq_zeroE) + also have "Polynomial.degree d = Polynomial.degree (gcd p (pderiv p))" + unfolding d_def of_int_hom.map_poly_pderiv[symmetric] gcd_of_int_poly by simp + finally have deg: "\ > 0" . + + have "gcd p (pderiv p) dvd p" + by auto + from irreducibleD'[OF assms(1) this] and deg have "p dvd gcd p (pderiv p)" + by auto + also have "\ dvd pderiv p" + by auto + finally have "Polynomial.degree p = 0" + by auto + with assms have False by simp + } + thus ?thesis by (auto simp: rsquarefree_roots) +qed + +lemma squarefree_of_int_polyI: + assumes "squarefree p" "content p = 1" + shows "squarefree (of_int_poly p :: 'a :: {field_char_0,field_gcd} poly)" +proof - + have "Rings.coprime p (pderiv p)" + by (rule squarefree_imp_coprime_pderiv) fact+ + hence "Rings.coprime (of_int_poly p :: 'a poly) (of_int_poly (pderiv p))" + by (rule coprime_of_int_polyI) + also have "of_int_poly (pderiv p) = pderiv (of_int_poly p :: 'a poly)" + by (simp add: of_int_hom.map_poly_pderiv) + finally show ?thesis + using coprime_pderiv_imp_squarefree by blast +qed + +lemma higher_pderiv_pcompose_linear: + "(pderiv ^^ n) (pcompose p [:0, c:]) = + Polynomial.smult (c ^ n) (pcompose ((pderiv ^^ n) p) [:0, c:])" + by (induction n) (simp_all add: pderiv_pcompose pderiv_smult pderiv_pCons pcompose_smult mult_ac) + +lemma poly_poly_eq: + "poly (poly p [:x:]) y = poly (eval_poly (\p. [:poly p y:]) p [:0, 1:]) x" + by (induction p) (auto simp: eval_poly_def) + +lemma poly_poly_poly_y_x [simp]: + fixes p :: "'a :: idom poly poly" + shows "poly (poly (poly_y_x p) [:y:]) x = poly (poly p [:x:]) y" +proof (induction p) + case (pCons a p) + have "poly (poly (poly_y_x (pCons a p)) [:y:]) x = + poly a y + poly (poly (map_poly (pCons 0) (poly_y_x p)) [:y:]) x" + by (simp add: poly_y_x_pCons eval_poly_def) + also have "pCons 0 = (\p::'a poly. Polynomial.monom 1 1 * p)" + by (simp add: Polynomial.monom_altdef) + also have "map_poly \ (poly_y_x p) = Polynomial.smult (Polynomial.monom 1 1) (poly_y_x p)" + by (simp add: smult_conv_map_poly) + also have "poly \ [:y:] = Polynomial.monom 1 1 * poly (poly_y_x p) [:y:]" + by simp + also have "poly a y + poly \ x = poly (poly (pCons a p) [:x:]) y" + by (simp add: pCons poly_monom) + finally show ?case . +qed auto + +lemma (in idom_hom) map_poly_higher_pderiv [hom_distribs]: + "map_poly hom ((pderiv ^^ n) p) = (pderiv ^^ n) (map_poly hom p)" + by (induction n) (simp_all add: map_poly_pderiv) + +lemma coeff_prod_linear_factors: + fixes f :: "'a \ 'b :: comm_ring_1" + assumes [intro]: "finite A" + shows "Polynomial.coeff (\x\A. [:-f x, 1:] ^ e x) i = + (\X | X \ Pow (SIGMA x:A. {.. i = sum e A - card X. + (-1) ^ card X * (\x\X. f (fst x)))" +proof - + define poly_X where "poly_X = (Polynomial.monom 1 1 :: 'b poly)" + have [simp]: "(- 1) ^ n = [:(- 1) ^ n :: 'b:]" for n :: nat + by (simp flip: pCons_one add: poly_const_pow) + have "(\x\A. [:-f x, 1:] ^ e x) = (\(x,_)\Sigma A (\x. {.. = (\(x,_)\Sigma A (\x. {.. = (\X\Pow (SIGMA x:A. {..x\X. f (fst x))) + (poly_X ^ card ((SIGMA x:A. {.. = (\X\Pow (SIGMA x:A. {..x\X. f (fst x))) (card ((SIGMA x:A. {.. i = (\X\{X\Pow (SIGMA x:A. {..x\X. f (fst x)))" + unfolding Polynomial.coeff_sum + proof (intro sum.mono_neutral_cong_right ballI, goal_cases) + case (3 X) + hence X: "X \ (SIGMA x:A. {.. card (SIGMA x:A. {.. (SIGMA x:A. {..i. poly.coeff p i \ A" "x \ A" + shows "poly p x \ A" + unfolding poly_altdef by (intro sum_closed mult_closed power_closed assms) + +lemma (in ring_closed) coeff_pCons_closed [intro]: + assumes "\i. poly.coeff p i \ A" "x \ A" + shows "poly.coeff (pCons x p) i \ A" + unfolding poly_altdef using assms by (auto simp: coeff_pCons split: nat.splits) + +lemma (in ring_closed) coeff_poly_mult_closed [intro]: + assumes "\i. poly.coeff p i \ A" "\i. poly.coeff q i \ A" + shows "poly.coeff (p * q) i \ A" + unfolding coeff_mult using assms by auto + +lemma (in ring_closed) coeff_poly_prod_closed [intro]: + assumes "\x i. x \ X \ poly.coeff (f x) i \ A" + shows "poly.coeff (prod f X) i \ A" + using assms by (induction X arbitrary: i rule: infinite_finite_induct) auto + +lemma (in ring_closed) coeff_poly_power_closed [intro]: + assumes "\i. poly.coeff p i \ A" + shows "poly.coeff (p ^ n) i \ A" + using coeff_poly_prod_closed[of "{.._. p" i] assms by simp + +lemma (in ring_closed) synthetic_div_closed: + assumes "\i. poly.coeff p i \ A" "x \ A" + shows "poly.coeff (synthetic_div p x) i \ A" +proof - + from assms(1) have "\i. poly.coeff p i \ A" + by blast + from this and assms(2) show ?thesis + by (induction p arbitrary: i) (auto simp: coeff_pCons split: nat.splits) +qed + +lemma pcompose_monom: "pcompose (Polynomial.monom c n) p = Polynomial.smult c (p ^ n)" + by (simp add: monom_altdef pcompose_hom.hom_power pcompose_smult) + +lemma poly_roots_uminus [simp]: "poly_roots (-p) = poly_roots p" + using poly_roots_smult[of "-1" p] by (simp del: poly_roots_smult) + +lemma poly_roots_normalize [simp]: + fixes p :: "'a :: {normalization_semidom, idom_divide} poly" + shows "poly_roots (normalize p) = poly_roots p" +proof (cases "p = 0") + case [simp]: False + have "poly_roots p = poly_roots (unit_factor p * normalize p)" + by simp + also have "\ = poly_roots (normalize p)" + unfolding unit_factor_poly_def by simp + finally show ?thesis .. +qed auto + + +lemma poly_roots_of_int_normalize [simp]: + "poly_roots (of_int_poly (normalize p) :: 'a :: {idom, ring_char_0} poly) = + poly_roots (of_int_poly p)" +proof (cases "p = 0") + case [simp]: False + have "poly_roots (of_int_poly p :: 'a poly) = poly_roots (of_int_poly (unit_factor p * normalize p))" + by simp + also have "\ = poly_roots (Polynomial.smult (of_int (sgn (Polynomial.lead_coeff p))) + (of_int_poly (normalize p)))" + by (simp add: unit_factor_poly_def of_int_hom.map_poly_hom_smult) + also have "\ = poly_roots (Ring_Hom_Poly.of_int_poly (normalize p) :: 'a poly)" + by (intro poly_roots_smult) (auto simp: sgn_if) + finally show ?thesis .. +qed auto + +lemma poly_roots_power [simp]: "poly_roots (p ^ n) = repeat_mset n (poly_roots p)" +proof (cases "p = 0") + case True + thus ?thesis by (cases n) auto +next + case False + thus ?thesis by (induction n) (auto simp: poly_roots_mult) +qed + +lemma poly_roots_conv_sum_prime_factors: + "poly_roots q = (\p\#prime_factorization q. poly_roots p)" +proof (cases "q = 0") + case [simp]: False + + have "(\p\#prime_factorization q. poly_roots p) = + poly_roots (prod_mset (prime_factorization q))" + by (rule poly_roots_prod_mset [symmetric]) auto + also have "\ = poly_roots (normalize (prod_mset (prime_factorization q)))" + by simp + also have "normalize (prod_mset (prime_factorization q)) = normalize q" + by (rule prod_mset_prime_factorization_weak) auto + also have "poly_roots \ = poly_roots q" + by simp + finally show ?thesis .. +qed auto + +lemma poly_roots_of_int_conv_sum_prime_factors: + "poly_roots (of_int_poly q :: 'a :: {idom, ring_char_0} poly) = + (\p\#prime_factorization q. poly_roots (of_int_poly p))" +proof (cases "q = 0") + case [simp]: False + + have "(\p\#prime_factorization q. poly_roots (of_int_poly p :: 'a poly)) = + poly_roots (\p\#prime_factorization q. of_int_poly p)" + by (subst poly_roots_prod_mset) (auto simp: multiset.map_comp o_def) + also have "(\p\#prime_factorization q. of_int_poly p :: 'a poly) = + of_int_poly (prod_mset (prime_factorization q))" + by simp + also have "poly_roots \ = poly_roots (of_int_poly (normalize (prod_mset (prime_factorization q))))" + by (rule poly_roots_of_int_normalize [symmetric]) + also have "normalize (prod_mset (prime_factorization q)) = normalize q" + by (rule prod_mset_prime_factorization_weak) auto + also have "poly_roots (of_int_poly \ :: 'a poly) = poly_roots (of_int_poly q)" + by simp + finally show ?thesis .. +qed auto + +lemma dvd_imp_poly_roots_subset: + assumes "q \ 0" "p dvd q" + shows "poly_roots p \# poly_roots q" +proof - + from assms have "p \ 0" + by auto + thus ?thesis + using assms by (intro mset_subset_eqI) (auto intro: dvd_imp_order_le) +qed + +lemma abs_prod_mset: "\prod_mset (A :: 'a :: idom_abs_sgn multiset)\ = prod_mset (image_mset abs A)" + by (induction A) (auto simp: abs_mult) + +lemma content_1_imp_nonconstant_prime_factors: + assumes "content (p :: int poly) = 1" and "q \ prime_factors p" + shows "Polynomial.degree q > 0" +proof - + let ?d = "Polynomial.degree :: int poly \ nat" + let ?lc = "Polynomial.lead_coeff :: int poly \ int" + define P where "P = prime_factorization p" + define P1 where "P1 = filter_mset (\p. ?d p = 0) P" + define P2 where "P2 = filter_mset (\p. ?d p > 0) P" + have [simp]: "p \ 0" + using assms by auto + have "1 = content (normalize p)" + using assms by simp + also have "normalize p = prod_mset P" + unfolding P_def by (rule prod_mset_prime_factorization [symmetric]) auto + also have "P = filter_mset (\p. ?d p = 0) P + filter_mset (\p. ?d p > 0) P" + by (induction P) auto + also have "prod_mset \ = prod_mset P1 * prod_mset P2" + unfolding P1_def P2_def by (subst prod_mset.union) auto + also have "content \ = content (prod_mset P1) * content (prod_mset P2)" + unfolding content_mult .. + also have "image_mset id P1 = image_mset (\q. [:?lc q:]) P1" + by (intro image_mset_cong) (auto simp: P1_def elim!: degree_eq_zeroE) + hence "P1 = image_mset (\q. [:?lc q:]) P1" + by simp + also have "content (prod_mset \) = \(\q\#P1. ?lc q)\" + by (simp add: content_prod_mset multiset.map_comp o_def abs_prod_mset) + finally have "\(\q\#P1. ?lc q)\ * content (prod_mset P2) = 1" .. + hence "\(\q\#P1. ?lc q)\ dvd 1" + unfolding dvd_def by metis + + have "set_mset P1 = {}" + proof (rule ccontr) + assume "set_mset P1 \ {}" + then obtain q where q: "q \# P1" + by blast + have "\?lc q\ dvd (\q\#P1. \?lc q\)" + by (rule dvd_prod_mset) (use q in auto) + also have "\ = \(\q\#P1. ?lc q)\" + by (simp add: abs_prod_mset multiset.map_comp o_def) + also have "\ dvd 1" + by fact + finally have "is_unit (?lc q)" + by simp + hence "is_unit q" + using q unfolding P1_def by (auto elim!: degree_eq_zeroE) + moreover have "prime q" + using q unfolding P1_def P_def by auto + ultimately show False by auto + qed + with assms show ?thesis + by (auto simp: P1_def P_def) +qed + +end \ No newline at end of file diff --git a/thys/Hermite_Lindemann/ROOT b/thys/Hermite_Lindemann/ROOT new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/ROOT @@ -0,0 +1,14 @@ +chapter AFP + +session Hermite_Lindemann (AFP) = "Pi_Transcendental" + + options [timeout = 1200] + sessions + "HOL-Library" + Algebraic_Numbers + Power_Sum_Polynomials + theories + Hermite_Lindemann + document_files + "root.tex" + "root.bib" + diff --git a/thys/Hermite_Lindemann/document/root.bib b/thys/Hermite_Lindemann/document/root.bib new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/document/root.bib @@ -0,0 +1,36 @@ +@book{baker, + series={Cambridge Mathematical Library}, + title={Transcendental Number Theory}, + DOI={10.1017/CBO9780511565977}, + isbn={9780521397919}, + publisher={Cambridge University Press}, + author={Baker, Alan}, + year={1975}, +} + +@article{redheffer_steinberg, +author = {Robert Steinberg and Raymond Moos Redheffer}, +title = {Analytic proof of the {L}indemann theorem}, +volume = {2}, +journal = {Pacific Journal of Mathematics}, +number = {2}, +pages = {231--242}, +year = {1952}, +doi = {10.2140/pjm.1952.2.231} +} + + +@inproceedings{bernard, + author = {Sophie Bernard}, + editor = {Mauricio Ayala{-}Rinc{\'{o}}n and + C{\'{e}}sar A. Mu{\~{n}}oz}, + title = {Formalization of the {L}indemann-{W}eierstrass Theorem}, + booktitle = {Interactive Theorem Proving - 8th International Conference, {ITP} + 2017, Bras{\'i}lia, Brazil, September 26-29, 2017, Proceedings}, + series = {Lecture Notes in Computer Science}, + volume = {10499}, + pages = {65--80}, + publisher = {Springer}, + year = {2017}, + doi = {10.1007/978-3-319-66107-0_5} +} \ No newline at end of file diff --git a/thys/Hermite_Lindemann/document/root.tex b/thys/Hermite_Lindemann/document/root.tex new file mode 100644 --- /dev/null +++ b/thys/Hermite_Lindemann/document/root.tex @@ -0,0 +1,63 @@ +\documentclass[11pt,a4paper]{article} +\usepackage{isabelle,isabellesym} +\usepackage{amsfonts, amsmath, amssymb} + +% this should be the last package used +\usepackage{pdfsetup} +\usepackage[shortcuts]{extdash} + +% urls in roman style, theory text in math-similar italics +\urlstyle{rm} +\isabellestyle{it} + +\begin{document} + +\title{The Hermite--Lindemann--Weierstraß Transcendence Theorem} +\author{Manuel Eberl} +\maketitle + +\begin{abstract} +This article provides a formalisation of the Her\-mite\--Lin\-de\-mann\--Wei\-er\-straß Theorem +(also known as simply Her\-mite\--Lin\-de\-mann or Lin\-de\-mann\--Wei\-er\-straß). + This theorem is one of the crowning achievements of 19th century number theory. + +The theorem states that if $\alpha_1, \ldots, \alpha_n\in\mathbb{C}$ are algebraic numbers that +are linearly independent over $\mathbb{Z}$, then $e^{\alpha_1},\ldots,e^{\alpha_n}$ are +algebraically independent over $\mathbb{Q}$. + +Like the previous formalisation in Coq by Bernard~\cite{bernard}, I proceeded by formalising +Baker's alternative formulation of the theorem~\cite{baker} and then deriving the original one from +that. Baker's version states that for any algebraic numbers +$\beta_1, \ldots, \beta_n\in\mathbb{C}$ and distinct algebraic numbers +$\alpha_i, \ldots, \alpha_n\in\mathbb{C}$, we have: +\[\beta_1 e^{\alpha_1} + \ldots + \beta_n e^{\alpha_n} = 0 \quad\quad\text{iff}\quad\quad + \forall i.\ \beta_i = 0\] + +This has a number of immediate corollaries, e.g.: +\begin{itemize} +\item $e$ and $\pi$ are transcendental +\item $e^z$, $\sin z$, $\tan z$, etc.\ are transcendental for algebraic $z\in\mathbb{C}\setminus\{0\}$ +\item $\ln z$ is transcendental for algebraic $z\in\mathbb{C}\setminus\{0, 1\}$ +\end{itemize} +\end{abstract} + +\newpage +\tableofcontents +\newpage +\parindent 0pt\parskip 0.5ex + +\input{session} + +\nocite{baker} +\nocite{redheffer_steinberg} +\nocite{bernard} + +\bibliographystyle{abbrv} +\bibliography{root} + +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/thys/ROOTS b/thys/ROOTS --- a/thys/ROOTS +++ b/thys/ROOTS @@ -1,589 +1,590 @@ ADS_Functor AI_Planning_Languages_Semantics AODV AVL-Trees AWN Abortable_Linearizable_Modules Abs_Int_ITP2012 Abstract-Hoare-Logics Abstract-Rewriting Abstract_Completeness Abstract_Soundness Adaptive_State_Counting Affine_Arithmetic Aggregation_Algebras Akra_Bazzi Algebraic_Numbers Algebraic_VCs Allen_Calculus Amicable_Numbers Amortized_Complexity AnselmGod Applicative_Lifting Approximation_Algorithms Architectural_Design_Patterns Aristotles_Assertoric_Syllogistic Arith_Prog_Rel_Primes ArrowImpossibilityGS Attack_Trees Auto2_HOL Auto2_Imperative_HOL AutoFocus-Stream Automated_Stateful_Protocol_Verification Automatic_Refinement AxiomaticCategoryTheory BDD BNF_CC BNF_Operations BTree Banach_Steinhaus Bell_Numbers_Spivey Berlekamp_Zassenhaus Bernoulli Bertrands_Postulate Bicategory BinarySearchTree Binding_Syntax_Theory Binomial-Heaps Binomial-Queues BirdKMP Blue_Eyes Bondy Boolean_Expression_Checkers Bounded_Deducibility_Security Buchi_Complementation Budan_Fourier Buffons_Needle Buildings BytecodeLogicJmlTypes C2KA_DistributedSystems CAVA_Automata CAVA_LTL_Modelchecker CCS CISC-Kernel CRDT CYK CakeML CakeML_Codegen Call_Arity Card_Equiv_Relations Card_Multisets Card_Number_Partitions Card_Partitions Cartan_FP Case_Labeling Catalan_Numbers Category Category2 Category3 Cauchy Cayley_Hamilton Certification_Monads Chandy_Lamport Chord_Segments Circus Clean ClockSynchInst Closest_Pair_Points CofGroups Coinductive Coinductive_Languages Collections Comparison_Sort_Lower_Bound Compiling-Exceptions-Correctly Complete_Non_Orders Completeness Complex_Geometry Complx ComponentDependencies ConcurrentGC ConcurrentIMP Concurrent_Ref_Alg Concurrent_Revisions Consensus_Refined Constructive_Cryptography Constructor_Funs Containers CoreC++ Core_DOM Core_SC_DOM Count_Complex_Roots CryptHOL CryptoBasedCompositionalProperties CSP_RefTK DFS_Framework DPT-SAT-Solver DataRefinementIBP Datatype_Order_Generator Decl_Sem_Fun_PL Decreasing-Diagrams Decreasing-Diagrams-II Deep_Learning Delta_System_Lemma Density_Compiler Dependent_SIFUM_Refinement Dependent_SIFUM_Type_Systems Depth-First-Search Derangements Deriving Descartes_Sign_Rule Dict_Construction Differential_Dynamic_Logic Differential_Game_Logic Dijkstra_Shortest_Path Diophantine_Eqns_Lin_Hom Dirichlet_L Dirichlet_Series DiscretePricing Discrete_Summation DiskPaxos DOM_Components DynamicArchitectures Dynamic_Tables E_Transcendental Echelon_Form EdmondsKarp_Maxflow Efficient-Mergesort Elliptic_Curves_Group_Law Encodability_Process_Calculi Epistemic_Logic Ergodic_Theory Error_Function Euler_MacLaurin Euler_Partition Example-Submission Extended_Finite_State_Machine_Inference Extended_Finite_State_Machines FFT FLP FOL-Fitting FOL_Harrison FOL_Seq_Calc1 Factored_Transition_System_Bounding Falling_Factorial_Sum Farkas FeatherweightJava Featherweight_OCL Fermat3_4 FileRefinement FinFun Finger-Trees Finite-Map-Extras Finite_Automata_HF First_Order_Terms First_Welfare_Theorem Fishburn_Impossibility Fisher_Yates Flow_Networks Floyd_Warshall Flyspeck-Tame FocusStreamsCaseStudies Forcing Formal_Puiseux_Series Formal_SSA Formula_Derivatives Fourier Free-Boolean-Algebra Free-Groups FunWithFunctions FunWithTilings Functional-Automata Functional_Ordered_Resolution_Prover Furstenberg_Topology GPU_Kernel_PL Gabow_SCC Game_Based_Crypto Gauss-Jordan-Elim-Fun Gauss_Jordan Gauss_Sums Gaussian_Integers GenClock General-Triangle Generalized_Counting_Sort Generic_Deriving Generic_Join GewirthPGCProof Girth_Chromatic GoedelGod Goedel_HFSet_Semantic Goedel_HFSet_Semanticless Goedel_Incompleteness Goodstein_Lambda GraphMarkingIBP Graph_Saturation Graph_Theory Green Groebner_Bases Groebner_Macaulay Gromov_Hyperbolicity Group-Ring-Module HOL-CSP HOLCF-Prelude HRB-Slicing Heard_Of Hello_World HereditarilyFinite Hermite +Hermite_Lindemann Hidden_Markov_Models Higher_Order_Terms Hoare_Time Hood_Melville_Queue HotelKeyCards Huffman Hybrid_Logic Hybrid_Multi_Lane_Spatial_Logic Hybrid_Systems_VCs HyperCTL IEEE_Floating_Point IMAP-CRDT IMO2019 IMP2 IMP2_Binary_Heap IP_Addresses Imperative_Insertion_Sort Impossible_Geometry Incompleteness Incredible_Proof_Machine Inductive_Confidentiality Inductive_Inference InfPathElimination InformationFlowSlicing InformationFlowSlicing_Inter Integration Interpreter_Optimizations Interval_Arithmetic_Word32 Iptables_Semantics Irrational_Series_Erdos_Straus Irrationality_J_Hancl Isabelle_C Isabelle_Marries_Dirac Isabelle_Meta_Model IsaGeoCoq Jacobson_Basic_Algebra Jinja JinjaDCI JinjaThreads JiveDataStoreModel Jordan_Hoelder Jordan_Normal_Form KAD KAT_and_DRA KBPs KD_Tree Key_Agreement_Strong_Adversaries Kleene_Algebra Knuth_Bendix_Order Knot_Theory Knuth_Bendix_Order Knuth_Morris_Pratt Koenigsberg_Friendship Kruskal Kuratowski_Closure_Complement LLL_Basis_Reduction LLL_Factorization LOFT LTL LTL_Master_Theorem LTL_Normal_Form LTL_to_DRA LTL_to_GBA Lam-ml-Normalization LambdaAuth LambdaMu Lambda_Free_EPO Lambda_Free_KBOs Lambda_Free_RPOs Lambert_W Landau_Symbols Laplace_Transform Latin_Square LatticeProperties Launchbury Laws_of_Large_Numbers Lazy-Lists-II Lazy_Case Lehmer Lifting_Definition_Option LightweightJava LinearQuantifierElim Linear_Inequalities Linear_Programming Linear_Recurrences Liouville_Numbers List-Index List-Infinite List_Interleaving List_Inversions List_Update LocalLexing Localization_Ring Locally-Nameless-Sigma Lowe_Ontological_Argument Lower_Semicontinuous Lp Lucas_Theorem MFMC_Countable MFODL_Monitor_Optimized MFOTL_Monitor MSO_Regex_Equivalence Markov_Models Marriage Mason_Stothers Matrices_for_ODEs Matrix Matrix_Tensor Matroids Max-Card-Matching Median_Of_Medians_Selection Menger Mereology Mersenne_Primes MiniML Minimal_SSA Minkowskis_Theorem Minsky_Machines Modal_Logics_for_NTS Modular_Assembly_Kit_Security Monad_Memo_DP Monad_Normalisation MonoBoolTranAlgebra MonoidalCategory Monomorphic_Monad MuchAdoAboutTwo Multi_Party_Computation Multirelations Myhill-Nerode Name_Carrying_Type_Inference Nash_Williams Nat-Interval-Logic Native_Word Nested_Multisets_Ordinals Network_Security_Policy_Verification Neumann_Morgenstern_Utility No_FTL_observers Nominal2 Noninterference_CSP Noninterference_Concurrent_Composition Noninterference_Generic_Unwinding Noninterference_Inductive_Unwinding Noninterference_Ipurge_Unwinding Noninterference_Sequential_Composition NormByEval Nullstellensatz Octonions OpSets Open_Induction Optics Optimal_BST Orbit_Stabiliser Order_Lattice_Props Ordered_Resolution_Prover Ordinal Ordinal_Partitions Ordinals_and_Cardinals Ordinary_Differential_Equations PAC_Checker PCF PLM POPLmark-deBruijn PSemigroupsConvolution Pairing_Heap Paraconsistency Parity_Game Partial_Function_MR Partial_Order_Reduction Password_Authentication_Protocol Pell Perfect-Number-Thm Perron_Frobenius Physical_Quantities Pi_Calculus Pi_Transcendental Planarity_Certificates Poincare_Bendixson Poincare_Disc Polynomial_Factorization Polynomial_Interpolation Polynomials Pop_Refinement Posix-Lexing Possibilistic_Noninterference Power_Sum_Polynomials Pratt_Certificate Presburger-Automata Prim_Dijkstra_Simple Prime_Distribution_Elementary Prime_Harmonic_Series Prime_Number_Theorem Priority_Queue_Braun Priority_Search_Trees Probabilistic_Noninterference Probabilistic_Prime_Tests Probabilistic_System_Zoo Probabilistic_Timed_Automata Probabilistic_While Program-Conflict-Analysis Projective_Geometry Projective_Measurements Promela Proof_Strategy_Language PropResPI Propositional_Proof_Systems Prpu_Maxflow PseudoHoops Psi_Calculi Ptolemys_Theorem QHLProver QR_Decomposition Quantales Quaternions Quick_Sort_Cost RIPEMD-160-SPARK ROBDD RSAPSS Ramsey-Infinite Random_BSTs Random_Graph_Subgraph_Threshold Randomised_BSTs Randomised_Social_Choice Rank_Nullity_Theorem Real_Impl Recursion-Addition Recursion-Theory-I Refine_Imperative_HOL Refine_Monadic RefinementReactive Regex_Equivalence Regular-Sets Regular_Algebras Relation_Algebra Relational-Incorrectness-Logic Relational_Disjoint_Set_Forests Relational_Method Relational_Minimum_Spanning_Trees Relational_Paths Rep_Fin_Groups Residuated_Lattices Resolution_FOL Rewriting_Z Ribbon_Proofs Robbins-Conjecture Robinson_Arithmetic Root_Balanced_Tree Routing Roy_Floyd_Warshall SATSolverVerification SC_DOM_Components SDS_Impossibility SIFPL SIFUM_Type_Systems SPARCv8 Safe_Distance Safe_OCL Saturation_Framework Saturation_Framework_Extensions Shadow_DOM Secondary_Sylow Security_Protocol_Refinement Selection_Heap_Sort SenSocialChoice Separata Separation_Algebra Separation_Logic_Imperative_HOL SequentInvertibility Shadow_SC_DOM Shivers-CFA ShortestPath Show Sigma_Commit_Crypto Signature_Groebner Simpl Simple_Firewall Simplex Skew_Heap Skip_Lists Slicing Sliding_Window_Algorithm Smith_Normal_Form Smooth_Manifolds Sort_Encodings Source_Coding_Theorem Special_Function_Bounds Splay_Tree Sqrt_Babylonian Stable_Matching Statecharts Stateful_Protocol_Composition_and_Typing Stellar_Quorums Stern_Brocot Stewart_Apollonius Stirling_Formula Stochastic_Matrices Stone_Algebras Stone_Kleene_Relation_Algebras Stone_Relation_Algebras Store_Buffer_Reduction Stream-Fusion Stream_Fusion_Code Strong_Security Sturm_Sequences Sturm_Tarski Stuttering_Equivalence Subresultants Subset_Boolean_Algebras SumSquares Sunflowers SuperCalc Surprise_Paradox Symmetric_Polynomials Syntax_Independent_Logic Szpilrajn TESL_Language TLA Tail_Recursive_Functions Tarskis_Geometry Taylor_Models Timed_Automata Topological_Semantics Topology TortoiseHare Transcendence_Series_Hancl_Rucki Transformer_Semantics Transition_Systems_and_Automata Transitive-Closure Transitive-Closure-II Treaps Tree-Automata Tree_Decomposition Triangle Trie Twelvefold_Way Tycon Types_Tableaus_and_Goedels_God UPF UPF_Firewall UTP Universal_Turing_Machine UpDown_Scheme Valuation VectorSpace VeriComp Verified-Prover Verified_SAT_Based_AI_Planning VerifyThis2018 VerifyThis2019 Vickrey_Clarke_Groves VolpanoSmith WHATandWHERE_Security WOOT_Strong_Eventual_Consistency WebAssembly Weight_Balanced_Trees Well_Quasi_Orders Winding_Number_Eval Word_Lib WorkerWrapper XML ZFC_in_HOL Zeta_3_Irrational Zeta_Function pGCL