Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 7fdeecc

Browse files
chore(ring_theory/root_of_unity): move and split a file (#19144)
We split `ring_theory.roots_of_unity` (almost 1200 lines) into `ring_theory.roots_of_unity.basic` and `ring_theory.roots_of_unity.minpoly`. We also move `analysis.complex.roots_of_unity` to `ring_theory.roots_of_unity.complex`.
1 parent 3d5c4a7 commit 7fdeecc

File tree

8 files changed

+239
-213
lines changed

8 files changed

+239
-213
lines changed

archive/100-theorems-list/16_abel_ruffini.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Authors: Thomas Browning
66
import analysis.calculus.local_extr
77
import data.nat.prime_norm_num
88
import field_theory.abel_ruffini
9+
import ring_theory.roots_of_unity.minpoly
910
import ring_theory.eisenstein_criterion
1011

1112
/-!

archive/100-theorems-list/37_solution_of_cubic.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Jeoff Lee
55
-/
66
import tactic.linear_combination
7-
import ring_theory.roots_of_unity
87
import ring_theory.polynomial.cyclotomic.roots
98

109
/-!

src/field_theory/abel_ruffini.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Authors: Thomas Browning, Patrick Lutz
66

77
import group_theory.solvable
88
import field_theory.polynomial_galois_group
9-
import ring_theory.roots_of_unity
9+
import ring_theory.roots_of_unity.basic
1010

1111
/-!
1212
# The Abel-Ruffini Theorem

src/ring_theory/polynomial/cyclotomic/basic.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ Authors: Riccardo Brasca
66

77
import algebra.ne_zero
88
import algebra.polynomial.big_operators
9-
import analysis.complex.roots_of_unity
9+
import ring_theory.roots_of_unity.complex
1010
import data.polynomial.lifts
1111
import data.polynomial.splits
1212
import data.zmod.algebra
1313
import field_theory.ratfunc
1414
import field_theory.separable
1515
import number_theory.arithmetic_function
16-
import ring_theory.roots_of_unity
16+
import ring_theory.roots_of_unity.basic
1717

1818
/-!
1919
# Cyclotomic polynomials.

src/ring_theory/polynomial/cyclotomic/roots.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Authors: Riccardo Brasca
55
-/
66

77
import ring_theory.polynomial.cyclotomic.basic
8+
import ring_theory.roots_of_unity.minpoly
89

910
/-!
1011
# Roots of cyclotomic polynomials.

src/ring_theory/roots_of_unity.lean renamed to src/ring_theory/roots_of_unity/basic.lean

Lines changed: 0 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import algebra.ne_zero
99
import algebra.gcd_monoid.integrally_closed
1010
import data.polynomial.ring_division
1111
import field_theory.finite.basic
12-
import field_theory.minpoly.is_integrally_closed
1312
import field_theory.separable
1413
import group_theory.specific_groups.cyclic
1514
import number_theory.divisors
@@ -880,213 +879,6 @@ end
880879

881880
end is_domain
882881

883-
section minpoly
884-
885-
open minpoly
886-
887-
section comm_ring
888-
variables {n : ℕ} {K : Type*} [comm_ring K] {μ : K} (h : is_primitive_root μ n) (hpos : 0 < n)
889-
890-
include n μ h hpos
891-
892-
/--`μ` is integral over `ℤ`. -/
893-
lemma is_integral : is_integral ℤ μ :=
894-
begin
895-
use (X ^ n - 1),
896-
split,
897-
{ exact (monic_X_pow_sub_C 1 (ne_of_lt hpos).symm) },
898-
{ simp only [((is_primitive_root.iff_def μ n).mp h).left, eval₂_one, eval₂_X_pow, eval₂_sub,
899-
sub_self] }
900-
end
901-
902-
section is_domain
903-
904-
variables [is_domain K] [char_zero K]
905-
906-
omit hpos
907-
908-
/--The minimal polynomial of a root of unity `μ` divides `X ^ n - 1`. -/
909-
lemma minpoly_dvd_X_pow_sub_one : minpoly ℤ μ ∣ X ^ n - 1 :=
910-
begin
911-
rcases n.eq_zero_or_pos with rfl | hpos,
912-
{ simp },
913-
letI : is_integrally_closed ℤ := gcd_monoid.to_is_integrally_closed,
914-
apply minpoly.is_integrally_closed_dvd (is_integral h hpos),
915-
simp only [((is_primitive_root.iff_def μ n).mp h).left, aeval_X_pow, eq_int_cast,
916-
int.cast_one, aeval_one, alg_hom.map_sub, sub_self]
917-
end
918-
919-
/-- The reduction modulo `p` of the minimal polynomial of a root of unity `μ` is separable. -/
920-
lemma separable_minpoly_mod {p : ℕ} [fact p.prime] (hdiv : ¬p ∣ n) :
921-
separable (map (int.cast_ring_hom (zmod p)) (minpoly ℤ μ)) :=
922-
begin
923-
have hdvd : (map (int.cast_ring_hom (zmod p))
924-
(minpoly ℤ μ)) ∣ X ^ n - 1,
925-
{ simpa [polynomial.map_pow, map_X, polynomial.map_one, polynomial.map_sub] using
926-
ring_hom.map_dvd (map_ring_hom (int.cast_ring_hom (zmod p)))
927-
(minpoly_dvd_X_pow_sub_one h) },
928-
refine separable.of_dvd (separable_X_pow_sub_C 1 _ one_ne_zero) hdvd,
929-
by_contra hzero,
930-
exact hdiv ((zmod.nat_coe_zmod_eq_zero_iff_dvd n p).1 hzero)
931-
end
932-
933-
/-- The reduction modulo `p` of the minimal polynomial of a root of unity `μ` is squarefree. -/
934-
lemma squarefree_minpoly_mod {p : ℕ} [fact p.prime] (hdiv : ¬ p ∣ n) :
935-
squarefree (map (int.cast_ring_hom (zmod p)) (minpoly ℤ μ)) :=
936-
(separable_minpoly_mod h hdiv).squarefree
937-
938-
/- Let `P` be the minimal polynomial of a root of unity `μ` and `Q` be the minimal polynomial of
939-
`μ ^ p`, where `p` is a natural number that does not divide `n`. Then `P` divides `expand ℤ p Q`. -/
940-
lemma minpoly_dvd_expand {p : ℕ} (hdiv : ¬ p ∣ n) : minpoly ℤ μ ∣ expand ℤ p (minpoly ℤ (μ ^ p)) :=
941-
begin
942-
rcases n.eq_zero_or_pos with rfl | hpos,
943-
{ simp * at *, },
944-
letI : is_integrally_closed ℤ := gcd_monoid.to_is_integrally_closed,
945-
refine minpoly.is_integrally_closed_dvd (h.is_integral hpos) _,
946-
{ rw [aeval_def, coe_expand, ← comp, eval₂_eq_eval_map, map_comp, polynomial.map_pow, map_X,
947-
eval_comp, eval_pow, eval_X, ← eval₂_eq_eval_map, ← aeval_def],
948-
exact minpoly.aeval _ _ }
949-
end
950-
951-
/- Let `P` be the minimal polynomial of a root of unity `μ` and `Q` be the minimal polynomial of
952-
`μ ^ p`, where `p` is a prime that does not divide `n`. Then `P` divides `Q ^ p` modulo `p`. -/
953-
lemma minpoly_dvd_pow_mod {p : ℕ} [hprime : fact p.prime] (hdiv : ¬ p ∣ n) :
954-
map (int.cast_ring_hom (zmod p)) (minpoly ℤ μ) ∣
955-
map (int.cast_ring_hom (zmod p)) (minpoly ℤ (μ ^ p)) ^ p :=
956-
begin
957-
set Q := minpoly ℤ (μ ^ p),
958-
have hfrob : map (int.cast_ring_hom (zmod p)) Q ^ p =
959-
map (int.cast_ring_hom (zmod p)) (expand ℤ p Q),
960-
by rw [← zmod.expand_card, map_expand],
961-
rw [hfrob],
962-
apply ring_hom.map_dvd (map_ring_hom (int.cast_ring_hom (zmod p))),
963-
exact minpoly_dvd_expand h hdiv
964-
end
965-
966-
/- Let `P` be the minimal polynomial of a root of unity `μ` and `Q` be the minimal polynomial of
967-
`μ ^ p`, where `p` is a prime that does not divide `n`. Then `P` divides `Q` modulo `p`. -/
968-
lemma minpoly_dvd_mod_p {p : ℕ} [hprime : fact p.prime] (hdiv : ¬ p ∣ n) :
969-
map (int.cast_ring_hom (zmod p)) (minpoly ℤ μ) ∣
970-
map (int.cast_ring_hom (zmod p)) (minpoly ℤ (μ ^ p)) :=
971-
(unique_factorization_monoid.dvd_pow_iff_dvd_of_squarefree (squarefree_minpoly_mod h
972-
hdiv) hprime.1.ne_zero).1 (minpoly_dvd_pow_mod h hdiv)
973-
974-
/-- If `p` is a prime that does not divide `n`,
975-
then the minimal polynomials of a primitive `n`-th root of unity `μ`
976-
and of `μ ^ p` are the same. -/
977-
lemma minpoly_eq_pow {p : ℕ} [hprime : fact p.prime] (hdiv : ¬ p ∣ n) :
978-
minpoly ℤ μ = minpoly ℤ (μ ^ p) :=
979-
begin
980-
by_cases hn : n = 0, { simp * at *, },
981-
have hpos := nat.pos_of_ne_zero hn,
982-
by_contra hdiff,
983-
set P := minpoly ℤ μ,
984-
set Q := minpoly ℤ (μ ^ p),
985-
have Pmonic : P.monic := minpoly.monic (h.is_integral hpos),
986-
have Qmonic : Q.monic := minpoly.monic ((h.pow_of_prime hprime.1 hdiv).is_integral hpos),
987-
have Pirr : irreducible P := minpoly.irreducible (h.is_integral hpos),
988-
have Qirr : irreducible Q :=
989-
minpoly.irreducible ((h.pow_of_prime hprime.1 hdiv).is_integral hpos),
990-
have PQprim : is_primitive (P * Q) := Pmonic.is_primitive.mul Qmonic.is_primitive,
991-
have prod : P * Q ∣ X ^ n - 1,
992-
{ rw [(is_primitive.int.dvd_iff_map_cast_dvd_map_cast (P * Q) (X ^ n - 1) PQprim
993-
(monic_X_pow_sub_C (1 : ℤ) (ne_of_gt hpos)).is_primitive), polynomial.map_mul],
994-
refine is_coprime.mul_dvd _ _ _,
995-
{ have aux := is_primitive.int.irreducible_iff_irreducible_map_cast Pmonic.is_primitive,
996-
refine (dvd_or_coprime _ _ (aux.1 Pirr)).resolve_left _,
997-
rw map_dvd_map (int.cast_ring_hom ℚ) int.cast_injective Pmonic,
998-
intro hdiv,
999-
refine hdiff (eq_of_monic_of_associated Pmonic Qmonic _),
1000-
exact associated_of_dvd_dvd hdiv (Pirr.dvd_symm Qirr hdiv) },
1001-
{ apply (map_dvd_map (int.cast_ring_hom ℚ) int.cast_injective Pmonic).2,
1002-
exact minpoly_dvd_X_pow_sub_one h },
1003-
{ apply (map_dvd_map (int.cast_ring_hom ℚ) int.cast_injective Qmonic).2,
1004-
exact minpoly_dvd_X_pow_sub_one (pow_of_prime h hprime.1 hdiv) } },
1005-
replace prod := ring_hom.map_dvd ((map_ring_hom (int.cast_ring_hom (zmod p)))) prod,
1006-
rw [coe_map_ring_hom, polynomial.map_mul, polynomial.map_sub,
1007-
polynomial.map_one, polynomial.map_pow, map_X] at prod,
1008-
obtain ⟨R, hR⟩ := minpoly_dvd_mod_p h hdiv,
1009-
rw [hR, ← mul_assoc, ← polynomial.map_mul, ← sq, polynomial.map_pow] at prod,
1010-
have habs : map (int.cast_ring_hom (zmod p)) P ^ 2 ∣ map (int.cast_ring_hom (zmod p)) P ^ 2 * R,
1011-
{ use R },
1012-
replace habs := lt_of_lt_of_le (part_enat.coe_lt_coe.2 one_lt_two)
1013-
(multiplicity.le_multiplicity_of_pow_dvd (dvd_trans habs prod)),
1014-
have hfree : squarefree (X ^ n - 1 : (zmod p)[X]),
1015-
{ exact (separable_X_pow_sub_C 1
1016-
(λ h, hdiv $ (zmod.nat_coe_zmod_eq_zero_iff_dvd n p).1 h) one_ne_zero).squarefree },
1017-
cases (multiplicity.squarefree_iff_multiplicity_le_one (X ^ n - 1)).1 hfree
1018-
(map (int.cast_ring_hom (zmod p)) P) with hle hunit,
1019-
{ rw nat.cast_one at habs, exact hle.not_lt habs },
1020-
{ replace hunit := degree_eq_zero_of_is_unit hunit,
1021-
rw degree_map_eq_of_leading_coeff_ne_zero (int.cast_ring_hom (zmod p)) _ at hunit,
1022-
{ exact (minpoly.degree_pos (is_integral h hpos)).ne' hunit },
1023-
simp only [Pmonic, eq_int_cast, monic.leading_coeff, int.cast_one, ne.def,
1024-
not_false_iff, one_ne_zero] }
1025-
end
1026-
1027-
/-- If `m : ℕ` is coprime with `n`,
1028-
then the minimal polynomials of a primitive `n`-th root of unity `μ`
1029-
and of `μ ^ m` are the same. -/
1030-
lemma minpoly_eq_pow_coprime {m : ℕ} (hcop : nat.coprime m n) :
1031-
minpoly ℤ μ = minpoly ℤ (μ ^ m) :=
1032-
begin
1033-
revert n hcop,
1034-
refine unique_factorization_monoid.induction_on_prime m _ _ _,
1035-
{ intros n hn h,
1036-
congr,
1037-
simpa [(nat.coprime_zero_left n).mp hn] using h },
1038-
{ intros u hunit n hcop h,
1039-
congr,
1040-
simp [nat.is_unit_iff.mp hunit] },
1041-
{ intros a p ha hprime hind n hcop h,
1042-
rw hind (nat.coprime.coprime_mul_left hcop) h, clear hind,
1043-
replace hprime := hprime.nat_prime,
1044-
have hdiv := (nat.prime.coprime_iff_not_dvd hprime).1 (nat.coprime.coprime_mul_right hcop),
1045-
haveI := fact.mk hprime,
1046-
rw [minpoly_eq_pow (h.pow_of_coprime a (nat.coprime.coprime_mul_left hcop)) hdiv],
1047-
congr' 1,
1048-
ring_exp }
1049-
end
1050-
1051-
/-- If `m : ℕ` is coprime with `n`,
1052-
then the minimal polynomial of a primitive `n`-th root of unity `μ`
1053-
has `μ ^ m` as root. -/
1054-
lemma pow_is_root_minpoly {m : ℕ} (hcop : nat.coprime m n) :
1055-
is_root (map (int.cast_ring_hom K) (minpoly ℤ μ)) (μ ^ m) :=
1056-
by simpa [minpoly_eq_pow_coprime h hcop, eval_map, aeval_def (μ ^ m) _]
1057-
using minpoly.aeval ℤ (μ ^ m)
1058-
1059-
/-- `primitive_roots n K` is a subset of the roots of the minimal polynomial of a primitive
1060-
`n`-th root of unity `μ`. -/
1061-
lemma is_roots_of_minpoly : primitive_roots n K ⊆ (map (int.cast_ring_hom K)
1062-
(minpoly ℤ μ)).roots.to_finset :=
1063-
begin
1064-
by_cases hn : n = 0, { simp * at *, },
1065-
have hpos := nat.pos_of_ne_zero hn,
1066-
intros x hx,
1067-
obtain ⟨m, hle, hcop, rfl⟩ := (is_primitive_root_iff h hpos).1 ((mem_primitive_roots hpos).1 hx),
1068-
simpa [multiset.mem_to_finset,
1069-
mem_roots (map_monic_ne_zero $ minpoly.monic $ is_integral h hpos)]
1070-
using pow_is_root_minpoly h hcop
1071-
end
1072-
1073-
/-- The degree of the minimal polynomial of `μ` is at least `totient n`. -/
1074-
lemma totient_le_degree_minpoly : nat.totient n ≤ (minpoly ℤ μ).nat_degree :=
1075-
let P : ℤ[X] := minpoly ℤ μ,-- minimal polynomial of `μ`
1076-
P_K : K[X] := map (int.cast_ring_hom K) P -- minimal polynomial of `μ` sent to `K[X]`
1077-
in calc
1078-
n.totient = (primitive_roots n K).card : h.card_primitive_roots.symm
1079-
... ≤ P_K.roots.to_finset.card : finset.card_le_of_subset (is_roots_of_minpoly h)
1080-
... ≤ P_K.roots.card : multiset.to_finset_card_le _
1081-
... ≤ P_K.nat_degree : card_roots' _
1082-
... ≤ P.nat_degree : nat_degree_map_le _ _
1083-
1084-
end is_domain
1085-
1086-
end comm_ring
1087-
1088-
end minpoly
1089-
1090882
section automorphisms
1091883

1092884
variables {S} [comm_ring S] [is_domain S] {μ : S} {n : ℕ+} (hμ : is_primitive_root μ n)

src/analysis/complex/roots_of_unity.lean renamed to src/ring_theory/roots_of_unity/complex.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Johan Commelin
55
-/
66
import analysis.special_functions.complex.log
7-
import ring_theory.roots_of_unity
7+
import ring_theory.roots_of_unity.basic
88

99
/-!
1010
# Complex roots of unity

0 commit comments

Comments
 (0)