Skip to content

Commit 5f9f01c

Browse files
committed
feat: strengthen Cayley-Hamilton (#37872)
* Strengthen the statement of Cayley-Hamilton to bound the degree of the annihilating polynomial by the number of generators * Generalise `minpoly.natDegree_le` to non-free modules: `minpoly.natDegree_le_spanFinrank`
1 parent 2c53994 commit 5f9f01c

File tree

13 files changed

+114
-51
lines changed

13 files changed

+114
-51
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4395,6 +4395,7 @@ public import Mathlib.FieldTheory.LinearDisjoint
43954395
public import Mathlib.FieldTheory.Minpoly.Basic
43964396
public import Mathlib.FieldTheory.Minpoly.ConjRootClass
43974397
public import Mathlib.FieldTheory.Minpoly.Field
4398+
public import Mathlib.FieldTheory.Minpoly.Finite
43984399
public import Mathlib.FieldTheory.Minpoly.IsConjRoot
43994400
public import Mathlib.FieldTheory.Minpoly.IsIntegrallyClosed
44004401
public import Mathlib.FieldTheory.Minpoly.MinpolyDiv

Mathlib/Algebra/Module/SpanRank.lean

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,15 @@ theorem FG.exists_span_set_encard_eq_spanFinrank {p : Submodule R M} (h : p.FG)
189189
rw [Set.encard, ENat.card, spanFinrank, hs₁, this]
190190
simp
191191

192+
/-- Constructs a generating finset with cardinality equal to the `spanFinrank` of the submodule
193+
when the submodule is finitely generated. -/
194+
theorem FG.exists_span_finset_card_eq_spanFinrank {p : Submodule R M} (h : p.FG) :
195+
∃ s : Finset M, s.card = p.spanFinrank ∧ span R s = p := by
196+
obtain ⟨s, ⟨hs₁, hs₂⟩⟩ := exists_span_set_encard_eq_spanFinrank h
197+
have s_f := Set.finite_of_encard_eq_coe hs₁
198+
refine ⟨s_f.toFinset, ⟨?_, by simpa using hs₂⟩⟩
199+
simpa [s_f.encard_eq_coe_toFinset_card, ENat.coe_inj] using hs₁
200+
192201
lemma lift_spanRank_le_iff_exists_span_set_card_le (p : Submodule R M) {a : Cardinal.{max u v}} :
193202
Cardinal.lift.{v} p.spanRank ≤ a ↔ ∃ s : Set M, Cardinal.lift.{v} #s ≤ a ∧ span R s = p := by
194203
constructor
@@ -220,6 +229,15 @@ lemma spanRank_bot : (⊥ : Ideal R).spanRank = 0 := Submodule.spanRank_eq_zero_
220229
@[simp]
221230
lemma spanFinrank_bot : (⊥ : Submodule R M).spanFinrank = 0 := by simp [spanFinrank]
222231

232+
@[nontriviality]
233+
lemma spanRank_subsingleton [Subsingleton R] (p : Submodule R M) : p.spanRank = 0 := by
234+
simp [nontriviality]
235+
236+
@[nontriviality]
237+
lemma spanFinrank_subsingleton [Subsingleton R] (p : Submodule R M) : p.spanFinrank = 0 := by
238+
have := Module.subsingleton R M
239+
simp [Submodule.eq_bot_of_subsingleton]
240+
223241
/-- Generating elements for the submodule of minimum cardinality. -/
224242
noncomputable def generators (p : Submodule R M) : Set M :=
225243
Classical.choose (exists_span_set_card_eq_spanRank p)

Mathlib/Analysis/Complex/Polynomial/Basic.lean

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ public import Mathlib.Analysis.Complex.Liouville
1010
public import Mathlib.FieldTheory.PolynomialGaloisGroup
1111
public import Mathlib.LinearAlgebra.Complex.FiniteDimensional
1212
public import Mathlib.Topology.Algebra.Polynomial
13-
public import Mathlib.LinearAlgebra.Charpoly.Basic
1413

1514
/-!
1615
# The fundamental theorem of algebra
@@ -199,7 +198,7 @@ lemma Irreducible.natDegree_le_two {p : ℝ[X]} (hp : Irreducible p) : natDegree
199198
obtain ⟨z, hz⟩ : ∃ z : ℂ, aeval z p = 0 :=
200199
IsAlgClosed.exists_aeval_eq_zero _ p (degree_pos_of_irreducible hp).ne'
201200
rw [← finrank_real_complex]
202-
suffices p.natDegree = (minpoly ℝ z).natDegree from this ▸ minpoly.natDegree_le (R := ℝ) z
201+
suffices p.natDegree = (minpoly ℝ z).natDegree from this ▸ minpoly.natDegree_le (A := ℝ) z
203202
rw [← minpoly.eq_of_irreducible hp hz, natDegree_mul hp.ne_zero (by simpa using hp.ne_zero),
204203
natDegree_C, add_zero]
205204

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/-
2+
Copyright (c) 2026 Artie Khovanov. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Artie Khovanov
5+
-/
6+
module
7+
8+
public import Mathlib.FieldTheory.Minpoly.Basic
9+
public import Mathlib.LinearAlgebra.Matrix.Charpoly.LinearMap
10+
public import Mathlib.RingTheory.FiniteType
11+
12+
/-!
13+
# Minimal polynomials on a finite algebra
14+
15+
This file proves the bound on the degree of a minimal polynomial on an algebra that is finite as a module.
16+
17+
-/
18+
19+
@[expose] public section
20+
21+
variable {A B : Type*} [CommRing A] [Ring B] [Algebra A B] [Module.Finite A B] (x : B)
22+
23+
open Polynomial
24+
25+
namespace minpoly
26+
27+
variable (A) in
28+
theorem natDegree_le_spanFinrank :
29+
(minpoly A x).natDegree ≤ (⊤ : Submodule A B).spanFinrank := by
30+
rcases LinearMap.exists_monic_and_natDegree_eq_and_aeval_eq_zero _ (Algebra.lmul A _ x) with
31+
⟨f, f_monic, f_deg, f_aeval⟩
32+
refine f_deg ▸ (natDegree_le_natDegree <| minpoly.min _ _ f_monic ?_)
33+
rw [aeval_algHom_apply] at f_aeval
34+
exact Algebra.lmul_injective (R := A) <| by simpa using f_aeval
35+
36+
theorem natDegree_le [Module.Free A B] : (minpoly A x).natDegree ≤ Module.finrank A B := by
37+
nontriviality A
38+
simpa [Module.finrank_eq_spanFinrank_of_free] using natDegree_le_spanFinrank A x
39+
40+
theorem degree_le [Module.Free A B] : (minpoly A x).degree ≤ Module.finrank A B :=
41+
degree_le_of_natDegree_le <| natDegree_le x
42+
43+
end minpoly

Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ Authors: Andrew Yang
55
-/
66
module
77

8+
public import Mathlib.FieldTheory.Minpoly.Finite
89
public import Mathlib.FieldTheory.Minpoly.IsIntegrallyClosed
910
public import Mathlib.FieldTheory.PrimitiveElement
10-
public import Mathlib.FieldTheory.IsAlgClosed.Basic
11-
public import Mathlib.LinearAlgebra.Charpoly.Basic
1211

1312
/-!
1413
# Results about `minpoly R x / (X - C x)`

Mathlib/FieldTheory/Normal/Basic.lean

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ Authors: Kenny Lau, Thomas Browning, Patrick Lutz
66
module
77

88
public import Mathlib.FieldTheory.Extension
9-
public import Mathlib.FieldTheory.Normal.Defs
10-
public import Mathlib.GroupTheory.Solvable
9+
public import Mathlib.FieldTheory.Minpoly.Finite
1110
public import Mathlib.FieldTheory.SplittingField.Construction
12-
public import Mathlib.LinearAlgebra.Charpoly.Basic
11+
public import Mathlib.GroupTheory.Solvable
1312

1413
/-!
1514
# Normal field extensions

Mathlib/FieldTheory/PurelyInseparable/Exponent.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ Authors: Michal Staromiejski
66
module
77

88
public import Mathlib.FieldTheory.PurelyInseparable.Basic
9-
public import Mathlib.LinearAlgebra.Charpoly.Basic
109

1110
/-!
1211

Mathlib/LinearAlgebra/Charpoly/Basic.lean

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ Authors: Riccardo Brasca
55
-/
66
module
77

8-
public import Mathlib.LinearAlgebra.FreeModule.Finite.Basic
9-
public import Mathlib.LinearAlgebra.Matrix.Charpoly.Coeff
10-
public import Mathlib.LinearAlgebra.Determinant
118
public import Mathlib.FieldTheory.Minpoly.Field
9+
public import Mathlib.LinearAlgebra.Determinant
1210

1311
/-!
1412
@@ -144,16 +142,4 @@ theorem Algebra.aeval_self_charpoly_lmul (α : M) :
144142
Algebra.lmul_injective (R := R) <| by
145143
simpa [← aeval_algHom_apply] using LinearMap.aeval_self_charpoly <| Algebra.lmul _ _ α
146144

147-
theorem minpoly.natDegree_le (α : M) :
148-
(minpoly R α).natDegree ≤ Module.finrank R M := by
149-
nontriviality R
150-
let f := Algebra.lmul R _ α
151-
have : (minpoly R α).natDegree ≤ f.charpoly.natDegree := natDegree_le_natDegree <|
152-
minpoly.min _ _ f.charpoly_monic (Algebra.aeval_self_charpoly_lmul α)
153-
simpa [← (Algebra.lmul _ _ α).charpoly_natDegree]
154-
155-
theorem minpoly.degree_le (α : M) :
156-
(minpoly R α).degree ≤ Module.finrank R M :=
157-
degree_le_of_natDegree_le (minpoly.natDegree_le α)
158-
159145
end Algebra

Mathlib/LinearAlgebra/Matrix/Charpoly/LinearMap.lean

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module
77

88
public import Mathlib.LinearAlgebra.Matrix.Charpoly.Coeff
99
public import Mathlib.LinearAlgebra.Matrix.ToLin
10+
public import Mathlib.Algebra.Module.SpanRank
1011

1112
/-!
1213
@@ -198,34 +199,46 @@ theorem Matrix.isRepresentation.toEnd_surjective :
198199
end
199200

200201
/-- The **Cayley-Hamilton Theorem** for f.g. modules over arbitrary rings states that for each
201-
`R`-endomorphism `φ` of an `R`-module `M` such that `φ(M) ≤ I • M` for some ideal `I`, there
202-
exists some `n` and some `aᵢ ∈ Iⁱ` such that `φⁿ + a₁ φⁿ⁻¹ + ⋯ + aₙ = 0`.
202+
`R`-endomorphism `φ` of an `R`-module `M` generated by `n` elements such that `φ(M) ≤ I • M`
203+
for some ideal `I`, there exist some `aᵢ ∈ Iⁱ` such that `φⁿ + a₁ φⁿ⁻¹ + ⋯ + aₙ = 0`.
203204
204-
This is the version found in Eisenbud 4.3, which is slightly weaker than Matsumura 2.1
205-
(this lacks the constraint on `n`), and is slightly stronger than Atiyah-Macdonald 2.4.
205+
This is the version in [Matsumura 2.1][matsumura1987], which is stronger than those in
206+
[Eisenbud 4.3][Eisenbud1995] and [Atiyah-Macdonald 2.4][atiyah-macdonald].
206207
-/
207-
theorem LinearMap.exists_monic_and_coeff_mem_pow_and_aeval_eq_zero_of_range_le_smul
208+
theorem LinearMap.exists_monic_and_natDegree_eq_and_coeff_mem_pow_and_aeval_eq_zero
208209
[Module.Finite R M] (f : Module.End R M) (I : Ideal R) (hI : LinearMap.range f ≤ I • ⊤) :
209-
∃ p : R[X], p.Monic ∧ (∀ k, p.coeff k ∈ I ^ (p.natDegree - k)) ∧ Polynomial.aeval f p = 0 := by
210+
∃ p : R[X], p.Monic ∧ p.natDegree = (⊤ : Submodule R M).spanFinrank ∧
211+
(∀ k, p.coeff k ∈ I ^ (p.natDegree - k)) ∧ Polynomial.aeval f p = 0 := by
210212
classical
211213
cases subsingleton_or_nontrivial R
212-
· exact ⟨0, Polynomial.monic_of_subsingleton _, by simp⟩
213-
obtain ⟨s : Finset M, hs : Submodule.span R (s : Set M) = ⊤⟩ :=
214-
Module.Finite.fg_top (R := R) (M := M)
215-
have : Submodule.span R (Set.range ((↑) : { x // x ∈ s } → M)) = ⊤ := by
216-
rw [Subtype.range_coe_subtype, Finset.setOf_mem, hs]
217-
obtain ⟨A, rfl, h⟩ :=
218-
Matrix.isRepresentation.toEnd_exists_mem_ideal R ((↑) : s → M) this f I hI
219-
refine ⟨A.1.charpoly, A.1.charpoly_monic, ?_, ?_⟩
220-
· rw [A.1.charpoly_natDegree_eq_dim]
221-
exact coeff_charpoly_mem_ideal_pow h
222-
· rw [Polynomial.aeval_algHom_apply,
223-
← map_zero (Matrix.isRepresentation.toEnd R ((↑) : s → M) this)]
224-
congr 1
225-
ext1
226-
rw [Polynomial.aeval_subalgebra_coe, Matrix.aeval_self_charpoly, Subalgebra.coe_zero]
214+
· exact ⟨0, by simp [nontriviality]⟩
215+
obtain ⟨s, hs_card, hs_span⟩ :=
216+
Submodule.FG.exists_span_finset_card_eq_spanFinrank (R := R) (M := M) Module.Finite.fg_top
217+
have : Submodule.span R (Set.range ((↑) : s → M)) = ⊤ := by simp [hs_span]
218+
obtain ⟨A, rfl, h⟩ := Matrix.isRepresentation.toEnd_exists_mem_ideal R ((↑) : s → M) this f I hI
219+
refine ⟨A.1.charpoly, A.1.charpoly_monic, by simp [hs_card],
220+
by simpa using coeff_charpoly_mem_ideal_pow h, ?_⟩
221+
rw [Polynomial.aeval_algHom_apply,
222+
← map_zero (Matrix.isRepresentation.toEnd R ((↑) : s → M) this)]
223+
congr 1
224+
ext1
225+
rw [Polynomial.aeval_subalgebra_coe, Matrix.aeval_self_charpoly, Subalgebra.coe_zero]
226+
227+
@[deprecated
228+
"strengthened conclusion to
229+
`LinearMap.exists_monic_and_natDegree_eq_and_coeff_mem_pow_and_aeval_eq_zero`"
230+
(since := "2026-04-10")] alias
231+
LinearMap.exists_monic_and_coeff_mem_pow_and_aeval_eq_zero_of_range_le_smul :=
232+
LinearMap.exists_monic_and_natDegree_eq_and_coeff_mem_pow_and_aeval_eq_zero
233+
234+
theorem LinearMap.exists_monic_and_natDegree_eq_and_aeval_eq_zero
235+
[Module.Finite R M] (f : Module.End R M) :
236+
∃ p : R[X], p.Monic ∧ p.natDegree = (⊤ : Submodule R M).spanFinrank ∧
237+
Polynomial.aeval f p = 0 :=
238+
(LinearMap.exists_monic_and_natDegree_eq_and_coeff_mem_pow_and_aeval_eq_zero R f ⊤ (by simp)).imp
239+
fun _ h ↦ h.imp_right (And.imp_right And.right)
227240

228241
theorem LinearMap.exists_monic_and_aeval_eq_zero [Module.Finite R M] (f : Module.End R M) :
229242
∃ p : R[X], p.Monic ∧ Polynomial.aeval f p = 0 :=
230-
(LinearMap.exists_monic_and_coeff_mem_pow_and_aeval_eq_zero_of_range_le_smul R f ⊤ (by simp)).imp
243+
(LinearMap.exists_monic_and_natDegree_eq_and_aeval_eq_zero R f).imp
231244
fun _ h => h.imp_right And.right

Mathlib/NumberTheory/NumberField/InfinitePlace/Embeddings.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ module
88
public import Mathlib.Algebra.Algebra.Hom.Rat
99
public import Mathlib.Analysis.Complex.Polynomial.Basic
1010
public import Mathlib.NumberTheory.NumberField.Basic
11-
public import Mathlib.LinearAlgebra.Charpoly.Basic
1211

1312
/-!
1413
# Embeddings of number fields

0 commit comments

Comments
 (0)