From 23cbc1d8f1a50299ce32056633f263ef7e8c5838 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sat, 4 Apr 2026 00:31:36 +0100 Subject: [PATCH 01/61] save --- Mathlib.lean | 2 + Mathlib/NumberTheory/ModularForms/Basic.lean | 24 +++++ .../ModularForms/CongruenceSubgroups.lean | 4 + .../ModularForms/Discriminant.lean | 87 ++++++++++++++++++- .../ModularForms/EisensteinSeries/Basic.lean | 7 +- .../EisensteinSeries/QExpansion.lean | 7 +- .../NumberTheory/ModularForms/LevelOne.lean | 8 +- 7 files changed, 131 insertions(+), 8 deletions(-) diff --git a/Mathlib.lean b/Mathlib.lean index 293afedbdf27b2..c8637a2c3d8cc8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5578,6 +5578,7 @@ public import Mathlib.NumberTheory.ModularForms.Basic public import Mathlib.NumberTheory.ModularForms.BoundedAtCusp public import Mathlib.NumberTheory.ModularForms.Bounds public import Mathlib.NumberTheory.ModularForms.CongruenceSubgroups +public import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta @@ -5600,6 +5601,7 @@ public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold public import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable public import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.NormTrace public import Mathlib.NumberTheory.ModularForms.Petersson public import Mathlib.NumberTheory.ModularForms.QExpansion diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index daff18550bed69..3100c9f841d33d 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -370,6 +370,18 @@ lemma coe_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : lemma toSlashInvariantForm_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : (z : ModularForm Γ 0).toSlashInvariantForm = z := rfl +/-- Transport a modular form along an equality of subgroups. -/ +def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) : + ModularForm Γ' k where + toFun := f + slash_action_eq' A hA := f.slash_action_eq' A (h ▸ hA) + holo' := f.holo' + bdd_at_cusps' hc := f.bdd_at_cusps' (h ▸ hc) + +@[simp] +lemma ofSubgroupEq_apply {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) + (z : ℍ) : (f.ofSubgroupEq h) z = f z := rfl + end ModularForm namespace CuspForm @@ -504,6 +516,18 @@ instance (priority := 99) [FunLike F ℍ ℂ] [CuspFormClass F Γ k] : ModularFo holo := CuspFormClass.holo bdd_at_cusps f _ hc g hg := (CuspFormClass.zero_at_cusps f hc g hg).boundedAtFilter +/-- Transport a cusp form along an equality of subgroups. -/ +def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : CuspForm Γ k) : + CuspForm Γ' k where + toFun := f + slash_action_eq' A hA := f.slash_action_eq' A (h ▸ hA) + holo' := f.holo' + zero_at_cusps' hc := f.zero_at_cusps' (h ▸ hc) + +@[simp] +lemma ofSubgroupEq_apply {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : CuspForm Γ k) + (z : ℍ) : (f.ofSubgroupEq h) z = f z := rfl + end CuspForm namespace ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean b/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean index c2e8ed6841c1f1..bda2a576528cb1 100644 --- a/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean +++ b/Mathlib/NumberTheory/ModularForms/CongruenceSubgroups.lean @@ -69,6 +69,10 @@ theorem Gamma_one_top : Gamma 1 = ⊤ := by lemma mem_Gamma_one (γ : SL(2, ℤ)) : γ ∈ Γ(1) := by simp only [Gamma_one_top, Subgroup.mem_top] +/-- The GL-image of `Γ(1)` equals `𝒮ℒ` (the image of `SL(2, ℤ)` in `GL(2, ℝ)`). -/ +theorem Gamma_one_coe_eq_SL : (↑(Gamma 1) : Subgroup (GL (Fin 2) ℝ)) = 𝒮ℒ := by + change (Gamma 1).map (mapGL ℝ) = (mapGL ℝ).range; rw [Gamma_one_top, MonoidHom.range_eq_map] + theorem Gamma_zero_bot : Gamma 0 = ⊥ := rfl lemma ModularGroup_T_pow_mem_Gamma (N M : ℤ) (hNM : N ∣ M) : diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 6861c50bb5bb92..fbca87f567f656 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -11,6 +11,7 @@ public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Basic public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.E2.Transform public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.QExpansion /-! # The modular discriminant Δ @@ -35,7 +36,8 @@ be expressed as `q * ∏' (1 - q ^ (n + 1)) ^ 24` where `q = e ^ (2πiz)`. * [F. Diamond and J. Shurman, *A First Course in Modular Forms*][diamondshurman2005], section 1.2 -/ -open Function Complex Topology Filter SlashInvariantForm CongruenceSubgroup MatrixGroups +open Function Complex Topology Filter SlashInvariantForm SlashInvariantFormClass + CongruenceSubgroup MatrixGroups ModularFormClass open UpperHalfPlane hiding I @@ -192,6 +194,89 @@ def discriminantCuspForm : CuspForm 𝒮ℒ 12 where rw [slash_action_generators_SL2Z discriminant_S_invariant discriminant_T_invariant] exact discriminant_isZeroAtImInfty +/-- The infinite product `∏ (1 - q^(n+1))` is multipliable for `‖q‖ < 1`. -/ +private lemma multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1) : + Multipliable fun i ↦ 1 - q ^ (i + 1) := by + rw [show (fun i ↦ 1 - q ^ (i + 1)) = (fun i ↦ 1 + (-q ^ (i + 1))) from by ext; ring] + apply multipliable_one_add_of_summable + simp only [norm_neg, norm_pow] + exact (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) + +/-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` +on `ball 0 (1/2)`. -/ +private lemma discriminant_cuspFunction_eqOn : + Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + intro q hq + by_cases hq0 : q = 0 + · simp only [hq0, zero_mul] + exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos + discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex + · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) + have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 + rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, + comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] + -- eta_q n z = (qParam 1 z)^(n+1), and qParam(invQParam(q)) = q + have hqr := Periodic.qParam_right_inv one_ne_zero hq0 + have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by + simp [eta_q, hqr] + simp only [hqr, heta] + +/-- The partial products `∏_{i simp [differentiableOn_const] + | succ n ih => + simp_rw [Finset.prod_range_succ]; exact ih.mul (by fun_prop)) + Metric.isOpen_ball + have hmem := Metric.mem_ball_self (x := (0 : ℂ)) (by norm_num : (0 : ℝ) < 1 / 2) + -- (∏(1-q^(n+1)))^24 is differentiable as a power of a differentiable function + have h24 := (hdiff 0 hmem).pow (n := 24) + -- ∏(1-q^(n+1))^24 = (∏(1-q^(n+1)))^24 by tprod_pow, so congr gives differentiability + refine h24.congr (fun q hq ↦ ?_) (by simp) + exact (multipliable_one_sub_pow (lt_trans (by simpa [dist_zero_right] using hq) + (by norm_num : (1 : ℝ) / 2 < 1))).tprod_pow 24 + +/-- The first q-expansion coefficient of the modular discriminant is 1. -/ +lemma discriminant_qExpansion_coeff_one : + (qExpansion 1 (discriminantCuspForm : ℍ → ℂ)).coeff 1 = 1 := by + rw [qExpansion_coeff] + simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, + iteratedDeriv_zero] + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) + change deriv (cuspFunction 1 Δ) 0 = 1 + rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] + rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] + have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = + derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + + id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := + derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow + rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + simp + end end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean index 386d86e4de8bbf..e6e4c33ee3bf95 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean @@ -26,7 +26,7 @@ noncomputable section namespace ModularForm -open EisensteinSeries CongruenceSubgroup Matrix.SpecialLinearGroup +open EisensteinSeries CongruenceSubgroup Matrix.SpecialLinearGroup MatrixGroups /-- This defines Eisenstein series as modular forms of weight `k`, level `Γ(N)` and congruence condition given by `a : Fin 2 → ZMod N`. -/ @@ -44,7 +44,8 @@ def eisensteinSeriesMF {k : ℤ} {N : ℕ} [NeZero N] (hk : 3 ≤ k) (a : Fin 2 /-- Normalised Eisenstein series of level 1 and weight `k`, here they have been scaled by `1/2` since we sum over coprime pairs. -/ -noncomputable def E {k : ℕ} (hk : 3 ≤ k) : ModularForm Γ(1) k := - (1 / 2 : ℂ) • eisensteinSeriesMF (mod_cast hk) 0 +noncomputable def E {k : ℕ} (hk : 3 ≤ k) : ModularForm 𝒮ℒ k := + ((1 / 2 : ℂ) • eisensteinSeriesMF (mod_cast hk) 0).ofSubgroupEq + CongruenceSubgroup.Gamma_one_coe_eq_SL end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean index 96dab6415c09b5..158f8c89164524 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean @@ -43,7 +43,7 @@ public section open Set Metric TopologicalSpace Function Filter Complex ArithmeticFunction ModularForm EisensteinSeries -open scoped Topology Real Nat Complex Pointwise ArithmeticFunction.sigma +open scoped Topology Real Nat Complex Pointwise ArithmeticFunction.sigma MatrixGroups open _root_.UpperHalfPlane hiding I @@ -277,7 +277,8 @@ lemma EisensteinSeries.q_expansion_riemannZeta {k : ℕ} (hk : 3 ≤ k) (hk2 : E E hk z = 1 + (riemannZeta k)⁻¹ * (-2 * π * I) ^ k / (k - 1)! * ∑' n : ℕ+, σ (k - 1) n * cexp (2 * π * I * z) ^ (n : ℤ) := by have : eisensteinSeriesMF (Int.toNat_le.mp hk) 0 z = eisensteinSeriesSIF (N := 1) 0 k z := rfl - rw [E, ModularForm.IsGLPos.smul_apply, this, eisensteinSeriesSIF_apply 0 k z, eisensteinSeries] + rw [E, ModularForm.ofSubgroupEq_apply, ModularForm.IsGLPos.smul_apply, this, + eisensteinSeriesSIF_apply 0 k z, eisensteinSeries] have HE1 := tsum_eisSummand_eq_tsum_sigma_mul_cexp_pow hk hk2 z have HE2 := tsum_eisSummand_eq_riemannZeta_mul_eisensteinSeries hk z have z2 : riemannZeta k ≠ 0 := riemannZeta_ne_zero_of_one_lt_re <| by norm_cast; grind @@ -326,6 +327,8 @@ lemma EisensteinSeries.E_qExpansion_coeff {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k if m = 0 then 1 else -(2 * k / bernoulli k : ℂ) * (σ (k - 1) m) := by set β : ℂ := -(2 * k / bernoulli k : ℂ) set c : ℕ → ℂ := fun m ↦ if m = 0 then 1 else β * ↑(σ (k - 1) m) + haveI : ModularFormClass (ModularForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance suffices ∀ τ : ℍ, HasSum (fun m ↦ c m • 𝕢 (1 : ℝ) τ ^ m) (E hk τ) from (qExpansion_coeff_unique one_pos one_mem_strictPeriods_SL2Z this m).symm intro τ diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean index f62bd3810ea1c2..30c515d4933a0b 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne.lean @@ -104,12 +104,16 @@ lemma levelOne_weight_zero_const [ModularFormClass F Γ(1) 0] (f : F) : end ModularFormClass -lemma ModularForm.levelOne_weight_zero_rank_one : Module.rank ℂ (ModularForm Γ(1) 0) = 1 := by +lemma ModularForm.levelOne_weight_zero_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 0) = 1 := by + haveI : ModularFormClass (ModularForm 𝒮ℒ 0) Γ(1) 0 := + Gamma_one_coe_eq_SL ▸ inferInstance refine rank_eq_one (const 1) (by simp [DFunLike.ne_iff]) fun g ↦ ?_ obtain ⟨c', hc'⟩ := levelOne_weight_zero_const g aesop lemma ModularForm.levelOne_neg_weight_rank_zero (hk : k < 0) : - Module.rank ℂ (ModularForm Γ(1) k) = 0 := by + Module.rank ℂ (ModularForm 𝒮ℒ k) = 0 := by + haveI : ModularFormClass (ModularForm 𝒮ℒ k) Γ(1) k := + Gamma_one_coe_eq_SL ▸ inferInstance refine rank_eq_zero_iff.mpr fun f ↦ ⟨_, one_ne_zero, ?_⟩ simpa [← coe_eq_zero_iff] using levelOne_neg_weight_eq_zero hk f From 1548cacc125e261f1d66152aae1d53ef3005ba13 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 08:22:54 +0100 Subject: [PATCH 02/61] feat(NumberTheory/ModularForms): add cusp form submodule and level one dimension formula Adds `CuspFormSubmodule.lean` providing the cusp form submodule of modular forms together with API, and `DimensionFormulas/LevelOne.lean` proving the classical dimension formula for spaces of level one modular forms. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/CuspFormSubmodule.lean | 143 ++++++ .../DimensionFormulas/LevelOne.lean | 463 ++++++++++++++++++ 2 files changed, 606 insertions(+) create mode 100644 Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean create mode 100644 Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean new file mode 100644 index 00000000000000..b75d24bcfa9c34 --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -0,0 +1,143 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +import Mathlib.NumberTheory.ModularForms.QExpansion +import Mathlib.NumberTheory.ModularForms.LevelOne +import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion + +/-! +# Cusp form submodule and IsCuspForm predicate + +This file defines the inclusion of cusp forms into modular forms as a linear map, the cusp form +submodule of modular forms, and the `IsCuspForm` predicate. It also provides a direct constructor +`ModularForm.toCuspForm` for building cusp forms from modular forms with vanishing constant +q-expansion coefficient (for `𝒮ℒ`). + +## Main definitions + +* `CuspForm.toModularFormₗ`: the inclusion `CuspForm Γ k →ₗ[ℂ] ModularForm Γ k`. +* `ModularForm.cuspFormSubmodule`: the submodule of `ModularForm Γ k` consisting of cusp forms. +* `ModularForm.IsCuspForm`: predicate that a modular form lies in the cusp form submodule. +* `ModularForm.toCuspForm`: builds a `CuspForm 𝒮ℒ k` from a `ModularForm` whose q-expansion + has vanishing constant term. + +## Main results + +* `CuspForm.toModularFormₗ_injective`: the inclusion is injective. +* `CuspForm.equivCuspFormSubmodule`: `CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule Γ k`. +* `ModularForm.isCuspForm_iff_coeffZero_eq_zero`: for `𝒮ℒ`, `IsCuspForm` is equivalent to the + q-expansion having vanishing constant term. +-/ + +open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass + ModularFormClass MatrixGroups OnePoint Filter Topology + +noncomputable section + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +namespace CuspForm + +/-- The inclusion of cusp forms into modular forms, as a ℂ-linear map. -/ +def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k where + toFun f := + { toSlashInvariantForm := f.toSlashInvariantForm + holo' := f.holo' + bdd_at_cusps' := fun hc g hg ↦ (f.zero_at_cusps' hc g hg).boundedAtFilter } + map_add' _ _ := by ext; rfl + map_smul' _ _ := by ext; rfl + +@[simp] +lemma toModularFormₗ_apply [Γ.HasDetOne] (f : CuspForm Γ k) (z : ℍ) : + (toModularFormₗ f) z = f z := rfl + +lemma toModularFormₗ_injective [Γ.HasDetOne] : + Function.Injective (toModularFormₗ : CuspForm Γ k → ModularForm Γ k) := + fun _ _ h ↦ DFunLike.ext _ _ fun z ↦ congr_fun (congr_arg DFunLike.coe h) z + +end CuspForm + +namespace ModularForm + +/-- The submodule of `ModularForm Γ k` consisting of cusp forms, defined as the range of +the inclusion `CuspForm.toModularFormₗ`. -/ +def cuspFormSubmodule [Γ.HasDetOne] : Submodule ℂ (ModularForm Γ k) := + LinearMap.range (CuspForm.toModularFormₗ) + +/-- A modular form is a cusp form if it lies in the cusp form submodule. -/ +def IsCuspForm [Γ.HasDetOne] (f : ModularForm Γ k) : Prop := + f ∈ cuspFormSubmodule (Γ := Γ) (k := k) + +/-- The cusp form submodule is linearly equivalent to the type of cusp forms. -/ +def CuspForm.equivCuspFormSubmodule [Γ.HasDetOne] : + CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule (Γ := Γ) (k := k) := + LinearEquiv.ofInjective CuspForm.toModularFormₗ CuspForm.toModularFormₗ_injective + +/-- A modular form is a cusp form if and only if it vanishes at every cusp. This is the +general characterization valid for any subgroup. -/ +lemma isCuspForm_iff [Γ.HasDetOne] (f : ModularForm Γ k) : + IsCuspForm f ↔ ∀ {c : OnePoint ℝ}, IsCusp c Γ → c.IsZeroAt f k := by + constructor + · rintro ⟨g, hg⟩ c hc + have : (f : ℍ → ℂ) = (g : ℍ → ℂ) := congr_arg DFunLike.coe hg.symm + simpa [this] using g.zero_at_cusps' hc + · intro h + exact ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, by ext; rfl⟩ + +section SL2Z + +open EisensteinSeries + +variable {k : ℤ} + +lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z + +/-- If an `𝒮ℒ` modular form has `valueAtInfty f = 0`, then it is zero at infinity. -/ +lemma isZeroAtImInfty_of_valueAtInfty_eq_zero + (f : ModularForm 𝒮ℒ k) (h : valueAtInfty f = 0) : IsZeroAtImInfty f := by + change Filter.Tendsto f atImInfty (𝓝 0) + rw [show (0 : ℂ) = cuspFunction 1 f 0 from by + rw [cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL]; exact h.symm] + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt.tendsto.comp + (qParam_tendsto_atImInfty one_pos)).congr + (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + +/-- An `𝒮ℒ` modular form with vanishing q-expansion constant term vanishes at every cusp. -/ +private lemma isZeroAt_of_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) + (h : (qExpansion 1 f).coeff 0 = 0) {c : OnePoint ℝ} (hc : IsCusp c 𝒮ℒ) : + c.IsZeroAt f k := by + rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc + rw [isZeroAt_iff_forall_SL2Z hc] + intro γ _ + rw [show (⇑f ∣[k] γ) = ⇑f from f.slash_action_eq' _ (MonoidHom.mem_range.mpr ⟨γ, rfl⟩)] + exact isZeroAtImInfty_of_valueAtInfty_eq_zero f <| by + rwa [← qExpansion_coeff_zero f one_pos one_mem_strictPeriods_SL] + +/-- Build a `CuspForm 𝒮ℒ k` from a `ModularForm 𝒮ℒ k` whose q-expansion has vanishing +constant term. The resulting cusp form has the same underlying function. -/ +def toCuspForm (f : ModularForm 𝒮ℒ k) (h : (qExpansion 1 f).coeff 0 = 0) : CuspForm 𝒮ℒ k where + toSlashInvariantForm := f.toSlashInvariantForm + holo' := f.holo' + zero_at_cusps' := isZeroAt_of_coeffZero_eq_zero f h + +@[simp] +lemma toCuspForm_apply (f : ModularForm 𝒮ℒ k) (h : (qExpansion 1 f).coeff 0 = 0) + (z : ℍ) : (toCuspForm f h) z = f z := rfl + +/-- For `𝒮ℒ` modular forms, `IsCuspForm` is equivalent to the q-expansion having vanishing +constant term. -/ +lemma isCuspForm_iff_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) : + IsCuspForm f ↔ (qExpansion 1 f).coeff 0 = 0 := by + constructor + · intro ⟨g, hg⟩ + rw [qExpansion_coeff_zero f one_pos one_mem_strictPeriods_SL] + exact congr_arg valueAtInfty (congr_arg DFunLike.coe hg.symm) ▸ + (CuspFormClass.zero_at_infty g).valueAtInfty_eq_zero + · exact fun h ↦ (isCuspForm_iff f).mpr (isZeroAt_of_coeffZero_eq_zero f h) + +end SL2Z + +end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean new file mode 100644 index 00000000000000..aff3fb037ce6be --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -0,0 +1,463 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule +import Mathlib.NumberTheory.ModularForms.Discriminant +import Mathlib.Data.Rat.Star +import Mathlib.LinearAlgebra.Dimension.Localization + +/-! +# Dimension formula for level 1 modular forms + +This file proves the dimension formula for the space of modular forms for `𝒮ℒ` (= `SL(2, ℤ)`) +of even weight `k ≥ 3`. + +## Main results + +* `CuspForm.discriminantEquiv`: `CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12)`. +* `ModularForm.rank_eq_one_add_rank_cuspForm`: `rank M_k = 1 + rank S_k` for even `k ≥ 3`. +* `ModularForm.dimension_level_one`: the full dimension formula. +-/ + +open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass + ModularFormClass CongruenceSubgroup MatrixGroups OnePoint Filter Topology EisensteinSeries + +noncomputable section + +/-! ### Delta isomorphism: `CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12)` -/ + +section DeltaIsomorphism + +variable {k : ℤ} + +local notation "Δ" => ModularForm.discriminant + +namespace CuspForm + +/-- Multiply a modular form of weight `k - 12` by the discriminant to get a cusp form of +weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ +def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := + let Δ' := CuspForm.toModularFormₗ discriminantCuspForm + ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) (by + have : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := by + rw [qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL] + exact (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero + rw [show (ModularForm.mcast _ (f.mul Δ') : ℍ → ℂ) = (f : ℍ → ℂ) * Δ' from rfl, + qExpansion_mul_coeff_zero + (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, + this, mul_zero]) + +@[simp] +lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : + (ofMulDiscriminant f) z = f z * Δ z := rfl + +private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, ℤ)) : + (fun z ↦ f z / Δ z) ∣[k - 12] γ = fun z ↦ f z / Δ z := by + haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance + haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ 12) (CongruenceSubgroup.Gamma 1) 12 := + CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance + have hf := slash_action_eqn_SL'' f (mem_Gamma_one γ) + have hΔ := slash_action_eqn_SL'' discriminantCuspForm (mem_Gamma_one γ) + ext z + rw [SL_slash_apply, hf, show Δ (γ • z) = denom γ z ^ (12 : ℤ) * Δ z from by + exact_mod_cast hΔ z] + have hd : (denom γ z : ℂ) ≠ 0 := denom_ne_zero γ z + rw [div_mul_eq_mul_div, mul_right_comm, ← zpow_add₀ hd, + show k + -(k - 12) = (12 : ℤ) from by ring] + exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ hd) + +private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : + (f : ℍ → ℂ) =O[atImInfty] Δ := by + have hf_decay := CuspFormClass.exp_decay_atImInfty (h := 1) f one_pos one_mem_strictPeriods_SL + have hΔ_lower : ∀ᶠ τ : ℍ in atImInfty, + ‖(fun τ : ℍ ↦ Real.exp (-2 * Real.pi * τ.im / 1)) τ‖ ≤ 2 * ‖Δ τ‖ := by + have hprod := discriminant_bounded_factor.eventually + (Metric.ball_mem_nhds (1 : ℂ) (by norm_num : (0 : ℝ) < 1/2)) + filter_upwards [hprod] with τ hτ + simp only [div_one] + rw [discriminant_eq_q_prod, norm_mul, Real.norm_of_nonneg (Real.exp_pos _).le] + have hq_norm : ‖Function.Periodic.qParam 1 (τ : ℂ)‖ = + Real.exp (-2 * Real.pi * τ.im) := by + simp [Function.Periodic.qParam, Complex.norm_exp, Complex.mul_re, div_one] + rw [← hq_norm] + have hprod_bound : 1 / 2 ≤ ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24‖ := by + have hsub : ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24 - 1‖ < 1 / 2 := by + rwa [Complex.dist_eq] at hτ + have h1 := norm_sub_norm_le (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24) + simp only [norm_one] at h1 + linarith [norm_sub_rev (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24)] + linarith [norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)), + mul_le_mul_of_nonneg_left hprod_bound + (norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)))] + exact hf_decay.trans (Asymptotics.IsBigO.of_bound 2 hΔ_lower) + +/-- Divide a cusp form by the discriminant to get a modular form of weight `k - 12`. -/ +def divDiscriminant (f : CuspForm 𝒮ℒ k) : ModularForm 𝒮ℒ (k - 12) where + toFun z := f z / Δ z + slash_action_eq' A hA := by + obtain ⟨γ, rfl⟩ := hA + exact divByDiscriminant_slash_eq f γ + holo' := by + rw [UpperHalfPlane.mdifferentiable_iff] + apply DifferentiableOn.div + · exact UpperHalfPlane.mdifferentiable_iff.mp f.holo' + · exact UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo' + · intro z hz + simp only [ofComplex_apply_of_im_pos hz] + exact discriminant_ne_zero ⟨z, hz⟩ + bdd_at_cusps' {c} hc := by + rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc + rw [isBoundedAt_iff_forall_SL2Z hc] + intro γ _ + rw [divByDiscriminant_slash_eq f γ, IsBoundedAtImInfty, BoundedAtFilter] + exact (Asymptotics.div_isBoundedUnder_of_isBigO + (exp_decay_isBigO_discriminant f)).isBigO_one ℝ + +@[simp] +lemma divDiscriminant_apply (f : CuspForm 𝒮ℒ k) (z : ℍ) : + (divDiscriminant f) z = f z / Δ z := rfl + +/-- The linear equivalence between cusp forms of weight `k` and modular forms of weight `k - 12`, +given by division by the discriminant. -/ +def discriminantEquiv : CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12) where + toFun := divDiscriminant + map_add' a b := by ext z; simp [add_div] + map_smul' c a := by ext z; simp [mul_div_assoc] + invFun := ofMulDiscriminant + left_inv f := by + ext z + simp only [divDiscriminant_apply, ofMulDiscriminant_apply] + exact div_mul_cancel₀ (f z) (discriminant_ne_zero z) + right_inv f := by + ext z + simp only [ofMulDiscriminant_apply, divDiscriminant_apply] + exact mul_div_cancel_right₀ (f z) (discriminant_ne_zero z) + +end CuspForm + +end DeltaIsomorphism + +/-! ### Rank identities -/ + +section RankIdentity + +variable {k : ℤ} + +/-- Cusp forms of weight `k < 12` for `𝒮ℒ` are zero-dimensional. -/ +lemma cuspForm_rank_lt_twelve (hk : k < 12) : + Module.rank ℂ (CuspForm 𝒮ℒ k) = 0 := by + rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv] + exact levelOne_neg_weight_rank_zero (by omega) + +/-- The space of weight 12 cusp forms for `𝒮ℒ` has rank 1. -/ +lemma cuspForm_rank_twelve : Module.rank ℂ (CuspForm 𝒮ℒ 12) = 1 := by + rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv, + show (12 : ℤ) - 12 = 0 from by norm_num] + exact levelOne_weight_zero_rank_one + +/-- Every weight 12 cusp form for `𝒮ℒ` is a scalar multiple of the discriminant. -/ +lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : + ∃ c : ℂ, c • discriminantCuspForm = f := by + have hne : discriminantCuspForm ≠ 0 := fun h ↦ + discriminant_ne_zero UpperHalfPlane.I (congr_fun (congr_arg DFunLike.coe h) _) + exact (finrank_eq_one_iff_of_nonzero' discriminantCuspForm hne).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp cuspForm_rank_twelve) f + +/-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of +cusp forms. -/ +lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : + Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by + have h_add := Submodule.rank_quotient_add_rank + (cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) + rw [show Module.rank ℂ ↥(cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) = + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from + (LinearEquiv.rank_eq CuspForm.equivCuspFormSubmodule).symm] at h_add + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 1 by + rw [← h_add, h1] + have hk' : 3 ≤ k := by exact_mod_cast hk + have hE_coeff_zero := E_qExpansion_coeff_zero hk' hk2 + apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule) (E hk')) + · intro h + rw [Submodule.Quotient.mk_eq_zero] at h + exact one_ne_zero <| + hE_coeff_zero.symm.trans <| + (isCuspForm_iff_coeffZero_eq_zero _).mp h + · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ + ⟨(qExpansion 1 f).coeff 0, ?_⟩ + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk' ∈ + cuspFormSubmodule := + (isCuspForm_iff_coeffZero_eq_zero _).mpr (by + set c := (qExpansion 1 ↑f).coeff 0 with hc + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (k : ℤ))).map_sub + f (c • E hk') + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub + rw [hsub] + have hcoe : ⇑(c • E hk') = c • (E hk' : ℍ → ℂ) := rfl + rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk')] + simp only [_root_.map_sub, _root_.map_smul, smul_eq_mul, hE_coeff_zero, mul_one, ← hc, + sub_self]) + have h0 : (cuspFormSubmodule.mkQ (f - (qExpansion 1 ↑f).coeff 0 • + E hk') : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 0 := + (Submodule.Quotient.mk_eq_zero _).mpr h_mem + rw [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, + sub_eq_zero] at h0 + exact h0.symm + +end RankIdentity + +/-! ### Dimension formula -/ + +section DimensionFormula + +/-! ### Helpers for weight 2 proof -/ + +/-- In a rank-1 module over ℂ, any element is a scalar multiple of any nonzero element. -/ +private lemma exists_smul_eq_of_rank_one {M : Type*} [AddCommGroup M] [Module ℂ M] + (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := by + obtain ⟨v, _, hv⟩ := rank_eq_one_iff.mp hrank + obtain ⟨a, rfl⟩ := hv e; obtain ⟨b, rfl⟩ := hv f + exact ⟨b * a⁻¹, by rw [smul_smul, mul_assoc, inv_mul_cancel₀ (fun h ↦ he (by simp [h])), + mul_one]⟩ + +/-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ +private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := + (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 4 by norm_num) ⟨2, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (4 : ℤ) < 12 by norm_num))).trans + (by norm_cast)) + +/-- Weight 6 modular forms for `𝒮ℒ` are 1-dimensional. -/ +private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ℤ)) = 1 := + (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 6 by norm_num) ⟨3, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (6 : ℤ) < 12 by norm_num))).trans + (by norm_cast)) + +private lemma E_qExpansion_coeff_one_four : + (qExpansion 1 (E (show 3 ≤ 4 by norm_num))).coeff 1 = 240 := by + rw [E_qExpansion_coeff (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩] + simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] + rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by + rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] + simp [ArithmeticFunction.sigma_one]; norm_num + +private lemma E_qExpansion_coeff_one_six : + (qExpansion 1 (E (show 3 ≤ 6 by norm_num))).coeff 1 = -504 := by + rw [E_qExpansion_coeff (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩] + simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] + rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by + rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] + norm_num [Finset.sum_range_succ, Finset.sum_range_zero, + show Nat.choose 6 2 = 15 from by decide, show Nat.choose 6 4 = 15 from by decide, + bernoulli'_eq_zero_of_odd (show Odd 5 from ⟨2, rfl⟩) (by norm_num)]] + simp [ArithmeticFunction.sigma_one]; norm_num + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : + 1728 * discriminant z = + E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2 := by + set E4 := E (show 3 ≤ 4 by norm_num) + set E6 := E (show 3 ≤ 6 by norm_num) + set F : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) + (E4.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E4.mul E4))) - + ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E6.mul E6) + have hF : ∀ w, F w = E4 w ^ 3 - E6 w ^ 2 := fun w ↦ by + change E4 w * (E4 w * E4 w) - E6 w * E6 w = E4 w ^ 3 - E6 w ^ 2; ring + have h0_4 := E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ + have h0_6 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + -- q-expansion of F splits as products minus products + -- F is a cusp form (coeff 0 = valueAtInfty F = 1³-1² = 0) + have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by + rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] + -- valueAtInfty F = valueAtInfty (E₄*E₄*E₄ - E₆*E₆) = 1*1*1 - 1*1 = 0 + have hv4 : valueAtInfty (E4 : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E4 one_pos one_mem_strictPeriods_SL] + have hv6 : valueAtInfty (E6 : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E6 one_pos one_mem_strictPeriods_SL] + change limUnder atImInfty (fun w ↦ E4 w * (E4 w * E4 w) - E6 w * E6 w) = 0 + have htend : ∀ (k' : ℤ) (f : ModularForm 𝒮ℒ k') (c' : ℂ) (_ : valueAtInfty f = c'), + Filter.Tendsto f atImInfty (𝓝 c') := fun _ f c' hv ↦ by + rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL + ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + have h4 := htend _ E4 _ hv4 + have h6 := htend _ E6 _ hv6 + convert ((h4.mul (h4.mul h4)).sub (h6.mul h6)).limUnder_eq using 1 + norm_num) + obtain ⟨g, hg⟩ := hF_cusp + obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g + -- c = 1728 by comparing q-expansion coeff 1 + have hc_eq : c = 1728 := by + -- coeff 1 of g = coeff 1 of F (since g = F as modular forms) + -- coeff 1 of g = c * coeff 1 of Δ = c * 1 = c (since c•Δ = g) + have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by + congr 1; exact congr_arg DFunLike.coe hg + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = + c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) + from congr_arg DFunLike.coe hc.symm] + exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm + -- coeff 1 of F = c (from hgF, hgΔ, and discriminant_qExpansion_coeff_one) + have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) + simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, + mul_one] at h + -- (qExpansion 1 F).coeff 1 = 3*240 - 2*(-504) = 1728 + -- Use ModularForm.qExpansion_mul which works on ModularForm, not raw functions + have hq44 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4 + have hq444 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 + (ModularForm.mcast rfl (E4.mul E4)) + have hq66 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6 + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub + (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) + (ModularForm.mcast (by norm_num) (E6.mul E6)) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub + -- mcast doesn't change coercions, so qExpansion is unaffected + have hmcast : ∀ (a b : ℤ) (h : a = b) (f : ModularForm 𝒮ℒ a), + qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := + fun _ _ _ _ ↦ rfl + simp only [hmcast] at hsub + rw [hsub, hq444] at h; simp only [hmcast] at h; rw [hq44, hq66] at h + -- h now has: coeff 1 of (p4 * (p4 * p4) - p6 * p6) = c + -- Build the numeric value via calc, avoiding simp-at-h which consumes h + have h1_4 : (PowerSeries.coeff 1) (qExpansion 1 E4) = 240 := E_qExpansion_coeff_one_four + have h1_6 : (PowerSeries.coeff 1) (qExpansion 1 E6) = -504 := E_qExpansion_coeff_one_six + have hc0_4 : PowerSeries.constantCoeff (qExpansion 1 (E4 : ℍ → ℂ)) = 1 := by + rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_4 + have hc0_6 : PowerSeries.constantCoeff (qExpansion 1 (E6 : ℍ → ℂ)) = 1 := by + rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_6 + -- Use native_decide or norm_num on the coefficient computation + simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, + Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, + Finset.map_singleton, Function.Embedding.prodMap, Prod.map, + Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, + Function.Embedding.refl_apply, h1_4, h1_6] at h + exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 + from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) + calc 1728 * discriminant z = c * discriminant z := by rw [hc_eq] + _ = (c • discriminantCuspForm) z := rfl + _ = g z := by rw [← hc] + _ = (CuspForm.toModularFormₗ g) z := rfl + _ = F z := by rw [hg] + _ = E4 z ^ 3 - E6 z ^ 2 := hF z + +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) + (hf : ¬IsCuspForm f) : f = 0 := by + exfalso + have hc0 : (qExpansion 1 f).coeff 0 ≠ 0 := + fun h ↦ hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr h) + obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one + (E_ne_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩) (f.mul f) + obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one + (E_ne_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩) ((f.mul f).mul f) + set p := qExpansion 1 f + set p4 := qExpansion 1 (E (show 3 ≤ 4 by norm_num)) + set p6 := qExpansion 1 (E (show 3 ≤ 6 by norm_num)) + have hqc4 : c4 • p4 = p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 + (E (show 3 ≤ 4 by norm_num)) + rw [show (c4 • E (show 3 ≤ 4 by norm_num) : ℍ → ℂ) = + (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] + exact hsmul.symm + have hqc6 : c6 • p6 = p * p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 + (E (show 3 ≤ 6 by norm_num)) + have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f + rw [show (c6 • E (show 3 ≤ 6 by norm_num) : ℍ → ℂ) = + ((f.mul f).mul f : ℍ → ℂ) from congrArg DFunLike.coe hc6] at hsmul + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 + rw [← hmul1]; exact hsmul.symm + have hp4_0 : p4.coeff 0 = 1 := + E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ + have hp6_0 : p6.coeff 0 = 1 := + E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + have hc4_eq : c4 = p.coeff 0 ^ 2 := by + have h := congr_arg (·.coeff 0) hqc4 + simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, + Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp4_0, mul_one] at h + rw [sq]; exact h + have hc6_eq : c6 = p.coeff 0 ^ 3 := by + have h := congr_arg (·.coeff 0) hqc6 + simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, + Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h + rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h + have hp4_1 : p4.coeff 1 = 240 := E_qExpansion_coeff_one_four + have hp6_1 : p6.coeff 1 = -504 := E_qExpansion_coeff_one_six + have heq4 : c4 * 240 = 2 * p.coeff 0 * p.coeff 1 := by + have h := congr_arg (·.coeff 1) hqc4 + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h + rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + exact h + have heq6 : c6 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by + have h := congr_arg (·.coeff 1) hqc6 + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h + rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + exact h + rw [hc4_eq] at heq4; rw [hc6_eq] at heq6 + have h1728 : 1728 * p.coeff 0 ^ 3 = 0 := by + linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 + exact hc0 (by + by_contra h + exact absurd h1728 (mul_ne_zero (by norm_num : (1728 : ℂ) ≠ 0) (pow_ne_zero 3 h))) + +/-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ +theorem ModularForm.levelOne_weight_two_rank_zero : + Module.rank ℂ (ModularForm 𝒮ℒ (2 : ℤ)) = 0 := by + rw [rank_zero_iff_forall_zero] + intro f + by_cases hf : IsCuspForm f + · obtain ⟨g, hg⟩ := hf + rw [← hg] + simp [rank_zero_iff_forall_zero.mp + (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + · exact weight_two_eq_zero_of_not_cuspForm f hf + +private lemma floor_lem1 (k a : ℚ) (ha : 0 < a) (hak : a ≤ k) : + 1 + Nat.floor ((k - a) / a) = Nat.floor (k / a) := by + rw [div_sub_same (Ne.symm (ne_of_lt ha))] + have := Nat.floor_sub_one (k / a) + push_cast at * + rw [this] + refine Nat.add_sub_cancel' ?_ + exact Nat.le_floor ((le_div_iff₀ ha).mpr (by simpa using hak)) + +/-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ +theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : + Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = + if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) + else Nat.floor ((k : ℚ) / 12) + 1 := by + induction k using Nat.strong_induction_on with | h k ihn => + rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, + LinearEquiv.rank_eq CuspForm.discriminantEquiv] + by_cases HK : (3 : ℤ) ≤ ((k : ℤ) - 12) + · have iH := ihn (k - 12) (by omega) (by omega) + ((Nat.even_sub (by omega)).mpr (by simp only [hk2, true_iff]; decide)) + have hk12 : (((k - 12) : ℕ) : ℤ) = k - 12 := by + norm_cast; exact Eq.symm (Int.subNatNat_of_le (by omega)) + rw [hk12] at iH + rw [iH, show ((k - 12 : ℕ) : ℚ) = (k : ℚ) - 12 from by norm_cast] + have hfl := floor_lem1 k 12 (by norm_num) + by_cases h12 : 12 ∣ ((k) : ℤ) - 2 + · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] + norm_cast at *; apply hfl; omega + · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, + Nat.cast_add, Nat.cast_one] + norm_cast at *; rw [← add_assoc, hfl]; omega + · simp only [not_le] at HK + have hkop : k ∈ Finset.filter Even (Finset.Icc 3 14) := by + simp only [Finset.mem_filter, Finset.mem_Icc, hk2, and_true]; omega + rw [show Finset.filter Even (Finset.Icc 3 14) = ({4, 6, 8, 10, 12, 14} : Finset ℕ) + from by decide] at hkop + fin_cases hkop <;> simp only [Nat.cast_ofNat, Int.reduceSub, Int.reduceNeg] at * + all_goals first + | exact (congrArg (1 + ·) (levelOne_neg_weight_rank_zero (by omega))).trans (by norm_cast) + | exact (congrArg (1 + ·) levelOne_weight_zero_rank_one).trans (by norm_cast) + | exact (congrArg (1 + ·) levelOne_weight_two_rank_zero).trans (by norm_cast) + +end DimensionFormula From 40cd50a3921bf7e79a9b68b789fa9e055531fb04 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:03:27 +0100 Subject: [PATCH 03/61] chore(NumberTheory/ModularForms): address PR review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Targeted fixes from PR #37789 review: - `cuspFormSubmodule` and `equivCuspFormSubmodule`: make `Γ`/`k` explicit - `isCuspForm_iff`: shorter proof - `ofMulDiscriminant`: simplify cusp-form coeff zero argument - `divDiscriminant.holo'`: golf by inlining the differentiability subgoals - `rank_eq_one_add_rank_cuspForm`: take `hk : 3 ≤ k` over `ℕ` - `discriminant_eq_E4_cube_sub_E6_sq`: restate as `Δ = (E₄³ - E₆²)/1728`, drop inline proof comments, fold redundant `have`s - `exists_smul_eq_of_rank_one`: use `finrank_eq_one_iff_of_nonzero'` from mathlib - Move `one_mem_strictPeriods_SL` to `LevelOne.lean` so the haveI workaround in `EisensteinSeries.E_qExpansion_coeff` can be dropped Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/CuspFormSubmodule.lean | 22 ++-- .../DimensionFormulas/LevelOne.lean | 123 +++++++----------- .../EisensteinSeries/QExpansion.lean | 4 +- .../NumberTheory/ModularForms/LevelOne.lean | 3 + 4 files changed, 62 insertions(+), 90 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index b75d24bcfa9c34..42f695b0886447 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -63,28 +63,25 @@ namespace ModularForm /-- The submodule of `ModularForm Γ k` consisting of cusp forms, defined as the range of the inclusion `CuspForm.toModularFormₗ`. -/ -def cuspFormSubmodule [Γ.HasDetOne] : Submodule ℂ (ModularForm Γ k) := - LinearMap.range (CuspForm.toModularFormₗ) +def cuspFormSubmodule (Γ : Subgroup (GL (Fin 2) ℝ)) (k : ℤ) [Γ.HasDetOne] : + Submodule ℂ (ModularForm Γ k) := + LinearMap.range CuspForm.toModularFormₗ /-- A modular form is a cusp form if it lies in the cusp form submodule. -/ def IsCuspForm [Γ.HasDetOne] (f : ModularForm Γ k) : Prop := - f ∈ cuspFormSubmodule (Γ := Γ) (k := k) + f ∈ cuspFormSubmodule Γ k /-- The cusp form submodule is linearly equivalent to the type of cusp forms. -/ -def CuspForm.equivCuspFormSubmodule [Γ.HasDetOne] : - CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule (Γ := Γ) (k := k) := +def CuspForm.equivCuspFormSubmodule (Γ : Subgroup (GL (Fin 2) ℝ)) (k : ℤ) [Γ.HasDetOne] : + CuspForm Γ k ≃ₗ[ℂ] cuspFormSubmodule Γ k := LinearEquiv.ofInjective CuspForm.toModularFormₗ CuspForm.toModularFormₗ_injective /-- A modular form is a cusp form if and only if it vanishes at every cusp. This is the general characterization valid for any subgroup. -/ lemma isCuspForm_iff [Γ.HasDetOne] (f : ModularForm Γ k) : IsCuspForm f ↔ ∀ {c : OnePoint ℝ}, IsCusp c Γ → c.IsZeroAt f k := by - constructor - · rintro ⟨g, hg⟩ c hc - have : (f : ℍ → ℂ) = (g : ℍ → ℂ) := congr_arg DFunLike.coe hg.symm - simpa [this] using g.zero_at_cusps' hc - · intro h - exact ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, by ext; rfl⟩ + refine ⟨fun ⟨g, hg⟩ c hc ↦ hg ▸ g.zero_at_cusps' hc, fun h ↦ + ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, rfl⟩⟩ section SL2Z @@ -92,9 +89,6 @@ open EisensteinSeries variable {k : ℤ} -lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := - CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z - /-- If an `𝒮ℒ` modular form has `valueAtInfty f = 0`, then it is zero at infinity. -/ lemma isZeroAtImInfty_of_valueAtInfty_eq_zero (f : ModularForm 𝒮ℒ k) (h : valueAtInfty f = 0) : IsZeroAtImInfty f := by diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index aff3fb037ce6be..7ddac2e6cffd59 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -41,14 +41,14 @@ weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := let Δ' := CuspForm.toModularFormₗ discriminantCuspForm ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) (by - have : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := by - rw [qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL] - exact (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero + have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := + (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans + (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero rw [show (ModularForm.mcast _ (f.mul Δ') : ℍ → ℂ) = (f : ℍ → ℂ) * Δ' from rfl, qExpansion_mul_coeff_zero (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, - this, mul_zero]) + hΔ', mul_zero]) @[simp] lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : @@ -103,12 +103,9 @@ def divDiscriminant (f : CuspForm 𝒮ℒ k) : ModularForm 𝒮ℒ (k - 12) wher exact divByDiscriminant_slash_eq f γ holo' := by rw [UpperHalfPlane.mdifferentiable_iff] - apply DifferentiableOn.div - · exact UpperHalfPlane.mdifferentiable_iff.mp f.holo' - · exact UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo' - · intro z hz - simp only [ofComplex_apply_of_im_pos hz] - exact discriminant_ne_zero ⟨z, hz⟩ + refine (UpperHalfPlane.mdifferentiable_iff.mp f.holo').div + (UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo') fun z hz ↦ ?_ + simpa [ofComplex_apply_of_im_pos hz] using discriminant_ne_zero ⟨z, hz⟩ bdd_at_cusps' {c} hc := by rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc rw [isBoundedAt_iff_forall_SL2Z hc] @@ -169,18 +166,16 @@ lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : /-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of cusp forms. -/ -lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : +lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k) : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by - have h_add := Submodule.rank_quotient_add_rank - (cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) - rw [show Module.rank ℂ ↥(cuspFormSubmodule (Γ := 𝒮ℒ) (k := (k : ℤ))) = + have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ (k : ℤ)) + rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ (k : ℤ)) = Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from - (LinearEquiv.rank_eq CuspForm.equivCuspFormSubmodule).symm] at h_add - suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 1 by + (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ (k : ℤ))).symm] at h_add + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by rw [← h_add, h1] - have hk' : 3 ≤ k := by exact_mod_cast hk - have hE_coeff_zero := E_qExpansion_coeff_zero hk' hk2 - apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule) (E hk')) + have hE_coeff_zero := E_qExpansion_coeff_zero hk hk2 + apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ (k : ℤ)) (E hk)) · intro h rw [Submodule.Quotient.mk_eq_zero] at h exact one_ne_zero <| @@ -188,20 +183,20 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ (k : ℤ)) (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk' ∈ - cuspFormSubmodule := + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ + cuspFormSubmodule 𝒮ℒ (k : ℤ) := (isCuspForm_iff_coeffZero_eq_zero _).mpr (by set c := (qExpansion 1 ↑f).coeff 0 with hc have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (k : ℤ))).map_sub - f (c • E hk') + f (c • E hk) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub rw [hsub] - have hcoe : ⇑(c • E hk') = c • (E hk' : ℍ → ℂ) := rfl - rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk')] + have hcoe : ⇑(c • E hk) = c • (E hk : ℍ → ℂ) := rfl + rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk)] simp only [_root_.map_sub, _root_.map_smul, smul_eq_mul, hE_coeff_zero, mul_one, ← hc, sub_self]) - have h0 : (cuspFormSubmodule.mkQ (f - (qExpansion 1 ↑f).coeff 0 • - E hk') : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule) = 0 := + have h0 : ((cuspFormSubmodule 𝒮ℒ (k : ℤ)).mkQ (f - (qExpansion 1 ↑f).coeff 0 • + E hk) : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 0 := (Submodule.Quotient.mk_eq_zero _).mpr h_mem rw [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, sub_eq_zero] at h0 @@ -215,25 +210,22 @@ section DimensionFormula /-! ### Helpers for weight 2 proof -/ -/-- In a rank-1 module over ℂ, any element is a scalar multiple of any nonzero element. -/ +/-- In a rank-one ℂ-module, every element is a scalar multiple of any nonzero element. +This is a thin wrapper around `finrank_eq_one_iff_of_nonzero'` adapted to `Module.rank`. -/ private lemma exists_smul_eq_of_rank_one {M : Type*} [AddCommGroup M] [Module ℂ M] - (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := by - obtain ⟨v, _, hv⟩ := rank_eq_one_iff.mp hrank - obtain ⟨a, rfl⟩ := hv e; obtain ⟨b, rfl⟩ := hv f - exact ⟨b * a⁻¹, by rw [smul_smul, mul_assoc, inv_mul_cancel₀ (fun h ↦ he (by simp [h])), - mul_one]⟩ + (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := + (finrank_eq_one_iff_of_nonzero' e he).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp hrank) f /-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := - (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 4 by norm_num) ⟨2, rfl⟩).trans - ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (4 : ℤ) < 12 by norm_num))).trans - (by norm_cast)) + (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨2, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) /-- Weight 6 modular forms for `𝒮ℒ` are 1-dimensional. -/ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ℤ)) = 1 := - (rank_eq_one_add_rank_cuspForm (show (3 : ℤ) ≤ 6 by norm_num) ⟨3, rfl⟩).trans - ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (show (6 : ℤ) < 12 by norm_num))).trans - (by norm_cast)) + (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨3, rfl⟩).trans + ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) private lemma E_qExpansion_coeff_one_four : (qExpansion 1 (E (show 3 ≤ 4 by norm_num))).coeff 1 = 240 := by @@ -256,8 +248,8 @@ private lemma E_qExpansion_coeff_one_six : /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : - 1728 * discriminant z = - E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2 := by + discriminant z = (1 / 1728) * + (E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2) := by set E4 := E (show 3 ≤ 4 by norm_num) set E6 := E (show 3 ≤ 6 by norm_num) set F : ModularForm 𝒮ℒ 12 := @@ -268,11 +260,8 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : change E4 w * (E4 w * E4 w) - E6 w * E6 w = E4 w ^ 3 - E6 w ^ 2; ring have h0_4 := E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ have h0_6 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ - -- q-expansion of F splits as products minus products - -- F is a cusp form (coeff 0 = valueAtInfty F = 1³-1² = 0) have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] - -- valueAtInfty F = valueAtInfty (E₄*E₄*E₄ - E₆*E₆) = 1*1*1 - 1*1 = 0 have hv4 : valueAtInfty (E4 : ℍ → ℂ) = 1 := by rwa [← qExpansion_coeff_zero E4 one_pos one_mem_strictPeriods_SL] have hv6 : valueAtInfty (E6 : ℍ → ℂ) = 1 := by @@ -290,10 +279,7 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : norm_num) obtain ⟨g, hg⟩ := hF_cusp obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g - -- c = 1728 by comparing q-expansion coeff 1 have hc_eq : c = 1728 := by - -- coeff 1 of g = coeff 1 of F (since g = F as modular forms) - -- coeff 1 of g = c * coeff 1 of Δ = c * 1 = c (since c•Δ = g) have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by congr 1; exact congr_arg DFunLike.coe hg have hgΔ : qExpansion 1 (g : ℍ → ℂ) = @@ -301,35 +287,23 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from congr_arg DFunLike.coe hc.symm] exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm - -- coeff 1 of F = c (from hgF, hgΔ, and discriminant_qExpansion_coeff_one) have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, mul_one] at h - -- (qExpansion 1 F).coeff 1 = 3*240 - 2*(-504) = 1728 - -- Use ModularForm.qExpansion_mul which works on ModularForm, not raw functions - have hq44 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4 - have hq444 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 - (ModularForm.mcast rfl (E4.mul E4)) - have hq66 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6 - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) - (ModularForm.mcast (by norm_num) (E6.mul E6)) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub - -- mcast doesn't change coercions, so qExpansion is unaffected have hmcast : ∀ (a b : ℤ) (h : a = b) (f : ModularForm 𝒮ℒ a), qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := fun _ _ _ _ ↦ rfl - simp only [hmcast] at hsub - rw [hsub, hq444] at h; simp only [hmcast] at h; rw [hq44, hq66] at h - -- h now has: coeff 1 of (p4 * (p4 * p4) - p6 * p6) = c - -- Build the numeric value via calc, avoiding simp-at-h which consumes h + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub + (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) + (ModularForm.mcast (by norm_num) (E6.mul E6)) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 + (ModularForm.mcast rfl (E4.mul E4))] at h + simp only [hmcast] at h + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6] at h have h1_4 : (PowerSeries.coeff 1) (qExpansion 1 E4) = 240 := E_qExpansion_coeff_one_four have h1_6 : (PowerSeries.coeff 1) (qExpansion 1 E6) = -504 := E_qExpansion_coeff_one_six - have hc0_4 : PowerSeries.constantCoeff (qExpansion 1 (E4 : ℍ → ℂ)) = 1 := by - rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_4 - have hc0_6 : PowerSeries.constantCoeff (qExpansion 1 (E6 : ℍ → ℂ)) = 1 := by - rw [← PowerSeries.coeff_zero_eq_constantCoeff]; exact h0_6 - -- Use native_decide or norm_num on the coefficient computation simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, Finset.map_singleton, Function.Embedding.prodMap, Prod.map, @@ -337,12 +311,15 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : Function.Embedding.refl_apply, h1_4, h1_6] at h exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) - calc 1728 * discriminant z = c * discriminant z := by rw [hc_eq] - _ = (c • discriminantCuspForm) z := rfl - _ = g z := by rw [← hc] - _ = (CuspForm.toModularFormₗ g) z := rfl - _ = F z := by rw [hg] - _ = E4 z ^ 3 - E6 z ^ 2 := hF z + have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := by + calc (1728 : ℂ) * discriminant z + = c * discriminant z := by rw [hc_eq] + _ = (c • discriminantCuspForm) z := rfl + _ = g z := by rw [← hc] + _ = (CuspForm.toModularFormₗ g) z := rfl + _ = F z := by rw [hg] + _ = E4 z ^ 3 - E6 z ^ 2 := hF z + linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) (hf : ¬IsCuspForm f) : f = 0 := by diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean index 158f8c89164524..8de94c3361db09 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/QExpansion.lean @@ -327,10 +327,8 @@ lemma EisensteinSeries.E_qExpansion_coeff {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k if m = 0 then 1 else -(2 * k / bernoulli k : ℂ) * (σ (k - 1) m) := by set β : ℂ := -(2 * k / bernoulli k : ℂ) set c : ℕ → ℂ := fun m ↦ if m = 0 then 1 else β * ↑(σ (k - 1) m) - haveI : ModularFormClass (ModularForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := - CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance suffices ∀ τ : ℍ, HasSum (fun m ↦ c m • 𝕢 (1 : ℝ) τ ^ m) (E hk τ) from - (qExpansion_coeff_unique one_pos one_mem_strictPeriods_SL2Z this m).symm + (qExpansion_coeff_unique one_pos one_mem_strictPeriods_SL this m).symm intro τ have hS : Summable fun n : ℕ ↦ (σ (k - 1) (n + 1) : ℂ) * cexp (2 * π * I * τ) ^ (n + 1) := (summable_nat_add_iff 1).mpr (summable_sigma_mul_cexp_pow (by omega) τ) diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean index 30c515d4933a0b..15fb58c051e639 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne.lean @@ -69,6 +69,9 @@ variable [ModularFormClass F Γ(1) k] lemma one_mem_strictPeriods_SL2Z : (1 : ℝ) ∈ Γ(1).strictPeriods := by simp +lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := + Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z + private theorem cuspFunction_eqOn_const_of_nonpos_wt (hk : k ≤ 0) (f : F) : Set.EqOn (cuspFunction 1 f) (const ℂ (cuspFunction 1 f 0)) (Metric.ball 0 1) := by refine eq_const_of_exists_le (fun q hq ↦ ?_) (exp_nonneg (-π)) ?_ (fun q hq ↦ ?_) From fda7c119519fa3cb4172fb7054126d5ced7eab9f Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:24:16 +0100 Subject: [PATCH 04/61] chore(NumberTheory/ModularForms): inline more haves in dimension formula proofs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `discriminant_eq_E4_cube_sub_E6_sq`: hoist `hmcast` (used 3x) above its use, drop redundant calc step `_ = (CuspForm.toModularFormₗ g) z := rfl` - `weight_two_eq_zero_of_not_cuspForm`: drop `hc0`, fold the c4/c6 substitutions directly into `heq4`/`heq6` rather than via separate `hc4_eq`/`hc6_eq` + `rw`, replace the by_contra finale with `pow_eq_zero_iff`/`mul_eq_zero` Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 7ddac2e6cffd59..578278f6f050de 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -280,6 +280,9 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : obtain ⟨g, hg⟩ := hF_cusp obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g have hc_eq : c = 1728 := by + have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), + qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := + fun _ _ ↦ rfl have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by congr 1; exact congr_arg DFunLike.coe hg have hgΔ : qExpansion 1 (g : ℍ → ℂ) = @@ -290,9 +293,6 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, mul_one] at h - have hmcast : ∀ (a b : ℤ) (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := - fun _ _ _ _ ↦ rfl have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) (ModularForm.mcast (by norm_num) (E6.mul E6)) @@ -311,21 +311,18 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : Function.Embedding.refl_apply, h1_4, h1_6] at h exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) - have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := by + have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] _ = (c • discriminantCuspForm) z := rfl _ = g z := by rw [← hc] - _ = (CuspForm.toModularFormₗ g) z := rfl - _ = F z := by rw [hg] + _ = F z := congr_fun (congr_arg DFunLike.coe hg) z _ = E4 z ^ 3 - E6 z ^ 2 := hF z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) (hf : ¬IsCuspForm f) : f = 0 := by exfalso - have hc0 : (qExpansion 1 f).coeff 0 ≠ 0 := - fun h ↦ hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr h) obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one (E_ne_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩) (f.mul f) obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one @@ -338,8 +335,7 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : (E (show 3 ≤ 4 by norm_num)) rw [show (c4 • E (show 3 ≤ 4 by norm_num) : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] - exact hsmul.symm + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm have hqc6 : c6 • p6 = p * p * p := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 (E (show 3 ≤ 6 by norm_num)) @@ -352,36 +348,35 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ have hp6_0 : p6.coeff 0 = 1 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ - have hc4_eq : c4 = p.coeff 0 ^ 2 := by + have h0_4 : c4 = p.coeff 0 ^ 2 := by have h := congr_arg (·.coeff 0) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp4_0, mul_one] at h rw [sq]; exact h - have hc6_eq : c6 = p.coeff 0 ^ 3 := by + have h0_6 : c6 = p.coeff 0 ^ 3 := by have h := congr_arg (·.coeff 0) hqc6 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h have hp4_1 : p4.coeff 1 = 240 := E_qExpansion_coeff_one_four have hp6_1 : p6.coeff 1 = -504 := E_qExpansion_coeff_one_six - have heq4 : c4 * 240 = 2 * p.coeff 0 * p.coeff 1 := by + have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h exact h - have heq6 : c6 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by + have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc6 simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring] at h + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h exact h - rw [hc4_eq] at heq4; rw [hc6_eq] at heq6 - have h1728 : 1728 * p.coeff 0 ^ 3 = 0 := by + refine hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr <| + pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_) + have h0 : (1728 : ℂ) * p.coeff 0 ^ 3 = 0 := by linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 - exact hc0 (by - by_contra h - exact absurd h1728 (mul_ne_zero (by norm_num : (1728 : ℂ) ≠ 0) (pow_ne_zero 3 h))) + exact (mul_eq_zero.mp h0).resolve_left (by norm_num) /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : From 563616ad36a66fab91253078f0c0eeb41b7b78b7 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:31:48 +0100 Subject: [PATCH 05/61] =?UTF-8?q?feat(NumberTheory/ModularForms):=20add=20?= =?UTF-8?q?E=E2=82=84=20and=20E=E2=82=86=20abbreviations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add public `noncomputable abbrev`s `ModularForm.E₄ : ModularForm 𝒮ℒ 4` and `ModularForm.E₆ : ModularForm 𝒮ℒ 6` for the normalised level 1 Eisenstein series of weights 4 and 6. Use them throughout `DimensionFormulas/LevelOne.lean` to drop the awkward `E (show 3 ≤ 4 by norm_num)` and `set E4 := …` patterns. The `abbrev` (rather than `def` or notation) is required so all uses share a single underlying proof of `3 ≤ 4` / `3 ≤ 6`, which lets simp lemmas about their q-expansions match consistently. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 114 ++++++++---------- .../ModularForms/EisensteinSeries/Basic.lean | 6 + 2 files changed, 58 insertions(+), 62 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 578278f6f050de..51ba125cbfbe19 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -227,18 +227,18 @@ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨3, rfl⟩).trans ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) -private lemma E_qExpansion_coeff_one_four : - (qExpansion 1 (E (show 3 ≤ 4 by norm_num))).coeff 1 = 240 := by - rw [E_qExpansion_coeff (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩] - simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] +private lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by + rw [show (E₄ : ModularForm 𝒮ℒ 4) = E (by norm_num : (3 : ℕ) ≤ 4) from rfl, + E_qExpansion_coeff _ ⟨2, rfl⟩] + simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] simp [ArithmeticFunction.sigma_one]; norm_num -private lemma E_qExpansion_coeff_one_six : - (qExpansion 1 (E (show 3 ≤ 6 by norm_num))).coeff 1 = -504 := by - rw [E_qExpansion_coeff (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩] - simp only [show (1 : ℕ) ≠ 0 from one_ne_zero, ↓reduceIte] +private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by + rw [show (E₆ : ModularForm 𝒮ℒ 6) = E (by norm_num : (3 : ℕ) ≤ 6) from rfl, + E_qExpansion_coeff _ ⟨3, rfl⟩] + simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] norm_num [Finset.sum_range_succ, Finset.sum_range_zero, @@ -248,33 +248,32 @@ private lemma E_qExpansion_coeff_one_six : /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : - discriminant z = (1 / 1728) * - (E (show 3 ≤ 4 by norm_num) z ^ 3 - E (show 3 ≤ 6 by norm_num) z ^ 2) := by - set E4 := E (show 3 ≤ 4 by norm_num) - set E6 := E (show 3 ≤ 6 by norm_num) + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by set F : ModularForm 𝒮ℒ 12 := ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) - (E4.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E4.mul E4))) - - ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E6.mul E6) - have hF : ∀ w, F w = E4 w ^ 3 - E6 w ^ 2 := fun w ↦ by - change E4 w * (E4 w * E4 w) - E6 w * E6 w = E4 w ^ 3 - E6 w ^ 2; ring - have h0_4 := E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ - have h0_6 := E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + (E₄.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E₄.mul E₄))) - + ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) + have hF : ∀ w, F w = E₄ w ^ 3 - E₆ w ^ 2 := fun w ↦ by + change E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w = E₄ w ^ 3 - E₆ w ^ 2; ring + have h0_4 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨2, rfl⟩ + have h0_6 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨3, rfl⟩ have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] - have hv4 : valueAtInfty (E4 : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E4 one_pos one_mem_strictPeriods_SL] - have hv6 : valueAtInfty (E6 : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E6 one_pos one_mem_strictPeriods_SL] - change limUnder atImInfty (fun w ↦ E4 w * (E4 w * E4 w) - E6 w * E6 w) = 0 - have htend : ∀ (k' : ℤ) (f : ModularForm 𝒮ℒ k') (c' : ℂ) (_ : valueAtInfty f = c'), - Filter.Tendsto f atImInfty (𝓝 c') := fun _ f c' hv ↦ by + have hv4 : valueAtInfty (E₄ : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] + have hv6 : valueAtInfty (E₆ : ℍ → ℂ) = 1 := by + rwa [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] + change limUnder atImInfty (fun w ↦ E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w) = 0 + have htend : ∀ {k' : ℤ} (f : ModularForm 𝒮ℒ k') {c' : ℂ}, valueAtInfty (f : ℍ → ℂ) = c' → + Filter.Tendsto f atImInfty (𝓝 c') := fun {_} f {_} hv ↦ by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) - have h4 := htend _ E4 _ hv4 - have h6 := htend _ E6 _ hv6 + have h4 := htend E₄ hv4 + have h6 := htend E₆ hv6 convert ((h4.mul (h4.mul h4)).sub (h6.mul h6)).limUnder_eq using 1 norm_num) obtain ⟨g, hg⟩ := hF_cusp @@ -294,60 +293,53 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, mul_one] at h have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E4.mul (ModularForm.mcast rfl (E4.mul E4)))) - (ModularForm.mcast (by norm_num) (E6.mul E6)) + (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 - (ModularForm.mcast rfl (E4.mul E4))] at h + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ + (ModularForm.mcast rfl (E₄.mul E₄))] at h simp only [hmcast] at h - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E4 E4, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E6 E6] at h - have h1_4 : (PowerSeries.coeff 1) (qExpansion 1 E4) = 240 := E_qExpansion_coeff_one_four - have h1_6 : (PowerSeries.coeff 1) (qExpansion 1 E6) = -504 := E_qExpansion_coeff_one_six + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] at h simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, Finset.map_singleton, Function.Embedding.prodMap, Prod.map, Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, - Function.Embedding.refl_apply, h1_4, h1_6] at h - exact h.symm.trans (by norm_num [show (PowerSeries.coeff 0) (qExpansion 1 (E4 : ℍ → ℂ)) = 1 - from h0_4, show (PowerSeries.coeff 0) (qExpansion 1 (E6 : ℍ → ℂ)) = 1 from h0_6]) - have h1728 : (1728 : ℂ) * discriminant z = E4 z ^ 3 - E6 z ^ 2 := + Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one] at h + exact h.symm.trans (by norm_num [h0_4, h0_6]) + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] _ = (c • discriminantCuspForm) z := rfl _ = g z := by rw [← hc] _ = F z := congr_fun (congr_arg DFunLike.coe hg) z - _ = E4 z ^ 3 - E6 z ^ 2 := hF z + _ = E₄ z ^ 3 - E₆ z ^ 2 := hF z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) (hf : ¬IsCuspForm f) : f = 0 := by exfalso obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one - (E_ne_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩) (f.mul f) + (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one - (E_ne_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩) ((f.mul f).mul f) + (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) set p := qExpansion 1 f - set p4 := qExpansion 1 (E (show 3 ≤ 4 by norm_num)) - set p6 := qExpansion 1 (E (show 3 ≤ 6 by norm_num)) - have hqc4 : c4 • p4 = p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 - (E (show 3 ≤ 4 by norm_num)) - rw [show (c4 • E (show 3 ≤ 4 by norm_num) : ℍ → ℂ) = - (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul + have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm - have hqc6 : c6 • p6 = p * p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 - (E (show 3 ≤ 6 by norm_num)) + have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = p * p * p := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E (show 3 ≤ 6 by norm_num) : ℍ → ℂ) = - ((f.mul f).mul f : ℍ → ℂ) from congrArg DFunLike.coe hc6] at hsmul + rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from + congrArg DFunLike.coe hc6] at hsmul rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 rw [← hmul1]; exact hsmul.symm - have hp4_0 : p4.coeff 0 = 1 := - E_qExpansion_coeff_zero (show 3 ≤ 4 by norm_num) ⟨2, rfl⟩ - have hp6_0 : p6.coeff 0 = 1 := - E_qExpansion_coeff_zero (show 3 ≤ 6 by norm_num) ⟨3, rfl⟩ + have hp4_0 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨2, rfl⟩ + have hp6_0 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := + E_qExpansion_coeff_zero _ ⟨3, rfl⟩ have h0_4 : c4 = p.coeff 0 ^ 2 := by have h := congr_arg (·.coeff 0) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, @@ -358,17 +350,15 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h - have hp4_1 : p4.coeff 1 = 240 := E_qExpansion_coeff_one_four - have hp6_1 : p6.coeff 1 = -504 := E_qExpansion_coeff_one_six have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, E₄_qExpansion_coeff_one] at h rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h exact h have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, E₆_qExpansion_coeff_one] at h rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h exact h diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean index e6e4c33ee3bf95..62b0a89b7fadf2 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/Basic.lean @@ -48,4 +48,10 @@ noncomputable def E {k : ℕ} (hk : 3 ≤ k) : ModularForm 𝒮ℒ k := ((1 / 2 : ℂ) • eisensteinSeriesMF (mod_cast hk) 0).ofSubgroupEq CongruenceSubgroup.Gamma_one_coe_eq_SL +/-- The normalised level 1 Eisenstein series of weight 4. -/ +noncomputable abbrev E₄ : ModularForm 𝒮ℒ 4 := E (by norm_num : (3 : ℕ) ≤ 4) + +/-- The normalised level 1 Eisenstein series of weight 6. -/ +noncomputable abbrev E₆ : ModularForm 𝒮ℒ 6 := E (by norm_num : (3 : ℕ) ≤ 6) + end ModularForm From ba215366fc3bb3271ef290a0e5cd7e54cd7e9829 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 10:38:59 +0100 Subject: [PATCH 06/61] golf --- Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index 42f695b0886447..a9b6378449a2f0 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -46,8 +46,8 @@ def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k { toSlashInvariantForm := f.toSlashInvariantForm holo' := f.holo' bdd_at_cusps' := fun hc g hg ↦ (f.zero_at_cusps' hc g hg).boundedAtFilter } - map_add' _ _ := by ext; rfl - map_smul' _ _ := by ext; rfl + map_add' _ _ := rfl + map_smul' _ _ := rfl @[simp] lemma toModularFormₗ_apply [Γ.HasDetOne] (f : CuspForm Γ k) (z : ℍ) : From 58ce4e1e1504910e36bd45bdf75b0abe9735779e Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 12:56:10 +0100 Subject: [PATCH 07/61] feat(Algebra/Order/Floor/Semifield): add `Nat.floor_div_eq_one_add_floor_sub_div` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the lemma `⌊k / a⌋₊ = 1 + ⌊(k - a) / a⌋₊` for `0 < a ≤ k` over a linear ordered field, generalising the local `floor_lem1` helper that was buried in `DimensionFormulas/LevelOne.lean`. Inline the helper at its single use site in `dimension_level_one`. Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib/Algebra/Order/Floor/Semifield.lean | 5 +++++ .../DimensionFormulas/LevelOne.lean | 19 +++++++------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Mathlib/Algebra/Order/Floor/Semifield.lean b/Mathlib/Algebra/Order/Floor/Semifield.lean index 4690b6da5f5b2d..5a78c62a053682 100644 --- a/Mathlib/Algebra/Order/Floor/Semifield.lean +++ b/Mathlib/Algebra/Order/Floor/Semifield.lean @@ -53,6 +53,11 @@ end LinearOrderedSemifield section LinearOrderedField variable [Field K] [LinearOrder K] [IsStrictOrderedRing K] [FloorSemiring K] {a b : K} +theorem floor_div_eq_one_add_floor_sub_div (k a : K) (ha : 0 < a) (hak : a ≤ k) : + ⌊k / a⌋₊ = 1 + ⌊(k - a) / a⌋₊ := by + rw [sub_div, div_self ha.ne', Nat.floor_sub_one] + exact (Nat.add_sub_cancel' (Nat.le_floor (mod_cast (one_le_div₀ ha).mpr hak))).symm + lemma mul_lt_floor (hb₀ : 0 < b) (hb : b < 1) (hba : ⌈b / (1 - b)⌉₊ ≤ a) : b * a < ⌊a⌋₊ := by calc b * a < b * (⌊a⌋₊ + 1) := by gcongr; apply lt_floor_add_one diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 51ba125cbfbe19..f137c1580b49f3 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -3,6 +3,7 @@ Copyright (c) 2026 Chris Birkbeck. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ +import Mathlib.Algebra.Order.Floor.Semifield import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule import Mathlib.NumberTheory.ModularForms.Discriminant import Mathlib.Data.Rat.Star @@ -380,15 +381,6 @@ theorem ModularForm.levelOne_weight_two_rank_zero : (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf -private lemma floor_lem1 (k a : ℚ) (ha : 0 < a) (hak : a ≤ k) : - 1 + Nat.floor ((k - a) / a) = Nat.floor (k / a) := by - rw [div_sub_same (Ne.symm (ne_of_lt ha))] - have := Nat.floor_sub_one (k / a) - push_cast at * - rw [this] - refine Nat.add_sub_cancel' ?_ - exact Nat.le_floor ((le_div_iff₀ ha).mpr (by simpa using hak)) - /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = @@ -404,13 +396,16 @@ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : norm_cast; exact Eq.symm (Int.subNatNat_of_le (by omega)) rw [hk12] at iH rw [iH, show ((k - 12 : ℕ) : ℚ) = (k : ℚ) - 12 from by norm_cast] - have hfl := floor_lem1 k 12 (by norm_num) + have hfl (hk' : (12 : ℚ) ≤ k) : + ⌊(k : ℚ) / 12⌋₊ = 1 + ⌊((k : ℚ) - 12) / 12⌋₊ := + Nat.floor_div_eq_one_add_floor_sub_div (k : ℚ) 12 (by norm_num) hk' by_cases h12 : 12 ∣ ((k) : ℤ) - 2 · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] - norm_cast at *; apply hfl; omega + norm_cast at *; rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, Nat.cast_add, Nat.cast_one] - norm_cast at *; rw [← add_assoc, hfl]; omega + norm_cast at * + rw [← add_assoc, ← hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [not_le] at HK have hkop : k ∈ Finset.filter Even (Finset.Icc 3 14) := by simp only [Finset.mem_filter, Finset.mem_Icc, hk2, and_true]; omega From c9064312d2e432a6421e3ae841b4fed249148d36 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 13:22:51 +0100 Subject: [PATCH 08/61] refactor(NumberTheory/ModularForms): pull q-coordinate eta-product helpers up to DedekindEta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds three q-coordinate lemmas to `DedekindEta.lean`: - `multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1)`: pointwise multipliability - `multipliableLocallyUniformlyOn_one_sub_pow`: local uniform convergence on the open unit disc - `differentiableOn_tprod_one_sub_pow_pow (k : ℕ)`: differentiability of the k-th power of the product on the open unit disc These cover the case `q = 0` (the cusp at infinity), which the existing eta-side lemmas (`multipliableLocallyUniformlyOn_eta` etc., stated on `ℍₒ`) cannot. In `Discriminant.lean`, deletes the three private helpers `multipliable_one_sub_pow`, `tendstoLocallyUniformlyOn_eta_prod`, `differentiableWithinAt_eta_prod_pow`, and rewrites `discriminant_cuspFunction_eqOn` and `discriminant_qExpansion_coeff_one` to work on the full open unit disc `Metric.ball 0 1` (instead of the arbitrary `Metric.ball 0 (1/2)`) and to call the new helpers from `DedekindEta.lean`. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/DedekindEta.lean | 54 +++++++++++++++ .../ModularForms/Discriminant.lean | 69 +++---------------- 2 files changed, 65 insertions(+), 58 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index b2905265b4ee9b..3ecd57ab784478 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -65,6 +65,60 @@ noncomputable def eta (z : ℂ) := 𝕢 24 z * ∏' n, (1 - eta_q n z) /-- Notation for the Dedekind eta function. -/ scoped[ModularForm] notation "η" => eta +/-! ### q-coordinate facts about `∏ (1 - q^(n+1))` + +The following lemmas describe the analytic behaviour of the infinite product +`∏' n, (1 - q^(n+1))` viewed as a function of `q` on the open unit disc, including the +behaviour at `q = 0` (the cusp at infinity). The eta-side lemmas below derive from these +by pulling back along `qParam 1 : ℍₒ → 𝔻 \ {0}`. +-/ + +/-- For `‖q‖ < 1`, the infinite product `∏ (1 - q^(n+1))` is multipliable. -/ +lemma multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1) : + Multipliable fun n : ℕ ↦ 1 - q ^ (n + 1) := by + rw [show (fun n : ℕ ↦ 1 - q ^ (n + 1)) = (fun n ↦ 1 + (-q ^ (n + 1))) from by ext; ring] + apply multipliable_one_add_of_summable + simp only [norm_neg, norm_pow] + exact (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) + +/-- The infinite product `∏ (1 - q^(n+1))` converges locally uniformly on the open unit disc, +with limit `q ↦ ∏' n, (1 - q^(n+1))`. -/ +lemma multipliableLocallyUniformlyOn_one_sub_pow : + MultipliableLocallyUniformlyOn (fun n q ↦ 1 - q ^ (n + 1)) (Metric.ball (0 : ℂ) 1) := by + use fun q ↦ ∏' n, (1 - q ^ (n + 1)) + simp_rw [sub_eq_add_neg] + apply hasProdLocallyUniformlyOn_of_forall_compact Metric.isOpen_ball + intro K hK hcK + by_cases hN : K.Nonempty + · have hc : ContinuousOn (fun q : ℂ ↦ ‖q‖) K := by fun_prop + obtain ⟨q₀, hq₀, _, HB⟩ := hcK.exists_sSup_image_eq_and_ge hN hc + have hq₀_lt : ‖q₀‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hK hq₀ + have hsum : Summable fun n : ℕ ↦ ‖q₀‖ ^ (n + 1) := + (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq₀_lt) + refine hsum.hasProdUniformlyOn_nat_one_add hcK (.of_forall fun n x hx ↦ ?_) + (fun _ ↦ by fun_prop) + simpa [norm_pow] using pow_le_pow_left₀ (norm_nonneg _) (HB x hx) (n + 1) + · rw [hasProdUniformlyOn_iff_tendstoUniformlyOn] + simpa [not_nonempty_iff_eq_empty.mp hN] using tendstoUniformlyOn_empty + +/-- The infinite product `q ↦ ∏' n, (1 - q^(n+1))` is differentiable on the open unit disc. -/ +lemma differentiableOn_tprod_one_sub_pow : + DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1))) (Metric.ball (0 : ℂ) 1) := by + apply multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn.differentiableOn + ?_ Metric.isOpen_ball + filter_upwards with n + simpa [Finset.prod_fn] using DifferentiableOn.finset_prod (fun _ _ ↦ by fun_prop) + +/-- For any `k`, the function `q ↦ ∏' n, (1 - q^(n+1))^k` is differentiable on the +open unit disc. -/ +lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : + DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1)) ^ k) (Metric.ball (0 : ℂ) 1) := by + refine (differentiableOn_tprod_one_sub_pow.fun_pow k).congr fun q hq ↦ ?_ + have hq_lt : ‖q‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hq + exact (multipliable_one_sub_pow hq_lt).tprod_pow k + +/-! ### z-coordinate eta product facts (derived from q-coordinate versions) -/ + theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by simp [eta_q, eta_q_eq_pow, summable_nat_add_iff 1, norm_exp_two_pi_I_lt_one z] diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index fbca87f567f656..4fb13197343168 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -194,87 +194,40 @@ def discriminantCuspForm : CuspForm 𝒮ℒ 12 where rw [slash_action_generators_SL2Z discriminant_S_invariant discriminant_T_invariant] exact discriminant_isZeroAtImInfty -/-- The infinite product `∏ (1 - q^(n+1))` is multipliable for `‖q‖ < 1`. -/ -private lemma multipliable_one_sub_pow {q : ℂ} (hq : ‖q‖ < 1) : - Multipliable fun i ↦ 1 - q ^ (i + 1) := by - rw [show (fun i ↦ 1 - q ^ (i + 1)) = (fun i ↦ 1 + (-q ^ (i + 1))) from by ext; ring] - apply multipliable_one_add_of_summable - simp only [norm_neg, norm_pow] - exact (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) - /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` -on `ball 0 (1/2)`. -/ +on the open unit disc. -/ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 · simp only [hq0, zero_mul] exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex - · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) + · have hqn : ‖q‖ < 1 := by simpa [dist_zero_right] using hq have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] - -- eta_q n z = (qParam 1 z)^(n+1), and qParam(invQParam(q)) = q have hqr := Periodic.qParam_right_inv one_ne_zero hq0 have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by simp [eta_q, hqr] simp only [hqr, heta] -/-- The partial products `∏_{i simp [differentiableOn_const] - | succ n ih => - simp_rw [Finset.prod_range_succ]; exact ih.mul (by fun_prop)) - Metric.isOpen_ball - have hmem := Metric.mem_ball_self (x := (0 : ℂ)) (by norm_num : (0 : ℝ) < 1 / 2) - -- (∏(1-q^(n+1)))^24 is differentiable as a power of a differentiable function - have h24 := (hdiff 0 hmem).pow (n := 24) - -- ∏(1-q^(n+1))^24 = (∏(1-q^(n+1)))^24 by tprod_pow, so congr gives differentiability - refine h24.congr (fun q hq ↦ ?_) (by simp) - exact (multipliable_one_sub_pow (lt_trans (by simpa [dist_zero_right] using hq) - (by norm_num : (1 : ℝ) / 2 < 1))).tprod_pow 24 - /-- The first q-expansion coefficient of the modular discriminant is 1. -/ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 (discriminantCuspForm : ℍ → ℂ)).coeff 1 = 1 := by rw [qExpansion_coeff] simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, iteratedDeriv_zero] - have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos change deriv (cuspFunction 1 Δ) 0 = 1 - rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] - rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] - have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = - derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + - id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := - derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow - rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem, + derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), + show (fun q : ℂ ↦ q * ∏' n, (1 - q ^ (n + 1)) ^ 24) = + (fun q ↦ id q * ∏' n, (1 - q ^ (n + 1)) ^ 24) from rfl, + derivWithin_fun_mul differentiableWithinAt_id + (differentiableOn_tprod_one_sub_pow_pow 24 0 hmem), + derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] simp end From 4870bfc8b33fdf25a1bfecba326d9bd281bc51da Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 13:53:27 +0100 Subject: [PATCH 09/61] refactor(NumberTheory/ModularForms): derive z-coord eta lemmas from q-coord base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than having parallel q-coord and z-coord proofs of the same convergence facts about the eta product, derive the z-coord versions from the q-coord ones by composing with `Periodic.qParam 1 : ℍₒ → Metric.ball 0 1`. - `multipliableLocallyUniformlyOn_eta` is now derived from `multipliableLocallyUniformlyOn_one_sub_pow` via `TendstoLocallyUniformlyOn.comp`, shrinking the proof from ~14 lines to ~7. - `differentiableAt_eta_tprod` now derives from `differentiableOn_tprod_one_sub_pow` by chain rule (instead of going through the eta-side multipliable lemma). - `summable_eta_q` switched to `norm_qParam_lt_one` (which the q-coord material already uses) for consistency. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/DedekindEta.lean | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 3ecd57ab784478..55411f1649cb51 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -120,24 +120,21 @@ lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : /-! ### z-coordinate eta product facts (derived from q-coordinate versions) -/ theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by - simp [eta_q, eta_q_eq_pow, summable_nat_add_iff 1, norm_exp_two_pi_I_lt_one z] + have hq : ‖(𝕢 (1 : ℝ) ↑z : ℂ)‖ < 1 := by exact_mod_cast norm_qParam_lt_one 1 z + simpa only [norm_neg, eta_q, norm_pow] using + (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) lemma multipliableLocallyUniformlyOn_eta : MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := by - use fun z ↦ ∏' n, (1 - eta_q n z) - simp_rw [sub_eq_add_neg] - apply hasProdLocallyUniformlyOn_of_forall_compact isOpen_upperHalfPlaneSet - intro K hK hcK - by_cases hN : K.Nonempty - · have hc : ContinuousOn (fun x ↦ ‖cexp (2 * π * I * x)‖) K := by fun_prop - obtain ⟨z, hz, hB, HB⟩ := hcK.exists_sSup_image_eq_and_ge hN hc - apply (summable_eta_q ⟨z, hK hz⟩).hasProdUniformlyOn_nat_one_add hcK - · filter_upwards with n x hx - simpa [eta_q, eta_q_eq_pow] using pow_le_pow_left₀ (by simp [norm_nonneg]) (HB x hx) _ - · simp_rw [eta_q, Periodic.qParam] - fun_prop - · rw [hasProdUniformlyOn_iff_tendstoUniformlyOn] - simpa [not_nonempty_iff_eq_empty.mp hN] using tendstoUniformlyOn_empty + refine ⟨fun z ↦ ∏' n, (1 - eta_q n z), ?_⟩ + rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] + have h := multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn + rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] at h + exact h.comp (Periodic.qParam 1) + (fun z hz ↦ by + simpa [Metric.mem_ball, dist_zero_right] using + (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) + (by fun_prop) lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ @@ -179,10 +176,11 @@ lemma tsum_logDeriv_eta_q (z : ℂ) : ∑' n, logDeriv (fun x ↦ 1 - eta_q n x) lemma differentiableAt_eta_tprod {z : ℂ} (hz : z ∈ ℍₒ) : DifferentiableAt ℂ (fun x ↦ ∏' n, (1 - eta_q n x)) z := by - apply (multipliableLocallyUniformlyOn_eta.hasProdLocallyUniformlyOn.differentiableOn ?_ - isOpen_upperHalfPlaneSet z hz).differentiableAt (isOpen_upperHalfPlaneSet.mem_nhds hz) - filter_upwards with b - simpa [Finset.prod_fn] using DifferentiableOn.finset_prod (by fun_prop) + have hq : (𝕢 (1 : ℝ) z : ℂ) ∈ Metric.ball (0 : ℂ) 1 := by + simpa [Metric.mem_ball, dist_zero_right] using + (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1) + exact (((differentiableOn_tprod_one_sub_pow).differentiableAt + (Metric.isOpen_ball.mem_nhds hq)).comp z (by fun_prop : DifferentiableAt ℂ (𝕢 (1 : ℝ)) z)) theorem differentiableAt_eta_of_mem_upperHalfPlaneSet {z : ℂ} (hz : z ∈ ℍₒ) : DifferentiableAt ℂ eta z := From 53ec44010ea7c2c03c80ba923cd520e503ab0348 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:00:40 +0100 Subject: [PATCH 10/61] chore(NumberTheory/ModularForms): shorten `multipliableLocallyUniformlyOn_eta` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn` is `Iff.rfl`, so the two `rw` calls in the previous proof are unnecessary — a type ascription on the underlying `HasProdLocallyUniformlyOn` is enough to invoke `TendstoLocallyUniformlyOn.comp` via dot notation. Collapse the proof to a 6-line term-mode expression. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../NumberTheory/ModularForms/DedekindEta.lean | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 55411f1649cb51..1b5e52c6561510 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -125,16 +125,12 @@ theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) lemma multipliableLocallyUniformlyOn_eta : - MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := by - refine ⟨fun z ↦ ∏' n, (1 - eta_q n z), ?_⟩ - rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] - have h := multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn - rw [hasProdLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] at h - exact h.comp (Periodic.qParam 1) - (fun z hz ↦ by - simpa [Metric.mem_ball, dist_zero_right] using - (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) - (by fun_prop) + MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := + ⟨_, (multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn : + TendstoLocallyUniformlyOn _ _ _ _).comp (Periodic.qParam 1) + (fun z hz ↦ by simpa [Metric.mem_ball, dist_zero_right] using + (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) + (by fun_prop)⟩ lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ From 1f1ec2dc04d69cce8c3bb9dfbba35589f7ebd7d5 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:10:52 +0100 Subject: [PATCH 11/61] refactor(NumberTheory/ModularForms): decompose dimension-formula proofs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extracts helper lemmas to shorten the two main proofs: - `tendsto_valueAtInfty`: a modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. Used in `E4_cube_sub_E6_sq_form_isCuspForm`. - `E4_cube_sub_E6_sq_form` (def): the explicit `ModularForm 𝒮ℒ 12` whose pointwise value is `E₄³ - E₆²`, with companion lemmas `_apply`, `_isCuspForm`, `_qExpansion_coeff_one`. The main theorem `discriminant_eq_E4_cube_sub_E6_sq` is now ~15 lines instead of ~70. - `coeffZero_eq_zero_of_pow_eq_smul`: the algebraic core of the weight-2 vanishing argument as a pure power-series fact (no modular forms). `weight_two_eq_zero_of_not_cuspForm` becomes a thin wrapper that transports the modular-form identities into the power-series form, shrinking from ~50 lines to ~25. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 183 ++++++++++-------- 1 file changed, 101 insertions(+), 82 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index f137c1580b49f3..8a517d753cce2b 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -247,100 +247,95 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := bernoulli'_eq_zero_of_odd (show Odd 5 from ⟨2, rfl⟩) (by norm_num)]] simp [ArithmeticFunction.sigma_one]; norm_num -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ -theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : - discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by - set F : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) - (E₄.mul (ModularForm.mcast (show 4 + 4 = 4 + 4 from rfl) (E₄.mul E₄))) - +/-- A modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. -/ +private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) + (hv : valueAtInfty (f : ℍ → ℂ) = c) : Filter.Tendsto f atImInfty (𝓝 c) := by + rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL + ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + +/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ +private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) + (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) - have hF : ∀ w, F w = E₄ w ^ 3 - E₆ w ^ 2 := fun w ↦ by - change E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w = E₄ w ^ 3 - E₆ w ^ 2; ring + +private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : + E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by + change E₄ z * (E₄ z * E₄ z) - E₆ z * E₆ z = _; ring + +private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + rw [qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] + have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₄ 1 (by + rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩) + have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₆ 1 (by + rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩) + refine ((Filter.Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq + simpa using (h4.pow 3).sub (h6.pow 2) + +private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : + (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by + have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), + qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := + fun _ _ ↦ rfl have h0_4 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := E_qExpansion_coeff_zero _ ⟨2, rfl⟩ have h0_6 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := E_qExpansion_coeff_zero _ ⟨3, rfl⟩ - have hF_cusp : IsCuspForm F := (isCuspForm_iff_coeffZero_eq_zero F).mpr (by - rw [qExpansion_coeff_zero F one_pos one_mem_strictPeriods_SL] - have hv4 : valueAtInfty (E₄ : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] - have hv6 : valueAtInfty (E₆ : ℍ → ℂ) = 1 := by - rwa [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] - change limUnder atImInfty (fun w ↦ E₄ w * (E₄ w * E₄ w) - E₆ w * E₆ w) = 0 - have htend : ∀ {k' : ℤ} (f : ModularForm 𝒮ℒ k') {c' : ℂ}, valueAtInfty (f : ℍ → ℂ) = c' → - Filter.Tendsto f atImInfty (𝓝 c') := fun {_} f {_} hv ↦ by - rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL - ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr - (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) - have h4 := htend E₄ hv4 - have h6 := htend E₆ hv6 - convert ((h4.mul (h4.mul h4)).sub (h6.mul h6)).limUnder_eq using 1 - norm_num) - obtain ⟨g, hg⟩ := hF_cusp + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub + (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub + rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + (((ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12)) : ℍ → ℂ) from rfl, + hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ + (ModularForm.mcast rfl (E₄.mul E₄)), hmcast, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, + Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, + Finset.map_singleton, Function.Embedding.prodMap, Prod.map, + Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, + Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one] + norm_num [h0_4, h0_6] + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by + obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g + have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) := by + congr 1; exact congr_arg DFunLike.coe hg + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) + from congr_arg DFunLike.coe hc.symm] + exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have hc_eq : c = 1728 := by - have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := - fun _ _ ↦ rfl - have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (F : ℍ → ℂ) := by - congr 1; exact congr_arg DFunLike.coe hg - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = - c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by - conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) - from congr_arg DFunLike.coe hc.symm] - exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, - mul_one] at h - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ - (ModularForm.mcast rfl (E₄.mul E₄))] at h - simp only [hmcast] at h - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] at h - simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, - Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, - Finset.map_singleton, Function.Embedding.prodMap, Prod.map, - Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, - Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, - E₆_qExpansion_coeff_one] at h - exact h.symm.trans (by norm_num [h0_4, h0_6]) + mul_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] at h + exact h.symm have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] _ = (c • discriminantCuspForm) z := rfl _ = g z := by rw [← hc] - _ = F z := congr_fun (congr_arg DFunLike.coe hg) z - _ = E₄ z ^ 3 - E₆ z ^ 2 := hF z + _ = E4_cube_sub_E6_sq_form z := congr_fun (congr_arg DFunLike.coe hg) z + _ = _ := E4_cube_sub_E6_sq_form_apply z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 -private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) - (hf : ¬IsCuspForm f) : f = 0 := by - exfalso - obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one - (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) - obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one - (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) - set p := qExpansion 1 f - have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm - have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = p * p * p := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ - have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from - congrArg DFunLike.coe hc6] at hsmul - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 - rw [← hmul1]; exact hsmul.symm - have hp4_0 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨2, rfl⟩ - have hp6_0 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨3, rfl⟩ +/-- Algebraic core of the weight-2 vanishing argument: if a complex power series `p` +satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant +terms equal to `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ +private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} + (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) + (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) + (hqc4 : c4 • p4 = p * p) (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by have h0_4 : c4 = p.coeff 0 ^ 2 := by have h := congr_arg (·.coeff 0) hqc4 simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, @@ -353,22 +348,46 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, E₄_qExpansion_coeff_one] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h exact h have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by have h := congr_arg (·.coeff 1) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, E₆_qExpansion_coeff_one] at h + simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h exact h - refine hf ((isCuspForm_iff_coeffZero_eq_zero f).mpr <| - pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_) + refine pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_ have h0 : (1728 : ℂ) * p.coeff 0 ^ 3 = 0 := by linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) + (hf : ¬IsCuspForm f) : f = 0 := by + exfalso + obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one + (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) + obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one + (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) + have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm + have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ + have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f + rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from + congrArg DFunLike.coe hc6] at hsmul + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 + rw [← hmul1]; exact hsmul.symm + exact hf <| (isCuspForm_iff_coeffZero_eq_zero f).mpr <| + coeffZero_eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) + (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one + hqc4 hqc6 + /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : Module.rank ℂ (ModularForm 𝒮ℒ (2 : ℤ)) = 0 := by From 9aee73773e5d6e237461aad506059c0360f8acc1 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:15:17 +0100 Subject: [PATCH 12/61] chore(NumberTheory/ModularForms): tighten dimension-formula proofs after decomposition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `discriminant_eq_E4_cube_sub_E6_sq`: move `hgΔ` back inside the local `hc_eq` block (it's only used there), inline `hgF`, and use `simpa` for the final step. - `E4_cube_sub_E6_sq_form_qExpansion_coeff_one`: minor simplification collapsing the chained `mcast`/`hmcast` rewrites. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 8a517d753cce2b..4e6c1ecc087c40 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -290,11 +290,10 @@ private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) (ModularForm.mcast (by norm_num) (E₆.mul E₆)) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - (((ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12)) : ℍ → ℂ) from rfl, - hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ - (ModularForm.mcast rfl (E₄.mul E₄)), hmcast, + rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = ((ModularForm.mcast (by norm_num) + (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, + hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, @@ -309,17 +308,16 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g - have hgF : qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) := by - congr 1; exact congr_arg DFunLike.coe hg - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by - conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) - from congr_arg DFunLike.coe hc.symm] - exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have hc_eq : c = 1728 := by - have h := congr_arg (·.coeff 1) (hgF.symm.trans hgΔ) - simp only [PowerSeries.coeff_smul, smul_eq_mul, discriminant_qExpansion_coeff_one, - mul_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] at h - exact h.symm + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) + from congr_arg DFunLike.coe hc.symm] + exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm + have h := congr_arg (·.coeff 1) <| + (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) + from congr_arg _ (congr_arg DFunLike.coe hg)).symm.trans hgΔ + simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, + E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := calc (1728 : ℂ) * discriminant z = c * discriminant z := by rw [hc_eq] From b8144c96040403f80814561bc005ac180eb6e4ff Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 14:18:38 +0100 Subject: [PATCH 13/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20wrap?= =?UTF-8?q?=20long=20lines=20to=20=E2=89=A4=20100=20chars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wraps several lines in the dimension-formula proofs to fit within mathlib's 100-character line length limit. No semantic changes. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DimensionFormulas/LevelOne.lean | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 4e6c1ecc087c40..cbbedae2751b12 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -168,12 +168,14 @@ lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : /-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of cusp forms. -/ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k) : - Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by + Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = + 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ (k : ℤ)) rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ (k : ℤ)) = Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ (k : ℤ))).symm] at h_add - suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ + cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by rw [← h_add, h1] have hE_coeff_zero := E_qExpansion_coeff_zero hk hk2 apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ (k : ℤ)) (E hk)) @@ -268,12 +270,14 @@ private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ rw [qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] - have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₄ 1 (by - rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩) - have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := tendsto_valueAtInfty E₆ 1 (by - rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩) + have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := + tendsto_valueAtInfty E₄ 1 <| by + rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩ + have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := + tendsto_valueAtInfty E₆ 1 <| by + rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩ refine ((Filter.Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq simpa using (h4.pow 3).sub (h6.pow 2) @@ -292,7 +296,8 @@ private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = ((ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) : ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, + ModularForm.mcast (by norm_num) (E₆.mul E₆) : + ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] @@ -309,9 +314,11 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g have hc_eq : c = 1728 := by - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by - conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) - from congr_arg DFunLike.coe hc.symm] + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = + c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + conv_lhs => rw [show (g : ℍ → ℂ) = + ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from + congr_arg DFunLike.coe hc.symm] exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have h := congr_arg (·.coeff 1) <| (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) @@ -327,9 +334,9 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : _ = _ := E4_cube_sub_E6_sq_form_apply z linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 -/-- Algebraic core of the weight-2 vanishing argument: if a complex power series `p` -satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant -terms equal to `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ +/-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies +`c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` +and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) @@ -371,10 +378,13 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f]; exact hsmul.symm + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from + congrArg DFunLike.coe hc4] at hsmul + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] + exact hsmul.symm have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * + qExpansion 1 (f : ℍ → ℂ) := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from From 3ab18d1e84974910ed9bed4f10eec525be5b10aa Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 15:03:59 +0100 Subject: [PATCH 14/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20drop?= =?UTF-8?q?=20redundant=20show=20in=20E=E2=82=84/E=E2=82=86=20qExpansion?= =?UTF-8?q?=20lemmas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `E₄` and `E₆` are `noncomputable abbrev`s, so they reduce automatically and the explicit `show E₄ = E (...) from rfl` step in `E₄_qExpansion_coeff_one` and `E₆_qExpansion_coeff_one` was unnecessary. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ModularForms/DimensionFormulas/LevelOne.lean | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index cbbedae2751b12..0c5c61cd10b273 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -231,16 +231,14 @@ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) private lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by - rw [show (E₄ : ModularForm 𝒮ℒ 4) = E (by norm_num : (3 : ℕ) ≤ 4) from rfl, - E_qExpansion_coeff _ ⟨2, rfl⟩] + rw [E_qExpansion_coeff _ ⟨2, rfl⟩] simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] simp [ArithmeticFunction.sigma_one]; norm_num private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by - rw [show (E₆ : ModularForm 𝒮ℒ 6) = E (by norm_num : (3 : ℕ) ≤ 6) from rfl, - E_qExpansion_coeff _ ⟨3, rfl⟩] + rw [E_qExpansion_coeff _ ⟨3, rfl⟩] simp only [one_ne_zero, ↓reduceIte] rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] From 1722006fd8c4487224519f0e8e2fc3bd7134d429 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 16:35:43 +0100 Subject: [PATCH 15/61] some golfs --- .../ModularForms/DedekindEta.lean | 4 +- .../DimensionFormulas/LevelOne.lean | 124 +++++++----------- .../ModularForms/Discriminant.lean | 11 +- 3 files changed, 53 insertions(+), 86 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 1b5e52c6561510..c2abe6a5a5d7d0 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -117,8 +117,6 @@ lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : have hq_lt : ‖q‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hq exact (multipliable_one_sub_pow hq_lt).tprod_pow k -/-! ### z-coordinate eta product facts (derived from q-coordinate versions) -/ - theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by have hq : ‖(𝕢 (1 : ℝ) ↑z : ℂ)‖ < 1 := by exact_mod_cast norm_qParam_lt_one 1 z simpa only [norm_neg, eta_q, norm_pow] using @@ -130,7 +128,7 @@ lemma multipliableLocallyUniformlyOn_eta : TendstoLocallyUniformlyOn _ _ _ _).comp (Periodic.qParam 1) (fun z hz ↦ by simpa [Metric.mem_ball, dist_zero_right] using (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) - (by fun_prop)⟩ + (by fun_prop)⟩ lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0c5c61cd10b273..0db6b772cb4a76 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -39,17 +39,16 @@ namespace CuspForm /-- Multiply a modular form of weight `k - 12` by the discriminant to get a cusp form of weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ -def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := +def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := by let Δ' := CuspForm.toModularFormₗ discriminantCuspForm - ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) (by - have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := - (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans - (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero - rw [show (ModularForm.mcast _ (f.mul Δ') : ℍ → ℂ) = (f : ℍ → ℂ) * Δ' from rfl, - qExpansion_mul_coeff_zero - (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt - (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, - hΔ', mul_zero]) + apply ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) + have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := + (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans + (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero + rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, + qExpansion_mul_coeff_zero + (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt,hΔ', mul_zero] @[simp] lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : @@ -57,9 +56,9 @@ lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, ℤ)) : (fun z ↦ f z / Δ z) ∣[k - 12] γ = fun z ↦ f z / Δ z := by - haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := + have : SlashInvariantFormClass (CuspForm 𝒮ℒ k) (CongruenceSubgroup.Gamma 1) k := CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance - haveI : SlashInvariantFormClass (CuspForm 𝒮ℒ 12) (CongruenceSubgroup.Gamma 1) 12 := + have : SlashInvariantFormClass (CuspForm 𝒮ℒ 12) (CongruenceSubgroup.Gamma 1) 12 := CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance have hf := slash_action_eqn_SL'' f (mem_Gamma_one γ) have hΔ := slash_action_eqn_SL'' discriminantCuspForm (mem_Gamma_one γ) @@ -153,8 +152,7 @@ lemma cuspForm_rank_lt_twelve (hk : k < 12) : /-- The space of weight 12 cusp forms for `𝒮ℒ` has rank 1. -/ lemma cuspForm_rank_twelve : Module.rank ℂ (CuspForm 𝒮ℒ 12) = 1 := by - rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv, - show (12 : ℤ) - 12 = 0 from by norm_num] + rw [LinearEquiv.rank_eq CuspForm.discriminantEquiv, show (12 : ℤ) - 12 = 0 from by norm_num] exact levelOne_weight_zero_rank_one /-- Every weight 12 cusp form for `𝒮ℒ` is a scalar multiple of the discriminant. -/ @@ -186,18 +184,14 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ - cuspFormSubmodule 𝒮ℒ (k : ℤ) := - (isCuspForm_iff_coeffZero_eq_zero _).mpr (by - set c := (qExpansion 1 ↑f).coeff 0 with hc - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (k : ℤ))).map_sub - f (c • E hk) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub - rw [hsub] - have hcoe : ⇑(c • E hk) = c • (E hk : ℍ → ℂ) := rfl - rw [hcoe, qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk)] - simp only [_root_.map_sub, _root_.map_smul, smul_eq_mul, hE_coeff_zero, mul_one, ← hc, - sub_self]) + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ cuspFormSubmodule 𝒮ℒ (k : ℤ) := by + apply (isCuspForm_iff_coeffZero_eq_zero _).mpr + set c := (qExpansion 1 ↑f).coeff 0 with hc + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f (c • E hk) + simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub + rw [hsub] + simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), + _root_.map_sub, _root_.map_smul, hE_coeff_zero, mul_one, ← hc] have h0 : ((cuspFormSubmodule 𝒮ℒ (k : ℤ)).mkQ (f - (qExpansion 1 ↑f).coeff 0 • E hk) : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 0 := (Submodule.Quotient.mk_eq_zero _).mpr h_mem @@ -211,15 +205,6 @@ end RankIdentity section DimensionFormula -/-! ### Helpers for weight 2 proof -/ - -/-- In a rank-one ℂ-module, every element is a scalar multiple of any nonzero element. -This is a thin wrapper around `finrank_eq_one_iff_of_nonzero'` adapted to `Module.rank`. -/ -private lemma exists_smul_eq_of_rank_one {M : Type*} [AddCommGroup M] [Module ℂ M] - (hrank : Module.rank ℂ M = 1) {e : M} (he : e ≠ 0) (f : M) : ∃ c : ℂ, c • e = f := - (finrank_eq_one_iff_of_nonzero' e he).mp - (Module.rank_eq_one_iff_finrank_eq_one.mp hrank) f - /-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨2, rfl⟩).trans @@ -249,10 +234,10 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := /-- A modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. -/ private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) - (hv : valueAtInfty (f : ℍ → ℂ) = c) : Filter.Tendsto f atImInfty (𝓝 c) := by + (hv : valueAtInfty f = c) : Filter.Tendsto f atImInfty (𝓝 c) := by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL - ).continuousAt.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt.tendsto.comp + (qParam_tendsto_atImInfty one_pos)).congr (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ @@ -282,20 +267,13 @@ private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_f private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (ModularForm.mcast h f : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) := - fun _ _ ↦ rfl - have h0_4 : (qExpansion 1 (E₄ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨2, rfl⟩ - have h0_6 : (qExpansion 1 (E₆ : ℍ → ℂ)).coeff 0 = 1 := - E_qExpansion_coeff_zero _ ⟨3, rfl⟩ + qExpansion 1 (mcast h f) = qExpansion 1 (f : ℍ → ℂ) := fun _ _ ↦ rfl have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (ModularForm.mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + (mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) + (mcast (by norm_num) (E₆.mul E₆)) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [show (E4_cube_sub_E6_sq_form : ℍ → ℂ) = ((ModularForm.mcast (by norm_num) - (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) : - ModularForm 𝒮ℒ 12) : ℍ → ℂ) from rfl, + rw [show (E4_cube_sub_E6_sq_form) = ((mcast (by norm_num) + (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - mcast (by norm_num) (E₆.mul E₆))) from rfl, hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] @@ -304,7 +282,7 @@ private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : Finset.map_singleton, Function.Embedding.prodMap, Prod.map, Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one] - norm_num [h0_4, h0_6] + norm_num [E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : @@ -312,14 +290,13 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g have hc_eq : c = 1728 := by - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = - c • qExpansion 1 (discriminantCuspForm : ℍ → ℂ) := by + have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm) := by conv_lhs => rw [show (g : ℍ → ℂ) = ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from congr_arg DFunLike.coe hc.symm] exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm have h := congr_arg (·.coeff 1) <| - (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) + (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form) from congr_arg _ (congr_arg DFunLike.coe hg)).symm.trans hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm @@ -330,7 +307,7 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : _ = g z := by rw [← hc] _ = E4_cube_sub_E6_sq_form z := congr_fun (congr_arg DFunLike.coe hg) z _ = _ := E4_cube_sub_E6_sq_form_apply z - linear_combination (norm := ring_nf) (1 / 1728 : ℂ) * h1728 + linear_combination (1 / 1728 : ℂ) * h1728 /-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` @@ -366,33 +343,31 @@ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) -private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ (2 : ℤ)) +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) (hf : ¬IsCuspForm f) : f = 0 := by exfalso - obtain ⟨c4, hc4⟩ := exists_smul_eq_of_rank_one weight_four_rank_one - (E_ne_zero _ ⟨2, rfl⟩ : (E₄ : ModularForm 𝒮ℒ 4) ≠ 0) (f.mul f) - obtain ⟨c6, hc6⟩ := exists_smul_eq_of_rank_one weight_six_rank_one - (E_ne_zero _ ⟨3, rfl⟩ : (E₆ : ModularForm 𝒮ℒ 6) ≠ 0) ((f.mul f).mul f) + have h0 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one + rw [(finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩ : E₄ ≠ 0))] at h0 + have h1 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one + rw [(finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩ : E₆ ≠ 0))] at h1 + obtain ⟨c4, hc4⟩ := h0 (f.mul f) + obtain ⟨c6, hc6⟩ := h1 ((f.mul f).mul f) have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) := by + qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f : ℍ → ℂ) from + rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] at hsmul rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] exact hsmul.symm - have hqc6 : c6 • qExpansion 1 (E₆ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 (f : ℍ → ℂ) * - qExpansion 1 (f : ℍ → ℂ) := by + have hqc6 : c6 • qExpansion 1 E₆ = qExpansion 1 f * qExpansion 1 f * qExpansion 1 f := by have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E₆ : ℍ → ℂ) = ((f.mul f).mul f : ℍ → ℂ) from - congrArg DFunLike.coe hc6] at hsmul + rw [show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] at hsmul rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 - rw [← hmul1]; exact hsmul.symm + simp [← hmul1, hsmul.symm] exact hf <| (isCuspForm_iff_coeffZero_eq_zero f).mpr <| coeffZero_eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) - (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one - hqc4 hqc6 + (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one hqc4 hqc6 /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : @@ -402,8 +377,7 @@ theorem ModularForm.levelOne_weight_two_rank_zero : by_cases hf : IsCuspForm f · obtain ⟨g, hg⟩ := hf rw [← hg] - simp [rank_zero_iff_forall_zero.mp - (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + simp [rank_zero_iff_forall_zero.mp (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ @@ -412,8 +386,7 @@ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) else Nat.floor ((k : ℚ) / 12) + 1 := by induction k using Nat.strong_induction_on with | h k ihn => - rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, - LinearEquiv.rank_eq CuspForm.discriminantEquiv] + rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, LinearEquiv.rank_eq CuspForm.discriminantEquiv] by_cases HK : (3 : ℤ) ≤ ((k : ℤ) - 12) · have iH := ihn (k - 12) (by omega) (by omega) ((Nat.even_sub (by omega)).mpr (by simp only [hk2, true_iff]; decide)) @@ -426,7 +399,8 @@ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Nat.floor_div_eq_one_add_floor_sub_div (k : ℚ) 12 (by norm_num) hk' by_cases h12 : 12 ∣ ((k) : ℤ) - 2 · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] - norm_cast at *; rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] + norm_cast at * + rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, Nat.cast_add, Nat.cast_one] norm_cast at * diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 4fb13197343168..a6a118d9fd92fd 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -197,8 +197,7 @@ def discriminantCuspForm : CuspForm 𝒮ℒ 12 where /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` on the open unit disc. -/ private lemma discriminant_cuspFunction_eqOn : - Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by + Set.EqOn (cuspFunction 1 Δ) (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 · simp only [hq0, zero_mul] @@ -208,14 +207,10 @@ private lemma discriminant_cuspFunction_eqOn : have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] - have hqr := Periodic.qParam_right_inv one_ne_zero hq0 - have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by - simp [eta_q, hqr] - simp only [hqr, heta] + simp [eta_q, Periodic.qParam_right_inv one_ne_zero hq0] /-- The first q-expansion coefficient of the modular discriminant is 1. -/ -lemma discriminant_qExpansion_coeff_one : - (qExpansion 1 (discriminantCuspForm : ℍ → ℂ)).coeff 1 = 1 := by +lemma discriminant_qExpansion_coeff_one : (qExpansion 1 discriminantCuspForm).coeff 1 = 1 := by rw [qExpansion_coeff] simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, iteratedDeriv_zero] From 8d4689c385bc5d5355fec6252ca8f523dc794495 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Wed, 8 Apr 2026 16:51:52 +0100 Subject: [PATCH 16/61] more golfs --- .../DimensionFormulas/LevelOne.lean | 19 ++++++------------- .../ModularForms/Discriminant.lean | 3 +-- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0db6b772cb4a76..1f6b388aaa7ca6 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -45,8 +45,7 @@ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero - rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, - qExpansion_mul_coeff_zero + rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, qExpansion_mul_coeff_zero (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt,hΔ', mul_zero] @@ -70,8 +69,7 @@ private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, show k + -(k - 12) = (12 : ℤ) from by ring] exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ hd) -private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : - (f : ℍ → ℂ) =O[atImInfty] Δ := by +private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atImInfty] Δ := by have hf_decay := CuspFormClass.exp_decay_atImInfty (h := 1) f one_pos one_mem_strictPeriods_SL have hΔ_lower : ∀ᶠ τ : ℍ in atImInfty, ‖(fun τ : ℍ ↦ Real.exp (-2 * Real.pi * τ.im / 1)) τ‖ ≤ 2 * ‖Δ τ‖ := by @@ -216,16 +214,12 @@ private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) private lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by - rw [E_qExpansion_coeff _ ⟨2, rfl⟩] - simp only [one_ne_zero, ↓reduceIte] - rw [show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by + rw [E_qExpansion_coeff _ ⟨2, rfl⟩, show bernoulli (4 : ℕ) = ((-1 : ℚ) / 30 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num)]; exact bernoulli'_four] simp [ArithmeticFunction.sigma_one]; norm_num private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by - rw [E_qExpansion_coeff _ ⟨3, rfl⟩] - simp only [one_ne_zero, ↓reduceIte] - rw [show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by + rw [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli (6 : ℕ) = ((1 : ℚ) / 42 : ℚ) from by rw [bernoulli_eq_bernoulli'_of_ne_one (by norm_num), bernoulli'_def] norm_num [Finset.sum_range_succ, Finset.sum_range_zero, show Nat.choose 6 2 = 15 from by decide, show Nat.choose 6 4 = 15 from by decide, @@ -242,9 +236,8 @@ private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (show 4 + (4 + 4) = 12 by norm_num) - (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - - ModularForm.mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) + mcast (show 4 + (4 + 4) = 12 by norm_num) (E₄.mul (mcast rfl (E₄.mul E₄))) - + mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index a6a118d9fd92fd..4705397a850a06 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -216,14 +216,13 @@ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 discriminantCuspForm).co iteratedDeriv_zero] have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos change deriv (cuspFunction 1 Δ) 0 = 1 - rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem, + simp [← derivWithin_of_isOpen Metric.isOpen_ball hmem, derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), show (fun q : ℂ ↦ q * ∏' n, (1 - q ^ (n + 1)) ^ 24) = (fun q ↦ id q * ∏' n, (1 - q ^ (n + 1)) ^ 24) from rfl, derivWithin_fun_mul differentiableWithinAt_id (differentiableOn_tprod_one_sub_pow_pow 24 0 hmem), derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] - simp end From 97c057c64ba3231e956cc931aa971340d7604396 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 10 Apr 2026 17:37:14 +0100 Subject: [PATCH 17/61] cleanup --- .../ModularForms/CuspFormSubmodule.lean | 14 +- .../DimensionFormulas/LevelOne.lean | 178 ++++++++---------- .../ModularForms/Discriminant.lean | 2 +- 3 files changed, 85 insertions(+), 109 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index a9b6378449a2f0..f717c96303b259 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -3,9 +3,11 @@ Copyright (c) 2026 Chris Birkbeck. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ -import Mathlib.NumberTheory.ModularForms.QExpansion -import Mathlib.NumberTheory.ModularForms.LevelOne -import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion +module + +public import Mathlib.NumberTheory.ModularForms.QExpansion +public import Mathlib.NumberTheory.ModularForms.LevelOne +public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion /-! # Cusp form submodule and IsCuspForm predicate @@ -31,11 +33,11 @@ q-expansion coefficient (for `𝒮ℒ`). q-expansion having vanishing constant term. -/ +@[expose] public noncomputable section + open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass ModularFormClass MatrixGroups OnePoint Filter Topology -noncomputable section - variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} namespace CuspForm @@ -100,7 +102,7 @@ lemma isZeroAtImInfty_of_valueAtInfty_eq_zero (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) /-- An `𝒮ℒ` modular form with vanishing q-expansion constant term vanishes at every cusp. -/ -private lemma isZeroAt_of_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) +lemma isZeroAt_of_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) (h : (qExpansion 1 f).coeff 0 = 0) {c : OnePoint ℝ} (hc : IsCusp c 𝒮ℒ) : c.IsZeroAt f k := by rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 1f6b388aaa7ca6..30e85a8f7b3e8a 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -3,11 +3,13 @@ Copyright (c) 2026 Chris Birkbeck. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Birkbeck -/ -import Mathlib.Algebra.Order.Floor.Semifield -import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule -import Mathlib.NumberTheory.ModularForms.Discriminant -import Mathlib.Data.Rat.Star -import Mathlib.LinearAlgebra.Dimension.Localization +module + +public import Mathlib.Algebra.Order.Floor.Semifield +public import Mathlib.NumberTheory.ModularForms.CuspFormSubmodule +public import Mathlib.NumberTheory.ModularForms.Discriminant +public import Mathlib.Data.Rat.Star +public import Mathlib.LinearAlgebra.Dimension.Localization /-! # Dimension formula for level 1 modular forms @@ -22,11 +24,11 @@ of even weight `k ≥ 3`. * `ModularForm.dimension_level_one`: the full dimension formula. -/ +@[expose] public noncomputable section + open UpperHalfPlane ModularForm Complex SlashInvariantForm SlashInvariantFormClass ModularFormClass CongruenceSubgroup MatrixGroups OnePoint Filter Topology EisensteinSeries -noncomputable section - /-! ### Delta isomorphism: `CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - 12)` -/ section DeltaIsomorphism @@ -45,9 +47,11 @@ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans (CuspFormClass.zero_at_infty discriminantCuspForm).valueAtInfty_eq_zero - rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, qExpansion_mul_coeff_zero + rw [show (ModularForm.mcast _ (f.mul Δ')) = (f : ℍ → ℂ) * Δ' from rfl, + qExpansion_mul_coeff_zero (analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt - (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt,hΔ', mul_zero] + (analyticAt_cuspFunction_zero Δ' one_pos one_mem_strictPeriods_SL).continuousAt, + hΔ', mul_zero] @[simp] lemma ofMulDiscriminant_apply (f : ModularForm 𝒮ℒ (k - 12)) (z : ℍ) : @@ -182,10 +186,12 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ cuspFormSubmodule 𝒮ℒ (k : ℤ) := by + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ + cuspFormSubmodule 𝒮ℒ (k : ℤ) := by apply (isCuspForm_iff_coeffZero_eq_zero _).mpr set c := (qExpansion 1 ↑f).coeff 0 with hc - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f (c • E hk) + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f + (c • E hk) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub rw [hsub] simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), @@ -228,139 +234,106 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := /-- A modular form whose `valueAtInfty` is `c` tends to `c` along `atImInfty`. -/ private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) - (hv : valueAtInfty f = c) : Filter.Tendsto f atImInfty (𝓝 c) := by + (hv : valueAtInfty f = c) : Tendsto f atImInfty (𝓝 c) := by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt.tendsto.comp - (qParam_tendsto_atImInfty one_pos)).congr - (fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero) + refine (((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + |>.tendsto.comp (qParam_tendsto_atImInfty one_pos))).congr fun τ ↦ ?_ + exact eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := - mcast (show 4 + (4 + 4) = 12 by norm_num) (E₄.mul (mcast rfl (E₄.mul E₄))) - - mcast (show 6 + 6 = 12 by norm_num) (E₆.mul E₆) + mcast (by norm_num) ((E₄.mul E₄).mul E₄) - mcast (by norm_num) (E₆.mul E₆) private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by - change E₄ z * (E₄ z * E₄ z) - E₆ z * E₆ z = _; ring + change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _; ring private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ rw [qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] - have h4 : Filter.Tendsto (E₄ : ℍ → ℂ) atImInfty (𝓝 1) := - tendsto_valueAtInfty E₄ 1 <| by - rw [← qExpansion_coeff_zero E₄ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨2, rfl⟩ - have h6 : Filter.Tendsto (E₆ : ℍ → ℂ) atImInfty (𝓝 1) := - tendsto_valueAtInfty E₆ 1 <| by - rw [← qExpansion_coeff_zero E₆ one_pos one_mem_strictPeriods_SL] - exact E_qExpansion_coeff_zero _ ⟨3, rfl⟩ - refine ((Filter.Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq - simpa using (h4.pow 3).sub (h6.pow 2) + have hE : ∀ {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k), + Tendsto ((E hk : ModularForm 𝒮ℒ k) : ℍ → ℂ) atImInfty (𝓝 1) := fun hk hk2 ↦ + tendsto_valueAtInfty _ 1 <| by + rw [← qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] + exact E_qExpansion_coeff_zero hk hk2 + refine ((Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq + simpa using ((hE _ ⟨2, rfl⟩).pow 3).sub ((hE _ ⟨3, rfl⟩).pow 2) private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by - have hmcast : ∀ {a b : ℤ} (h : a = b) (f : ModularForm 𝒮ℒ a), - qExpansion 1 (mcast h f) = qExpansion 1 (f : ℍ → ℂ) := fun _ _ ↦ rfl - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := (12 : ℤ))).map_sub - (mcast (by norm_num) (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄)))) - (mcast (by norm_num) (E₆.mul E₆)) - simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk, hmcast] at hsub - rw [show (E4_cube_sub_E6_sq_form) = ((mcast (by norm_num) - (E₄.mul (ModularForm.mcast rfl (E₄.mul E₄))) - mcast (by norm_num) (E₆.mul E₆))) from rfl, - hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ _, hmcast, + have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - + qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + qExpansion_sub one_pos one_mem_strictPeriods_SL + (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) (mcast (by norm_num) (E₆.mul E₆)) + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - simp only [map_sub, PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, - Finset.Nat.antidiagonal_zero, Finset.sum_cons, Finset.sum_singleton, - Finset.map_singleton, Function.Embedding.prodMap, Prod.map, - Function.Embedding.coeFn_mk, Nat.succ_eq_add_one, Nat.zero_add, - Function.Embedding.refl_apply, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one] - norm_num [E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, + E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, + E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + ring /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm obtain ⟨c, hc⟩ := cuspForm_twelve_smul_discriminant g + have hgE : (g : ℍ → ℂ) = E4_cube_sub_E6_sq_form := congrArg DFunLike.coe hg have hc_eq : c = 1728 := by - have hgΔ : qExpansion 1 (g : ℍ → ℂ) = c • qExpansion 1 (discriminantCuspForm) := by - conv_lhs => rw [show (g : ℍ → ℂ) = - ((c • discriminantCuspForm : CuspForm 𝒮ℒ 12) : ℍ → ℂ) from - congr_arg DFunLike.coe hc.symm] - exact qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm - have h := congr_arg (·.coeff 1) <| - (show qExpansion 1 (g : ℍ → ℂ) = qExpansion 1 (E4_cube_sub_E6_sq_form) - from congr_arg _ (congr_arg DFunLike.coe hg)).symm.trans hgΔ + have hcΔ : (c • discriminantCuspForm : ℍ → ℂ) = g := congrArg DFunLike.coe hc + have hgΔ := qExpansion_smul one_pos one_mem_strictPeriods_SL c discriminantCuspForm + rw [hcΔ, hgE] at hgΔ + have h := congr_arg (·.coeff 1) hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm - have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := - calc (1728 : ℂ) * discriminant z - = c * discriminant z := by rw [hc_eq] - _ = (c • discriminantCuspForm) z := rfl - _ = g z := by rw [← hc] - _ = E4_cube_sub_E6_sq_form z := congr_fun (congr_arg DFunLike.coe hg) z - _ = _ := E4_cube_sub_E6_sq_form_apply z + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by + rw [← hc_eq, show c * discriminant z = (c • discriminantCuspForm) z from rfl, hc, + congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] linear_combination (1 / 1728 : ℂ) * h1728 -/-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies -`c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` -and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ +/-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` +satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with +constant term `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) (hqc4 : c4 • p4 = p * p) (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by - have h0_4 : c4 = p.coeff 0 ^ 2 := by - have h := congr_arg (·.coeff 0) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, - Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp4_0, mul_one] at h - rw [sq]; exact h - have h0_6 : c6 = p.coeff 0 ^ 3 := by - have h := congr_arg (·.coeff 0) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, - Finset.Nat.antidiagonal_zero, Finset.sum_singleton, hp6_0, mul_one] at h - rw [show p.coeff 0 ^ 3 = p.coeff 0 * p.coeff 0 * p.coeff 0 by ring]; exact h - have heq4 : p.coeff 0 ^ 2 * 240 = 2 * p.coeff 0 * p.coeff 1 := by - have h := congr_arg (·.coeff 1) hqc4 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp4_1] at h - rw [show (p * p).coeff 1 = 2 * p.coeff 0 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_4] at h - exact h - have heq6 : p.coeff 0 ^ 3 * (-504) = 3 * p.coeff 0 ^ 2 * p.coeff 1 := by - have h := congr_arg (·.coeff 1) hqc6 - simp only [PowerSeries.coeff_smul, smul_eq_mul, hp6_1] at h - rw [show (p * p * p).coeff 1 = 3 * p.coeff 0 ^ 2 * p.coeff 1 from by - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ]; ring, h0_6] at h - exact h + have h40 := congr_arg (·.coeff 0) hqc4 + have h41 := congr_arg (·.coeff 1) hqc4 + have h60 := congr_arg (·.coeff 0) hqc6 + have h61 := congr_arg (·.coeff 1) hqc6 + simp only [PowerSeries.coeff_smul, smul_eq_mul, PowerSeries.coeff_mul, + Finset.Nat.antidiagonal_zero, Finset.Nat.antidiagonal_succ, Finset.sum_singleton, + Finset.sum_cons, Finset.map_singleton, Function.Embedding.prodMap, Prod.map, + Function.Embedding.coeFn_mk, Function.Embedding.refl_apply, hp4_0, hp4_1, hp6_0, hp6_1, + mul_one] at h40 h41 h60 h61 refine pow_eq_zero_iff (n := 3) three_ne_zero |>.mp ?_ have h0 : (1728 : ℂ) * p.coeff 0 ^ 3 = 0 := by - linear_combination 3 * p.coeff 0 * heq4 - 2 * heq6 + linear_combination 3 * p.coeff 0 * h41 - 2 * h61 - 720 * p.coeff 0 * h40 - 1008 * h60 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) (hf : ¬IsCuspForm f) : f = 0 := by exfalso - have h0 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one - rw [(finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩ : E₄ ≠ 0))] at h0 - have h1 := Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one - rw [(finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩ : E₆ ≠ 0))] at h1 - obtain ⟨c4, hc4⟩ := h0 (f.mul f) - obtain ⟨c6, hc6⟩ := h1 ((f.mul f).mul f) + obtain ⟨c4, hc4⟩ := (finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩)).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one) (f.mul f) + obtain ⟨c6, hc6⟩ := (finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩)).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one) ((f.mul f).mul f) have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄ - rw [show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from - congrArg DFunLike.coe hc4] at hsmul - rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] - exact hsmul.symm + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, + ← qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, + show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] have hqc6 : c6 • qExpansion 1 E₆ = qExpansion 1 f * qExpansion 1 f * qExpansion 1 f := by - have hsmul := qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆ - have hmul1 := ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f - rw [show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] at hsmul - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f] at hmul1 - simp [← hmul1, hsmul.symm] + rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, + ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f, + ← qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆, + show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] exact hf <| (isCuspForm_iff_coeffZero_eq_zero f).mpr <| coeffZero_eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) - (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one hqc4 hqc6 + (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one + hqc4 hqc6 /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : @@ -370,7 +343,8 @@ theorem ModularForm.levelOne_weight_two_rank_zero : by_cases hf : IsCuspForm f · obtain ⟨g, hg⟩ := hf rw [← hg] - simp [rank_zero_iff_forall_zero.mp (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + simp [rank_zero_iff_forall_zero.mp + (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index ff85b397cc0b17..a570ab86c2b05e 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -177,7 +177,7 @@ lemma discriminant_isZeroAtImInfty : IsZeroAtImInfty Δ := by (discriminant_bounded_factor.congr fun z ↦ by congr 1) /-- The modular discriminant `Δ` as a cusp form of weight 12 and level 1. -/ -def discriminantCuspForm : CuspForm 𝒮ℒ 12 where +@[expose] def discriminantCuspForm : CuspForm 𝒮ℒ 12 where toFun := Δ slash_action_eq' A hA := by obtain ⟨A, rfl⟩ := hA From 8d9031061f15578f43bc70154db2d2b28e1cbe4a Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 13 Apr 2026 10:24:33 +0100 Subject: [PATCH 18/61] feat(NumberTheory/ModularForms): Coe from CuspForm to ModularForm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `CuspForm.toModularForm` and a `Coe (CuspForm Γ k) (ModularForm Γ k)` instance so cusp forms can be viewed as modular forms automatically. Refactors `CuspForm.toModularFormₗ` to delegate to this plain function and updates call sites. Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib/NumberTheory/ModularForms/Basic.lean | 15 ++ .../ModularForms/CuspFormSubmodule.lean | 8 +- .../DimensionFormulas/LevelOne.lean | 191 ++++++++---------- 3 files changed, 104 insertions(+), 110 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index 3100c9f841d33d..9a356680b7c080 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -516,6 +516,21 @@ instance (priority := 99) [FunLike F ℍ ℂ] [CuspFormClass F Γ k] : ModularFo holo := CuspFormClass.holo bdd_at_cusps f _ hc g hg := (CuspFormClass.zero_at_cusps f hc g hg).boundedAtFilter +/-- The underlying modular form of a cusp form. -/ +def toModularForm (f : CuspForm Γ k) : ModularForm Γ k where + toSlashInvariantForm := f.toSlashInvariantForm + holo' := f.holo' + bdd_at_cusps' hc g hg := (f.zero_at_cusps' hc g hg).boundedAtFilter + +@[simp] +lemma toModularForm_apply (f : CuspForm Γ k) (z : ℍ) : (toModularForm f) z = f z := rfl + +/-- A cusp form can be viewed as a modular form. -/ +instance : Coe (CuspForm Γ k) (ModularForm Γ k) := ⟨toModularForm⟩ + +@[simp] +lemma coe_toModularForm (f : CuspForm Γ k) (z : ℍ) : ((f : ModularForm Γ k) : ℍ → ℂ) z = f z := rfl + /-- Transport a cusp form along an equality of subgroups. -/ def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : CuspForm Γ k) : CuspForm Γ' k where diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index f717c96303b259..5b7dbde9c17d3f 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -44,10 +44,7 @@ namespace CuspForm /-- The inclusion of cusp forms into modular forms, as a ℂ-linear map. -/ def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k where - toFun f := - { toSlashInvariantForm := f.toSlashInvariantForm - holo' := f.holo' - bdd_at_cusps' := fun hc g hg ↦ (f.zero_at_cusps' hc g hg).boundedAtFilter } + toFun := toModularForm map_add' _ _ := rfl map_smul' _ _ := rfl @@ -55,6 +52,9 @@ def toModularFormₗ [Γ.HasDetOne] : CuspForm Γ k →ₗ[ℂ] ModularForm Γ k lemma toModularFormₗ_apply [Γ.HasDetOne] (f : CuspForm Γ k) (z : ℍ) : (toModularFormₗ f) z = f z := rfl +lemma toModularFormₗ_eq_coe [Γ.HasDetOne] (f : CuspForm Γ k) : + toModularFormₗ f = (f : ModularForm Γ k) := rfl + lemma toModularFormₗ_injective [Γ.HasDetOne] : Function.Injective (toModularFormₗ : CuspForm Γ k → ModularForm Γ k) := fun _ _ h ↦ DFunLike.ext _ _ fun z ↦ congr_fun (congr_arg DFunLike.coe h) z diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 30e85a8f7b3e8a..fcfd2bb195e0b0 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -42,7 +42,7 @@ namespace CuspForm /-- Multiply a modular form of weight `k - 12` by the discriminant to get a cusp form of weight `k`. Built directly as a CuspForm (no `IsCuspForm` intermediary). -/ def ofMulDiscriminant (f : ModularForm 𝒮ℒ (k - 12)) : CuspForm 𝒮ℒ k := by - let Δ' := CuspForm.toModularFormₗ discriminantCuspForm + let Δ' : ModularForm 𝒮ℒ 12 := discriminantCuspForm apply ModularForm.toCuspForm (ModularForm.mcast (by ring) (f.mul Δ')) have hΔ' : (qExpansion 1 (Δ' : ℍ → ℂ)).coeff 0 = 0 := (qExpansion_coeff_zero Δ' one_pos one_mem_strictPeriods_SL).trans @@ -65,15 +65,12 @@ private lemma divByDiscriminant_slash_eq (f : CuspForm 𝒮ℒ k) (γ : SL(2, CongruenceSubgroup.Gamma_one_coe_eq_SL ▸ inferInstance have hf := slash_action_eqn_SL'' f (mem_Gamma_one γ) have hΔ := slash_action_eqn_SL'' discriminantCuspForm (mem_Gamma_one γ) - ext z - rw [SL_slash_apply, hf, show Δ (γ • z) = denom γ z ^ (12 : ℤ) * Δ z from by - exact_mod_cast hΔ z] - have hd : (denom γ z : ℂ) ≠ 0 := denom_ne_zero γ z - rw [div_mul_eq_mul_div, mul_right_comm, ← zpow_add₀ hd, - show k + -(k - 12) = (12 : ℤ) from by ring] - exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ hd) - -private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atImInfty] Δ := by + ext z; rw [SL_slash_apply, hf, show Δ (γ • z) = denom γ z ^ (12 : ℤ) * Δ z from by + exact_mod_cast hΔ z, div_mul_eq_mul_div, mul_right_comm, + ← zpow_add₀ (denom_ne_zero γ z), show k + -(k - 12) = (12 : ℤ) from by ring] + exact mul_div_mul_left (f z) (Δ z) (zpow_ne_zero _ (denom_ne_zero γ z)) + +lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atImInfty] Δ := by have hf_decay := CuspFormClass.exp_decay_atImInfty (h := 1) f one_pos one_mem_strictPeriods_SL have hΔ_lower : ∀ᶠ τ : ℍ in atImInfty, ‖(fun τ : ℍ ↦ Real.exp (-2 * Real.pi * τ.im / 1)) τ‖ ≤ 2 * ‖Δ τ‖ := by @@ -82,37 +79,30 @@ private lemma exp_decay_isBigO_discriminant (f : CuspForm 𝒮ℒ k) : f =O[atIm filter_upwards [hprod] with τ hτ simp only [div_one] rw [discriminant_eq_q_prod, norm_mul, Real.norm_of_nonneg (Real.exp_pos _).le] - have hq_norm : ‖Function.Periodic.qParam 1 (τ : ℂ)‖ = - Real.exp (-2 * Real.pi * τ.im) := by + have hq_norm : ‖Function.Periodic.qParam 1 (τ : ℂ)‖ = Real.exp (-2 * Real.pi * τ.im) := by simp [Function.Periodic.qParam, Complex.norm_exp, Complex.mul_re, div_one] rw [← hq_norm] have hprod_bound : 1 / 2 ≤ ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24‖ := by - have hsub : ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24 - 1‖ < 1 / 2 := by - rwa [Complex.dist_eq] at hτ + have hsub : ‖∏' (n : ℕ), (1 - eta_q n τ) ^ 24 - 1‖ < 1 / 2 := by rwa [Complex.dist_eq] at hτ have h1 := norm_sub_norm_le (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24) simp only [norm_one] at h1 linarith [norm_sub_rev (1 : ℂ) (∏' (n : ℕ), (1 - eta_q n τ) ^ 24)] - linarith [norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)), - mul_le_mul_of_nonneg_left hprod_bound - (norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)))] + linarith [norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)), mul_le_mul_of_nonneg_left + hprod_bound (norm_nonneg (Function.Periodic.qParam 1 (τ : ℂ)))] exact hf_decay.trans (Asymptotics.IsBigO.of_bound 2 hΔ_lower) /-- Divide a cusp form by the discriminant to get a modular form of weight `k - 12`. -/ def divDiscriminant (f : CuspForm 𝒮ℒ k) : ModularForm 𝒮ℒ (k - 12) where toFun z := f z / Δ z - slash_action_eq' A hA := by - obtain ⟨γ, rfl⟩ := hA - exact divByDiscriminant_slash_eq f γ + slash_action_eq' _ hA := by obtain ⟨γ, rfl⟩ := hA; exact divByDiscriminant_slash_eq f γ holo' := by rw [UpperHalfPlane.mdifferentiable_iff] - refine (UpperHalfPlane.mdifferentiable_iff.mp f.holo').div - (UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo') fun z hz ↦ ?_ - simpa [ofComplex_apply_of_im_pos hz] using discriminant_ne_zero ⟨z, hz⟩ + exact (UpperHalfPlane.mdifferentiable_iff.mp f.holo').div + (UpperHalfPlane.mdifferentiable_iff.mp discriminantCuspForm.holo') fun z hz ↦ by + simpa [ofComplex_apply_of_im_pos hz] using discriminant_ne_zero ⟨z, hz⟩ bdd_at_cusps' {c} hc := by - rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc - rw [isBoundedAt_iff_forall_SL2Z hc] - intro γ _ - rw [divByDiscriminant_slash_eq f γ, IsBoundedAtImInfty, BoundedAtFilter] + rw [Subgroup.IsArithmetic.isCusp_iff_isCusp_SL2Z] at hc; rw [isBoundedAt_iff_forall_SL2Z hc] + intro γ _; rw [divByDiscriminant_slash_eq f γ, IsBoundedAtImInfty, BoundedAtFilter] exact (Asymptotics.div_isBoundedUnder_of_isBigO (exp_decay_isBigO_discriminant f)).isBigO_one ℝ @@ -127,14 +117,8 @@ def discriminantEquiv : CuspForm 𝒮ℒ k ≃ₗ[ℂ] ModularForm 𝒮ℒ (k - map_add' a b := by ext z; simp [add_div] map_smul' c a := by ext z; simp [mul_div_assoc] invFun := ofMulDiscriminant - left_inv f := by - ext z - simp only [divDiscriminant_apply, ofMulDiscriminant_apply] - exact div_mul_cancel₀ (f z) (discriminant_ne_zero z) - right_inv f := by - ext z - simp only [ofMulDiscriminant_apply, divDiscriminant_apply] - exact mul_div_cancel_right₀ (f z) (discriminant_ne_zero z) + left_inv f := by ext z; simpa using div_mul_cancel₀ (f z) (discriminant_ne_zero z) + right_inv f := by ext z; simpa using mul_div_cancel_right₀ (f z) (discriminant_ne_zero z) end CuspForm @@ -159,49 +143,38 @@ lemma cuspForm_rank_twelve : Module.rank ℂ (CuspForm 𝒮ℒ 12) = 1 := by /-- Every weight 12 cusp form for `𝒮ℒ` is a scalar multiple of the discriminant. -/ lemma cuspForm_twelve_smul_discriminant (f : CuspForm 𝒮ℒ 12) : - ∃ c : ℂ, c • discriminantCuspForm = f := by - have hne : discriminantCuspForm ≠ 0 := fun h ↦ - discriminant_ne_zero UpperHalfPlane.I (congr_fun (congr_arg DFunLike.coe h) _) - exact (finrank_eq_one_iff_of_nonzero' discriminantCuspForm hne).mp + ∃ c : ℂ, c • discriminantCuspForm = f := + (finrank_eq_one_iff_of_nonzero' discriminantCuspForm (fun h ↦ + discriminant_ne_zero UpperHalfPlane.I (congr_fun (congr_arg DFunLike.coe h) _))).mp (Module.rank_eq_one_iff_finrank_eq_one.mp cuspForm_rank_twelve) f /-- For even `k ≥ 3`, the rank of `𝒮ℒ` modular forms is one more than the rank of cusp forms. -/ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : Even k) : - Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = - 1 + Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) := by - have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ (k : ℤ)) - rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ (k : ℤ)) = - Module.rank ℂ (CuspForm 𝒮ℒ (k : ℤ)) from - (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ (k : ℤ))).symm] at h_add - suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ) ⧸ - cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 1 by + Module.rank ℂ (ModularForm 𝒮ℒ k) = 1 + Module.rank ℂ (CuspForm 𝒮ℒ k) := by + have h_add := Submodule.rank_quotient_add_rank (cuspFormSubmodule 𝒮ℒ k) + rw [show Module.rank ℂ ↥(cuspFormSubmodule 𝒮ℒ k) = Module.rank ℂ (CuspForm 𝒮ℒ k) from + (LinearEquiv.rank_eq (CuspForm.equivCuspFormSubmodule 𝒮ℒ k)).symm] at h_add + suffices h1 : Module.rank ℂ (ModularForm 𝒮ℒ k ⧸ cuspFormSubmodule 𝒮ℒ k) = 1 by rw [← h_add, h1] - have hE_coeff_zero := E_qExpansion_coeff_zero hk hk2 - apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ (k : ℤ)) (E hk)) + have hE := E_qExpansion_coeff_zero hk hk2 + apply rank_eq_one (Submodule.Quotient.mk (p := cuspFormSubmodule 𝒮ℒ k) (E hk)) · intro h rw [Submodule.Quotient.mk_eq_zero] at h - exact one_ne_zero <| - hE_coeff_zero.symm.trans <| - (isCuspForm_iff_coeffZero_eq_zero _).mp h + exact one_ne_zero <| hE.symm.trans <| (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.mk_surjective _).forall.mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ - have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ - cuspFormSubmodule 𝒮ℒ (k : ℤ) := by + have h_mem : f - (qExpansion 1 ↑f).coeff 0 • E hk ∈ cuspFormSubmodule 𝒮ℒ k := by apply (isCuspForm_iff_coeffZero_eq_zero _).mpr set c := (qExpansion 1 ↑f).coeff 0 with hc - have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f - (c • E hk) + have hsub := (qExpansionAddHom one_pos one_mem_strictPeriods_SL (k := k)).map_sub f (c • E hk) simp only [qExpansionAddHom, AddMonoidHom.coe_mk, ZeroHom.coe_mk] at hsub - rw [hsub] - simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), - _root_.map_sub, _root_.map_smul, hE_coeff_zero, mul_one, ← hc] - have h0 : ((cuspFormSubmodule 𝒮ℒ (k : ℤ)).mkQ (f - (qExpansion 1 ↑f).coeff 0 • - E hk) : ModularForm 𝒮ℒ (k : ℤ) ⧸ cuspFormSubmodule 𝒮ℒ (k : ℤ)) = 0 := + rw [hsub]; simp [qExpansion_smul one_pos one_mem_strictPeriods_SL c (E hk), + _root_.map_sub, _root_.map_smul, hE, mul_one, ← hc] + have h0 : (cuspFormSubmodule 𝒮ℒ k).mkQ (f - (qExpansion 1 ↑f).coeff 0 • E hk) = 0 := (Submodule.Quotient.mk_eq_zero _).mpr h_mem - rw [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, - sub_eq_zero] at h0 - exact h0.symm + rwa [map_sub, LinearMap.map_smul, Submodule.mkQ_apply, Submodule.mkQ_apply, + sub_eq_zero, eq_comm] at h0 end RankIdentity @@ -210,12 +183,12 @@ end RankIdentity section DimensionFormula /-- Weight 4 modular forms for `𝒮ℒ` are 1-dimensional. -/ -private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (4 : ℤ)) = 1 := +private lemma weight_four_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 4) = 1 := (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨2, rfl⟩).trans ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) /-- Weight 6 modular forms for `𝒮ℒ` are 1-dimensional. -/ -private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ (6 : ℤ)) = 1 := +private lemma weight_six_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 6) = 1 := (rank_eq_one_add_rank_cuspForm (by norm_num) ⟨3, rfl⟩).trans ((congrArg (1 + ·) (cuspForm_rank_lt_twelve (by norm_num))).trans (by norm_cast)) @@ -236,9 +209,9 @@ private lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := private lemma tendsto_valueAtInfty {k : ℤ} (f : ModularForm 𝒮ℒ k) (c : ℂ) (hv : valueAtInfty f = c) : Tendsto f atImInfty (𝓝 c) := by rw [← hv, ← cuspFunction_apply_zero f one_pos one_mem_strictPeriods_SL] - refine (((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt - |>.tendsto.comp (qParam_tendsto_atImInfty one_pos))).congr fun τ ↦ ?_ - exact eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero + exact ((analyticAt_cuspFunction_zero f one_pos one_mem_strictPeriods_SL).continuousAt + |>.tendsto.comp (qParam_tendsto_atImInfty one_pos)).congr + fun τ ↦ eq_cuspFunction f τ one_mem_strictPeriods_SL one_ne_zero /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := @@ -256,22 +229,20 @@ private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_f tendsto_valueAtInfty _ 1 <| by rw [← qExpansion_coeff_zero _ one_pos one_mem_strictPeriods_SL] exact E_qExpansion_coeff_zero hk hk2 - refine ((Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) ?_)).limUnder_eq - simpa using ((hE _ ⟨2, rfl⟩).pow 3).sub ((hE _ ⟨3, rfl⟩).pow 2) + exact (Tendsto.congr (fun w ↦ (E4_cube_sub_E6_sq_form_apply w).symm) + (by simpa using ((hE _ ⟨2, rfl⟩).pow 3).sub ((hE _ ⟨3, rfl⟩).pow 2))).limUnder_eq private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := - qExpansion_sub one_pos one_mem_strictPeriods_SL - (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) (mcast (by norm_num) (E₆.mul E₆)) + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + qExpansion_sub one_pos one_mem_strictPeriods_SL (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (mcast (by norm_num) (E₆.mul E₆)) rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, - E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, - E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] ring /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ @@ -292,13 +263,30 @@ theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] linear_combination (1 / 1728 : ℂ) * h1728 +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring +`⨁ k, ModularForm 𝒮ℒ k`. -/ +theorem ModularForm.discriminant_eq_E4_cube_sub_E6_sq_in_graded_ring : + DirectSum.of (ModularForm 𝒮ℒ) 12 (discriminantCuspForm : ModularForm 𝒮ℒ 12) = + (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (mcast (by norm_num) ((E₄.mul E₄).mul E₄)) := by + rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of]; rfl + have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (mcast (by norm_num) (E₆.mul E₆)) := by + rw [pow_two, DirectSum.of_mul_of]; rfl + rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] + congr 1; ext z + change discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + rw [discriminant_eq_E4_cube_sub_E6_sq z]; ring + /-- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p.coeff 0 = 0`. -/ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c6 : ℂ} - (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) - (hp4_1 : p4.coeff 1 = 240) (hp6_1 : p6.coeff 1 = -504) - (hqc4 : c4 • p4 = p * p) (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by + (hp4_0 : p4.coeff 0 = 1) (hp6_0 : p6.coeff 0 = 1) (hp4_1 : p4.coeff 1 = 240) + (hp6_1 : p6.coeff 1 = -504) (hqc4 : c4 • p4 = p * p) + (hqc6 : c6 • p6 = p * p * p) : p.coeff 0 = 0 := by have h40 := congr_arg (·.coeff 0) hqc4 have h41 := congr_arg (·.coeff 1) hqc4 have h60 := congr_arg (·.coeff 0) hqc6 @@ -313,15 +301,14 @@ private lemma coeffZero_eq_zero_of_pow_eq_smul {p p4 p6 : PowerSeries ℂ} {c4 c linear_combination 3 * p.coeff 0 * h41 - 2 * h61 - 720 * p.coeff 0 * h40 - 1008 * h60 exact (mul_eq_zero.mp h0).resolve_left (by norm_num) -private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) - (hf : ¬IsCuspForm f) : f = 0 := by +private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) (hf : ¬IsCuspForm f) : + f = 0 := by exfalso obtain ⟨c4, hc4⟩ := (finrank_eq_one_iff_of_nonzero' E₄ (E_ne_zero _ ⟨2, rfl⟩)).mp (Module.rank_eq_one_iff_finrank_eq_one.mp weight_four_rank_one) (f.mul f) obtain ⟨c6, hc6⟩ := (finrank_eq_one_iff_of_nonzero' E₆ (E_ne_zero _ ⟨3, rfl⟩)).mp (Module.rank_eq_one_iff_finrank_eq_one.mp weight_six_rank_one) ((f.mul f).mul f) - have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = - qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by + have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) * qExpansion 1 f := by rw [← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, ← qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] @@ -337,46 +324,38 @@ private lemma weight_two_eq_zero_of_not_cuspForm (f : ModularForm 𝒮ℒ 2) /-- Modular forms of weight 2 for `𝒮ℒ` are zero. -/ theorem ModularForm.levelOne_weight_two_rank_zero : - Module.rank ℂ (ModularForm 𝒮ℒ (2 : ℤ)) = 0 := by - rw [rank_zero_iff_forall_zero] - intro f + Module.rank ℂ (ModularForm 𝒮ℒ 2) = 0 := by + rw [rank_zero_iff_forall_zero]; intro f by_cases hf : IsCuspForm f - · obtain ⟨g, hg⟩ := hf - rw [← hg] - simp [rank_zero_iff_forall_zero.mp - (cuspForm_rank_lt_twelve (show (2 : ℤ) < 12 by norm_num)) g] + · obtain ⟨g, hg⟩ := hf; rw [← hg] + simp [rank_zero_iff_forall_zero.mp (cuspForm_rank_lt_twelve (by norm_num)) g] · exact weight_two_eq_zero_of_not_cuspForm f hf /-- The dimension formula for `𝒮ℒ` modular forms of even weight `k ≥ 3`. -/ theorem ModularForm.dimension_level_one (k : ℕ) (hk : 3 ≤ (k : ℤ)) (hk2 : Even k) : - Module.rank ℂ (ModularForm 𝒮ℒ (k : ℤ)) = - if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) + Module.rank ℂ (ModularForm 𝒮ℒ k) = if 12 ∣ ((k : ℤ) - 2) then Nat.floor ((k : ℚ) / 12) else Nat.floor ((k : ℚ) / 12) + 1 := by induction k using Nat.strong_induction_on with | h k ihn => rw [rank_eq_one_add_rank_cuspForm (by omega) hk2, LinearEquiv.rank_eq CuspForm.discriminantEquiv] - by_cases HK : (3 : ℤ) ≤ ((k : ℤ) - 12) + by_cases HK : (3 : ℤ) ≤ (k : ℤ) - 12 · have iH := ihn (k - 12) (by omega) (by omega) ((Nat.even_sub (by omega)).mpr (by simp only [hk2, true_iff]; decide)) - have hk12 : (((k - 12) : ℕ) : ℤ) = k - 12 := by - norm_cast; exact Eq.symm (Int.subNatNat_of_le (by omega)) + have hk12 : (((k - 12) : ℕ) : ℤ) = k - 12 := by grind rw [hk12] at iH rw [iH, show ((k - 12 : ℕ) : ℚ) = (k : ℚ) - 12 from by norm_cast] - have hfl (hk' : (12 : ℚ) ≤ k) : - ⌊(k : ℚ) / 12⌋₊ = 1 + ⌊((k : ℚ) - 12) / 12⌋₊ := + have hfl (hk' : (12 : ℚ) ≤ k) : ⌊(k : ℚ) / 12⌋₊ = 1 + ⌊((k : ℚ) - 12) / 12⌋₊ := Nat.floor_div_eq_one_add_floor_sub_div (k : ℚ) 12 (by norm_num) hk' - by_cases h12 : 12 ∣ ((k) : ℤ) - 2 - · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12] - norm_cast at * + by_cases h12 : 12 ∣ (k : ℤ) - 2 + · simp only [show 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12]; norm_cast at * rw [hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [show ¬ 12 ∣ (k : ℤ) - 12 - 2 from by omega, ↓reduceIte, h12, - Nat.cast_add, Nat.cast_one] - norm_cast at * + Nat.cast_add, Nat.cast_one]; norm_cast at * rw [← add_assoc, ← hfl (by exact_mod_cast (by omega : (12 : ℤ) ≤ k))] · simp only [not_le] at HK have hkop : k ∈ Finset.filter Even (Finset.Icc 3 14) := by simp only [Finset.mem_filter, Finset.mem_Icc, hk2, and_true]; omega - rw [show Finset.filter Even (Finset.Icc 3 14) = ({4, 6, 8, 10, 12, 14} : Finset ℕ) - from by decide] at hkop + rw [show Finset.filter Even (Finset.Icc 3 14) = ({4, 6, 8, 10, 12, 14} : Finset ℕ) from by + decide] at hkop fin_cases hkop <;> simp only [Nat.cast_ofNat, Int.reduceSub, Int.reduceNeg] at * all_goals first | exact (congrArg (1 + ·) (levelOne_neg_weight_rank_zero (by omega))).trans (by norm_cast) From 43c4faed12cd741a4c5dbee9f2952271aa4f0e43 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 13 Apr 2026 10:58:47 +0100 Subject: [PATCH 19/61] chore: run mk_all to fix Mathlib.lean import order Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib.lean b/Mathlib.lean index 2c55ac3de481c2..99802f82937a45 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5589,6 +5589,7 @@ public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta public import Mathlib.NumberTheory.ModularForms.Derivative +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.Discriminant public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Defs @@ -5607,7 +5608,6 @@ public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold public import Mathlib.NumberTheory.ModularForms.JacobiTheta.OneVariable public import Mathlib.NumberTheory.ModularForms.JacobiTheta.TwoVariable public import Mathlib.NumberTheory.ModularForms.LevelOne -public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.NormTrace public import Mathlib.NumberTheory.ModularForms.Petersson public import Mathlib.NumberTheory.ModularForms.QExpansion From f91e8daf2061d88d325ff4fe721f15baea3d921b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 13 Apr 2026 11:26:41 +0100 Subject: [PATCH 20/61] feat(NumberTheory/ModularForms): CuspFormClass instance for cuspFormSubmodule Co-Authored-By: Claude Opus 4.6 (1M context) --- Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index 5b7dbde9c17d3f..86faed2b8a72fa 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -85,6 +85,15 @@ lemma isCuspForm_iff [Γ.HasDetOne] (f : ModularForm Γ k) : refine ⟨fun ⟨g, hg⟩ c hc ↦ hg ▸ g.zero_at_cusps' hc, fun h ↦ ⟨⟨f.toSlashInvariantForm, f.holo', h⟩, rfl⟩⟩ +instance [Γ.HasDetOne] : FunLike (cuspFormSubmodule Γ k) ℍ ℂ where + coe f := (f : ModularForm Γ k) + coe_injective' _ _ h := Subtype.ext (DFunLike.ext _ _ (congr_fun h)) + +instance [Γ.HasDetOne] : CuspFormClass (cuspFormSubmodule Γ k) Γ k where + slash_action_eq f := (f : ModularForm Γ k).slash_action_eq' + holo f := (f : ModularForm Γ k).holo' + zero_at_cusps f := (isCuspForm_iff f.1).mp f.2 + section SL2Z open EisensteinSeries From b5f280eba93b610f8e2cb370d44e4b1f1a0941af Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 11:30:10 +0100 Subject: [PATCH 21/61] =?UTF-8?q?feat(NumberTheory/ModularForms):=20restor?= =?UTF-8?q?e=20=CE=94=20=3D=20(E=E2=82=84=C2=B3=20-=20E=E2=82=86=C2=B2)=20?= =?UTF-8?q?/=201728?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restores ModularForm.discriminant_eq_E4_cube_sub_E6_sq, ported from earlier work (commit 8d9031061f1) and updated to current master's API: - discriminantCuspForm → CuspForm.discriminant - cuspForm_twelve_smul_discriminant → CuspForm.exists_smul_discriminant_of_weight_eq_twelve - qExpansion_sub/qExpansion_smul → ModularFormClass.qExpansion_sub/qExpansion_smul - The `IsCuspForm` proof uses an algebraic q-expansion split rather than the no-longer-available tendsto_valueAtInfty. Adds supporting lemmas in Discriminant.lean: - discriminant_cuspFunction_eqOn (private) - differentiableWithinAt_eta_prod_pow (private; shorter than original since differentiableOn_tprod_one_sub_pow_pow is now in mathlib) - discriminant_qExpansion_coeff_one Also drops merge-induced duplicates of master lemmas (summable_eta_q, multipliableLocallyUniformlyOn_eta, differentiableOn_tprod_one_sub_pow, differentiableOn_tprod_one_sub_pow_pow, one_mem_strictPeriods_SL) and removes two unused/duplicating helpers (floor_div_eq_one_add_floor_sub_div, which is too specific for a top-level file and unused, and ModularForm.ofSubgroupEq, which duplicates mcast). --- Mathlib/Algebra/Order/Floor/Semifield.lean | 5 -- Mathlib/NumberTheory/ModularForms/Basic.lean | 12 ---- .../ModularForms/DedekindEta.lean | 29 --------- .../DimensionFormulas/LevelOne.lean | 59 +++++++++++++++++++ .../ModularForms/Discriminant.lean | 44 ++++++++++++++ .../NumberTheory/ModularForms/LevelOne.lean | 3 - 6 files changed, 103 insertions(+), 49 deletions(-) diff --git a/Mathlib/Algebra/Order/Floor/Semifield.lean b/Mathlib/Algebra/Order/Floor/Semifield.lean index 43af3f6b88c848..e3bdf9a4329851 100644 --- a/Mathlib/Algebra/Order/Floor/Semifield.lean +++ b/Mathlib/Algebra/Order/Floor/Semifield.lean @@ -53,11 +53,6 @@ end LinearOrderedSemifield section LinearOrderedField variable [Field K] [LinearOrder K] [IsOrderedRing K] [FloorSemiring K] {a b : K} -theorem floor_div_eq_one_add_floor_sub_div (k a : K) (ha : 0 < a) (hak : a ≤ k) : - ⌊k / a⌋₊ = 1 + ⌊(k - a) / a⌋₊ := by - rw [sub_div, div_self ha.ne', Nat.floor_sub_one] - exact (Nat.add_sub_cancel' (Nat.le_floor (mod_cast (one_le_div₀ ha).mpr hak))).symm - lemma mul_lt_floor (hb₀ : 0 < b) (hb : b < 1) (hba : ⌈b / (1 - b)⌉₊ ≤ a) : b * a < ⌊a⌋₊ := by calc b * a < b * (⌊a⌋₊ + 1) := by gcongr; apply lt_floor_add_one diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index 9ef354b962b0d6..cfb4abba9ed314 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -395,18 +395,6 @@ lemma coe_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : lemma toSlashInvariantForm_intCast [Γ.HasDetPlusMinusOne] (z : ℤ) : (z : ModularForm Γ 0).toSlashInvariantForm = z := rfl -/-- Transport a modular form along an equality of subgroups. -/ -def ofSubgroupEq {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) : - ModularForm Γ' k where - toFun := f - slash_action_eq' A hA := f.slash_action_eq' A (h ▸ hA) - holo' := f.holo' - bdd_at_cusps' hc := f.bdd_at_cusps' (h ▸ hc) - -@[simp] -lemma ofSubgroupEq_apply {Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) - (z : ℍ) : (f.ofSubgroupEq h) z = f z := rfl - end ModularForm namespace CuspForm diff --git a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean index 0a0107a7debfb9..b8b69cf7e4c144 100644 --- a/Mathlib/NumberTheory/ModularForms/DedekindEta.lean +++ b/Mathlib/NumberTheory/ModularForms/DedekindEta.lean @@ -108,35 +108,6 @@ lemma multipliableLocallyUniformlyOn_eta : multipliableLocallyUniformlyOn_one_sub_pow.comp (𝕢 1) (fun z hz ↦ by simpa using norm_qParam_lt_one 1 ⟨z, hz⟩) (by fun_prop) -/-- The infinite product `q ↦ ∏' n, (1 - q^(n+1))` is differentiable on the open unit disc. -/ -lemma differentiableOn_tprod_one_sub_pow : - DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1))) (Metric.ball (0 : ℂ) 1) := by - apply multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn.differentiableOn - ?_ Metric.isOpen_ball - filter_upwards with n - simpa [Finset.prod_fn] using DifferentiableOn.finset_prod (fun _ _ ↦ by fun_prop) - -/-- For any `k`, the function `q ↦ ∏' n, (1 - q^(n+1))^k` is differentiable on the -open unit disc. -/ -lemma differentiableOn_tprod_one_sub_pow_pow (k : ℕ) : - DifferentiableOn ℂ (fun q ↦ ∏' n, (1 - q ^ (n + 1)) ^ k) (Metric.ball (0 : ℂ) 1) := by - refine (differentiableOn_tprod_one_sub_pow.fun_pow k).congr fun q hq ↦ ?_ - have hq_lt : ‖q‖ < 1 := by simpa [Metric.mem_ball, dist_zero_right] using hq - exact (multipliable_one_sub_pow hq_lt).tprod_pow k - -theorem summable_eta_q (z : ℍ) : Summable fun n ↦ ‖-eta_q n z‖ := by - have hq : ‖(𝕢 (1 : ℝ) ↑z : ℂ)‖ < 1 := by exact_mod_cast norm_qParam_lt_one 1 z - simpa only [norm_neg, eta_q, norm_pow] using - (summable_nat_add_iff 1).mpr (summable_geometric_of_lt_one (norm_nonneg _) hq) - -lemma multipliableLocallyUniformlyOn_eta : - MultipliableLocallyUniformlyOn (fun n a ↦ 1 - eta_q n a) ℍₒ := - ⟨_, (multipliableLocallyUniformlyOn_one_sub_pow.hasProdLocallyUniformlyOn : - TendstoLocallyUniformlyOn _ _ _ _).comp (Periodic.qParam 1) - (fun z hz ↦ by simpa [Metric.mem_ball, dist_zero_right] using - (by exact_mod_cast norm_qParam_lt_one 1 ⟨z, hz⟩ : ‖(𝕢 (1 : ℝ) z : ℂ)‖ < 1)) - (by fun_prop)⟩ - lemma eta_tprod_ne_zero {z : ℂ} (hz : z ∈ ℍₒ) : ∏' n, (1 - eta_q n z) ≠ 0 := by refine tprod_one_add_ne_zero_of_summable (f := fun n ↦ -eta_q n z) ?_ ?_ · exact fun i ↦ by simpa using one_sub_eta_q_ne_zero i hz diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0ddf7a000f7e55..83083c0afe4ccb 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -163,6 +163,65 @@ lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by norm_num [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli 6 = 1 / 42 by decide +kernel] +/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ +private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) + +private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : + E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by + change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ + ring + +private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + have h4 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 4 by norm_num) ⟨2, rfl⟩ + have h6 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 6 by norm_num) ⟨3, rfl⟩ + rw [PowerSeries.coeff_zero_eq_constantCoeff] at h4 h6 ⊢ + simp [h4, h6] + +private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : + (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by + have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)) + rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, + E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + ring + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by + obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm + obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g + have hgE : (g : ℍ → ℂ) = E4_cube_sub_E6_sq_form := congrArg DFunLike.coe hg + have hc_eq : c = 1728 := by + have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc + have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c + CuspForm.discriminant + rw [hcΔ, hgE] at hgΔ + have h := congr_arg (·.coeff 1) hgΔ + simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, + E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by + rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, + congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] + linear_combination (1 / 1728 : ℂ) * h1728 + /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p = 0`. -/ diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 582d40a8fefd1d..d22a368066fde1 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -192,6 +192,50 @@ lemma exp_isBigO_discriminant : (fun τ ↦ Real.exp (-2 * π * τ.im)) =O[atImI grind [norm_one, norm_sub_rev] linarith [norm_nonneg (𝕢 1 τ), mul_le_mul_of_nonneg_left hprod_bound (norm_nonneg (𝕢 1 τ))] +/-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` +on `ball 0 (1/2)`. -/ +private lemma discriminant_cuspFunction_eqOn : + Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + intro q hq + by_cases hq0 : q = 0 + · simp only [hq0, zero_mul] + exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos + discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex + · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) + have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 + rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, + comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] + have hqr := Periodic.qParam_right_inv one_ne_zero hq0 + have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by + simp [eta_q, hqr] + simp only [hqr, heta] + +/-- The product `∏' i, (1 - q^(i+1))^24` is differentiable within `ball 0 (1/2)` at 0. -/ +private lemma differentiableWithinAt_eta_prod_pow : + DifferentiableWithinAt ℂ (fun q : ℂ ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) + (Metric.ball 0 (1 / 2)) 0 := + (differentiableOn_tprod_one_sub_pow_pow 24 0 + (by simp [Metric.mem_ball] : (0 : ℂ) ∈ Metric.ball 0 1)).mono + (Metric.ball_subset_ball (by norm_num)) + +/-- The first q-expansion coefficient of the modular discriminant is 1. -/ +lemma discriminant_qExpansion_coeff_one : + (qExpansion 1 (Δ : ℍ → ℂ)).coeff 1 = 1 := by + rw [qExpansion_coeff] + simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, + iteratedDeriv_zero] + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) + change deriv (cuspFunction 1 Δ) 0 = 1 + rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] + rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] + have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = + derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + + id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := + derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow + rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + simp + end end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/LevelOne.lean index 90e84f176c71fc..18b54c2095a625 100644 --- a/Mathlib/NumberTheory/ModularForms/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/LevelOne.lean @@ -72,9 +72,6 @@ namespace ModularFormClass variable [ModularFormClass F 𝒮ℒ k] -lemma one_mem_strictPeriods_SL : (1 : ℝ) ∈ (𝒮ℒ : Subgroup (GL (Fin 2) ℝ)).strictPeriods := - Gamma_one_coe_eq_SL ▸ one_mem_strictPeriods_SL2Z - private theorem cuspFunction_eqOn_const_of_nonpos_wt (hk : k ≤ 0) (f : F) : Set.EqOn (cuspFunction 1 f) (const ℂ (cuspFunction 1 f 0)) (Metric.ball 0 1) := by refine eq_const_of_exists_le (fun q hq ↦ ?_) (exp_nonneg (-π)) ?_ (fun q hq ↦ ?_) From 5ebde02548a1ed952501090401a0f46abd55e265 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 12:53:34 +0100 Subject: [PATCH 22/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20clean?= =?UTF-8?q?=20up=20=CE=94=20=3D=20(E=E2=82=84=C2=B3=20-=20E=E2=82=86=C2=B2?= =?UTF-8?q?)=20/=201728=20proof?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applies findings from /simplify code review: - Extract the duplicated `qExpansion_sub` rewrite chain into a shared `E₄CubeSubE₆SqForm_qExpansion_eq` helper. Both `_isCuspForm` and `_qExpansion_coeff_one` now reduce to a one-line `rw` of this helper (~16 lines saved). - `linear_combination (1 / 1728 : ℂ) * h1728` → `linear_combination h1728 / 1728`. - Rename `E4_cube_sub_E6_sq_form` → `E₄CubeSubE₆SqForm` (camelCase + subscripts per mathlib def naming convention) and `discriminant_eq_E4_cube_sub_E6_sq` → `discriminant_eq_E₄_cube_sub_E₆_sq`. - Use `ball 0 1` instead of `ball 0 (1/2)` in `discriminant_cuspFunction_eqOn` and `discriminant_qExpansion_coeff_one` (the actual constraint is `‖q‖ < 1`), which lets `differentiableOn_tprod_one_sub_pow_pow` apply directly and removes the now-unnecessary `differentiableWithinAt_eta_prod_pow` helper. --- .../DimensionFormulas/LevelOne.lean | 65 +++++++++---------- .../ModularForms/Discriminant.lean | 48 +++++--------- 2 files changed, 45 insertions(+), 68 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 83083c0afe4ccb..f32cf75aa63e3d 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -164,63 +164,58 @@ lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by norm_num [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli 6 = 1 / 42 by decide +kernel] /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ -private noncomputable def E4_cube_sub_E6_sq_form : ModularForm 𝒮ℒ 12 := +private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - ModularForm.mcast (by norm_num) (E₆.mul E₆) -private lemma E4_cube_sub_E6_sq_form_apply (z : ℍ) : - E4_cube_sub_E6_sq_form z = E₄ z ^ 3 - E₆ z ^ 2 := by +private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : + E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ ring -private lemma E4_cube_sub_E6_sq_form_isCuspForm : IsCuspForm E4_cube_sub_E6_sq_form := by - refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ - have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - have h4 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 4 by norm_num) ⟨2, rfl⟩ - have h6 := E_qExpansion_coeff_zero (show (3 : ℕ) ≤ 6 by norm_num) ⟨3, rfl⟩ - rw [PowerSeries.coeff_zero_eq_constantCoeff] at h4 h6 ⊢ - simp [h4, h6] - -private lemma E4_cube_sub_E6_sq_form_qExpansion_coeff_one : - (qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ)).coeff 1 = 1728 := by - have hsub : qExpansion 1 (E4_cube_sub_E6_sq_form : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) := - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)) - rw [hsub, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, +private lemma E₄CubeSubE₆SqForm_qExpansion_eq : + qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = + qExpansion 1 (E₄ : ℍ → ℂ) * qExpansion 1 E₄ * qExpansion 1 E₄ - + qExpansion 1 (E₆ : ℍ → ℂ) * qExpansion 1 E₆ := by + rw [show qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = + qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) from + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)), + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - simp [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + +private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, + E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + +private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : + (qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ)).coeff 1 = 1728 := by + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - ring /-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ -theorem discriminant_eq_E4_cube_sub_E6_sq (z : ℍ) : +theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by - obtain ⟨g, hg⟩ := E4_cube_sub_E6_sq_form_isCuspForm + obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g - have hgE : (g : ℍ → ℂ) = E4_cube_sub_E6_sq_form := congrArg DFunLike.coe hg + have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg have hc_eq : c = 1728 := by have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c CuspForm.discriminant rw [hcΔ, hgE] at hgΔ - have h := congr_arg (·.coeff 1) hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, - E4_cube_sub_E6_sq_form_qExpansion_coeff_one] using h.symm + E₄CubeSubE₆SqForm_qExpansion_coeff_one] using (congr_arg (·.coeff 1) hgΔ).symm have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, - congr_fun hgE z, E4_cube_sub_E6_sq_form_apply] - linear_combination (1 / 1728 : ℂ) * h1728 + congr_fun hgE z, E₄CubeSubE₆SqForm_apply] + linear_combination h1728 / 1728 /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index d22a368066fde1..9798ae883c45f5 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -193,48 +193,30 @@ lemma exp_isBigO_discriminant : (fun τ ↦ Real.exp (-2 * π * τ.im)) =O[atImI linarith [norm_nonneg (𝕢 1 τ), mul_le_mul_of_nonneg_left hprod_bound (norm_nonneg (𝕢 1 τ))] /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` -on `ball 0 (1/2)`. -/ +on the open unit disc. -/ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) := by + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 - · simp only [hq0, zero_mul] - exact Periodic.cuspFunction_zero_of_zero_at_inf one_pos + · simpa [hq0] using Periodic.cuspFunction_zero_of_zero_at_inf one_pos discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex - · have hqn : ‖q‖ < 1 := lt_trans (by simpa [dist_zero_right] using hq) (by norm_num) - have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos hqn hq0 - rw [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, - comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩] - have hqr := Periodic.qParam_right_inv one_ne_zero hq0 - have heta : ∀ n : ℕ, eta_q n (Periodic.invQParam 1 q) = q ^ (n + 1) := fun n ↦ by - simp [eta_q, hqr] - simp only [hqr, heta] - -/-- The product `∏' i, (1 - q^(i+1))^24` is differentiable within `ball 0 (1/2)` at 0. -/ -private lemma differentiableWithinAt_eta_prod_pow : - DifferentiableWithinAt ℂ (fun q : ℂ ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) - (Metric.ball 0 (1 / 2)) 0 := - (differentiableOn_tprod_one_sub_pow_pow 24 0 - (by simp [Metric.mem_ball] : (0 : ℂ) ∈ Metric.ball 0 1)).mono - (Metric.ball_subset_ball (by norm_num)) + · have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos + (by simpa [dist_zero_right] using hq) hq0 + simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, + comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, + Periodic.qParam_right_inv one_ne_zero hq0, eta_q] /-- The first q-expansion coefficient of the modular discriminant is 1. -/ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 (Δ : ℍ → ℂ)).coeff 1 = 1 := by - rw [qExpansion_coeff] - simp only [Nat.factorial_one, Nat.cast_one, inv_one, one_mul, iteratedDeriv_succ, - iteratedDeriv_zero] - have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) (1 / 2 : ℝ) := Metric.mem_ball_self (by norm_num) - change deriv (cuspFunction 1 Δ) 0 = 1 - rw [← derivWithin_of_isOpen Metric.isOpen_ball hmem] - rw [derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem)] - have : derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 = - derivWithin id (Metric.ball 0 (1 / 2)) 0 * (∏' i, (1 - (0 : ℂ) ^ (i + 1)) ^ 24) + - id 0 * derivWithin (fun q ↦ ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 (1 / 2)) 0 := - derivWithin_mul differentiableWithinAt_id' differentiableWithinAt_eta_prod_pow - rw [this, derivWithin_id _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] - simp + have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos + simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, + ← derivWithin_of_isOpen Metric.isOpen_ball hmem, + derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), + derivWithin_fun_mul (s := Metric.ball 0 1) differentiableWithinAt_id' + (differentiableOn_tprod_one_sub_pow_pow 24 _ hmem), + derivWithin_id' _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] end From 82028aa9cc1036b5c52b431e04d28bd58c51729b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 13:02:40 +0100 Subject: [PATCH 23/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20drop?= =?UTF-8?q?=20redundant=20=E2=84=8D=20=E2=86=92=20=E2=84=82=20ascriptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drops `(... : ℍ → ℂ)` type ascriptions where the surrounding term already forces the coercion (`qExpansion 1 E₄`, `cuspFunction 1 Δ`, `qExpansion 1 E₄CubeSubE₆SqForm`, etc.). Also reflows the affected declarations to fit the 100-character line limit. --- .../ModularForms/DimensionFormulas/LevelOne.lean | 11 +++++------ Mathlib/NumberTheory/ModularForms/Discriminant.lean | 12 +++++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index f32cf75aa63e3d..ad1db030e3eba2 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -174,11 +174,10 @@ private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : ring private lemma E₄CubeSubE₆SqForm_qExpansion_eq : - qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = - qExpansion 1 (E₄ : ℍ → ℂ) * qExpansion 1 E₄ * qExpansion 1 E₄ - - qExpansion 1 (E₆ : ℍ → ℂ) * qExpansion 1 E₆ := by - rw [show qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ) = - qExpansion 1 ((E₄.mul E₄).mul E₄ : ℍ → ℂ) - qExpansion 1 (E₆.mul E₆ : ℍ → ℂ) from + qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - + qExpansion 1 E₆ * qExpansion 1 E₆ := by + rw [show qExpansion 1 E₄CubeSubE₆SqForm = + qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) (ModularForm.mcast (by norm_num) (E₆.mul E₆)), @@ -193,7 +192,7 @@ private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqFor E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : - (qExpansion 1 (E₄CubeSubE₆SqForm : ℍ → ℂ)).coeff 1 = 1728 := by + (qExpansion 1 E₄CubeSubE₆SqForm).coeff 1 = 1728 := by rw [E₄CubeSubE₆SqForm_qExpansion_eq] norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 9798ae883c45f5..08efb060e5203e 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -194,22 +194,20 @@ lemma exp_isBigO_discriminant : (fun τ ↦ Real.exp (-2 * π * τ.im)) =O[atImI /-- The cusp function of the discriminant equals `q * ∏' n, (1 - q^(n+1))^24` on the open unit disc. -/ -private lemma discriminant_cuspFunction_eqOn : - Set.EqOn (cuspFunction 1 (Δ : ℍ → ℂ)) - (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by +private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 Δ) + (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) := by intro q hq by_cases hq0 : q = 0 · simpa [hq0] using Periodic.cuspFunction_zero_of_zero_at_inf one_pos discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex · have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos (by simpa [dist_zero_right] using hq) hq0 - simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, - comp_apply, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, + simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, + ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, Periodic.qParam_right_inv one_ne_zero hq0, eta_q] /-- The first q-expansion coefficient of the modular discriminant is 1. -/ -lemma discriminant_qExpansion_coeff_one : - (qExpansion 1 (Δ : ℍ → ℂ)).coeff 1 = 1 := by +lemma discriminant_qExpansion_coeff_one : (qExpansion 1 Δ).coeff 1 = 1 := by have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, ← derivWithin_of_isOpen Metric.isOpen_ball hmem, From d2b5d0e8dfeb17ee675d8b4fdd4cf3e9b8c35b7b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 15:46:36 +0100 Subject: [PATCH 24/61] =?UTF-8?q?feat(NumberTheory/ModularForms):=20graded?= =?UTF-8?q?-ring=20version=20of=20=CE=94=20=3D=20(E=E2=82=84=C2=B3=20-=20E?= =?UTF-8?q?=E2=82=86=C2=B2)=20/=201728?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`, the analogue of `discriminant_eq_E₄_cube_sub_E₆_sq` in the graded ring `⨁ k, ModularForm 𝒮ℒ k`: DirectSum.of (ModularForm 𝒮ℒ) 12 (CuspForm.discriminant : ModularForm 𝒮ℒ 12) = (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) The proof reduces to the pointwise identity via `DirectSum.of_mul_of`, `congr 1`, and `ext`, then closes by `discriminant_eq_E₄_cube_sub_E₆_sq` and `ring`. --- .../DimensionFormulas/LevelOne.lean | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index ad1db030e3eba2..d65412a50ecf90 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -23,6 +23,8 @@ of even weight. * `ModularForm.rank_eq_one_add_rank_cuspForm`: `rank M_k = 1 + rank S_k` for even `k ≥ 3`. * `ModularForm.dimension_level_one`: the full dimension formula for all even `k : ℕ`. * `ModularForm.levelOne_odd_weight_rank_zero`: modular forms of odd weight are zero. +* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq`: the identity `Δ = (E₄³ - E₆²) / 1728`, + with a graded-ring version `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`. * A `FiniteDimensional ℂ (ModularForm 𝒮ℒ k)` instance for every `k : ℤ`. -/ @@ -216,6 +218,28 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : congr_fun hgE z, E₄CubeSubE₆SqForm_apply] linear_combination h1728 / 1728 +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring +`⨁ k, ModularForm 𝒮ℒ k`. -/ +theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : + DirectSum.of (ModularForm 𝒮ℒ) 12 (CuspForm.discriminant : ModularForm 𝒮ℒ 12) = + (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) := by + rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] + rfl + have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by norm_num) (E₆.mul E₆)) := by + rw [pow_two, DirectSum.of_mul_of] + rfl + rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] + congr 1 + ext z + change ModularForm.discriminant z = + (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + rw [discriminant_eq_E₄_cube_sub_E₆_sq z] + ring + /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p = 0`. -/ From 4b367badbfe4266a158531426cd15117b040dd3f Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 15:54:08 +0100 Subject: [PATCH 25/61] chore(NumberTheory/ModularForms): use decide for nat equalities in mcast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In `discriminant_eq_E₄_cube_sub_E₆_sq_graded`, replace `(by norm_num)` proofs of `4 + 4 + 4 = 12` and `6 + 6 = 12` with `(by decide)` (kernel reduction). --- .../ModularForms/DimensionFormulas/LevelOne.lean | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index d65412a50ecf90..ab4f264c03b330 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -221,24 +221,21 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : /-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring `⨁ k, ModularForm 𝒮ℒ k`. -/ theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : - DirectSum.of (ModularForm 𝒮ℒ) 12 (CuspForm.discriminant : ModularForm 𝒮ℒ 12) = - (1 / 1728 : ℂ) • (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + DirectSum.of (ModularForm 𝒮ℒ) 12 CuspForm.discriminant = + (1 / 1728 : ℂ) • (.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - .of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) := by + (ModularForm.mcast (by decide) ((E₄.mul E₄).mul E₄)) := by rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] rfl have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = - DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by norm_num) (E₆.mul E₆)) := by + DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by decide) (E₆.mul E₆)) := by rw [pow_two, DirectSum.of_mul_of] rfl rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] congr 1 ext z - change ModularForm.discriminant z = - (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) - rw [discriminant_eq_E₄_cube_sub_E₆_sq z] - ring + change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + grind [discriminant_eq_E₄_cube_sub_E₆_sq z] /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with From 8de2aff96a1c5443840512d551fc0d7a9cc82110 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:01:05 +0100 Subject: [PATCH 26/61] feat(NumberTheory/ModularForms): mcast_apply simp lemmas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `@[simp]` lemmas `ModularForm.mcast_apply` and `CuspForm.mcast_apply` saying `mcast h f hΓ z = f z` (true by `rfl`). These let `simp` automatically unfold `mcast` in pointwise reasoning, and are useful API for any future proofs that mix `ModularForm.mcast`/`CuspForm.mcast` with `simp`-based function-level rewriting. --- Mathlib/NumberTheory/ModularForms/Basic.lean | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index cfb4abba9ed314..6a3070e0e34275 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -549,6 +549,10 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Cusp holo' := f.holo' zero_at_cusps' hc := h ▸ f.zero_at_cusps' (hΓ ▸ hc) +@[simp] +lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : CuspForm Γ a) + (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl + end CuspForm namespace ModularForm @@ -564,6 +568,10 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Modu holo' := f.holo' bdd_at_cusps' hc := h ▸ f.bdd_at_cusps' (hΓ ▸ hc) +@[simp] +lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : ModularForm Γ a) + (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl + @[ext (iff := false)] theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMonoid (ModularForm Γ)} (h : a.fst = b.fst) (h2 : mcast h a.snd = b.snd) : a = b := by From 0ce59fdc426ca49ac3781248fc681f910c0f531c Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:35:31 +0100 Subject: [PATCH 27/61] Revert "feat(NumberTheory/ModularForms): mcast_apply simp lemmas" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The simp lemmas were unused — `change` in `discriminant_eq_E₄_cube_sub_E₆_sq_graded` goes through defeq directly, and the `simp only`-based alternatives I tried didn't close the goal. Removing per "no unused API" guideline; can be re-added later when there's a proof that benefits. This reverts commit 8de2aff96a1. --- Mathlib/NumberTheory/ModularForms/Basic.lean | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index 6a3070e0e34275..cfb4abba9ed314 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -549,10 +549,6 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Cusp holo' := f.holo' zero_at_cusps' hc := h ▸ f.zero_at_cusps' (hΓ ▸ hc) -@[simp] -lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : CuspForm Γ a) - (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl - end CuspForm namespace ModularForm @@ -568,10 +564,6 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Modu holo' := f.holo' bdd_at_cusps' hc := h ▸ f.bdd_at_cusps' (hΓ ▸ hc) -@[simp] -lemma mcast_apply {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : ModularForm Γ a) - (hΓ : Γ' = Γ := by rfl) (z : ℍ) : mcast h f hΓ z = f z := rfl - @[ext (iff := false)] theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMonoid (ModularForm Γ)} (h : a.fst = b.fst) (h2 : mcast h a.snd = b.snd) : a = b := by From 9f3dadc6b2e1f24100a399a7a5db99f045338376 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:46:48 +0100 Subject: [PATCH 28/61] refactor(NumberTheory/ModularForms): move discriminant identity to GradedRing.lean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Splits the `Δ = (E₄³ - E₆²) / 1728` results out of `DimensionFormulas/LevelOne.lean` into a new file `DimensionFormulas/GradedRing.lean`. This new file is intended to collect structural results about the graded ring `⨁ k, ModularForm 𝒮ℒ k` of level-1 modular forms (e.g. that `E₄, E₆` generate the full graded ring, to come). Moved declarations: - `E₄CubeSubE₆SqForm` (private) - `E₄CubeSubE₆SqForm_apply` (private) - `E₄CubeSubE₆SqForm_qExpansion_eq` (private) - `E₄CubeSubE₆SqForm_isCuspForm` (private) - `E₄CubeSubE₆SqForm_qExpansion_coeff_one` (private) - `discriminant_eq_E₄_cube_sub_E₆_sq` - `discriminant_eq_E₄_cube_sub_E₆_sq_graded` --- Mathlib.lean | 1 + .../DimensionFormulas/GradedRing.lean | 104 ++++++++++++++++++ .../DimensionFormulas/LevelOne.lean | 74 ------------- .../ModularForms/Discriminant.lean | 2 +- 4 files changed, 106 insertions(+), 75 deletions(-) create mode 100644 Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean diff --git a/Mathlib.lean b/Mathlib.lean index 06e253281cc1da..4735ad3e08a74e 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5655,6 +5655,7 @@ public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta public import Mathlib.NumberTheory.ModularForms.Derivative +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.GradedRing public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.Discriminant public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean new file mode 100644 index 00000000000000..f3c55e20f78f1b --- /dev/null +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2026 Chris Birkbeck. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Chris Birkbeck +-/ +module + +public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne + +/-! +# The graded ring of level-1 modular forms + +This file collects structural results about the graded ring `⨁ k, ModularForm 𝒮ℒ k` of +level-1 modular forms, beyond those that fall out of the dimension formula directly. + +## Main results + +* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq`: the pointwise identity + `Δ = (E₄³ - E₆²) / 1728`. +* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`: the same identity in the graded + ring `⨁ k, ModularForm 𝒮ℒ k`. +-/ + +@[expose] public noncomputable section + +open UpperHalfPlane ModularForm ModularFormClass MatrixGroups EisensteinSeries + +namespace ModularForm + +/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ +private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := + ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - + ModularForm.mcast (by norm_num) (E₆.mul E₆) + +private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : + E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by + change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ + ring + +private lemma E₄CubeSubE₆SqForm_qExpansion_eq : + qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - + qExpansion 1 E₆ * qExpansion 1 E₆ := by + rw [show qExpansion 1 E₄CubeSubE₆SqForm = + qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from + ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) + (ModularForm.mcast (by norm_num) (E₆.mul E₆)), + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + +private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by + refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, + E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + +private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : + (qExpansion 1 E₄CubeSubE₆SqForm).coeff 1 = 1728 := by + rw [E₄CubeSubE₆SqForm_qExpansion_eq] + norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, + E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, + E_qExpansion_coeff_zero _ ⟨3, rfl⟩] + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ +theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : + discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by + obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm + obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g + have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg + have hc_eq : c = 1728 := by + have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc + have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c + CuspForm.discriminant + rw [hcΔ, hgE] at hgΔ + simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, + E₄CubeSubE₆SqForm_qExpansion_coeff_one] using (congr_arg (·.coeff 1) hgΔ).symm + have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by + rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, + congr_fun hgE z, E₄CubeSubE₆SqForm_apply] + linear_combination h1728 / 1728 + +/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring +`⨁ k, ModularForm 𝒮ℒ k`. -/ +theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : + DirectSum.of (ModularForm 𝒮ℒ) 12 CuspForm.discriminant = + (1 / 1728 : ℂ) • (.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - .of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by + have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 + (ModularForm.mcast (by decide) ((E₄.mul E₄).mul E₄)) := by + rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] + rfl + have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = + DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by decide) (E₆.mul E₆)) := by + rw [pow_two, DirectSum.of_mul_of] + rfl + rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] + congr 1 + ext z + change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) + grind [discriminant_eq_E₄_cube_sub_E₆_sq z] + +end ModularForm + +end diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index ab4f264c03b330..0ddf7a000f7e55 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -23,8 +23,6 @@ of even weight. * `ModularForm.rank_eq_one_add_rank_cuspForm`: `rank M_k = 1 + rank S_k` for even `k ≥ 3`. * `ModularForm.dimension_level_one`: the full dimension formula for all even `k : ℕ`. * `ModularForm.levelOne_odd_weight_rank_zero`: modular forms of odd weight are zero. -* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq`: the identity `Δ = (E₄³ - E₆²) / 1728`, - with a graded-ring version `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`. * A `FiniteDimensional ℂ (ModularForm 𝒮ℒ k)` instance for every `k : ℤ`. -/ @@ -165,78 +163,6 @@ lemma E₄_qExpansion_coeff_one : (qExpansion 1 E₄).coeff 1 = 240 := by lemma E₆_qExpansion_coeff_one : (qExpansion 1 E₆).coeff 1 = -504 := by norm_num [E_qExpansion_coeff _ ⟨3, rfl⟩, show bernoulli 6 = 1 / 42 by decide +kernel] -/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ -private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) - -private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : - E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by - change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ - ring - -private lemma E₄CubeSubE₆SqForm_qExpansion_eq : - qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - - qExpansion 1 E₆ * qExpansion 1 E₆ := by - rw [show qExpansion 1 E₄CubeSubE₆SqForm = - qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)), - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] - -private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by - refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ - rw [E₄CubeSubE₆SqForm_qExpansion_eq] - simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, - E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - -private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : - (qExpansion 1 E₄CubeSubE₆SqForm).coeff 1 = 1728 := by - rw [E₄CubeSubE₆SqForm_qExpansion_eq] - norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, - E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, - E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ -theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : - discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by - obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm - obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g - have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg - have hc_eq : c = 1728 := by - have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc - have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c - CuspForm.discriminant - rw [hcΔ, hgE] at hgΔ - simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, - E₄CubeSubE₆SqForm_qExpansion_coeff_one] using (congr_arg (·.coeff 1) hgΔ).symm - have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by - rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, - congr_fun hgE z, E₄CubeSubE₆SqForm_apply] - linear_combination h1728 / 1728 - -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring -`⨁ k, ModularForm 𝒮ℒ k`. -/ -theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : - DirectSum.of (ModularForm 𝒮ℒ) 12 CuspForm.discriminant = - (1 / 1728 : ℂ) • (.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - .of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by - have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 - (ModularForm.mcast (by decide) ((E₄.mul E₄).mul E₄)) := by - rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] - rfl - have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = - DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by decide) (E₆.mul E₆)) := by - rw [pow_two, DirectSum.of_mul_of] - rfl - rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] - congr 1 - ext z - change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) - grind [discriminant_eq_E₄_cube_sub_E₆_sq z] - /- Algebraic core of the weight-2 vanishing argument: if `p : PowerSeries ℂ` satisfies `c₄ • p₄ = p²` and `c₆ • p₆ = p³` for power series `p₄`, `p₆` with constant term `1` and first-order coefficients `240` and `-504`, then `p = 0`. -/ diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 08efb060e5203e..627a7139ddaa04 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -202,7 +202,7 @@ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 Δ) discriminant_isZeroAtImInfty.zero_at_infty_comp_ofComplex · have him := Periodic.im_invQParam_pos_of_norm_lt_one one_pos (by simpa [dist_zero_right] using hq) hq0 - simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, comp_apply, + simp [cuspFunction, Periodic.cuspFunction_eq_of_nonzero 1 _ hq0, ofComplex_apply_of_im_pos him, discriminant_eq_q_prod ⟨_, him⟩, Periodic.qParam_right_inv one_ne_zero hq0, eta_q] From a4125e642e648e05bef5674067fc47cfea30f9b9 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 16:54:24 +0100 Subject: [PATCH 29/61] chore(NumberTheory/ModularForms): move GradedRing.lean to ModularForms/ root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move `DimensionFormulas/GradedRing.lean` → `GradedRing.lean`. The graded-ring results aren't specifically about dimension formulas, so they belong at the top of the `ModularForms/` directory. --- Mathlib.lean | 2 +- .../ModularForms/{DimensionFormulas => }/GradedRing.lean | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Mathlib/NumberTheory/ModularForms/{DimensionFormulas => }/GradedRing.lean (100%) diff --git a/Mathlib.lean b/Mathlib.lean index 4735ad3e08a74e..094ddc76d96bb5 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -5655,7 +5655,6 @@ public import Mathlib.NumberTheory.ModularForms.Cusps public import Mathlib.NumberTheory.ModularForms.DedekindEta public import Mathlib.NumberTheory.ModularForms.Delta public import Mathlib.NumberTheory.ModularForms.Derivative -public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.GradedRing public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne public import Mathlib.NumberTheory.ModularForms.Discriminant public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic @@ -5669,6 +5668,7 @@ public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.MDifferentiable public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.QExpansion public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Summable public import Mathlib.NumberTheory.ModularForms.EisensteinSeries.UniformConvergence +public import Mathlib.NumberTheory.ModularForms.GradedRing public import Mathlib.NumberTheory.ModularForms.Identities public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Bounds public import Mathlib.NumberTheory.ModularForms.JacobiTheta.Manifold diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean similarity index 100% rename from Mathlib/NumberTheory/ModularForms/DimensionFormulas/GradedRing.lean rename to Mathlib/NumberTheory/ModularForms/GradedRing.lean From 3f560bee4233f3350b0153d68efd3ffec23c706e Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 17:23:44 +0100 Subject: [PATCH 30/61] =?UTF-8?q?feat(NumberTheory/ModularForms):=20scaffo?= =?UTF-8?q?lding=20for=20E=E2=82=84,=20E=E2=82=86=20generate=20graded=20ri?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the evaluation homomorphism `evalE₄E₆ : ℂ[X₀, X₁] →ₐ[ℂ] ⨁ k, ModularForm 𝒮ℒ k` and signposts the surjectivity / injectivity results (currently `sorry`) used to conclude that `E₄, E₆` generate the graded ring of level-1 modular forms. The proofs will be ported from (Modularforms/Generators/) in follow-up commits. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index f3c55e20f78f1b..d41b87ae9fca44 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -6,12 +6,19 @@ Authors: Chris Birkbeck module public import Mathlib.NumberTheory.ModularForms.DimensionFormulas.LevelOne +public import Mathlib.RingTheory.MvPolynomial.WeightedHomogeneous /-! # The graded ring of level-1 modular forms This file collects structural results about the graded ring `⨁ k, ModularForm 𝒮ℒ k` of -level-1 modular forms, beyond those that fall out of the dimension formula directly. +level-1 modular forms. + +## Main definitions + +* `ModularForm.E₄E₆Weight`: the weight function `Fin 2 → ℕ` mapping `0 ↦ 4`, `1 ↦ 6`. +* `ModularForm.evalE₄E₆`: the evaluation homomorphism + `ℂ[X₀, X₁] →ₐ[ℂ] ⨁ k, ModularForm 𝒮ℒ k` sending `X₀ ↦ E₄`, `X₁ ↦ E₆`. ## Main results @@ -19,6 +26,12 @@ level-1 modular forms, beyond those that fall out of the dimension formula direc `Δ = (E₄³ - E₆²) / 1728`. * `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`: the same identity in the graded ring `⨁ k, ModularForm 𝒮ℒ k`. +* `ModularForm.evalE₄E₆_surjective`: `evalE₄E₆` is surjective. +* `ModularForm.evalE₄E₆_injective`: `evalE₄E₆` is injective (E₄ and E₆ are algebraically + independent). +* `ModularForm.modularFormsEquivMvPolynomial`: the algebra isomorphism + `ℂ[X₀, X₁] ≃ₐ[ℂ] ⨁ k, ModularForm 𝒮ℒ k`. +* `ModularForm.E₄E₆_generate`: `E₄, E₆` generate the graded ring as an ℂ-algebra. -/ @[expose] public noncomputable section @@ -27,6 +40,8 @@ open UpperHalfPlane ModularForm ModularFormClass MatrixGroups EisensteinSeries namespace ModularForm +/-! ### `Δ = (E₄³ - E₆²) / 1728` -/ + /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - @@ -99,6 +114,72 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) grind [discriminant_eq_E₄_cube_sub_E₆_sq z] +/-! ### Generators of the graded ring + +The remainder of this file establishes that `E₄, E₆` generate the graded ring of level-1 +modular forms freely as an `ℂ`-algebra: the evaluation homomorphism `evalE₄E₆` is an +isomorphism. The proofs are ported from + (`Modularforms/Generators/`). -/ + +/-- Weight function assigning weight 4 to E₄ (variable 0) and weight 6 to E₆ (variable 1). -/ +def E₄E₆Weight : Fin 2 → ℕ := ![4, 6] + +/-- Evaluation homomorphism sending `ℂ[X₀, X₁]` to the graded ring of level 1 modular forms +via `X₀ ↦ E₄` and `X₁ ↦ E₆`. -/ +noncomputable def evalE₄E₆ : MvPolynomial (Fin 2) ℂ →ₐ[ℂ] DirectSum ℤ (ModularForm 𝒮ℒ) := + MvPolynomial.aeval + ![DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, DirectSum.of (ModularForm 𝒮ℒ) 6 E₆] + +@[simp] +lemma evalE₄E₆_X0 : evalE₄E₆ (MvPolynomial.X 0) = DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ := by + simp [evalE₄E₆] + +@[simp] +lemma evalE₄E₆_X1 : evalE₄E₆ (MvPolynomial.X 1) = DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ := by + simp [evalE₄E₆] + +lemma evalE₄E₆_C (c : ℂ) : + evalE₄E₆ (MvPolynomial.C c) = algebraMap ℂ (DirectSum ℤ (ModularForm 𝒮ℒ)) c := + MvPolynomial.aeval_C _ c + +/-- The evaluation homomorphism `evalE₄E₆` is surjective. -/ +theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by + -- Port from `LeanModularForms/Modularforms/Generators/Surjectivity.lean`. + -- Strong induction on weight: for each weight `k ≥ 12 even`, take a monomial `E₄^a E₆^b` + -- with `4a + 6b = k`, subtract a scalar multiple to land in the cusp form subspace, then + -- divide by `Δ` (using `discriminantEquiv`) and apply the induction hypothesis. + -- Base cases for even `k < 12`: weight 0 (constants), weight 2 (zero), weights 4, 6, 8, 10 + -- (one-dimensional, generated by `E₄`, `E₆`, `E₄²`, `E₄E₆`). + sorry + +/-- The evaluation homomorphism `evalE₄E₆` is injective: `E₄` and `E₆` are algebraically +independent. -/ +theorem evalE₄E₆_injective : Function.Injective evalE₄E₆ := by + -- Port from `LeanModularForms/Modularforms/Generators/Injectivity.lean`. + -- Decompose into weighted-homogeneous components (weights `![4, 6]`); show each maps + -- independently into a single graded piece. Per-weight injectivity is by strong induction + -- on the weight, using the relation `X₀³ - X₁² = 1728 · Δ_poly`. + sorry + +/-- The graded ring of level-1 modular forms is isomorphic to the polynomial ring +`ℂ[X₀, X₁]` via evaluation at `E₄` and `E₆`. -/ +noncomputable def modularFormsEquivMvPolynomial : + MvPolynomial (Fin 2) ℂ ≃ₐ[ℂ] DirectSum ℤ (ModularForm 𝒮ℒ) := + AlgEquiv.ofBijective evalE₄E₆ ⟨evalE₄E₆_injective, evalE₄E₆_surjective⟩ + +/-- `E₄` and `E₆` generate the entire graded ring of level 1 modular forms as an +`ℂ`-algebra. -/ +theorem E₄E₆_generate : + Algebra.adjoin ℂ ({DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆} : Set (DirectSum ℤ (ModularForm 𝒮ℒ))) = ⊤ := by + rw [show ({DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, DirectSum.of (ModularForm 𝒮ℒ) 6 E₆} : Set _) = + Set.range (![DirectSum.of _ 4 E₄, DirectSum.of _ 6 E₆] : Fin 2 → _) + from (Matrix.range_cons_cons_empty _ _ _).symm, + Algebra.adjoin_range_eq_range_aeval, + show MvPolynomial.aeval (![DirectSum.of _ 4 E₄, DirectSum.of _ 6 E₆] : Fin 2 → _) = + evalE₄E₆ from rfl] + exact (AlgHom.range_eq_top evalE₄E₆).mpr evalE₄E₆_surjective + end ModularForm end From 4c7b24e7ef4e908d04951c8c09567b3e65802d29 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 18:32:49 +0100 Subject: [PATCH 31/61] =?UTF-8?q?feat(NumberTheory/ModularForms):=20partia?= =?UTF-8?q?l=20port=20of=20E=E2=82=84,=20E=E2=82=86=20generators=20(surjec?= =?UTF-8?q?tivity=20scaffolding)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Brings over the bulk of the surjectivity argument from LeanModularForms/Modularforms/Generators/. The remaining `sorry`s are scoped to: * `monomial_qExpansion_coeff_zero_eq_one`: q-expansion 0th coefficient of a homogeneous monomial in `(of _ 4 E₄, of _ 6 E₆)`. * the cusp-form predicate inside `surj_at_weight_inductive` (linearity step). * `evalE₄E₆_injective` (still entirely TODO). The strong-induction surjectivity proof, base cases, and weight-rank lemmas for weights 8/10 are now complete. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 228 +++++++++++++++++- 1 file changed, 221 insertions(+), 7 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index d41b87ae9fca44..e682de0780e034 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -142,15 +142,229 @@ lemma evalE₄E₆_C (c : ℂ) : evalE₄E₆ (MvPolynomial.C c) = algebraMap ℂ (DirectSum ℤ (ModularForm 𝒮ℒ)) c := MvPolynomial.aeval_C _ c +/-- `evalE₄E₆` maps the monomial `X₀^a * X₁^b` to `(of _ 4 E₄)^a * (of _ 6 E₆)^b`. -/ +lemma evalE₄E₆_monomial (a b : ℕ) : + evalE₄E₆ (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b) = + DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by + rw [map_mul, map_pow, map_pow, evalE₄E₆_X0, evalE₄E₆_X1] + +/-- For even `k ≥ 4`, there exist `a, b ∈ ℕ` with `4a + 6b = k`. -/ +private lemma exists_monomial_weight {k : ℕ} (hk : 4 ≤ k) (hkeven : Even k) : + ∃ a b : ℕ, 4 * a + 6 * b = k := by + obtain ⟨m, rfl⟩ := hkeven + rcases Nat.even_or_odd m with ⟨n, hn⟩ | ⟨n, hn⟩ + · exact ⟨n, 0, by omega⟩ + · exact ⟨n - 1, 1, by omega⟩ + +/-! ### Surjectivity of `evalE₄E₆` -/ + +/-- In a 1-dimensional weight space, if `g ≠ 0` is in the image of `evalE₄E₆`, +then every element of that weight is in the image. -/ +private lemma surj_of_rank_one {k : ℤ} + (hrank : Module.rank ℂ (ModularForm 𝒮ℒ k) = 1) {g : ModularForm 𝒮ℒ k} (hg : g ≠ 0) + (p : MvPolynomial (Fin 2) ℂ) (hp : evalE₄E₆ p = DirectSum.of _ k g) + (f : ModularForm 𝒮ℒ k) : + DirectSum.of _ k f ∈ Set.range evalE₄E₆ := by + obtain ⟨c, rfl⟩ := (finrank_eq_one_iff_of_nonzero' g hg).mp + (Module.rank_eq_one_iff_finrank_eq_one.mp hrank) f + exact ⟨MvPolynomial.C c * p, by + rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, + smul_mul_assoc, one_mul, ← DirectSum.of_smul]⟩ + +/-- The product `f * g` of two modular forms with constant-term-1 q-expansions is nonzero. -/ +private lemma mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one {k₁ k₂ : ℤ} + (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) + (hf : (qExpansion 1 f).coeff 0 = 1) (hg : (qExpansion 1 g).coeff 0 = 1) : + f.mul g ≠ 0 := by + intro h + have : (qExpansion 1 (f.mul g)).coeff 0 = 0 := by + rw [show (f.mul g : ModularForm 𝒮ℒ (k₁ + k₂)) = 0 from h] + simp [UpperHalfPlane.qExpansion_zero] + rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, + PowerSeries.coeff_mul] at this + simp [hf, hg] at this + +/-- The 0th q-expansion coefficient of `(of _ 4 E₄)^a * (of _ 6 E₆)^b` evaluated at +weight `n = 4a + 6b` equals `1`. -/ +private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + 6 * b = n) : + (qExpansion 1 + ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (n : ℤ))).coeff 0 = 1 := by + -- TODO: complete proof. Strategy: show the product is concentrated at weight n, + -- use ModularForm.qExpansion_mul and ModularForm.qExpansion_of_pow to compute + -- the q-expansion as `(qExpansion E₄)^a * (qExpansion E₆)^b`, then use + -- E_qExpansion_coeff_zero to reduce to 1 * 1 = 1. + sorry + +/-- For weight 12 ≤ n, every cusp form of weight n is `Δ * h` for some modular form +`h` of weight `n - 12`. Lifted to the graded ring. -/ +private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ ↑n) + (hg : ModularForm.IsCuspForm g) : + DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) g = + DirectSum.of (ModularForm 𝒮ℒ) (↑n - 12 : ℤ) + (CuspForm.discriminantEquiv (ModularForm.toCuspForm g + ((ModularForm.isCuspForm_iff_coeffZero_eq_zero g).mp hg))) * + DirectSum.of (ModularForm 𝒮ℒ) 12 + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := by + rw [DirectSum.of_mul_of] + symm + apply DirectSum.of_eq_of_gradedMonoid_eq + refine ModularForm.gradedMonoid_eq_of_cast ?_ ?_ + · change (↑n - 12 + 12 : ℤ) = ↑n; ring + ext z + set hcusp := (ModularForm.isCuspForm_iff_coeffZero_eq_zero g).mp hg + change ((CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)).mul + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12)) z = g z + have hdiv : (CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)) z = + g z / ModularForm.discriminant z := + CuspForm.divDiscriminant_apply (ModularForm.toCuspForm g hcusp) z + rw [ModularForm.coe_mul, Pi.mul_apply, hdiv] + change g z / ModularForm.discriminant z * ModularForm.discriminant z = g z + exact div_mul_cancel₀ _ (discriminant_ne_zero z) + +/-- The discriminant `Δ`, viewed as a modular form of weight 12, lies in the range of +`evalE₄E₆`. -/ +private lemma discriminant_mem_range_evalE₄E₆ : + DirectSum.of (ModularForm 𝒮ℒ) 12 + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ Set.range evalE₄E₆ := by + refine ⟨(1 / 1728 : ℂ) • (MvPolynomial.X 0 ^ 3 - MvPolynomial.X 1 ^ 2), ?_⟩ + simp only [map_smul, map_sub, map_pow, evalE₄E₆_X0, evalE₄E₆_X1] + rw [← discriminant_eq_E₄_cube_sub_E₆_sq_graded] + +/-- Weight casting: rewriting the index of `DirectSum.of` along an equality of weights. -/ +private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : + DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by + subst hk; rfl + +/-- Inductive step: for `n ≥ 12` even, surjectivity at weight `n` follows from surjectivity +at all lower weights via the cusp-form / `Δ` decomposition. -/ +private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Even (n : ℤ)) + (ih : ∀ m < n, ∀ (f : ModularForm 𝒮ℒ ↑m), + DirectSum.of _ (↑m : ℤ) f ∈ Set.range evalE₄E₆) + (f : ModularForm 𝒮ℒ ↑n) : + DirectSum.of _ (↑n : ℤ) f ∈ Set.range evalE₄E₆ := by + obtain ⟨a, b, hab⟩ : ∃ a b : ℕ, 4 * a + 6 * b = n := + exists_monomial_weight (by omega) (by exact_mod_cast hk_even) + set mo := DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b + set mn := mo (↑n : ℤ) + set c := (qExpansion 1 f).coeff 0 + have hmn_coeff : (qExpansion 1 mn).coeff 0 = 1 := monomial_qExpansion_coeff_zero_eq_one hab + have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := by + -- TODO: fill in via qExpansion linearity (subtraction + smul). + sorry + have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by omega + set h' := CuspForm.discriminantEquiv + (ModularForm.toCuspForm (f - c • mn) + ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp)) + have hg_ds : DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) (f - c • mn) = + DirectSum.of _ ((↑n : ℤ) - 12) h' * + DirectSum.of _ 12 + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := + cuspForm_eq_discriminant_mul _ hg_cusp + have hih : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by + rw [directSumOf_cast_eq hcast] + exact ih (n - 12) (by omega) (hcast ▸ h') + have hg_in : DirectSum.of _ (↑n : ℤ) (f - c • mn) ∈ Set.range evalE₄E₆ := by + rw [hg_ds] + obtain ⟨p1, hp1⟩ := hih + obtain ⟨p2, hp2⟩ := discriminant_mem_range_evalE₄E₆ + exact ⟨p1 * p2, by rw [map_mul, hp1, hp2]⟩ + have hmn_in : mo ∈ Set.range evalE₄E₆ := + ⟨MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b, evalE₄E₆_monomial a b⟩ + have hmn_eq : DirectSum.of _ (↑n : ℤ) mn = mo := by + have h4 : ((a : ℤ) * 4 + b * 6) = ↑n := by push_cast [← hab]; ring + simp only [mn, mo, DirectSum.ofPow, DirectSum.of_mul_of] + rw [show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) from by + simp only [Int.nsmul_eq_mul]; linarith, DirectSum.of_eq_same] + have hf_ds : DirectSum.of _ (↑n : ℤ) f = + DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn := by + rw [← DirectSum.of_smul, ← map_add] + congr 1 + abel + rw [hf_ds, hmn_eq] + obtain ⟨p1, hp1⟩ := hg_in + obtain ⟨p2, hp2⟩ := hmn_in + exact ⟨p1 + MvPolynomial.C c * p2, by + rw [map_add, hp1, map_mul, evalE₄E₆_C, hp2, + Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul]⟩ + +private lemma weight_eight_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 8) = 1 := + (ModularForm.rank_eq_one_add_rank_cuspForm (by norm_num) ⟨4, rfl⟩).trans + ((congrArg (1 + ·) (CuspForm.rank_eq_zero_of_weight_lt_twelve (by norm_num))).trans + (by norm_cast)) + +private lemma weight_ten_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 10) = 1 := + (ModularForm.rank_eq_one_add_rank_cuspForm (by norm_num) ⟨5, rfl⟩).trans + ((congrArg (1 + ·) (CuspForm.rank_eq_zero_of_weight_lt_twelve (by norm_num))).trans + (by norm_cast)) + +private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := by + intro h + have := congr_arg (DFunLike.coe (F := ModularForm 𝒮ℒ 0)) h + exact (one_ne_zero (α := ℂ)) (congr_fun this UpperHalfPlane.I) + +/-- For each weight `k`, every element of weight `k` lies in the range of `evalE₄E₆`. -/ +private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), + DirectSum.of (ModularForm 𝒮ℒ) k f ∈ Set.range evalE₄E₆ := by + intro k f + by_cases hk_neg : k < 0 + · rw [(rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero hk_neg)) f, + map_zero] + exact ⟨0, map_zero _⟩ + push Not at hk_neg + obtain ⟨n, rfl⟩ : ∃ n : ℕ, k = (n : ℤ) := ⟨k.toNat, by omega⟩ + clear hk_neg + revert f + induction n using Nat.strong_induction_on with | _ n ih => ?_ + intro f + by_cases hk_odd : Odd (n : ℤ) + · rw [ModularForm.levelOne_odd_weight_eq_zero hk_odd f, map_zero] + exact ⟨0, map_zero _⟩ + rw [Int.not_odd_iff_even] at hk_odd + by_cases hn12 : n < 12 + · interval_cases n + · exact surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one + one_ne_zero_modularForm 1 (by rw [map_one]; rfl) f + · rcases hk_odd with ⟨r, hr⟩; omega + · rw [(rank_zero_iff_forall_zero.mp ModularForm.levelOne_weight_two_rank_zero) f, map_zero] + exact ⟨0, map_zero _⟩ + · rcases hk_odd with ⟨r, hr⟩; omega + · exact surj_of_rank_one ModularForm.levelOne_weight_four_rank_one + (show E₄ ≠ 0 from E_ne_zero (by norm_num) ⟨2, rfl⟩) (MvPolynomial.X 0) evalE₄E₆_X0 f + · rcases hk_odd with ⟨r, hr⟩; omega + · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one + (show E₆ ≠ 0 from E_ne_zero (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f + · rcases hk_odd with ⟨r, hr⟩; omega + · refine surj_of_rank_one weight_eight_rank_one + (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₄ + (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨2, rfl⟩)) + (MvPolynomial.X 0 ^ 2) ?_ f + rw [map_pow, evalE₄E₆_X0, pow_two, DirectSum.of_mul_of] + apply DirectSum.of_eq_of_gradedMonoid_eq + exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 4 : ℤ) = 8 from by norm_num).symm + rfl + · rcases hk_odd with ⟨r, hr⟩; omega + · refine surj_of_rank_one weight_ten_rank_one + (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₆ + (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨3, rfl⟩)) + (MvPolynomial.X 0 * MvPolynomial.X 1) ?_ f + rw [map_mul, evalE₄E₆_X0, evalE₄E₆_X1, DirectSum.of_mul_of] + apply DirectSum.of_eq_of_gradedMonoid_eq + exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 6 : ℤ) = 10 from by norm_num).symm + rfl + · rcases hk_odd with ⟨r, hr⟩; omega + · push Not at hn12 + exact surj_at_weight_inductive hn12 hk_odd ih f + /-- The evaluation homomorphism `evalE₄E₆` is surjective. -/ theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by - -- Port from `LeanModularForms/Modularforms/Generators/Surjectivity.lean`. - -- Strong induction on weight: for each weight `k ≥ 12 even`, take a monomial `E₄^a E₆^b` - -- with `4a + 6b = k`, subtract a scalar multiple to land in the cusp form subspace, then - -- divide by `Δ` (using `discriminantEquiv`) and apply the induction hypothesis. - -- Base cases for even `k < 12`: weight 0 (constants), weight 2 (zero), weights 4, 6, 8, 10 - -- (one-dimensional, generated by `E₄`, `E₆`, `E₄²`, `E₄E₆`). - sorry + classical + intro x + suffices x ∈ Set.range evalE₄E₆ from this + rw [show x = x.sum (fun i m => DirectSum.of _ i m) from (DFinsupp.sum_single (f := x)).symm, + show (Set.range evalE₄E₆ : Set _) = ↑evalE₄E₆.range from (AlgHom.coe_range evalE₄E₆).symm] + exact Subalgebra.sum_mem _ (fun k _ => surj_of_weight k (x k)) /-- The evaluation homomorphism `evalE₄E₆` is injective: `E₄` and `E₆` are algebraically independent. -/ From 37085883e7e83498de96c0e866ce4f717a4c8293 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 18:37:31 +0100 Subject: [PATCH 32/61] feat(NumberTheory/ModularForms): complete cusp-form decomposition for surjectivity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the `cuspForm_eq_discriminant_mul` helper and the inductive cusp-form decomposition step inside `surj_at_weight_inductive`. Remaining `sorry`s: * `monomial_qExpansion_coeff_zero_eq_one`: q-expansion identity for homogeneous monomials in `(of _ 4 E₄, of _ 6 E₆)`. * `evalE₄E₆_injective`: injectivity of the evaluation homomorphism (TODO). Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/NumberTheory/ModularForms/GradedRing.lean | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index e682de0780e034..f82584cfbc1e34 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -251,8 +251,17 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev set c := (qExpansion 1 f).coeff 0 have hmn_coeff : (qExpansion 1 mn).coeff 0 = 1 := monomial_qExpansion_coeff_zero_eq_one hab have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := by - -- TODO: fill in via qExpansion linearity (subtraction + smul). - sorry + rw [ModularForm.isCuspForm_iff_coeffZero_eq_zero] + have hQsub := (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL (↑n : ℤ)).map_sub + f (c • mn) + have hQsmul := ModularFormClass.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := (↑n : ℤ)) + one_pos one_mem_strictPeriods_SL c mn + change (qExpansion 1 ⇑(f - c • mn : ModularForm 𝒮ℒ ↑n)).coeff 0 = 0 + rw [show qExpansion 1 ⇑(f - c • mn : ModularForm 𝒮ℒ ↑n) = + qExpansion 1 ⇑f - qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) from hQsub] + rw [show qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) = c • qExpansion 1 ⇑mn from hQsmul] + rw [map_sub, PowerSeries.coeff_smul] + simp [hmn_coeff, c] have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by omega set h' := CuspForm.discriminantEquiv (ModularForm.toCuspForm (f - c • mn) From e34abee775a2c31aed12c72349eb8b7bfcfa8aca Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 18:50:12 +0100 Subject: [PATCH 33/61] feat(NumberTheory/ModularForms): close `monomial_qExpansion_coeff_zero_eq_one` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses the `qExpansionRingHom` ring homomorphism plus the fact that the monomial `(of _ 4 E₄)^a * (of _ 6 E₆)^b` is concentrated at weight `n = 4a + 6b`. Surjectivity is now fully proved. Only `evalE₄E₆_injective` (the algebraic independence of E₄ and E₆) remains as `sorry`. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index f82584cfbc1e34..e78806c3deeaab 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -185,17 +185,45 @@ private lemma mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one {k₁ k₂ PowerSeries.coeff_mul] at this simp [hf, hg] at this +/-- Weight casting: rewriting the index of `DirectSum.of` along an equality of weights. -/ +private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : + DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by + subst hk; rfl + /-- The 0th q-expansion coefficient of `(of _ 4 E₄)^a * (of _ 6 E₆)^b` evaluated at weight `n = 4a + 6b` equals `1`. -/ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + 6 * b = n) : (qExpansion 1 ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (n : ℤ))).coeff 0 = 1 := by - -- TODO: complete proof. Strategy: show the product is concentrated at weight n, - -- use ModularForm.qExpansion_mul and ModularForm.qExpansion_of_pow to compute - -- the q-expansion as `(qExpansion E₄)^a * (qExpansion E₆)^b`, then use - -- E_qExpansion_coeff_zero to reduce to 1 * 1 = 1. - sorry + set R := ModularForm.qExpansionRingHom (1 : ℝ) one_pos one_mem_strictPeriods_SL with hR_def + set prod := DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b + with hprod_def + have hweight : (a • (4 : ℤ) + b • (6 : ℤ)) = (n : ℤ) := by + change ((a : ℤ) * 4 + (b : ℤ) * 6) = (n : ℤ) + push_cast [← hab]; ring + -- `prod` is concentrated at weight `n`. + have hprod_eq : prod = DirectSum.of (ModularForm 𝒮ℒ) (n : ℤ) (prod (n : ℤ)) := by + refine DFinsupp.ext (fun k : ℤ => ?_) + by_cases hk : k = (n : ℤ) + · subst hk; simp + · rw [DirectSum.of_eq_of_ne _ _ _ hk] + rw [hprod_def, DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of] + refine DirectSum.of_eq_of_ne _ _ _ ?_ + rw [← hweight] at hk + exact hk + -- Compute `R prod` two ways. + have hR_eval : R prod = qExpansion 1 E₄ ^ a * qExpansion 1 E₆ ^ b := by + rw [hprod_def, hR_def, map_mul, map_pow, map_pow, + ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL, + ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL] + have hR_concentrated : R prod = qExpansion 1 (prod (n : ℤ)) := by + conv_lhs => rw [hprod_eq] + rw [hR_def] + exact ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL _ _ + rw [← hR_concentrated, hR_eval, PowerSeries.coeff_mul] + simp [Finset.antidiagonal_zero, PowerSeries.coeff_pow, + E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] /-- For weight 12 ≤ n, every cusp form of weight n is `Δ * h` for some modular form `h` of weight `n - 12`. Lifted to the graded ring. -/ @@ -232,11 +260,6 @@ private lemma discriminant_mem_range_evalE₄E₆ : simp only [map_smul, map_sub, map_pow, evalE₄E₆_X0, evalE₄E₆_X1] rw [← discriminant_eq_E₄_cube_sub_E₆_sq_graded] -/-- Weight casting: rewriting the index of `DirectSum.of` along an equality of weights. -/ -private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : - DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by - subst hk; rfl - /-- Inductive step: for `n ≥ 12` even, surjectivity at weight `n` follows from surjectivity at all lower weights via the cusp-form / `Δ` decomposition. -/ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Even (n : ℤ)) From 73d4cef7ebb6ecc4e0235ec5e573c6bf97d43c08 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 19:11:32 +0100 Subject: [PATCH 34/61] feat(NumberTheory/ModularForms): scaffold injectivity proof MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the full structural framework for `evalE₄E₆_injective`: - `discriminantPoly = (1/1728)(X₀³ - X₁²)` - weight helpers `weight_eq_4a_6b`, `weight_fin2_cast`, `no_wt_monomial_of_*` - per-weight machinery: `whomog_unique_monomial`, `evalE₄E₆_*_grade` - weighted-homogeneous-component evaluation helpers - structural induction over the weight in `per_weight_injective` - main theorem `evalE₄E₆_injective` derived from per-weight injectivity 4 `sorry`s remain (component decomposition, Δ-mul cusp form, weight-0 base case, and the Δ-poly inductive step), to be filled in subsequent commits. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 243 +++++++++++++++++- 1 file changed, 238 insertions(+), 5 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index e78806c3deeaab..af23dcefcb9f12 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -398,14 +398,247 @@ theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by show (Set.range evalE₄E₆ : Set _) = ↑evalE₄E₆.range from (AlgHom.coe_range evalE₄E₆).symm] exact Subalgebra.sum_mem _ (fun k _ => surj_of_weight k (x k)) +/-! ### Injectivity of `evalE₄E₆` -/ + +/-- The polynomial `Δ_poly = (1/1728) (X₀³ - X₁²)`, which `evalE₄E₆` sends to `Δ` in the +graded ring of level-1 modular forms. -/ +private noncomputable def discriminantPoly : MvPolynomial (Fin 2) ℂ := + (1 / 1728 : ℂ) • (MvPolynomial.X 0 ^ 3 - MvPolynomial.X 1 ^ 2) + +private lemma X0_cubed_eq_smul_discriminantPoly : + (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ 3 = + MvPolynomial.X (1 : Fin 2) ^ 2 + (1728 : ℂ) • discriminantPoly := by + simp only [discriminantPoly, smul_smul] + norm_num + +private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : + Finsupp.weight E₄E₆Weight d = d 0 * 4 + d 1 * 6 := by + change (Finsupp.linearCombination ℕ E₄E₆Weight).toAddMonoidHom d = d 0 * 4 + d 1 * 6 + simp only [LinearMap.toAddMonoidHom_coe, Finsupp.linearCombination_apply] + rw [d.sum_fintype (fun i a => a • E₄E₆Weight i) (fun i => by simp only [zero_smul])] + simp only [Fin.sum_univ_two, E₄E₆Weight, Matrix.cons_val_zero, Matrix.cons_val_one, + mul_comm, smul_eq_mul] + +private lemma weight_fin2_cast (d : Fin 2 →₀ ℕ) : + (Finsupp.weight E₄E₆Weight d : ℤ) = ↑(d 0) * 4 + ↑(d 1) * 6 := by + rw [weight_eq_4a_6b]; push_cast; ring + +private lemma finsupp_of_fin2 (a b : ℕ) : ∃ d : Fin 2 →₀ ℕ, d 0 = a ∧ d 1 = b := + ⟨Finsupp.equivFunOnFinite.invFun ![a, b], rfl, rfl⟩ + +private lemma no_wt_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ ℕ) : + Finsupp.weight E₄E₆Weight d ≠ n := by + intro h + rw [weight_eq_4a_6b] at h + have hev : Even n := ⟨d 0 * 2 + d 1 * 3, by omega⟩ + exact (Nat.not_odd_iff_even.mpr hev) hn + +private lemma no_wt_monomial_of_two (d : Fin 2 →₀ ℕ) : + Finsupp.weight E₄E₆Weight d ≠ 2 := by + intro h; rw [weight_eq_4a_6b] at h; omega + +private lemma whomog_eq_zero_of_no_monomials {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (hno : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d ≠ n) : p = 0 := by + rw [← MvPolynomial.support_eq_empty] + by_contra h + obtain ⟨d, hd⟩ := Finset.nonempty_of_ne_empty h + exact hno d (hp (MvPolynomial.mem_support_iff.mp hd)) + +private lemma whomog_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (d₀ : Fin 2 →₀ ℕ) (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) : + p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by + ext d + by_cases hd : d = d₀ + · subst hd; simp only [MvPolynomial.coeff_monomial, ↓reduceIte] + · rw [MvPolynomial.coeff_monomial, if_neg (Ne.symm hd)] + exact hp.coeff_eq_zero d (fun h => hd (huniq d h)) + +private lemma unique_small_weight_soln {a₁ b₁ a₂ b₂ : ℕ} + (ha₁ : a₁ < 3) (ha₂ : a₂ < 3) + (h : a₁ * 4 + b₁ * 6 = a₂ * 4 + b₂ * 6) : a₁ = a₂ ∧ b₁ = b₂ := + ⟨by interval_cases a₁ <;> interval_cases a₂ <;> omega, by omega⟩ + +private lemma monomial_fin2_eq (d : Fin 2 →₀ ℕ) (c : ℂ) : + MvPolynomial.monomial d c = + MvPolynomial.C c * MvPolynomial.X 0 ^ d 0 * MvPolynomial.X 1 ^ d 1 := by + rw [MvPolynomial.monomial_eq, mul_assoc]; congr 1 + rw [Finsupp.prod, Finset.prod_subset (fun _ _ => Finset.mem_univ _) (fun i _ hi => by + have : d i = 0 := by rwa [Finsupp.mem_support_iff, not_not] at hi + rw [this, pow_zero])] + simp only [Fin.prod_univ_two] + +private lemma evalE₄E₆_mono_grade (a b : ℕ) (k : ℤ) + (hk : k ≠ (↑a * 4 + ↑b * 6 : ℤ)) : + (evalE₄E₆ (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b)) k = 0 := by + rw [evalE₄E₆_monomial, DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of] + refine DirectSum.of_eq_of_ne _ _ _ ?_ + intro heq + apply hk + simp only [Int.nsmul_eq_mul] at heq + linarith + +private lemma evalE₄E₆_monomial_grade (d : Fin 2 →₀ ℕ) (c : ℂ) (k : ℤ) + (hk : k ≠ (↑(d 0) * 4 + ↑(d 1) * 6 : ℤ)) : + (evalE₄E₆ (MvPolynomial.monomial d c)) k = 0 := by + rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, + smul_mul_assoc, one_mul, DirectSum.smul_apply, + evalE₄E₆_mono_grade (d 0) (d 1) k hk, smul_zero] + +/-- A weighted-homogeneous polynomial of weight `n` evaluates (at any other weight) to `0`. -/ +private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (k : ℤ) (hk : k ≠ ↑n) : + (evalE₄E₆ p) k = 0 := by + rw [← MvPolynomial.support_sum_monomial_coeff p, map_sum, + show (∑ x ∈ p.support, evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k = + ∑ x ∈ p.support, (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k from + map_sum (DFinsupp.evalAddMonoidHom k) _ _] + apply Finset.sum_eq_zero + intro d hd + apply evalE₄E₆_monomial_grade + intro heq; apply hk + have hwd : Finsupp.weight E₄E₆Weight d = n := hp (MvPolynomial.mem_support_iff.mp hd) + rw [heq, ← weight_fin2_cast d, hwd] + +private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : + evalE₄E₆ p = DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) ((evalE₄E₆ p) ↑n) := by + refine DFinsupp.ext (fun k : ℤ => ?_) + by_cases hk : k = (↑n : ℤ) + · subst hk; simp + · rw [DirectSum.of_eq_of_ne _ _ _ hk, evalE₄E₆_whc_grade p hp k hk] + +private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) : + (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p)) (↑n : ℤ) = + (evalE₄E₆ p) (↑n : ℤ) := by + -- TODO: complete proof using component decomposition. + sorry + +private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 + b * 6 = n) : + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight + (MvPolynomial.X (0 : Fin 2) ^ a * MvPolynomial.X (1 : Fin 2) ^ b : + MvPolynomial (Fin 2) ℂ) n := by + convert ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (0 : Fin 2)).pow a).mul + ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow b) using 1 + simp only [E₄E₆Weight, Matrix.cons_val_zero, Matrix.cons_val_one, smul_eq_mul]; omega + +private lemma discriminantPoly_isWeightedHomogeneous : + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight discriminantPoly 12 := by + unfold discriminantPoly + simp only [MvPolynomial.smul_eq_C_mul] + intro d hd + simp only [MvPolynomial.coeff_C_mul, MvPolynomial.coeff_sub] at hd + by_cases hd3 : MvPolynomial.coeff d + (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) ≠ 0 + · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (0 : Fin 2)).pow 3) hd3 + · push_neg at hd3 + by_cases hd6 : MvPolynomial.coeff d + (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 + · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow 2) hd6 + · push_neg at hd6; simp only [hd3, hd6, sub_self, mul_zero, ne_eq, not_true] at hd + +/-- The 0th q-expansion coefficient of a `Δ_poly * s` term in the graded ring vanishes. -/ +private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 ≤ n) + (s : MvPolynomial (Fin 2) ℂ) + (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) : + (qExpansion 1 ↑((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by + -- TODO: Δ_poly evaluates to Δ at weight 12; multiplying by anything gives a cusp form, + -- whose 0th q-expansion coefficient vanishes. + sorry + +private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) + (d₀ : Fin 2 →₀ ℕ) + (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) + (hmf_ne : (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ) ≠ 0) : p = 0 := by + have hpc := whomog_unique_monomial p hp d₀ huniq + rw [hpc] at heval ⊢ + rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, + smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply] at heval + rcases smul_eq_zero.mp heval with hc | hmz + · rw [show MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) = + MvPolynomial.monomial d₀ 0 from by rw [hc], MvPolynomial.monomial_zero] + · exact absurd hmz hmf_ne + +private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn : n < 12) + (hab : 4 * a + 6 * b = n) + (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) : p = 0 := by + obtain ⟨d₀, hd0a, hd0b⟩ := finsupp_of_fin2 a b + apply per_weight_injective_unique_monomial p hp heval d₀ + · intro d hd + have h46 := weight_eq_4a_6b d; rw [hd] at h46 + obtain ⟨hda, hdb⟩ := unique_small_weight_soln (by omega : d 0 < 3) ha + (show d 0 * 4 + d 1 * 6 = a * 4 + b * 6 by omega) + ext i; fin_cases i <;> [exact hda ▸ hd0a.symm; exact hdb ▸ hd0b.symm] + · rw [hd0a, hd0b]; intro habs + have hcz := monomial_qExpansion_coeff_zero_eq_one (n := n) (a := a) (b := b) (by omega) + rw [habs] at hcz + simp [UpperHalfPlane.qExpansion_zero] at hcz + +private lemma per_weight_injective_zero + (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p 0) + (heval : (evalE₄E₆ p) (0 : ℤ) = 0) : p = 0 := by + -- Weight-0 weighted-homogeneous polys are constants; constants map to scalar multiples of 1. + -- TODO: The full proof. + sorry + +private lemma per_weight_injective_inductive_step (n : ℕ) + (ih : ∀ m < n, ∀ (p : MvPolynomial (Fin 2) ℂ), + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p m → + (evalE₄E₆ p) (↑m : ℤ) = 0 → p = 0) + (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) + (hn12 : 12 ≤ n) : p = 0 := by + -- Use Δ_poly divisibility: any p of weight n ≥ 12 evaluating to 0 is divisible by Δ_poly, + -- and the quotient (of weight n-12) also evaluates to 0, then apply IH. + -- TODO: complete proof. + sorry + +private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ), + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n → + (evalE₄E₆ p) (↑n : ℤ) = 0 → p = 0 := by + intro n + induction n using Nat.strong_induction_on with | _ n ih => ?_ + intro p hp heval + by_cases hk_odd : Odd n + · exact whomog_eq_zero_of_no_monomials p hp (fun d => no_wt_monomial_of_odd hk_odd d) + rw [Nat.not_odd_iff_even] at hk_odd + by_cases hn4 : n < 4 + · have hn02 : n = 0 ∨ n = 2 := by obtain ⟨m, rfl⟩ := hk_odd; omega + rcases hn02 with rfl | rfl + · exact per_weight_injective_zero p hp heval + · exact whomog_eq_zero_of_no_monomials p hp (fun d => no_wt_monomial_of_two d) + push_neg at hn4 + by_cases hn12 : n < 12 + · have hn_cases : n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by + obtain ⟨m, rfl⟩ := hk_odd; omega + rcases hn_cases with rfl | rfl | rfl | rfl + · exact per_weight_injective_small 1 0 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_small 0 1 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_small 2 0 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_small 1 1 (by omega) (by omega) rfl p hp heval + push_neg at hn12 + exact per_weight_injective_inductive_step n ih p hp heval hn12 + /-- The evaluation homomorphism `evalE₄E₆` is injective: `E₄` and `E₆` are algebraically independent. -/ theorem evalE₄E₆_injective : Function.Injective evalE₄E₆ := by - -- Port from `LeanModularForms/Modularforms/Generators/Injectivity.lean`. - -- Decompose into weighted-homogeneous components (weights `![4, 6]`); show each maps - -- independently into a single graded piece. Per-weight injectivity is by strong induction - -- on the weight, using the relation `X₀³ - X₁² = 1728 · Δ_poly`. - sorry + intro p q hpq + rw [← sub_eq_zero] + set r := p - q with hr_def + have hr : evalE₄E₆ r = 0 := by rw [hr_def, map_sub, sub_eq_zero]; exact hpq + rw [← MvPolynomial.sum_weightedHomogeneousComponent (E₄E₆Weight) r] + refine finsum_eq_zero_of_forall_eq_zero (fun n => ?_) + refine per_weight_injective n _ + (MvPolynomial.weightedHomogeneousComponent_isWeightedHomogeneous _ _) ?_ + rw [evalE₄E₆_component_eq, hr]; rfl /-- The graded ring of level-1 modular forms is isomorphic to the polynomial ring `ℂ[X₀, X₁]` via evaluation at `E₄` and `E₆`. -/ From cf68a22f13c2e00ceff1b77db9eced0a3118e742 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 19:17:01 +0100 Subject: [PATCH 35/61] feat(NumberTheory/ModularForms): close component_eq and weight-0 base case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remaining `sorry`s: * `evalE₄E₆_discriminantPoly_mul_coeff_zero` (Δ_poly * s gives a cusp form at weight n) * `per_weight_injective_inductive_step` (the Δ_poly divisibility induction) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index af23dcefcb9f12..f874beb6bb2b86 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -512,8 +512,29 @@ private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) : (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p)) (↑n : ℤ) = (evalE₄E₆ p) (↑n : ℤ) := by - -- TODO: complete proof using component decomposition. - sorry + set q := p - MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p with hq_def + have hdecomp : p = MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p + q := by + rw [hq_def]; ring + conv_rhs => rw [hdecomp, map_add] + rw [show (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p) + + evalE₄E₆ q) (↑n : ℤ) = + (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p)) (↑n : ℤ) + + (evalE₄E₆ q) (↑n : ℤ) from rfl] + suffices h : (evalE₄E₆ q) (↑n : ℤ) = 0 by rw [h, add_zero] + rw [← MvPolynomial.support_sum_monomial_coeff q, map_sum, + show (∑ x ∈ q.support, evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x q))) + (↑n : ℤ) = + ∑ x ∈ q.support, + (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x q))) (↑n : ℤ) from + map_sum (DFinsupp.evalAddMonoidHom (↑n : ℤ)) _ _] + apply Finset.sum_eq_zero + intro d hd + apply evalE₄E₆_monomial_grade + intro heq + apply MvPolynomial.mem_support_iff.mp hd + rw [hq_def, MvPolynomial.coeff_sub, MvPolynomial.coeff_weightedHomogeneousComponent, + if_pos ?_, sub_self] + rw [weight_eq_4a_6b]; omega private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 + b * 6 = n) : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight @@ -584,9 +605,24 @@ private lemma per_weight_injective_zero (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p 0) (heval : (evalE₄E₆ p) (0 : ℤ) = 0) : p = 0 := by - -- Weight-0 weighted-homogeneous polys are constants; constants map to scalar multiples of 1. - -- TODO: The full proof. - sorry + have hpc : p = MvPolynomial.C (MvPolynomial.coeff 0 p) := by + ext d' + simp only [MvPolynomial.coeff_C] + by_cases hd' : 0 = d' + · simp [hd'] + · rw [if_neg hd'] + exact hp.coeff_eq_zero d' (fun hw => hd' (by + have h46' := weight_eq_4a_6b d'; rw [hw] at h46' + symm; ext i; fin_cases i <;> simp [Finsupp.coe_zero] <;> omega)) + rw [hpc] at heval ⊢ + rw [evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, DirectSum.smul_apply] at heval + have h1eq : (1 : DirectSum ℤ (ModularForm 𝒮ℒ)) (0 : ℤ) = (1 : ModularForm 𝒮ℒ 0) := by + conv_lhs => rw [← DirectSum.of_zero_one (ModularForm 𝒮ℒ)] + exact DirectSum.of_eq_same _ _ + rw [h1eq] at heval + rcases smul_eq_zero.mp heval with hc | h1z + · rw [hc, map_zero] + · exact absurd h1z one_ne_zero_modularForm private lemma per_weight_injective_inductive_step (n : ℕ) (ih : ∀ m < n, ∀ (p : MvPolynomial (Fin 2) ℂ), From 2af27474abc27345ea834ec9702d7e446e271a55 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 19:23:17 +0100 Subject: [PATCH 36/61] feat(NumberTheory/ModularForms): close eval_discriminantPoly_mul_zero_imp + helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close `evalE₄E₆_discriminantPoly_mul_coeff_zero` (uses the discriminant identity and the cusp form property of Δ) and `eval_discriminantPoly_mul_zero_imp` (uses that `Δ z ≠ 0`). Remaining `sorry`s: * `whomog_poly_Delta_decomp` (induction on `∑ d ∈ p.support, d 0`) * `reduced_part_eq_zero` (q-expansion-coeff-0 argument) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 103 ++++++++++++++++-- 1 file changed, 96 insertions(+), 7 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index f874beb6bb2b86..951cdd2c03e4ab 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -559,14 +559,40 @@ private lemma discriminantPoly_isWeightedHomogeneous : · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow 2) hd6 · push_neg at hd6; simp only [hd3, hd6, sub_self, mul_zero, ne_eq, not_true] at hd +/-- `evalE₄E₆ discriminantPoly = DirectSum.of _ 12 Δ`. -/ +private lemma evalE₄E₆_discriminantPoly : + evalE₄E₆ discriminantPoly = + DirectSum.of (ModularForm 𝒮ℒ) 12 + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := by + rw [discriminantPoly, map_smul, map_sub, map_pow, map_pow, evalE₄E₆_X0, evalE₄E₆_X1, + ← discriminant_eq_E₄_cube_sub_E₆_sq_graded] + /-- The 0th q-expansion coefficient of a `Δ_poly * s` term in the graded ring vanishes. -/ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) : (qExpansion 1 ↑((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by - -- TODO: Δ_poly evaluates to Δ at weight 12; multiplying by anything gives a cusp form, - -- whose 0th q-expansion coefficient vanishes. - sorry + rw [map_mul, evalE₄E₆_discriminantPoly, + evalE₄E₆_whc_eq_single (n - 12) s hs, DirectSum.of_mul_of] + have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega + rw [DirectSum.of_apply, dif_pos hcast] + -- The product evaluated at ↑n is a modular form of weight n with q-expansion Δ * s_eval. + -- Its 0th q-expansion coefficient vanishes since Δ is a cusp form. + set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) + set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) + show (qExpansion 1 ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ)).coeff 0 = 0 + have hcoe : ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ) = + ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ) := by + ext z + have helper : ∀ {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ), + (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by + intros; subst_vars; rfl + exact helper hcast _ z + rw [hcoe, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, + PowerSeries.coeff_mul] + have hΔ_coeff : (qExpansion 1 (f : ℍ → ℂ)).coeff 0 = 0 := + (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩ + simp [Finset.antidiagonal_zero, hΔ_coeff] private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) @@ -624,6 +650,67 @@ private lemma per_weight_injective_zero · rw [hc, map_zero] · exact absurd h1z one_ne_zero_modularForm +private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous' {a b : ℕ} : + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight + (MvPolynomial.X (0 : Fin 2) ^ a * MvPolynomial.X (1 : Fin 2) ^ b : + MvPolynomial (Fin 2) ℂ) (a * 4 + b * 6) := + X0_pow_mul_X1_pow_isWeightedHomogeneous a b _ rfl + +/-- Polynomial decomposition: any weighted-homogeneous polynomial `p` of weight `n ≥ 12` can +be written as `r + Δ_poly * s` where `r` is weighted-homogeneous of weight `n` whose monomials +all have `X₀`-degree `< 3`. -/ +private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) + (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : + ∃ r s : MvPolynomial (Fin 2) ℂ, + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n ∧ + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12) ∧ + p = r + discriminantPoly * s ∧ + (∀ d ∈ r.support, d 0 < 3) := by + -- TODO: induction on `∑ d ∈ p.support, d 0`. Each step uses + -- `X₀³ = X₁² + 1728 • Δ_poly` to reduce a monomial with `d 0 ≥ 3`. + sorry + +/-- If `eval (r + Δ_poly * s) ↑n = 0` and `r` is reduced, then `r = 0`. -/ +private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) + (r s : MvPolynomial (Fin 2) ℂ) + (hr : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n) + (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) + (hr_red : ∀ d ∈ r.support, d 0 < 3) + (heval : (evalE₄E₆ (r + discriminantPoly * s)) (↑n : ℤ) = 0) : + r = 0 := by + -- TODO: use that `qExp 0` of `Δ_poly * s` is 0 and the q-expansion-coeff at 0 of `r` + -- equals its leading coefficient (since r is reduced and weighted-homog). + sorry + +/-- If `eval (Δ_poly * s) ↑n = 0` (with `s` weighted-homog of weight `n - 12`), +then `eval s ↑(n - 12) = 0`. -/ +private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) + (s : MvPolynomial (Fin 2) ℂ) + (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) + (hds : (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) = 0) : + (evalE₄E₆ s) (↑(n - 12) : ℤ) = 0 := by + rw [map_mul, evalE₄E₆_discriminantPoly, + evalE₄E₆_whc_eq_single (n - 12) s hs, DirectSum.of_mul_of] at hds + have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega + rw [DirectSum.of_apply, dif_pos hcast] at hds + set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) + set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) + have helper : ∀ {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ), + (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by intros; subst_vars; rfl + ext z + simp only [ModularForm.zero_apply] + have hpw := DFunLike.congr_fun hds z + simp only [ModularForm.zero_apply] at hpw + rw [helper hcast _ z] at hpw + -- hpw : (GMul.mul f g) z = 0, i.e., f z * g z = 0 + have hpw' : f z * g z = 0 := by + have heq : (GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ (12 + ↑(n - 12))) z = f z * g z := rfl + rw [← heq]; exact hpw + rcases mul_eq_zero.mp hpw' with hf0 | hg0 + · exact absurd hf0 (discriminant_ne_zero z) + · exact hg0 + private lemma per_weight_injective_inductive_step (n : ℕ) (ih : ∀ m < n, ∀ (p : MvPolynomial (Fin 2) ℂ), MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p m → @@ -632,10 +719,12 @@ private lemma per_weight_injective_inductive_step (n : ℕ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) (hn12 : 12 ≤ n) : p = 0 := by - -- Use Δ_poly divisibility: any p of weight n ≥ 12 evaluating to 0 is divisible by Δ_poly, - -- and the quotient (of weight n-12) also evaluates to 0, then apply IH. - -- TODO: complete proof. - sorry + obtain ⟨r, s, hr_wh, hs_wh, hp_eq, hr_red⟩ := whomog_poly_Delta_decomp hn12 p hp + have hr0 : r = 0 := reduced_part_eq_zero hn12 r s hr_wh hs_wh hr_red (hp_eq ▸ heval) + rw [hp_eq, hr0, zero_add] at heval ⊢ + have hs0 : s = 0 := ih (n - 12) (by omega) s hs_wh + (eval_discriminantPoly_mul_zero_imp hn12 s hs_wh heval) + rw [hs0, mul_zero] private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ), MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n → From b7a9ca6fb4f34419d42a5e05e6fcc731bf1818cc Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 19:25:46 +0100 Subject: [PATCH 37/61] feat(NumberTheory/ModularForms): close `reduced_part_eq_zero` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses the q-expansion-coeff-0 argument: take qExpansion of the identity `r + Δ_poly * s` evaluated at weight n, the Δ_poly term contributes 0, the r term equals its leading scalar `c`, hence `c = 0`. Last remaining `sorry`: `whomog_poly_Delta_decomp`, the polynomial decomposition by induction on the support sum of `d 0` exponents. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 951cdd2c03e4ab..74805bddd3e6ad 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -679,9 +679,67 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (hr_red : ∀ d ∈ r.support, d 0 < 3) (heval : (evalE₄E₆ (r + discriminantPoly * s)) (↑n : ℤ) = 0) : r = 0 := by - -- TODO: use that `qExp 0` of `Δ_poly * s` is 0 and the q-expansion-coeff at 0 of `r` - -- equals its leading coefficient (since r is reduced and weighted-homog). - sorry + by_cases hr_empty : r.support = ∅ + · rwa [MvPolynomial.support_eq_empty] at hr_empty + obtain ⟨d₀, hd₀⟩ := Finset.nonempty_of_ne_empty hr_empty + have hwd₀ := hr (MvPolynomial.mem_support_iff.mp hd₀) + -- Reduced + weight n forces all monomials in r.support to have the same exponent vector d₀. + have hr_mono : r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by + ext d + by_cases hd : d = d₀ + · subst hd; simp only [MvPolynomial.coeff_monomial, ↓reduceIte] + rw [MvPolynomial.coeff_monomial, if_neg (Ne.symm hd)] + by_cases hd_supp : d ∈ r.support + · have h1 := weight_eq_4a_6b d + have h_wd := hr (MvPolynomial.mem_support_iff.mp hd_supp) + rw [h_wd] at h1 + have h2 := weight_eq_4a_6b d₀ + rw [hwd₀] at h2 + obtain ⟨ha, hb⟩ := unique_small_weight_soln (hr_red d hd_supp) (hr_red d₀ hd₀) + (show d 0 * 4 + d 1 * 6 = d₀ 0 * 4 + d₀ 1 * 6 by omega) + exact absurd (Finsupp.ext fun i => by fin_cases i <;> [exact ha; exact hb]) hd + · rwa [MvPolynomial.mem_support_iff, not_not] at hd_supp + -- Now the goal: show MvPolynomial.coeff d₀ r = 0 + set c := MvPolynomial.coeff d₀ r + suffices hc : c = 0 by rw [hr_mono, hc, MvPolynomial.monomial_zero] + -- Take q-expansion coeff 0 of evaluated polynomial. + rw [hr_mono, map_add] at heval + have hd₀_weight : 4 * d₀ 0 + 6 * d₀ 1 = n := by + have := weight_eq_4a_6b d₀; rw [hwd₀] at this; omega + -- Define Q = qExpansionAddHom 1 ↑n : ModularForm 𝒮ℒ ↑n →+ PowerSeries ℂ. + set Q := ModularForm.qExpansionAddHom (h := 1) one_pos one_mem_strictPeriods_SL (↑n : ℤ) + have hQ_zero : Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + + (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ)) = 0 := by + rw [show (evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + + (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) = + (evalE₄E₆ (MvPolynomial.monomial d₀ c) + + evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) from rfl, heval] + exact map_zero Q + rw [map_add] at hQ_zero + have h_coeff_sum : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 + + (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by + have := congr_arg (fun (p : PowerSeries ℂ) => p.coeff 0) hQ_zero + simpa using this + -- The Δ_poly * s term contributes 0. + have h_Δ_term : (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by + show (qExpansion 1 ↑((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 + exact evalE₄E₆_discriminantPoly_mul_coeff_zero hn12 s hs + rw [h_Δ_term, add_zero] at h_coeff_sum + -- The monomial term contributes c. + have h_mono_term : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c := by + show (qExpansion 1 ↑((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c + rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, + smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply, + show (↑(c • ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ))) : ℍ → ℂ) = + c • (↑((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ)) : ℍ → ℂ) from rfl, + UpperHalfPlane.qExpansion_smul (ModularFormClass.analyticAt_cuspFunction_zero _ + one_pos one_mem_strictPeriods_SL) c, PowerSeries.coeff_smul] + rw [monomial_qExpansion_coeff_zero_eq_one hd₀_weight] + simp + rw [h_mono_term] at h_coeff_sum + exact h_coeff_sum /-- If `eval (Δ_poly * s) ↑n = 0` (with `s` weighted-homog of weight `n - 12`), then `eval s ↑(n - 12) = 0`. -/ From 32322121fd96c8f769d0d49e06eb43ee7b8f6220 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 19:27:40 +0100 Subject: [PATCH 38/61] feat(NumberTheory/ModularForms): close `whomog_poly_Delta_decomp` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Final piece of the injectivity proof. The polynomial decomposition is by strong induction on `∑ d ∈ p.support, d 0`: each step uses the identity `X₀³ = X₁² + 1728 • Δ_poly` to replace a monomial with `d 0 ≥ 3` by a combination with strictly smaller support sum. The full result is now established: - `evalE₄E₆_surjective`: `evalE₄E₆` is surjective. - `evalE₄E₆_injective`: E₄ and E₆ are algebraically independent. - `modularFormsEquivMvPolynomial`: `ℂ[X₀, X₁] ≃ₐ[ℂ] ⨁ k, ModularForm 𝒮ℒ k`. - `E₄E₆_generate`: E₄, E₆ generate the graded ring. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 182 +++++++++++++++++- 1 file changed, 179 insertions(+), 3 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 74805bddd3e6ad..fe826ef74e8139 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -656,6 +656,130 @@ private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous' {a b : ℕ} : MvPolynomial (Fin 2) ℂ) (a * 4 + b * 6) := X0_pow_mul_X1_pow_isWeightedHomogeneous a b _ rfl +private lemma discriminantPoly_piece_isWeightedHomogeneous {n : ℕ} (hn12 : 12 ≤ n) + (d : Fin 2 →₀ ℕ) (hd_ge : 3 ≤ d 0) (hwd : d 0 * 4 + d 1 * 6 = n) (c : ℂ) : + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight + (MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * + MvPolynomial.X (1 : Fin 2) ^ (d 1)))) n := by + apply MvPolynomial.IsWeightedHomogeneous.C_mul + rw [MvPolynomial.smul_eq_C_mul, + show MvPolynomial.C (1728 : ℂ) * discriminantPoly * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = + MvPolynomial.C (1728 : ℂ) * (discriminantPoly * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * + MvPolynomial.X (1 : Fin 2) ^ d 1)) from by ring] + apply MvPolynomial.IsWeightedHomogeneous.C_mul + convert discriminantPoly_isWeightedHomogeneous.mul + (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) + using 1 + omega + +private lemma discriminantPoly_piece_eq_monomial_sub + (d : Fin 2 →₀ ℕ) (hd_ge : 3 ≤ d 0) (c : ℂ) + (d' : Fin 2 →₀ ℕ) (hd' : d' = Finsupp.single (0 : Fin 2) (d 0 - 3) + + Finsupp.single (1 : Fin 2) (d 1 + 2)) : + MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) = + (MvPolynomial.monomial d) c - (MvPolynomial.monomial d') c := by + subst hd' + have h1728 : (1728 : ℂ) • discriminantPoly = + MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2 := by + simp only [discriminantPoly, smul_smul]; norm_num + have hd_fin : d = Finsupp.single (0 : Fin 2) (d 0) + + Finsupp.single (1 : Fin 2) (d 1) := by + ext i; fin_cases i <;> simp [Finsupp.add_apply] + rw [show MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) = + MvPolynomial.C c * + (MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2) * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * + MvPolynomial.X (1 : Fin 2) ^ (d 1)) from by rw [h1728]; ring] + have h3 : (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = + MvPolynomial.X (0 : Fin 2) ^ d 0 * MvPolynomial.X (1 : Fin 2) ^ d 1 := by + rw [show (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ 3 * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) + = (MvPolynomial.X (0 : Fin 2) ^ 3 * MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3)) * + MvPolynomial.X (1 : Fin 2) ^ d 1 from by ring, + ← pow_add, show 3 + (d 0 - 3) = d 0 from by omega] + have h2 : (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = + MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1 + 2) := by + rw [show (MvPolynomial.X (1 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ 2 * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) + = MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * + (MvPolynomial.X (1 : Fin 2) ^ d 1 * MvPolynomial.X (1 : Fin 2) ^ 2) from by ring, + ← pow_add] + rw [show MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ 3 - + MvPolynomial.X (1 : Fin 2) ^ 2) * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = + MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ 3 * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) - + MvPolynomial.C c * (MvPolynomial.X (1 : Fin 2) ^ 2 * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * + MvPolynomial.X (1 : Fin 2) ^ d 1)) from by ring, + h3, h2] + congr 1 + · rw [MvPolynomial.X_pow_eq_monomial, MvPolynomial.X_pow_eq_monomial, + MvPolynomial.monomial_mul, one_mul, MvPolynomial.C_mul_monomial, mul_one] + exact congrArg (· c) (congrArg MvPolynomial.monomial hd_fin.symm) + · rw [MvPolynomial.X_pow_eq_monomial, MvPolynomial.X_pow_eq_monomial, + MvPolynomial.monomial_mul, one_mul, MvPolynomial.C_mul_monomial, mul_one] + +private lemma sum_lt_sum_of_replace {α : Type*} [DecidableEq α] + (S S' : Finset α) (f : α → ℕ) (d d' : α) + (hd_mem : d ∈ S) (hd_not : d ∉ S') + (hS' : S' ⊆ S.erase d ∪ {d'}) + (hlt : f d' < f d) : + ∑ x ∈ S', f x < ∑ x ∈ S, f x := by + by_cases hd'S : d' ∈ S + · calc ∑ x ∈ S', f x + ≤ ∑ x ∈ S.erase d, f x := Finset.sum_le_sum_of_subset (fun x hx => + Finset.mem_erase.mpr ⟨fun h => hd_not (h ▸ hx), + match Finset.mem_union.mp (hS' hx) with + | .inl h => Finset.mem_of_mem_erase h + | .inr h => Finset.mem_singleton.mp h ▸ hd'S⟩) + _ < ∑ x ∈ S.erase d, f x + f d := + Nat.lt_add_of_pos_right (Nat.pos_of_ne_zero (by omega)) + _ = ∑ x ∈ S, f x := Finset.sum_erase_add S f hd_mem + · calc ∑ x ∈ S', f x + ≤ ∑ x ∈ S.erase d ∪ {d'}, f x := Finset.sum_le_sum_of_subset hS' + _ = ∑ x ∈ S.erase d, f x + f d' := by + rw [Finset.sum_union (Finset.disjoint_singleton_right.mpr + (fun h => hd'S (Finset.mem_of_mem_erase h))), Finset.sum_singleton] + _ < ∑ x ∈ S.erase d, f x + f d := Nat.add_lt_add_left hlt _ + _ = ∑ x ∈ S, f x := Finset.sum_erase_add S f hd_mem + +open Classical in +private lemma mvpoly_support_after_reduction {σ R : Type*} [CommRing R] [DecidableEq σ] + (p : MvPolynomial σ R) (d d' : σ →₀ ℕ) (c : R) + (hdd' : d ≠ d') (hc : MvPolynomial.coeff d p = c) : + let δ := MvPolynomial.monomial d c - MvPolynomial.monomial d' c + d ∉ (p - δ).support ∧ (p - δ).support ⊆ p.support.erase d ∪ {d'} := by + have hcoeff_d : MvPolynomial.coeff d + (p - (MvPolynomial.monomial d c - MvPolynomial.monomial d' c)) = 0 := by + rw [MvPolynomial.coeff_sub, MvPolynomial.coeff_sub, + MvPolynomial.coeff_monomial, MvPolynomial.coeff_monomial, + if_pos rfl, if_neg hdd'.symm, sub_zero, hc, sub_self] + have hd_not : d ∉ (p - (MvPolynomial.monomial d c - + MvPolynomial.monomial d' c)).support := + MvPolynomial.notMem_support_iff.mpr hcoeff_d + refine ⟨hd_not, fun x hx => ?_⟩ + rcases Finset.mem_union.mp (MvPolynomial.support_sub σ p _ hx) with hp | hdelta + · by_cases hxd : x = d + · exact absurd (hxd ▸ hx) hd_not + · exact Finset.mem_union_left _ (Finset.mem_erase.mpr ⟨hxd, hp⟩) + · rcases Finset.mem_union.mp (MvPolynomial.support_sub σ _ _ hdelta) with h1 | h2 + · rw [MvPolynomial.support_monomial] at h1 + split_ifs at h1 + · exact absurd h1 (Finset.notMem_empty _) + · exact absurd ((Finset.mem_singleton.mp h1) ▸ hx) hd_not + · rw [MvPolynomial.support_monomial] at h2 + split_ifs at h2 + · exact absurd h2 (Finset.notMem_empty _) + · exact Finset.mem_union_right _ (by rwa [Finset.mem_singleton] at h2 ⊢) + /-- Polynomial decomposition: any weighted-homogeneous polynomial `p` of weight `n ≥ 12` can be written as `r + Δ_poly * s` where `r` is weighted-homogeneous of weight `n` whose monomials all have `X₀`-degree `< 3`. -/ @@ -667,9 +791,61 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12) ∧ p = r + discriminantPoly * s ∧ (∀ d ∈ r.support, d 0 < 3) := by - -- TODO: induction on `∑ d ∈ p.support, d 0`. Each step uses - -- `X₀³ = X₁² + 1728 • Δ_poly` to reduce a monomial with `d 0 ≥ 3`. - sorry + suffices key : ∀ (M : ℕ) (p : MvPolynomial (Fin 2) ℂ), + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n → + (∑ d ∈ p.support, d 0) ≤ M → + ∃ r s : MvPolynomial (Fin 2) ℂ, + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n ∧ + MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12) ∧ + p = r + discriminantPoly * s ∧ + (∀ d ∈ r.support, d 0 < 3) from + key _ p hp le_rfl + intro M + induction M using Nat.strong_induction_on with | _ M ih => ?_ + intro p hp _hM + by_cases hall : ∀ d ∈ p.support, d 0 < 3 + · exact ⟨p, 0, hp, MvPolynomial.isWeightedHomogeneous_zero ℂ E₄E₆Weight (n - 12), + by simp only [mul_zero, add_zero], hall⟩ + push Not at hall + obtain ⟨d, hd_mem, hd_ge⟩ := hall + have hwd : d 0 * 4 + d 1 * 6 = n := by + have := hp (MvPolynomial.mem_support_iff.mp hd_mem) + have := weight_eq_4a_6b d; omega + set c := MvPolynomial.coeff d p + set δ_piece := MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) + set p' := p - δ_piece with hp'_def + have hp_eq : p = p' + δ_piece := by simp only [p', sub_add_cancel] + have hp'_wh : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p' n := by + rw [hp'_def] + exact (MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n _).mp + (Submodule.sub_mem _ + ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n p).mpr hp) + ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n + δ_piece).mpr (discriminantPoly_piece_isWeightedHomogeneous hn12 d hd_ge hwd c))) + set q₁ := MvPolynomial.C (c * 1728) * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1)) + have hδ_eq : δ_piece = discriminantPoly * q₁ := by + simp only [δ_piece, q₁, MvPolynomial.smul_eq_C_mul, map_mul]; ring + have hM_lt : ∑ d' ∈ p'.support, d' 0 < ∑ d' ∈ p.support, d' 0 := by + set d' := Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2) + with hd'_def + have hdd' : d ≠ d' := by + intro heq; have h0 := Finsupp.ext_iff.mp heq (0 : Fin 2) + simp only [Fin.isValue, hd'_def, Finsupp.add_apply, Finsupp.single_eq_same, + ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 + omega + have hdp_mono : δ_piece = + (MvPolynomial.monomial d) c - (MvPolynomial.monomial d') c := + discriminantPoly_piece_eq_monomial_sub d hd_ge c d' hd'_def + obtain ⟨hd_not, hsupp⟩ := hdp_mono ▸ mvpoly_support_after_reduction p d d' c hdd' rfl + exact sum_lt_sum_of_replace p.support p'.support + (· 0) d d' hd_mem hd_not hsupp (by simp [hd'_def, Finsupp.add_apply]; omega) + obtain ⟨r, s', hr_wh, hs'_wh, hp'_eq, hr_red⟩ := + ih (∑ d' ∈ p'.support, d' 0) (by omega) p' hp'_wh le_rfl + refine ⟨r, s' + q₁, hr_wh, hs'_wh.add (.C_mul + (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) _), ?_, hr_red⟩ + rw [hp_eq, hδ_eq, hp'_eq, mul_add]; ring /-- If `eval (r + Δ_poly * s) ↑n = 0` and `r` is reduced, then `r = 0`. -/ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) From 4a313bd30d042700ab82ab1c96f1deb15c6b8bc7 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 19:40:11 +0100 Subject: [PATCH 39/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20clean?= =?UTF-8?q?up=20pass=20on=20E=E2=82=84/E=E2=82=86=20generators?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Replace deprecated `push_neg` with `push Not` (4 sites). * Replace `show` with `change` where the tactic actually changes the goal, silencing `linter.style.show`. * Remove unused private helpers `X0_cubed_eq_smul_discriminantPoly` and `X0_pow_mul_X1_pow_isWeightedHomogeneous'`. * Strip narrative inline `-- ...` comments from proof bodies; keep docstrings and section dividers. No semantic changes; the file builds with zero warnings. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 44 +++++-------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index fe826ef74e8139..3789a99025b359 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -202,7 +202,6 @@ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + have hweight : (a • (4 : ℤ) + b • (6 : ℤ)) = (n : ℤ) := by change ((a : ℤ) * 4 + (b : ℤ) * 6) = (n : ℤ) push_cast [← hab]; ring - -- `prod` is concentrated at weight `n`. have hprod_eq : prod = DirectSum.of (ModularForm 𝒮ℒ) (n : ℤ) (prod (n : ℤ)) := by refine DFinsupp.ext (fun k : ℤ => ?_) by_cases hk : k = (n : ℤ) @@ -212,7 +211,6 @@ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + refine DirectSum.of_eq_of_ne _ _ _ ?_ rw [← hweight] at hk exact hk - -- Compute `R prod` two ways. have hR_eval : R prod = qExpansion 1 E₄ ^ a * qExpansion 1 E₆ ^ b := by rw [hprod_def, hR_def, map_mul, map_pow, map_pow, ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL, @@ -405,12 +403,6 @@ graded ring of level-1 modular forms. -/ private noncomputable def discriminantPoly : MvPolynomial (Fin 2) ℂ := (1 / 1728 : ℂ) • (MvPolynomial.X 0 ^ 3 - MvPolynomial.X 1 ^ 2) -private lemma X0_cubed_eq_smul_discriminantPoly : - (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ 3 = - MvPolynomial.X (1 : Fin 2) ^ 2 + (1728 : ℂ) • discriminantPoly := by - simp only [discriminantPoly, smul_smul] - norm_num - private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d = d 0 * 4 + d 1 * 6 := by change (Finsupp.linearCombination ℕ E₄E₆Weight).toAddMonoidHom d = d 0 * 4 + d 1 * 6 @@ -553,11 +545,11 @@ private lemma discriminantPoly_isWeightedHomogeneous : by_cases hd3 : MvPolynomial.coeff d (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) ≠ 0 · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (0 : Fin 2)).pow 3) hd3 - · push_neg at hd3 + · push Not at hd3 by_cases hd6 : MvPolynomial.coeff d (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow 2) hd6 - · push_neg at hd6; simp only [hd3, hd6, sub_self, mul_zero, ne_eq, not_true] at hd + · push Not at hd6; simp only [hd3, hd6, sub_self, mul_zero, ne_eq, not_true] at hd /-- `evalE₄E₆ discriminantPoly = DirectSum.of _ 12 Δ`. -/ private lemma evalE₄E₆_discriminantPoly : @@ -576,11 +568,8 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 evalE₄E₆_whc_eq_single (n - 12) s hs, DirectSum.of_mul_of] have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega rw [DirectSum.of_apply, dif_pos hcast] - -- The product evaluated at ↑n is a modular form of weight n with q-expansion Δ * s_eval. - -- Its 0th q-expansion coefficient vanishes since Δ is a cusp form. set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) - show (qExpansion 1 ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ)).coeff 0 = 0 have hcoe : ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ) = ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ) := by ext z @@ -588,7 +577,10 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by intros; subst_vars; rfl exact helper hcast _ z - rw [hcoe, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, + rw [show + (qExpansion 1 ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ)).coeff 0 = + (qExpansion 1 ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ)).coeff 0 from + by rw [hcoe], ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, PowerSeries.coeff_mul] have hΔ_coeff : (qExpansion 1 (f : ℍ → ℂ)).coeff 0 = 0 := (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩ @@ -650,12 +642,6 @@ private lemma per_weight_injective_zero · rw [hc, map_zero] · exact absurd h1z one_ne_zero_modularForm -private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous' {a b : ℕ} : - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight - (MvPolynomial.X (0 : Fin 2) ^ a * MvPolynomial.X (1 : Fin 2) ^ b : - MvPolynomial (Fin 2) ℂ) (a * 4 + b * 6) := - X0_pow_mul_X1_pow_isWeightedHomogeneous a b _ rfl - private lemma discriminantPoly_piece_isWeightedHomogeneous {n : ℕ} (hn12 : 12 ≤ n) (d : Fin 2 →₀ ℕ) (hd_ge : 3 ≤ d 0) (hwd : d 0 * 4 + d 1 * 6 = n) (c : ℂ) : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight @@ -859,7 +845,6 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) · rwa [MvPolynomial.support_eq_empty] at hr_empty obtain ⟨d₀, hd₀⟩ := Finset.nonempty_of_ne_empty hr_empty have hwd₀ := hr (MvPolynomial.mem_support_iff.mp hd₀) - -- Reduced + weight n forces all monomials in r.support to have the same exponent vector d₀. have hr_mono : r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by ext d by_cases hd : d = d₀ @@ -875,14 +860,11 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (show d 0 * 4 + d 1 * 6 = d₀ 0 * 4 + d₀ 1 * 6 by omega) exact absurd (Finsupp.ext fun i => by fin_cases i <;> [exact ha; exact hb]) hd · rwa [MvPolynomial.mem_support_iff, not_not] at hd_supp - -- Now the goal: show MvPolynomial.coeff d₀ r = 0 set c := MvPolynomial.coeff d₀ r suffices hc : c = 0 by rw [hr_mono, hc, MvPolynomial.monomial_zero] - -- Take q-expansion coeff 0 of evaluated polynomial. rw [hr_mono, map_add] at heval have hd₀_weight : 4 * d₀ 0 + 6 * d₀ 1 = n := by have := weight_eq_4a_6b d₀; rw [hwd₀] at this; omega - -- Define Q = qExpansionAddHom 1 ↑n : ModularForm 𝒮ℒ ↑n →+ PowerSeries ℂ. set Q := ModularForm.qExpansionAddHom (h := 1) one_pos one_mem_strictPeriods_SL (↑n : ℤ) have hQ_zero : Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ)) = 0 := by @@ -896,14 +878,11 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by have := congr_arg (fun (p : PowerSeries ℂ) => p.coeff 0) hQ_zero simpa using this - -- The Δ_poly * s term contributes 0. - have h_Δ_term : (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by - show (qExpansion 1 ↑((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 - exact evalE₄E₆_discriminantPoly_mul_coeff_zero hn12 s hs + have h_Δ_term : (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := + evalE₄E₆_discriminantPoly_mul_coeff_zero hn12 s hs rw [h_Δ_term, add_zero] at h_coeff_sum - -- The monomial term contributes c. have h_mono_term : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c := by - show (qExpansion 1 ↑((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c + change (qExpansion 1 ↑((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply, show (↑(c • ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * @@ -937,7 +916,6 @@ private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) have hpw := DFunLike.congr_fun hds z simp only [ModularForm.zero_apply] at hpw rw [helper hcast _ z] at hpw - -- hpw : (GMul.mul f g) z = 0, i.e., f z * g z = 0 have hpw' : f z * g z = 0 := by have heq : (GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ (12 + ↑(n - 12))) z = f z * g z := rfl rw [← heq]; exact hpw @@ -974,7 +952,7 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ rcases hn02 with rfl | rfl · exact per_weight_injective_zero p hp heval · exact whomog_eq_zero_of_no_monomials p hp (fun d => no_wt_monomial_of_two d) - push_neg at hn4 + push Not at hn4 by_cases hn12 : n < 12 · have hn_cases : n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by obtain ⟨m, rfl⟩ := hk_odd; omega @@ -983,7 +961,7 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ · exact per_weight_injective_small 0 1 (by omega) (by omega) rfl p hp heval · exact per_weight_injective_small 2 0 (by omega) (by omega) rfl p hp heval · exact per_weight_injective_small 1 1 (by omega) (by omega) rfl p hp heval - push_neg at hn12 + push Not at hn12 exact per_weight_injective_inductive_step n ih p hp heval hn12 /-- The evaluation homomorphism `evalE₄E₆` is injective: `E₄` and `E₆` are algebraically From 917e66de58407cda88229ff962ea099b5392766b Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 21:03:04 +0100 Subject: [PATCH 40/61] chore(NumberTheory/ModularForms): one-tactic-per-line + simplify pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply user-stated rule: each tactic on its own line (no `; ` chaining). Combine the duplicate `weight_eight_rank_one` / `weight_ten_rank_one` into a single parametric `rank_one_of_lt_twelve {k : ℕ} (hk3 : 3 ≤ k) (hk2 : Even k) (hk12 : k < 12) : Module.rank ℂ (ModularForm 𝒮ℒ ↑k) = 1`. * Split every `tac1; tac2` chain across two lines (~30 sites). * Combine the two near-identical rank lemmas into one parametric helper. * Move the `rcases hk_odd with ⟨r, hr⟩; omega` odd-case dismissals inside `surj_of_weight` to two-line `obtain`/`omega` form. No semantic changes; the file builds with zero warnings. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 190 +++++++++++------- 1 file changed, 121 insertions(+), 69 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 3789a99025b359..17754d34ab8253 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -188,7 +188,8 @@ private lemma mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one {k₁ k₂ /-- Weight casting: rewriting the index of `DirectSum.of` along an equality of weights. -/ private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by - subst hk; rfl + subst hk + rfl /-- The 0th q-expansion coefficient of `(of _ 4 E₄)^a * (of _ 6 E₆)^b` evaluated at weight `n = 4a + 6b` equals `1`. -/ @@ -201,13 +202,15 @@ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + with hprod_def have hweight : (a • (4 : ℤ) + b • (6 : ℤ)) = (n : ℤ) := by change ((a : ℤ) * 4 + (b : ℤ) * 6) = (n : ℤ) - push_cast [← hab]; ring + push_cast [← hab] + ring have hprod_eq : prod = DirectSum.of (ModularForm 𝒮ℒ) (n : ℤ) (prod (n : ℤ)) := by refine DFinsupp.ext (fun k : ℤ => ?_) by_cases hk : k = (n : ℤ) - · subst hk; simp - · rw [DirectSum.of_eq_of_ne _ _ _ hk] - rw [hprod_def, DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of] + · subst hk + simp + · rw [DirectSum.of_eq_of_ne _ _ _ hk, hprod_def, DirectSum.ofPow, DirectSum.ofPow, + DirectSum.of_mul_of] refine DirectSum.of_eq_of_ne _ _ _ ?_ rw [← hweight] at hk exact hk @@ -237,7 +240,8 @@ private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ symm apply DirectSum.of_eq_of_gradedMonoid_eq refine ModularForm.gradedMonoid_eq_of_cast ?_ ?_ - · change (↑n - 12 + 12 : ℤ) = ↑n; ring + · change (↑n - 12 + 12 : ℤ) = ↑n + ring ext z set hcusp := (ModularForm.isCuspForm_iff_coeffZero_eq_zero g).mp hg change ((CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)).mul @@ -303,10 +307,14 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev have hmn_in : mo ∈ Set.range evalE₄E₆ := ⟨MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b, evalE₄E₆_monomial a b⟩ have hmn_eq : DirectSum.of _ (↑n : ℤ) mn = mo := by - have h4 : ((a : ℤ) * 4 + b * 6) = ↑n := by push_cast [← hab]; ring + have h4 : ((a : ℤ) * 4 + b * 6) = ↑n := by + push_cast [← hab] + ring simp only [mn, mo, DirectSum.ofPow, DirectSum.of_mul_of] - rw [show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) from by - simp only [Int.nsmul_eq_mul]; linarith, DirectSum.of_eq_same] + rw [show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) by + simp only [Int.nsmul_eq_mul] + linarith, + DirectSum.of_eq_same] have hf_ds : DirectSum.of _ (↑n : ℤ) f = DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn := by rw [← DirectSum.of_smul, ← map_add] @@ -319,15 +327,11 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev rw [map_add, hp1, map_mul, evalE₄E₆_C, hp2, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul]⟩ -private lemma weight_eight_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 8) = 1 := - (ModularForm.rank_eq_one_add_rank_cuspForm (by norm_num) ⟨4, rfl⟩).trans - ((congrArg (1 + ·) (CuspForm.rank_eq_zero_of_weight_lt_twelve (by norm_num))).trans - (by norm_cast)) - -private lemma weight_ten_rank_one : Module.rank ℂ (ModularForm 𝒮ℒ 10) = 1 := - (ModularForm.rank_eq_one_add_rank_cuspForm (by norm_num) ⟨5, rfl⟩).trans - ((congrArg (1 + ·) (CuspForm.rank_eq_zero_of_weight_lt_twelve (by norm_num))).trans - (by norm_cast)) +private lemma rank_one_of_lt_twelve {k : ℕ} (hk3 : 3 ≤ k) (hk2 : Even k) (hk12 : k < 12) : + Module.rank ℂ (ModularForm 𝒮ℒ (↑k : ℤ)) = 1 := by + rw [ModularForm.rank_eq_one_add_rank_cuspForm hk3 hk2, + CuspForm.rank_eq_zero_of_weight_lt_twelve (by exact_mod_cast hk12 : (↑k : ℤ) < 12)] + norm_cast private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := by intro h @@ -354,36 +358,42 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), rw [Int.not_odd_iff_even] at hk_odd by_cases hn12 : n < 12 · interval_cases n - · exact surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one - one_ne_zero_modularForm 1 (by rw [map_one]; rfl) f - · rcases hk_odd with ⟨r, hr⟩; omega + · refine surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one + one_ne_zero_modularForm 1 ?_ f + rw [map_one] + rfl + · obtain ⟨r, hr⟩ := hk_odd + omega · rw [(rank_zero_iff_forall_zero.mp ModularForm.levelOne_weight_two_rank_zero) f, map_zero] exact ⟨0, map_zero _⟩ - · rcases hk_odd with ⟨r, hr⟩; omega + · obtain ⟨r, hr⟩ := hk_odd + omega · exact surj_of_rank_one ModularForm.levelOne_weight_four_rank_one (show E₄ ≠ 0 from E_ne_zero (by norm_num) ⟨2, rfl⟩) (MvPolynomial.X 0) evalE₄E₆_X0 f - · rcases hk_odd with ⟨r, hr⟩; omega + · obtain ⟨r, hr⟩ := hk_odd + omega · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one (show E₆ ≠ 0 from E_ne_zero (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f - · rcases hk_odd with ⟨r, hr⟩; omega - · refine surj_of_rank_one weight_eight_rank_one + · obtain ⟨r, hr⟩ := hk_odd + omega + · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₄ (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨2, rfl⟩)) (MvPolynomial.X 0 ^ 2) ?_ f rw [map_pow, evalE₄E₆_X0, pow_two, DirectSum.of_mul_of] apply DirectSum.of_eq_of_gradedMonoid_eq - exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 4 : ℤ) = 8 from by norm_num).symm - rfl - · rcases hk_odd with ⟨r, hr⟩; omega - · refine surj_of_rank_one weight_ten_rank_one + exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 4 : ℤ) = 8 by norm_num).symm rfl + · obtain ⟨r, hr⟩ := hk_odd + omega + · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₆ (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨3, rfl⟩)) (MvPolynomial.X 0 * MvPolynomial.X 1) ?_ f rw [map_mul, evalE₄E₆_X0, evalE₄E₆_X1, DirectSum.of_mul_of] apply DirectSum.of_eq_of_gradedMonoid_eq - exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 6 : ℤ) = 10 from by norm_num).symm - rfl - · rcases hk_odd with ⟨r, hr⟩; omega + exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 6 : ℤ) = 10 by norm_num).symm rfl + · obtain ⟨r, hr⟩ := hk_odd + omega · push Not at hn12 exact surj_at_weight_inductive hn12 hk_odd ih f @@ -413,7 +423,9 @@ private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : private lemma weight_fin2_cast (d : Fin 2 →₀ ℕ) : (Finsupp.weight E₄E₆Weight d : ℤ) = ↑(d 0) * 4 + ↑(d 1) * 6 := by - rw [weight_eq_4a_6b]; push_cast; ring + rw [weight_eq_4a_6b] + push_cast + ring private lemma finsupp_of_fin2 (a b : ℕ) : ∃ d : Fin 2 →₀ ℕ, d 0 = a ∧ d 1 = b := ⟨Finsupp.equivFunOnFinite.invFun ![a, b], rfl, rfl⟩ @@ -427,7 +439,9 @@ private lemma no_wt_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ ℕ private lemma no_wt_monomial_of_two (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d ≠ 2 := by - intro h; rw [weight_eq_4a_6b] at h; omega + intro h + rw [weight_eq_4a_6b] at h + omega private lemma whomog_eq_zero_of_no_monomials {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) @@ -443,7 +457,8 @@ private lemma whomog_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by ext d by_cases hd : d = d₀ - · subst hd; simp only [MvPolynomial.coeff_monomial, ↓reduceIte] + · subst hd + simp only [MvPolynomial.coeff_monomial, ↓reduceIte] · rw [MvPolynomial.coeff_monomial, if_neg (Ne.symm hd)] exact hp.coeff_eq_zero d (fun h => hd (huniq d h)) @@ -455,10 +470,11 @@ private lemma unique_small_weight_soln {a₁ b₁ a₂ b₂ : ℕ} private lemma monomial_fin2_eq (d : Fin 2 →₀ ℕ) (c : ℂ) : MvPolynomial.monomial d c = MvPolynomial.C c * MvPolynomial.X 0 ^ d 0 * MvPolynomial.X 1 ^ d 1 := by - rw [MvPolynomial.monomial_eq, mul_assoc]; congr 1 + rw [MvPolynomial.monomial_eq, mul_assoc] + congr 1 rw [Finsupp.prod, Finset.prod_subset (fun _ _ => Finset.mem_univ _) (fun i _ hi => by - have : d i = 0 := by rwa [Finsupp.mem_support_iff, not_not] at hi - rw [this, pow_zero])] + have hdi : d i = 0 := by rwa [Finsupp.mem_support_iff, not_not] at hi + rw [hdi, pow_zero])] simp only [Fin.prod_univ_two] private lemma evalE₄E₆_mono_grade (a b : ℕ) (k : ℤ) @@ -489,7 +505,8 @@ private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) apply Finset.sum_eq_zero intro d hd apply evalE₄E₆_monomial_grade - intro heq; apply hk + intro heq + apply hk have hwd : Finsupp.weight E₄E₆Weight d = n := hp (MvPolynomial.mem_support_iff.mp hd) rw [heq, ← weight_fin2_cast d, hwd] @@ -498,7 +515,8 @@ private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ evalE₄E₆ p = DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) ((evalE₄E₆ p) ↑n) := by refine DFinsupp.ext (fun k : ℤ => ?_) by_cases hk : k = (↑n : ℤ) - · subst hk; simp + · subst hk + simp · rw [DirectSum.of_eq_of_ne _ _ _ hk, evalE₄E₆_whc_grade p hp k hk] private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) : @@ -506,7 +524,8 @@ private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) (evalE₄E₆ p) (↑n : ℤ) := by set q := p - MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p with hq_def have hdecomp : p = MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p + q := by - rw [hq_def]; ring + rw [hq_def] + ring conv_rhs => rw [hdecomp, map_add] rw [show (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p) + evalE₄E₆ q) (↑n : ℤ) = @@ -526,7 +545,8 @@ private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) apply MvPolynomial.mem_support_iff.mp hd rw [hq_def, MvPolynomial.coeff_sub, MvPolynomial.coeff_weightedHomogeneousComponent, if_pos ?_, sub_self] - rw [weight_eq_4a_6b]; omega + rw [weight_eq_4a_6b] + omega private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 + b * 6 = n) : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight @@ -534,7 +554,8 @@ private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 MvPolynomial (Fin 2) ℂ) n := by convert ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (0 : Fin 2)).pow a).mul ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow b) using 1 - simp only [E₄E₆Weight, Matrix.cons_val_zero, Matrix.cons_val_one, smul_eq_mul]; omega + simp only [E₄E₆Weight, Matrix.cons_val_zero, Matrix.cons_val_one, smul_eq_mul] + omega private lemma discriminantPoly_isWeightedHomogeneous : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight discriminantPoly 12 := by @@ -549,7 +570,8 @@ private lemma discriminantPoly_isWeightedHomogeneous : by_cases hd6 : MvPolynomial.coeff d (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow 2) hd6 - · push Not at hd6; simp only [hd3, hd6, sub_self, mul_zero, ne_eq, not_true] at hd + · push Not at hd6 + simp only [hd3, hd6, sub_self, mul_zero, ne_eq, not_true] at hd /-- `evalE₄E₆ discriminantPoly = DirectSum.of _ 12 Δ`. -/ private lemma evalE₄E₆_discriminantPoly : @@ -575,12 +597,14 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 ext z have helper : ∀ {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ), (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by - intros; subst_vars; rfl + intros + subst_vars + rfl exact helper hcast _ z rw [show (qExpansion 1 ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ)).coeff 0 = - (qExpansion 1 ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ)).coeff 0 from - by rw [hcoe], ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, + (qExpansion 1 ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ)).coeff 0 by + rw [hcoe], ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, PowerSeries.coeff_mul] have hΔ_coeff : (qExpansion 1 (f : ℍ → ℂ)).coeff 0 = 0 := (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩ @@ -610,11 +634,14 @@ private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn obtain ⟨d₀, hd0a, hd0b⟩ := finsupp_of_fin2 a b apply per_weight_injective_unique_monomial p hp heval d₀ · intro d hd - have h46 := weight_eq_4a_6b d; rw [hd] at h46 + have h46 := weight_eq_4a_6b d + rw [hd] at h46 obtain ⟨hda, hdb⟩ := unique_small_weight_soln (by omega : d 0 < 3) ha (show d 0 * 4 + d 1 * 6 = a * 4 + b * 6 by omega) - ext i; fin_cases i <;> [exact hda ▸ hd0a.symm; exact hdb ▸ hd0b.symm] - · rw [hd0a, hd0b]; intro habs + ext i + fin_cases i <;> [exact hda ▸ hd0a.symm; exact hdb ▸ hd0b.symm] + · rw [hd0a, hd0b] + intro habs have hcz := monomial_qExpansion_coeff_zero_eq_one (n := n) (a := a) (b := b) (by omega) rw [habs] at hcz simp [UpperHalfPlane.qExpansion_zero] at hcz @@ -630,8 +657,11 @@ private lemma per_weight_injective_zero · simp [hd'] · rw [if_neg hd'] exact hp.coeff_eq_zero d' (fun hw => hd' (by - have h46' := weight_eq_4a_6b d'; rw [hw] at h46' - symm; ext i; fin_cases i <;> simp [Finsupp.coe_zero] <;> omega)) + have h46' := weight_eq_4a_6b d' + rw [hw] at h46' + symm + ext i + fin_cases i <;> simp [Finsupp.coe_zero] <;> omega)) rw [hpc] at heval ⊢ rw [evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, DirectSum.smul_apply] at heval have h1eq : (1 : DirectSum ℤ (ModularForm 𝒮ℒ)) (0 : ℤ) = (1 : ModularForm 𝒮ℒ 0) := by @@ -671,16 +701,20 @@ private lemma discriminantPoly_piece_eq_monomial_sub subst hd' have h1728 : (1728 : ℂ) • discriminantPoly = MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2 := by - simp only [discriminantPoly, smul_smul]; norm_num + simp only [discriminantPoly, smul_smul] + norm_num have hd_fin : d = Finsupp.single (0 : Fin 2) (d 0) + Finsupp.single (1 : Fin 2) (d 1) := by - ext i; fin_cases i <;> simp [Finsupp.add_apply] + ext i + fin_cases i <;> simp [Finsupp.add_apply] rw [show MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) = MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2) * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * - MvPolynomial.X (1 : Fin 2) ^ (d 1)) from by rw [h1728]; ring] + MvPolynomial.X (1 : Fin 2) ^ (d 1)) by + rw [h1728] + ring] have h3 : (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = MvPolynomial.X (0 : Fin 2) ^ d 0 * MvPolynomial.X (1 : Fin 2) ^ d 1 := by @@ -796,7 +830,8 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) obtain ⟨d, hd_mem, hd_ge⟩ := hall have hwd : d 0 * 4 + d 1 * 6 = n := by have := hp (MvPolynomial.mem_support_iff.mp hd_mem) - have := weight_eq_4a_6b d; omega + have := weight_eq_4a_6b d + omega set c := MvPolynomial.coeff d p set δ_piece := MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) @@ -812,12 +847,14 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) set q₁ := MvPolynomial.C (c * 1728) * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1)) have hδ_eq : δ_piece = discriminantPoly * q₁ := by - simp only [δ_piece, q₁, MvPolynomial.smul_eq_C_mul, map_mul]; ring + simp only [δ_piece, q₁, MvPolynomial.smul_eq_C_mul, map_mul] + ring have hM_lt : ∑ d' ∈ p'.support, d' 0 < ∑ d' ∈ p.support, d' 0 := by set d' := Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2) with hd'_def have hdd' : d ≠ d' := by - intro heq; have h0 := Finsupp.ext_iff.mp heq (0 : Fin 2) + intro heq + have h0 := Finsupp.ext_iff.mp heq (0 : Fin 2) simp only [Fin.isValue, hd'_def, Finsupp.add_apply, Finsupp.single_eq_same, ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 omega @@ -825,13 +862,15 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) (MvPolynomial.monomial d) c - (MvPolynomial.monomial d') c := discriminantPoly_piece_eq_monomial_sub d hd_ge c d' hd'_def obtain ⟨hd_not, hsupp⟩ := hdp_mono ▸ mvpoly_support_after_reduction p d d' c hdd' rfl - exact sum_lt_sum_of_replace p.support p'.support - (· 0) d d' hd_mem hd_not hsupp (by simp [hd'_def, Finsupp.add_apply]; omega) + refine sum_lt_sum_of_replace p.support p'.support (· 0) d d' hd_mem hd_not hsupp ?_ + simp [hd'_def, Finsupp.add_apply] + omega obtain ⟨r, s', hr_wh, hs'_wh, hp'_eq, hr_red⟩ := ih (∑ d' ∈ p'.support, d' 0) (by omega) p' hp'_wh le_rfl refine ⟨r, s' + q₁, hr_wh, hs'_wh.add (.C_mul (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) _), ?_, hr_red⟩ - rw [hp_eq, hδ_eq, hp'_eq, mul_add]; ring + rw [hp_eq, hδ_eq, hp'_eq, mul_add] + ring /-- If `eval (r + Δ_poly * s) ↑n = 0` and `r` is reduced, then `r = 0`. -/ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) @@ -848,7 +887,8 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) have hr_mono : r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by ext d by_cases hd : d = d₀ - · subst hd; simp only [MvPolynomial.coeff_monomial, ↓reduceIte] + · subst hd + simp only [MvPolynomial.coeff_monomial, ↓reduceIte] rw [MvPolynomial.coeff_monomial, if_neg (Ne.symm hd)] by_cases hd_supp : d ∈ r.support · have h1 := weight_eq_4a_6b d @@ -864,7 +904,9 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) suffices hc : c = 0 by rw [hr_mono, hc, MvPolynomial.monomial_zero] rw [hr_mono, map_add] at heval have hd₀_weight : 4 * d₀ 0 + 6 * d₀ 1 = n := by - have := weight_eq_4a_6b d₀; rw [hwd₀] at this; omega + have := weight_eq_4a_6b d₀ + rw [hwd₀] at this + omega set Q := ModularForm.qExpansionAddHom (h := 1) one_pos one_mem_strictPeriods_SL (↑n : ℤ) have hQ_zero : Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ)) = 0 := by @@ -910,7 +952,10 @@ private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) have helper : ∀ {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ), - (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by intros; subst_vars; rfl + (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by + intros + subst_vars + rfl ext z simp only [ModularForm.zero_apply] have hpw := DFunLike.congr_fun hds z @@ -918,7 +963,8 @@ private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) rw [helper hcast _ z] at hpw have hpw' : f z * g z = 0 := by have heq : (GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ (12 + ↑(n - 12))) z = f z * g z := rfl - rw [← heq]; exact hpw + rw [← heq] + exact hpw rcases mul_eq_zero.mp hpw' with hf0 | hg0 · exact absurd hf0 (discriminant_ne_zero z) · exact hg0 @@ -948,14 +994,17 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ · exact whomog_eq_zero_of_no_monomials p hp (fun d => no_wt_monomial_of_odd hk_odd d) rw [Nat.not_odd_iff_even] at hk_odd by_cases hn4 : n < 4 - · have hn02 : n = 0 ∨ n = 2 := by obtain ⟨m, rfl⟩ := hk_odd; omega + · have hn02 : n = 0 ∨ n = 2 := by + obtain ⟨m, rfl⟩ := hk_odd + omega rcases hn02 with rfl | rfl · exact per_weight_injective_zero p hp heval · exact whomog_eq_zero_of_no_monomials p hp (fun d => no_wt_monomial_of_two d) push Not at hn4 by_cases hn12 : n < 12 · have hn_cases : n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by - obtain ⟨m, rfl⟩ := hk_odd; omega + obtain ⟨m, rfl⟩ := hk_odd + omega rcases hn_cases with rfl | rfl | rfl | rfl · exact per_weight_injective_small 1 0 (by omega) (by omega) rfl p hp heval · exact per_weight_injective_small 0 1 (by omega) (by omega) rfl p hp heval @@ -970,12 +1019,15 @@ theorem evalE₄E₆_injective : Function.Injective evalE₄E₆ := by intro p q hpq rw [← sub_eq_zero] set r := p - q with hr_def - have hr : evalE₄E₆ r = 0 := by rw [hr_def, map_sub, sub_eq_zero]; exact hpq + have hr : evalE₄E₆ r = 0 := by + rw [hr_def, map_sub, sub_eq_zero] + exact hpq rw [← MvPolynomial.sum_weightedHomogeneousComponent (E₄E₆Weight) r] refine finsum_eq_zero_of_forall_eq_zero (fun n => ?_) refine per_weight_injective n _ (MvPolynomial.weightedHomogeneousComponent_isWeightedHomogeneous _ _) ?_ - rw [evalE₄E₆_component_eq, hr]; rfl + rw [evalE₄E₆_component_eq, hr] + rfl /-- The graded ring of level-1 modular forms is isomorphic to the polynomial ring `ℂ[X₀, X₁]` via evaluation at `E₄` and `E₆`. -/ From 34d7479f51e657f40df4ff1e629852bc8d6eeca5 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Fri, 1 May 2026 21:45:37 +0100 Subject: [PATCH 41/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20golf?= =?UTF-8?q?=20E=E2=82=84/E=E2=82=86=20generators=20(1047=20=E2=86=92=20941?= =?UTF-8?q?=20lines)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply mathlib-style golf to all new declarations from PR #38813. Highlights: * Reorganize so `discriminantPoly` and `evalE₄E₆_discriminantPoly` come before `discriminant_mem_range_evalE₄E₆`, collapsing the latter to a one-line term-mode proof. * Extract a `cast_modularForm_apply` helper used in `evalE₄E₆_discriminantPoly_mul_coeff_zero` and `eval_discriminantPoly_mul_zero_imp`. * Replace `obtain ⟨r, hr⟩ := hk_odd; omega` odd-case dismissals in `surj_of_weight` with `exact absurd hk_odd (by decide)`. * Inline single-use `have foo := bar` statements throughout. * Collapse three sequential `rw [show ... from by ring]` blocks in `discriminantPoly_piece_eq_monomial_sub` into one (~30 lines saved). * Use `simp [...]` in place of `rw [...]; simp` chains where applicable. * Apply `Finsupp.weight_apply` + `Finsupp.sum_fintype` in `weight_eq_4a_6b` (per code-reuse review). * Apply `Finsupp.prod_fintype` in `monomial_fin2_eq` (per code-reuse review). Hard constraints respected: * Each tactic on its own line; sequential `rw` calls combined into one. * No `tac1; tac2` chains introduced. * Build clean with zero warnings. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 418 +++++++----------- 1 file changed, 153 insertions(+), 265 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 17754d34ab8253..050b3433c90a6a 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -147,15 +147,14 @@ lemma evalE₄E₆_monomial (a b : ℕ) : evalE₄E₆ (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b) = DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by - rw [map_mul, map_pow, map_pow, evalE₄E₆_X0, evalE₄E₆_X1] + simp [map_mul, map_pow] /-- For even `k ≥ 4`, there exist `a, b ∈ ℕ` with `4a + 6b = k`. -/ private lemma exists_monomial_weight {k : ℕ} (hk : 4 ≤ k) (hkeven : Even k) : ∃ a b : ℕ, 4 * a + 6 * b = k := by obtain ⟨m, rfl⟩ := hkeven rcases Nat.even_or_odd m with ⟨n, hn⟩ | ⟨n, hn⟩ - · exact ⟨n, 0, by omega⟩ - · exact ⟨n - 1, 1, by omega⟩ + exacts [⟨n, 0, by omega⟩, ⟨n - 1, 1, by omega⟩] /-! ### Surjectivity of `evalE₄E₆` -/ @@ -191,6 +190,11 @@ private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : Modu subst hk rfl +private lemma cast_modularForm_apply {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ) : + (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by + subst heq + rfl + /-- The 0th q-expansion coefficient of `(of _ 4 E₄)^a * (of _ 6 E₆)^b` evaluated at weight `n = 4a + 6b` equals `1`. -/ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + 6 * b = n) : @@ -201,26 +205,23 @@ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + set prod := DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b with hprod_def have hweight : (a • (4 : ℤ) + b • (6 : ℤ)) = (n : ℤ) := by - change ((a : ℤ) * 4 + (b : ℤ) * 6) = (n : ℤ) + simp only [Int.nsmul_eq_mul] push_cast [← hab] ring have hprod_eq : prod = DirectSum.of (ModularForm 𝒮ℒ) (n : ℤ) (prod (n : ℤ)) := by - refine DFinsupp.ext (fun k : ℤ => ?_) + refine DFinsupp.ext fun k : ℤ => ?_ by_cases hk : k = (n : ℤ) · subst hk simp - · rw [DirectSum.of_eq_of_ne _ _ _ hk, hprod_def, DirectSum.ofPow, DirectSum.ofPow, - DirectSum.of_mul_of] - refine DirectSum.of_eq_of_ne _ _ _ ?_ - rw [← hweight] at hk - exact hk + rw [DirectSum.of_eq_of_ne _ _ _ hk, hprod_def, DirectSum.ofPow, DirectSum.ofPow, + DirectSum.of_mul_of] + exact DirectSum.of_eq_of_ne _ _ _ (hweight ▸ hk) have hR_eval : R prod = qExpansion 1 E₄ ^ a * qExpansion 1 E₆ ^ b := by rw [hprod_def, hR_def, map_mul, map_pow, map_pow, ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL, ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL] have hR_concentrated : R prod = qExpansion 1 (prod (n : ℤ)) := by - conv_lhs => rw [hprod_eq] - rw [hR_def] + conv_lhs => rw [hprod_eq, hR_def] exact ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL _ _ rw [← hR_concentrated, hR_eval, PowerSeries.coeff_mul] simp [Finset.antidiagonal_zero, PowerSeries.coeff_pow, @@ -253,14 +254,25 @@ private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ change g z / ModularForm.discriminant z * ModularForm.discriminant z = g z exact div_mul_cancel₀ _ (discriminant_ne_zero z) +/-- The polynomial `Δ_poly = (1/1728) (X₀³ - X₁²)`, which `evalE₄E₆` sends to `Δ` in the +graded ring of level-1 modular forms. -/ +private noncomputable def discriminantPoly : MvPolynomial (Fin 2) ℂ := + (1 / 1728 : ℂ) • (MvPolynomial.X 0 ^ 3 - MvPolynomial.X 1 ^ 2) + +/-- `evalE₄E₆ discriminantPoly = DirectSum.of _ 12 Δ`. -/ +private lemma evalE₄E₆_discriminantPoly : + evalE₄E₆ discriminantPoly = + DirectSum.of (ModularForm 𝒮ℒ) 12 + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := by + rw [discriminantPoly, map_smul, map_sub, map_pow, map_pow, evalE₄E₆_X0, evalE₄E₆_X1, + ← discriminant_eq_E₄_cube_sub_E₆_sq_graded] + /-- The discriminant `Δ`, viewed as a modular form of weight 12, lies in the range of `evalE₄E₆`. -/ private lemma discriminant_mem_range_evalE₄E₆ : DirectSum.of (ModularForm 𝒮ℒ) 12 - ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ Set.range evalE₄E₆ := by - refine ⟨(1 / 1728 : ℂ) • (MvPolynomial.X 0 ^ 3 - MvPolynomial.X 1 ^ 2), ?_⟩ - simp only [map_smul, map_sub, map_pow, evalE₄E₆_X0, evalE₄E₆_X1] - rw [← discriminant_eq_E₄_cube_sub_E₆_sq_graded] + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ Set.range evalE₄E₆ := + ⟨discriminantPoly, evalE₄E₆_discriminantPoly⟩ /-- Inductive step: for `n ≥ 12` even, surjectivity at weight `n` follows from surjectivity at all lower weights via the cusp-form / `Δ` decomposition. -/ @@ -276,67 +288,50 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev set c := (qExpansion 1 f).coeff 0 have hmn_coeff : (qExpansion 1 mn).coeff 0 = 1 := monomial_qExpansion_coeff_zero_eq_one hab have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := by - rw [ModularForm.isCuspForm_iff_coeffZero_eq_zero] - have hQsub := (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL (↑n : ℤ)).map_sub - f (c • mn) - have hQsmul := ModularFormClass.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := (↑n : ℤ)) - one_pos one_mem_strictPeriods_SL c mn - change (qExpansion 1 ⇑(f - c • mn : ModularForm 𝒮ℒ ↑n)).coeff 0 = 0 - rw [show qExpansion 1 ⇑(f - c • mn : ModularForm 𝒮ℒ ↑n) = - qExpansion 1 ⇑f - qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) from hQsub] - rw [show qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) = c • qExpansion 1 ⇑mn from hQsmul] - rw [map_sub, PowerSeries.coeff_smul] + rw [ModularForm.isCuspForm_iff_coeffZero_eq_zero, + show qExpansion 1 ⇑(f - c • mn : ModularForm 𝒮ℒ ↑n) = + qExpansion 1 ⇑f - qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) from + (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL (↑n : ℤ)).map_sub + f (c • mn), + show qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) = c • qExpansion 1 ⇑mn from + ModularFormClass.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := (↑n : ℤ)) + one_pos one_mem_strictPeriods_SL c mn, + map_sub, PowerSeries.coeff_smul] simp [hmn_coeff, c] have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by omega set h' := CuspForm.discriminantEquiv (ModularForm.toCuspForm (f - c • mn) ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp)) - have hg_ds : DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) (f - c • mn) = - DirectSum.of _ ((↑n : ℤ) - 12) h' * - DirectSum.of _ 12 - ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := - cuspForm_eq_discriminant_mul _ hg_cusp - have hih : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by + obtain ⟨p1, hp1⟩ : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by rw [directSumOf_cast_eq hcast] exact ih (n - 12) (by omega) (hcast ▸ h') - have hg_in : DirectSum.of _ (↑n : ℤ) (f - c • mn) ∈ Set.range evalE₄E₆ := by - rw [hg_ds] - obtain ⟨p1, hp1⟩ := hih - obtain ⟨p2, hp2⟩ := discriminant_mem_range_evalE₄E₆ - exact ⟨p1 * p2, by rw [map_mul, hp1, hp2]⟩ - have hmn_in : mo ∈ Set.range evalE₄E₆ := - ⟨MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b, evalE₄E₆_monomial a b⟩ have hmn_eq : DirectSum.of _ (↑n : ℤ) mn = mo := by - have h4 : ((a : ℤ) * 4 + b * 6) = ↑n := by - push_cast [← hab] - ring simp only [mn, mo, DirectSum.ofPow, DirectSum.of_mul_of] rw [show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) by simp only [Int.nsmul_eq_mul] - linarith, + push_cast [← hab] + ring, DirectSum.of_eq_same] - have hf_ds : DirectSum.of _ (↑n : ℤ) f = - DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn := by + rw [show DirectSum.of _ (↑n : ℤ) f = + DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn by rw [← DirectSum.of_smul, ← map_add] congr 1 - abel - rw [hf_ds, hmn_eq] - obtain ⟨p1, hp1⟩ := hg_in - obtain ⟨p2, hp2⟩ := hmn_in - exact ⟨p1 + MvPolynomial.C c * p2, by - rw [map_add, hp1, map_mul, evalE₄E₆_C, hp2, + abel, hmn_eq] + exact ⟨p1 * discriminantPoly + MvPolynomial.C c * (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b), + by rw [map_add, map_mul, hp1, evalE₄E₆_discriminantPoly, + cuspForm_eq_discriminant_mul (f - c • mn) hg_cusp, map_mul, + evalE₄E₆_C, evalE₄E₆_monomial a b, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul]⟩ private lemma rank_one_of_lt_twelve {k : ℕ} (hk3 : 3 ≤ k) (hk2 : Even k) (hk12 : k < 12) : Module.rank ℂ (ModularForm 𝒮ℒ (↑k : ℤ)) = 1 := by rw [ModularForm.rank_eq_one_add_rank_cuspForm hk3 hk2, - CuspForm.rank_eq_zero_of_weight_lt_twelve (by exact_mod_cast hk12 : (↑k : ℤ) < 12)] + CuspForm.rank_eq_zero_of_weight_lt_twelve (mod_cast hk12 : (↑k : ℤ) < 12)] norm_cast -private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := by - intro h - have := congr_arg (DFunLike.coe (F := ModularForm 𝒮ℒ 0)) h - exact (one_ne_zero (α := ℂ)) (congr_fun this UpperHalfPlane.I) +private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := fun h => + one_ne_zero (α := ℂ) (congr_fun (congr_arg (DFunLike.coe (F := ModularForm 𝒮ℒ 0)) h) + UpperHalfPlane.I) /-- For each weight `k`, every element of weight `k` lies in the range of `evalE₄E₆`. -/ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), @@ -362,20 +357,16 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), one_ne_zero_modularForm 1 ?_ f rw [map_one] rfl - · obtain ⟨r, hr⟩ := hk_odd - omega + · exact absurd hk_odd (by decide) · rw [(rank_zero_iff_forall_zero.mp ModularForm.levelOne_weight_two_rank_zero) f, map_zero] exact ⟨0, map_zero _⟩ - · obtain ⟨r, hr⟩ := hk_odd - omega + · exact absurd hk_odd (by decide) · exact surj_of_rank_one ModularForm.levelOne_weight_four_rank_one (show E₄ ≠ 0 from E_ne_zero (by norm_num) ⟨2, rfl⟩) (MvPolynomial.X 0) evalE₄E₆_X0 f - · obtain ⟨r, hr⟩ := hk_odd - omega + · exact absurd hk_odd (by decide) · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one (show E₆ ≠ 0 from E_ne_zero (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f - · obtain ⟨r, hr⟩ := hk_odd - omega + · exact absurd hk_odd (by decide) · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₄ (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨2, rfl⟩)) @@ -383,8 +374,7 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), rw [map_pow, evalE₄E₆_X0, pow_two, DirectSum.of_mul_of] apply DirectSum.of_eq_of_gradedMonoid_eq exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 4 : ℤ) = 8 by norm_num).symm rfl - · obtain ⟨r, hr⟩ := hk_odd - omega + · exact absurd hk_odd (by decide) · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₆ (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨3, rfl⟩)) @@ -392,8 +382,7 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), rw [map_mul, evalE₄E₆_X0, evalE₄E₆_X1, DirectSum.of_mul_of] apply DirectSum.of_eq_of_gradedMonoid_eq exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 6 : ℤ) = 10 by norm_num).symm rfl - · obtain ⟨r, hr⟩ := hk_odd - omega + · exact absurd hk_odd (by decide) · push Not at hn12 exact surj_at_weight_inductive hn12 hk_odd ih f @@ -401,25 +390,17 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by classical intro x - suffices x ∈ Set.range evalE₄E₆ from this rw [show x = x.sum (fun i m => DirectSum.of _ i m) from (DFinsupp.sum_single (f := x)).symm, - show (Set.range evalE₄E₆ : Set _) = ↑evalE₄E₆.range from (AlgHom.coe_range evalE₄E₆).symm] - exact Subalgebra.sum_mem _ (fun k _ => surj_of_weight k (x k)) + ← AlgHom.mem_range] + exact Subalgebra.sum_mem _ fun k _ => surj_of_weight k (x k) /-! ### Injectivity of `evalE₄E₆` -/ -/-- The polynomial `Δ_poly = (1/1728) (X₀³ - X₁²)`, which `evalE₄E₆` sends to `Δ` in the -graded ring of level-1 modular forms. -/ -private noncomputable def discriminantPoly : MvPolynomial (Fin 2) ℂ := - (1 / 1728 : ℂ) • (MvPolynomial.X 0 ^ 3 - MvPolynomial.X 1 ^ 2) - private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d = d 0 * 4 + d 1 * 6 := by - change (Finsupp.linearCombination ℕ E₄E₆Weight).toAddMonoidHom d = d 0 * 4 + d 1 * 6 - simp only [LinearMap.toAddMonoidHom_coe, Finsupp.linearCombination_apply] - rw [d.sum_fintype (fun i a => a • E₄E₆Weight i) (fun i => by simp only [zero_smul])] - simp only [Fin.sum_univ_two, E₄E₆Weight, Matrix.cons_val_zero, Matrix.cons_val_one, - mul_comm, smul_eq_mul] + rw [Finsupp.weight_apply, + d.sum_fintype (fun i c => c • E₄E₆Weight i) fun _ => zero_smul _ _] + simp [Fin.sum_univ_two, E₄E₆Weight, mul_comm] private lemma weight_fin2_cast (d : Fin 2 →₀ ℕ) : (Finsupp.weight E₄E₆Weight d : ℤ) = ↑(d 0) * 4 + ↑(d 1) * 6 := by @@ -434,8 +415,7 @@ private lemma no_wt_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ ℕ Finsupp.weight E₄E₆Weight d ≠ n := by intro h rw [weight_eq_4a_6b] at h - have hev : Even n := ⟨d 0 * 2 + d 1 * 3, by omega⟩ - exact (Nat.not_odd_iff_even.mpr hev) hn + exact Nat.not_odd_iff_even.mpr ⟨d 0 * 2 + d 1 * 3, by omega⟩ hn private lemma no_wt_monomial_of_two (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d ≠ 2 := by @@ -446,21 +426,20 @@ private lemma no_wt_monomial_of_two (d : Fin 2 →₀ ℕ) : private lemma whomog_eq_zero_of_no_monomials {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (hno : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d ≠ n) : p = 0 := by - rw [← MvPolynomial.support_eq_empty] - by_contra h - obtain ⟨d, hd⟩ := Finset.nonempty_of_ne_empty h - exact hno d (hp (MvPolynomial.mem_support_iff.mp hd)) + rw [← MvPolynomial.support_eq_empty, ← Finset.not_nonempty_iff_eq_empty] + rintro ⟨d, hd⟩ + exact hno _ (hp (MvPolynomial.mem_support_iff.mp hd)) private lemma whomog_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (d₀ : Fin 2 →₀ ℕ) (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) : p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by ext d + rw [MvPolynomial.coeff_monomial] by_cases hd : d = d₀ - · subst hd - simp only [MvPolynomial.coeff_monomial, ↓reduceIte] - · rw [MvPolynomial.coeff_monomial, if_neg (Ne.symm hd)] - exact hp.coeff_eq_zero d (fun h => hd (huniq d h)) + · simp [hd] + rw [if_neg (Ne.symm hd)] + exact hp.coeff_eq_zero d (fun h => hd (huniq d h)) private lemma unique_small_weight_soln {a₁ b₁ a₂ b₂ : ℕ} (ha₁ : a₁ < 3) (ha₂ : a₂ < 3) @@ -470,22 +449,16 @@ private lemma unique_small_weight_soln {a₁ b₁ a₂ b₂ : ℕ} private lemma monomial_fin2_eq (d : Fin 2 →₀ ℕ) (c : ℂ) : MvPolynomial.monomial d c = MvPolynomial.C c * MvPolynomial.X 0 ^ d 0 * MvPolynomial.X 1 ^ d 1 := by - rw [MvPolynomial.monomial_eq, mul_assoc] - congr 1 - rw [Finsupp.prod, Finset.prod_subset (fun _ _ => Finset.mem_univ _) (fun i _ hi => by - have hdi : d i = 0 := by rwa [Finsupp.mem_support_iff, not_not] at hi - rw [hdi, pow_zero])] - simp only [Fin.prod_univ_two] + rw [MvPolynomial.monomial_eq, mul_assoc, d.prod_fintype _ fun _ => pow_zero _] + simp [Fin.prod_univ_two] private lemma evalE₄E₆_mono_grade (a b : ℕ) (k : ℤ) (hk : k ≠ (↑a * 4 + ↑b * 6 : ℤ)) : (evalE₄E₆ (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b)) k = 0 := by rw [evalE₄E₆_monomial, DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of] - refine DirectSum.of_eq_of_ne _ _ _ ?_ - intro heq - apply hk + refine DirectSum.of_eq_of_ne _ _ _ fun heq => hk ?_ simp only [Int.nsmul_eq_mul] at heq - linarith + omega private lemma evalE₄E₆_monomial_grade (d : Fin 2 →₀ ℕ) (c : ℂ) (k : ℤ) (hk : k ≠ (↑(d 0) * 4 + ↑(d 1) * 6 : ℤ)) : @@ -502,18 +475,13 @@ private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) show (∑ x ∈ p.support, evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k = ∑ x ∈ p.support, (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k from map_sum (DFinsupp.evalAddMonoidHom k) _ _] - apply Finset.sum_eq_zero - intro d hd - apply evalE₄E₆_monomial_grade - intro heq - apply hk - have hwd : Finsupp.weight E₄E₆Weight d = n := hp (MvPolynomial.mem_support_iff.mp hd) - rw [heq, ← weight_fin2_cast d, hwd] + refine Finset.sum_eq_zero fun d hd => evalE₄E₆_monomial_grade _ _ _ fun heq => hk ?_ + rw [heq, ← weight_fin2_cast d, hp (MvPolynomial.mem_support_iff.mp hd)] private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : evalE₄E₆ p = DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) ((evalE₄E₆ p) ↑n) := by - refine DFinsupp.ext (fun k : ℤ => ?_) + refine DFinsupp.ext fun k : ℤ => ?_ by_cases hk : k = (↑n : ℤ) · subst hk simp @@ -524,8 +492,7 @@ private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) (evalE₄E₆ p) (↑n : ℤ) := by set q := p - MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p with hq_def have hdecomp : p = MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p + q := by - rw [hq_def] - ring + simp [q] conv_rhs => rw [hdecomp, map_add] rw [show (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p) + evalE₄E₆ q) (↑n : ℤ) = @@ -538,11 +505,8 @@ private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) ∑ x ∈ q.support, (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x q))) (↑n : ℤ) from map_sum (DFinsupp.evalAddMonoidHom (↑n : ℤ)) _ _] - apply Finset.sum_eq_zero - intro d hd - apply evalE₄E₆_monomial_grade - intro heq - apply MvPolynomial.mem_support_iff.mp hd + refine Finset.sum_eq_zero fun d hd => + evalE₄E₆_monomial_grade _ _ _ fun heq => MvPolynomial.mem_support_iff.mp hd ?_ rw [hq_def, MvPolynomial.coeff_sub, MvPolynomial.coeff_weightedHomogeneousComponent, if_pos ?_, sub_self] rw [weight_eq_4a_6b] @@ -559,27 +523,18 @@ private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 private lemma discriminantPoly_isWeightedHomogeneous : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight discriminantPoly 12 := by - unfold discriminantPoly - simp only [MvPolynomial.smul_eq_C_mul] + rw [discriminantPoly, MvPolynomial.smul_eq_C_mul] intro d hd simp only [MvPolynomial.coeff_C_mul, MvPolynomial.coeff_sub] at hd by_cases hd3 : MvPolynomial.coeff d (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) ≠ 0 · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (0 : Fin 2)).pow 3) hd3 - · push Not at hd3 - by_cases hd6 : MvPolynomial.coeff d - (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 - · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow 2) hd6 - · push Not at hd6 - simp only [hd3, hd6, sub_self, mul_zero, ne_eq, not_true] at hd - -/-- `evalE₄E₆ discriminantPoly = DirectSum.of _ 12 Δ`. -/ -private lemma evalE₄E₆_discriminantPoly : - evalE₄E₆ discriminantPoly = - DirectSum.of (ModularForm 𝒮ℒ) 12 - ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := by - rw [discriminantPoly, map_smul, map_sub, map_pow, map_pow, evalE₄E₆_X0, evalE₄E₆_X1, - ← discriminant_eq_E₄_cube_sub_E₆_sq_graded] + push Not at hd3 + by_cases hd6 : MvPolynomial.coeff d + (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 + · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow 2) hd6 + push Not at hd6 + simp [hd3, hd6] at hd /-- The 0th q-expansion coefficient of a `Δ_poly * s` term in the graded ring vanishes. -/ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 ≤ n) @@ -592,23 +547,12 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 rw [DirectSum.of_apply, dif_pos hcast] set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) - have hcoe : ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ) = - ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ) := by - ext z - have helper : ∀ {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ), - (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by - intros - subst_vars - rfl - exact helper hcast _ z - rw [show - (qExpansion 1 ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ)).coeff 0 = - (qExpansion 1 ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ)).coeff 0 by - rw [hcoe], ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, - PowerSeries.coeff_mul] - have hΔ_coeff : (qExpansion 1 (f : ℍ → ℂ)).coeff 0 = 0 := - (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩ - simp [Finset.antidiagonal_zero, hΔ_coeff] + rw [show ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ) = + ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ) from + funext fun z => cast_modularForm_apply hcast _ z, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, PowerSeries.coeff_mul] + simp [Finset.antidiagonal_zero, + (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩] private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) @@ -622,8 +566,7 @@ private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial ( rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply] at heval rcases smul_eq_zero.mp heval with hc | hmz - · rw [show MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) = - MvPolynomial.monomial d₀ 0 from by rw [hc], MvPolynomial.monomial_zero] + · rw [hc, MvPolynomial.monomial_zero] · exact absurd hmz hmf_ne private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn : n < 12) @@ -652,22 +595,21 @@ private lemma per_weight_injective_zero (heval : (evalE₄E₆ p) (0 : ℤ) = 0) : p = 0 := by have hpc : p = MvPolynomial.C (MvPolynomial.coeff 0 p) := by ext d' - simp only [MvPolynomial.coeff_C] + rw [MvPolynomial.coeff_C] by_cases hd' : 0 = d' · simp [hd'] - · rw [if_neg hd'] - exact hp.coeff_eq_zero d' (fun hw => hd' (by - have h46' := weight_eq_4a_6b d' - rw [hw] at h46' - symm - ext i - fin_cases i <;> simp [Finsupp.coe_zero] <;> omega)) + rw [if_neg hd'] + exact hp.coeff_eq_zero d' (fun hw => hd' (by + have h46' := weight_eq_4a_6b d' + rw [hw] at h46' + symm + ext i + fin_cases i <;> simp [Finsupp.coe_zero] <;> omega)) rw [hpc] at heval ⊢ - rw [evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, DirectSum.smul_apply] at heval - have h1eq : (1 : DirectSum ℤ (ModularForm 𝒮ℒ)) (0 : ℤ) = (1 : ModularForm 𝒮ℒ 0) := by - conv_lhs => rw [← DirectSum.of_zero_one (ModularForm 𝒮ℒ)] - exact DirectSum.of_eq_same _ _ - rw [h1eq] at heval + rw [evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, DirectSum.smul_apply, + show (1 : DirectSum ℤ (ModularForm 𝒮ℒ)) (0 : ℤ) = (1 : ModularForm 𝒮ℒ 0) from by + conv_lhs => rw [← DirectSum.of_zero_one (ModularForm 𝒮ℒ)] + exact DirectSum.of_eq_same _ _] at heval rcases smul_eq_zero.mp heval with hc | h1z · rw [hc, map_zero] · exact absurd h1z one_ne_zero_modularForm @@ -707,45 +649,24 @@ private lemma discriminantPoly_piece_eq_monomial_sub Finsupp.single (1 : Fin 2) (d 1) := by ext i fin_cases i <;> simp [Finsupp.add_apply] - rw [show MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) = - MvPolynomial.C c * - (MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2) * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * - MvPolynomial.X (1 : Fin 2) ^ (d 1)) by - rw [h1728] + rw [h1728, show MvPolynomial.C c * ((MvPolynomial.X (0 : Fin 2) ^ 3 - + MvPolynomial.X (1 : Fin 2) ^ 2) * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) = + MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ d 0 * MvPolynomial.X (1 : Fin 2) ^ d 1) - + MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * + MvPolynomial.X (1 : Fin 2) ^ (d 1 + 2)) by + rw [show (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ d 0 = + MvPolynomial.X (0 : Fin 2) ^ 3 * MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) from by + rw [← pow_add, show 3 + (d 0 - 3) = d 0 from by omega], + show (MvPolynomial.X (1 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ (d 1 + 2) = + MvPolynomial.X (1 : Fin 2) ^ d 1 * MvPolynomial.X (1 : Fin 2) ^ 2 from by rw [pow_add]] ring] - have h3 : (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = - MvPolynomial.X (0 : Fin 2) ^ d 0 * MvPolynomial.X (1 : Fin 2) ^ d 1 := by - rw [show (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ 3 * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) - = (MvPolynomial.X (0 : Fin 2) ^ 3 * MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3)) * - MvPolynomial.X (1 : Fin 2) ^ d 1 from by ring, - ← pow_add, show 3 + (d 0 - 3) = d 0 from by omega] - have h2 : (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = - MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1 + 2) := by - rw [show (MvPolynomial.X (1 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ 2 * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) - = MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * - (MvPolynomial.X (1 : Fin 2) ^ d 1 * MvPolynomial.X (1 : Fin 2) ^ 2) from by ring, - ← pow_add] - rw [show MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ 3 - - MvPolynomial.X (1 : Fin 2) ^ 2) * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) = - MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ 3 * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) - - MvPolynomial.C c * (MvPolynomial.X (1 : Fin 2) ^ 2 * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * - MvPolynomial.X (1 : Fin 2) ^ d 1)) from by ring, - h3, h2] congr 1 · rw [MvPolynomial.X_pow_eq_monomial, MvPolynomial.X_pow_eq_monomial, MvPolynomial.monomial_mul, one_mul, MvPolynomial.C_mul_monomial, mul_one] exact congrArg (· c) (congrArg MvPolynomial.monomial hd_fin.symm) - · rw [MvPolynomial.X_pow_eq_monomial, MvPolynomial.X_pow_eq_monomial, - MvPolynomial.monomial_mul, one_mul, MvPolynomial.C_mul_monomial, mul_one] + rw [MvPolynomial.X_pow_eq_monomial, MvPolynomial.X_pow_eq_monomial, + MvPolynomial.monomial_mul, one_mul, MvPolynomial.C_mul_monomial, mul_one] private lemma sum_lt_sum_of_replace {α : Type*} [DecidableEq α] (S S' : Finset α) (f : α → ℕ) (d d' : α) @@ -777,28 +698,25 @@ private lemma mvpoly_support_after_reduction {σ R : Type*} [CommRing R] [Decida (hdd' : d ≠ d') (hc : MvPolynomial.coeff d p = c) : let δ := MvPolynomial.monomial d c - MvPolynomial.monomial d' c d ∉ (p - δ).support ∧ (p - δ).support ⊆ p.support.erase d ∪ {d'} := by - have hcoeff_d : MvPolynomial.coeff d - (p - (MvPolynomial.monomial d c - MvPolynomial.monomial d' c)) = 0 := by - rw [MvPolynomial.coeff_sub, MvPolynomial.coeff_sub, + have hd_not : d ∉ (p - (MvPolynomial.monomial d c - + MvPolynomial.monomial d' c)).support := by + rw [MvPolynomial.notMem_support_iff, MvPolynomial.coeff_sub, MvPolynomial.coeff_sub, MvPolynomial.coeff_monomial, MvPolynomial.coeff_monomial, if_pos rfl, if_neg hdd'.symm, sub_zero, hc, sub_self] - have hd_not : d ∉ (p - (MvPolynomial.monomial d c - - MvPolynomial.monomial d' c)).support := - MvPolynomial.notMem_support_iff.mpr hcoeff_d refine ⟨hd_not, fun x hx => ?_⟩ rcases Finset.mem_union.mp (MvPolynomial.support_sub σ p _ hx) with hp | hdelta · by_cases hxd : x = d · exact absurd (hxd ▸ hx) hd_not - · exact Finset.mem_union_left _ (Finset.mem_erase.mpr ⟨hxd, hp⟩) - · rcases Finset.mem_union.mp (MvPolynomial.support_sub σ _ _ hdelta) with h1 | h2 - · rw [MvPolynomial.support_monomial] at h1 - split_ifs at h1 - · exact absurd h1 (Finset.notMem_empty _) - · exact absurd ((Finset.mem_singleton.mp h1) ▸ hx) hd_not - · rw [MvPolynomial.support_monomial] at h2 - split_ifs at h2 - · exact absurd h2 (Finset.notMem_empty _) - · exact Finset.mem_union_right _ (by rwa [Finset.mem_singleton] at h2 ⊢) + exact Finset.mem_union_left _ (Finset.mem_erase.mpr ⟨hxd, hp⟩) + rcases Finset.mem_union.mp (MvPolynomial.support_sub σ _ _ hdelta) with h1 | h2 + · rw [MvPolynomial.support_monomial] at h1 + split_ifs at h1 + · exact absurd h1 (Finset.notMem_empty _) + exact absurd ((Finset.mem_singleton.mp h1) ▸ hx) hd_not + rw [MvPolynomial.support_monomial] at h2 + split_ifs at h2 + · exact absurd h2 (Finset.notMem_empty _) + exact Finset.mem_union_right _ (by rwa [Finset.mem_singleton] at h2 ⊢) /-- Polynomial decomposition: any weighted-homogeneous polynomial `p` of weight `n ≥ 12` can be written as `r + Δ_poly * s` where `r` is weighted-homogeneous of weight `n` whose monomials @@ -829,17 +747,15 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) push Not at hall obtain ⟨d, hd_mem, hd_ge⟩ := hall have hwd : d 0 * 4 + d 1 * 6 = n := by - have := hp (MvPolynomial.mem_support_iff.mp hd_mem) - have := weight_eq_4a_6b d + have := (weight_eq_4a_6b d).symm.trans <| hp <| MvPolynomial.mem_support_iff.mp hd_mem omega set c := MvPolynomial.coeff d p set δ_piece := MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) set p' := p - δ_piece with hp'_def - have hp_eq : p = p' + δ_piece := by simp only [p', sub_add_cancel] - have hp'_wh : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p' n := by - rw [hp'_def] - exact (MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n _).mp + have hp_eq : p = p' + δ_piece := by simp [p'] + have hp'_wh : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p' n := + (MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n _).mp (Submodule.sub_mem _ ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n p).mpr hp) ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n @@ -852,8 +768,7 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) have hM_lt : ∑ d' ∈ p'.support, d' 0 < ∑ d' ∈ p.support, d' 0 := by set d' := Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2) with hd'_def - have hdd' : d ≠ d' := by - intro heq + have hdd' : d ≠ d' := fun heq => by have h0 := Finsupp.ext_iff.mp heq (0 : Fin 2) simp only [Fin.isValue, hd'_def, Finsupp.add_apply, Finsupp.single_eq_same, ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 @@ -886,14 +801,13 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) have hwd₀ := hr (MvPolynomial.mem_support_iff.mp hd₀) have hr_mono : r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by ext d + rw [MvPolynomial.coeff_monomial] by_cases hd : d = d₀ - · subst hd - simp only [MvPolynomial.coeff_monomial, ↓reduceIte] - rw [MvPolynomial.coeff_monomial, if_neg (Ne.symm hd)] + · simp [hd] + rw [if_neg (Ne.symm hd)] by_cases hd_supp : d ∈ r.support · have h1 := weight_eq_4a_6b d - have h_wd := hr (MvPolynomial.mem_support_iff.mp hd_supp) - rw [h_wd] at h1 + rw [hr (MvPolynomial.mem_support_iff.mp hd_supp)] at h1 have h2 := weight_eq_4a_6b d₀ rw [hwd₀] at h2 obtain ⟨ha, hb⟩ := unique_small_weight_soln (hr_red d hd_supp) (hr_red d₀ hd₀) @@ -904,8 +818,7 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) suffices hc : c = 0 by rw [hr_mono, hc, MvPolynomial.monomial_zero] rw [hr_mono, map_add] at heval have hd₀_weight : 4 * d₀ 0 + 6 * d₀ 1 = n := by - have := weight_eq_4a_6b d₀ - rw [hwd₀] at this + have := (weight_eq_4a_6b d₀).symm.trans hwd₀ omega set Q := ModularForm.qExpansionAddHom (h := 1) one_pos one_mem_strictPeriods_SL (↑n : ℤ) have hQ_zero : Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + @@ -918,8 +831,7 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) rw [map_add] at hQ_zero have h_coeff_sum : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 + (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by - have := congr_arg (fun (p : PowerSeries ℂ) => p.coeff 0) hQ_zero - simpa using this + simpa using congr_arg (fun (p : PowerSeries ℂ) => p.coeff 0) hQ_zero have h_Δ_term : (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := evalE₄E₆_discriminantPoly_mul_coeff_zero hn12 s hs rw [h_Δ_term, add_zero] at h_coeff_sum @@ -949,25 +861,10 @@ private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) evalE₄E₆_whc_eq_single (n - 12) s hs, DirectSum.of_mul_of] at hds have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega rw [DirectSum.of_apply, dif_pos hcast] at hds - set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) - set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) - have helper : ∀ {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ), - (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by - intros - subst_vars - rfl ext z - simp only [ModularForm.zero_apply] have hpw := DFunLike.congr_fun hds z - simp only [ModularForm.zero_apply] at hpw - rw [helper hcast _ z] at hpw - have hpw' : f z * g z = 0 := by - have heq : (GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ (12 + ↑(n - 12))) z = f z * g z := rfl - rw [← heq] - exact hpw - rcases mul_eq_zero.mp hpw' with hf0 | hg0 - · exact absurd hf0 (discriminant_ne_zero z) - · exact hg0 + simp only [ModularForm.zero_apply, cast_modularForm_apply hcast] at hpw ⊢ + exact (mul_eq_zero.mp hpw).resolve_left (discriminant_ne_zero z) private lemma per_weight_injective_inductive_step (n : ℕ) (ih : ∀ m < n, ∀ (p : MvPolynomial (Fin 2) ℂ), @@ -980,9 +877,8 @@ private lemma per_weight_injective_inductive_step (n : ℕ) obtain ⟨r, s, hr_wh, hs_wh, hp_eq, hr_red⟩ := whomog_poly_Delta_decomp hn12 p hp have hr0 : r = 0 := reduced_part_eq_zero hn12 r s hr_wh hs_wh hr_red (hp_eq ▸ heval) rw [hp_eq, hr0, zero_add] at heval ⊢ - have hs0 : s = 0 := ih (n - 12) (by omega) s hs_wh - (eval_discriminantPoly_mul_zero_imp hn12 s hs_wh heval) - rw [hs0, mul_zero] + rw [ih (n - 12) (by omega) s hs_wh + (eval_discriminantPoly_mul_zero_imp hn12 s hs_wh heval), mul_zero] private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ), MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n → @@ -991,7 +887,7 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ induction n using Nat.strong_induction_on with | _ n ih => ?_ intro p hp heval by_cases hk_odd : Odd n - · exact whomog_eq_zero_of_no_monomials p hp (fun d => no_wt_monomial_of_odd hk_odd d) + · exact whomog_eq_zero_of_no_monomials p hp (no_wt_monomial_of_odd hk_odd) rw [Nat.not_odd_iff_even] at hk_odd by_cases hn4 : n < 4 · have hn02 : n = 0 ∨ n = 2 := by @@ -999,7 +895,7 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ omega rcases hn02 with rfl | rfl · exact per_weight_injective_zero p hp heval - · exact whomog_eq_zero_of_no_monomials p hp (fun d => no_wt_monomial_of_two d) + · exact whomog_eq_zero_of_no_monomials p hp no_wt_monomial_of_two push Not at hn4 by_cases hn12 : n < 12 · have hn_cases : n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by @@ -1017,16 +913,10 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ independent. -/ theorem evalE₄E₆_injective : Function.Injective evalE₄E₆ := by intro p q hpq - rw [← sub_eq_zero] - set r := p - q with hr_def - have hr : evalE₄E₆ r = 0 := by - rw [hr_def, map_sub, sub_eq_zero] - exact hpq - rw [← MvPolynomial.sum_weightedHomogeneousComponent (E₄E₆Weight) r] - refine finsum_eq_zero_of_forall_eq_zero (fun n => ?_) - refine per_weight_injective n _ + rw [← sub_eq_zero, ← MvPolynomial.sum_weightedHomogeneousComponent (E₄E₆Weight) (p - q)] + refine finsum_eq_zero_of_forall_eq_zero fun n => per_weight_injective n _ (MvPolynomial.weightedHomogeneousComponent_isWeightedHomogeneous _ _) ?_ - rw [evalE₄E₆_component_eq, hr] + rw [evalE₄E₆_component_eq, map_sub, hpq, sub_self] rfl /-- The graded ring of level-1 modular forms is isomorphic to the polynomial ring @@ -1043,9 +933,7 @@ theorem E₄E₆_generate : rw [show ({DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, DirectSum.of (ModularForm 𝒮ℒ) 6 E₆} : Set _) = Set.range (![DirectSum.of _ 4 E₄, DirectSum.of _ 6 E₆] : Fin 2 → _) from (Matrix.range_cons_cons_empty _ _ _).symm, - Algebra.adjoin_range_eq_range_aeval, - show MvPolynomial.aeval (![DirectSum.of _ 4 E₄, DirectSum.of _ 6 E₆] : Fin 2 → _) = - evalE₄E₆ from rfl] + Algebra.adjoin_range_eq_range_aeval] exact (AlgHom.range_eq_top evalE₄E₆).mpr evalE₄E₆_surjective end ModularForm From 6b2081768a1bede9b04ab3cb9764fc01005bbff0 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 06:49:43 +0100 Subject: [PATCH 42/61] chore(NumberTheory/ModularForms): strip docstrings from private helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the cleanup convention, docstrings should only appear on key public declarations. Remove docstrings from all private helpers introduced by this PR (and trim the multi-paragraph section divider at the start of the generators section to a single line). Public declarations that retain a one-sentence docstring: * `E₄E₆Weight`, `evalE₄E₆` * `evalE₄E₆_surjective`, `evalE₄E₆_injective` * `modularFormsEquivMvPolynomial`, `E₄E₆_generate` * (plus the discriminant identity theorems from PR #38806). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 33 +------------------ 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 050b3433c90a6a..fcc90f9158277d 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -114,12 +114,7 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) grind [discriminant_eq_E₄_cube_sub_E₆_sq z] -/-! ### Generators of the graded ring - -The remainder of this file establishes that `E₄, E₆` generate the graded ring of level-1 -modular forms freely as an `ℂ`-algebra: the evaluation homomorphism `evalE₄E₆` is an -isomorphism. The proofs are ported from - (`Modularforms/Generators/`). -/ +/-! ### Generators of the graded ring -/ /-- Weight function assigning weight 4 to E₄ (variable 0) and weight 6 to E₆ (variable 1). -/ def E₄E₆Weight : Fin 2 → ℕ := ![4, 6] @@ -142,14 +137,12 @@ lemma evalE₄E₆_C (c : ℂ) : evalE₄E₆ (MvPolynomial.C c) = algebraMap ℂ (DirectSum ℤ (ModularForm 𝒮ℒ)) c := MvPolynomial.aeval_C _ c -/-- `evalE₄E₆` maps the monomial `X₀^a * X₁^b` to `(of _ 4 E₄)^a * (of _ 6 E₆)^b`. -/ lemma evalE₄E₆_monomial (a b : ℕ) : evalE₄E₆ (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b) = DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by simp [map_mul, map_pow] -/-- For even `k ≥ 4`, there exist `a, b ∈ ℕ` with `4a + 6b = k`. -/ private lemma exists_monomial_weight {k : ℕ} (hk : 4 ≤ k) (hkeven : Even k) : ∃ a b : ℕ, 4 * a + 6 * b = k := by obtain ⟨m, rfl⟩ := hkeven @@ -158,8 +151,6 @@ private lemma exists_monomial_weight {k : ℕ} (hk : 4 ≤ k) (hkeven : Even k) /-! ### Surjectivity of `evalE₄E₆` -/ -/-- In a 1-dimensional weight space, if `g ≠ 0` is in the image of `evalE₄E₆`, -then every element of that weight is in the image. -/ private lemma surj_of_rank_one {k : ℤ} (hrank : Module.rank ℂ (ModularForm 𝒮ℒ k) = 1) {g : ModularForm 𝒮ℒ k} (hg : g ≠ 0) (p : MvPolynomial (Fin 2) ℂ) (hp : evalE₄E₆ p = DirectSum.of _ k g) @@ -171,7 +162,6 @@ private lemma surj_of_rank_one {k : ℤ} rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, ← DirectSum.of_smul]⟩ -/-- The product `f * g` of two modular forms with constant-term-1 q-expansions is nonzero. -/ private lemma mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one {k₁ k₂ : ℤ} (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) (hf : (qExpansion 1 f).coeff 0 = 1) (hg : (qExpansion 1 g).coeff 0 = 1) : @@ -184,7 +174,6 @@ private lemma mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one {k₁ k₂ PowerSeries.coeff_mul] at this simp [hf, hg] at this -/-- Weight casting: rewriting the index of `DirectSum.of` along an equality of weights. -/ private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by subst hk @@ -195,8 +184,6 @@ private lemma cast_modularForm_apply {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : subst heq rfl -/-- The 0th q-expansion coefficient of `(of _ 4 E₄)^a * (of _ 6 E₆)^b` evaluated at -weight `n = 4a + 6b` equals `1`. -/ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + 6 * b = n) : (qExpansion 1 ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * @@ -227,8 +214,6 @@ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + simp [Finset.antidiagonal_zero, PowerSeries.coeff_pow, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] -/-- For weight 12 ≤ n, every cusp form of weight n is `Δ * h` for some modular form -`h` of weight `n - 12`. Lifted to the graded ring. -/ private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ ↑n) (hg : ModularForm.IsCuspForm g) : DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) g = @@ -254,12 +239,9 @@ private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ change g z / ModularForm.discriminant z * ModularForm.discriminant z = g z exact div_mul_cancel₀ _ (discriminant_ne_zero z) -/-- The polynomial `Δ_poly = (1/1728) (X₀³ - X₁²)`, which `evalE₄E₆` sends to `Δ` in the -graded ring of level-1 modular forms. -/ private noncomputable def discriminantPoly : MvPolynomial (Fin 2) ℂ := (1 / 1728 : ℂ) • (MvPolynomial.X 0 ^ 3 - MvPolynomial.X 1 ^ 2) -/-- `evalE₄E₆ discriminantPoly = DirectSum.of _ 12 Δ`. -/ private lemma evalE₄E₆_discriminantPoly : evalE₄E₆ discriminantPoly = DirectSum.of (ModularForm 𝒮ℒ) 12 @@ -267,15 +249,11 @@ private lemma evalE₄E₆_discriminantPoly : rw [discriminantPoly, map_smul, map_sub, map_pow, map_pow, evalE₄E₆_X0, evalE₄E₆_X1, ← discriminant_eq_E₄_cube_sub_E₆_sq_graded] -/-- The discriminant `Δ`, viewed as a modular form of weight 12, lies in the range of -`evalE₄E₆`. -/ private lemma discriminant_mem_range_evalE₄E₆ : DirectSum.of (ModularForm 𝒮ℒ) 12 ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ Set.range evalE₄E₆ := ⟨discriminantPoly, evalE₄E₆_discriminantPoly⟩ -/-- Inductive step: for `n ≥ 12` even, surjectivity at weight `n` follows from surjectivity -at all lower weights via the cusp-form / `Δ` decomposition. -/ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Even (n : ℤ)) (ih : ∀ m < n, ∀ (f : ModularForm 𝒮ℒ ↑m), DirectSum.of _ (↑m : ℤ) f ∈ Set.range evalE₄E₆) @@ -333,7 +311,6 @@ private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := fun one_ne_zero (α := ℂ) (congr_fun (congr_arg (DFunLike.coe (F := ModularForm 𝒮ℒ 0)) h) UpperHalfPlane.I) -/-- For each weight `k`, every element of weight `k` lies in the range of `evalE₄E₆`. -/ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), DirectSum.of (ModularForm 𝒮ℒ) k f ∈ Set.range evalE₄E₆ := by intro k f @@ -467,7 +444,6 @@ private lemma evalE₄E₆_monomial_grade (d : Fin 2 →₀ ℕ) (c : ℂ) (k : smul_mul_assoc, one_mul, DirectSum.smul_apply, evalE₄E₆_mono_grade (d 0) (d 1) k hk, smul_zero] -/-- A weighted-homogeneous polynomial of weight `n` evaluates (at any other weight) to `0`. -/ private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (k : ℤ) (hk : k ≠ ↑n) : (evalE₄E₆ p) k = 0 := by @@ -536,7 +512,6 @@ private lemma discriminantPoly_isWeightedHomogeneous : push Not at hd6 simp [hd3, hd6] at hd -/-- The 0th q-expansion coefficient of a `Δ_poly * s` term in the graded ring vanishes. -/ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) : @@ -718,9 +693,6 @@ private lemma mvpoly_support_after_reduction {σ R : Type*} [CommRing R] [Decida · exact absurd h2 (Finset.notMem_empty _) exact Finset.mem_union_right _ (by rwa [Finset.mem_singleton] at h2 ⊢) -/-- Polynomial decomposition: any weighted-homogeneous polynomial `p` of weight `n ≥ 12` can -be written as `r + Δ_poly * s` where `r` is weighted-homogeneous of weight `n` whose monomials -all have `X₀`-degree `< 3`. -/ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : @@ -787,7 +759,6 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) rw [hp_eq, hδ_eq, hp'_eq, mul_add] ring -/-- If `eval (r + Δ_poly * s) ↑n = 0` and `r` is reduced, then `r = 0`. -/ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (r s : MvPolynomial (Fin 2) ℂ) (hr : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n) @@ -850,8 +821,6 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) rw [h_mono_term] at h_coeff_sum exact h_coeff_sum -/-- If `eval (Δ_poly * s) ↑n = 0` (with `s` weighted-homog of weight `n - 12`), -then `eval s ↑(n - 12) = 0`. -/ private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) From d1f58fc1c73ff2d748ce3ab446ea60e17d157a58 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:08:04 +0100 Subject: [PATCH 43/61] chore(NumberTheory/ModularForms): address PR review comments (round 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove all section divider headers in the new content (per review). * Inline `finsupp_of_fin2` (it was a one-liner used once). * Replace `mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one` with the cleaner `mul_ne_zero` that takes `f ≠ 0` and `g ≠ 0` directly, using `qExpansion_eq_zero_iff` and the integral domain structure of `PowerSeries ℂ`. * Extract `sub_smul_qExpansion_coeff_zero_isCuspForm` and `directSumOf_evalE₄E₆_monomial_apply` as separate helpers, breaking down the `surj_at_weight_inductive` proof. * Drop the redundant explicit `d'` parameter from `discriminantPoly_piece_eq_monomial_sub` and rewrite the proof to use `monomial_fin2_eq` and `ring`, removing ~25 lines of manual algebra. Build clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 138 ++++++++---------- 1 file changed, 60 insertions(+), 78 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index fcc90f9158277d..57f281aa9eb4c8 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -114,8 +114,6 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) grind [discriminant_eq_E₄_cube_sub_E₆_sq z] -/-! ### Generators of the graded ring -/ - /-- Weight function assigning weight 4 to E₄ (variable 0) and weight 6 to E₆ (variable 1). -/ def E₄E₆Weight : Fin 2 → ℕ := ![4, 6] @@ -149,8 +147,6 @@ private lemma exists_monomial_weight {k : ℕ} (hk : 4 ≤ k) (hkeven : Even k) rcases Nat.even_or_odd m with ⟨n, hn⟩ | ⟨n, hn⟩ exacts [⟨n, 0, by omega⟩, ⟨n - 1, 1, by omega⟩] -/-! ### Surjectivity of `evalE₄E₆` -/ - private lemma surj_of_rank_one {k : ℤ} (hrank : Module.rank ℂ (ModularForm 𝒮ℒ k) = 1) {g : ModularForm 𝒮ℒ k} (hg : g ≠ 0) (p : MvPolynomial (Fin 2) ℂ) (hp : evalE₄E₆ p = DirectSum.of _ k g) @@ -162,17 +158,12 @@ private lemma surj_of_rank_one {k : ℤ} rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, ← DirectSum.of_smul]⟩ -private lemma mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one {k₁ k₂ : ℤ} - (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) - (hf : (qExpansion 1 f).coeff 0 = 1) (hg : (qExpansion 1 g).coeff 0 = 1) : - f.mul g ≠ 0 := by - intro h - have : (qExpansion 1 (f.mul g)).coeff 0 = 0 := by - rw [show (f.mul g : ModularForm 𝒮ℒ (k₁ + k₂)) = 0 from h] - simp [UpperHalfPlane.qExpansion_zero] - rw [ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, - PowerSeries.coeff_mul] at this - simp [hf, hg] at this +private lemma mul_ne_zero {k₁ k₂ : ℤ} (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) + (hf : f ≠ 0) (hg : g ≠ 0) : f.mul g ≠ 0 := by + rw [Ne, ← ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL, + ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL, mul_eq_zero, not_or] + exact ⟨(ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hf, + (ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hg⟩ private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by @@ -254,6 +245,32 @@ private lemma discriminant_mem_range_evalE₄E₆ : ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ Set.range evalE₄E₆ := ⟨discriminantPoly, evalE₄E₆_discriminantPoly⟩ +private lemma sub_smul_qExpansion_coeff_zero_isCuspForm {k : ℤ} (f g : ModularForm 𝒮ℒ k) + (hg : (qExpansion 1 g).coeff 0 = 1) : + ModularForm.IsCuspForm (f - (qExpansion 1 f).coeff 0 • g) := by + set c := (qExpansion 1 f).coeff 0 + rw [ModularForm.isCuspForm_iff_coeffZero_eq_zero, + show qExpansion 1 ⇑(f - c • g : ModularForm 𝒮ℒ k) = + qExpansion 1 ⇑f - qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) from + (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL k).map_sub f (c • g), + show qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) = c • qExpansion 1 ⇑g from + ModularFormClass.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := k) + one_pos one_mem_strictPeriods_SL c g, + map_sub, PowerSeries.coeff_smul] + simp [hg, c] + +private lemma directSumOf_evalE₄E₆_monomial_apply {a b n : ℕ} (hab : 4 * a + 6 * b = n) : + DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) + ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (↑n : ℤ)) = + DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by + rw [DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of, + show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) by + simp only [Int.nsmul_eq_mul] + push_cast [← hab] + ring, + DirectSum.of_eq_same] + private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Even (n : ℤ)) (ih : ∀ m < n, ∀ (f : ModularForm 𝒮ℒ ↑m), DirectSum.of _ (↑m : ℤ) f ∈ Set.range evalE₄E₆) @@ -264,18 +281,8 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev set mo := DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b set mn := mo (↑n : ℤ) set c := (qExpansion 1 f).coeff 0 - have hmn_coeff : (qExpansion 1 mn).coeff 0 = 1 := monomial_qExpansion_coeff_zero_eq_one hab - have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := by - rw [ModularForm.isCuspForm_iff_coeffZero_eq_zero, - show qExpansion 1 ⇑(f - c • mn : ModularForm 𝒮ℒ ↑n) = - qExpansion 1 ⇑f - qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) from - (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL (↑n : ℤ)).map_sub - f (c • mn), - show qExpansion 1 ⇑(c • mn : ModularForm 𝒮ℒ ↑n) = c • qExpansion 1 ⇑mn from - ModularFormClass.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := (↑n : ℤ)) - one_pos one_mem_strictPeriods_SL c mn, - map_sub, PowerSeries.coeff_smul] - simp [hmn_coeff, c] + have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := + sub_smul_qExpansion_coeff_zero_isCuspForm f mn (monomial_qExpansion_coeff_zero_eq_one hab) have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by omega set h' := CuspForm.discriminantEquiv (ModularForm.toCuspForm (f - c • mn) @@ -283,18 +290,11 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev obtain ⟨p1, hp1⟩ : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by rw [directSumOf_cast_eq hcast] exact ih (n - 12) (by omega) (hcast ▸ h') - have hmn_eq : DirectSum.of _ (↑n : ℤ) mn = mo := by - simp only [mn, mo, DirectSum.ofPow, DirectSum.of_mul_of] - rw [show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) by - simp only [Int.nsmul_eq_mul] - push_cast [← hab] - ring, - DirectSum.of_eq_same] rw [show DirectSum.of _ (↑n : ℤ) f = DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn by rw [← DirectSum.of_smul, ← map_add] congr 1 - abel, hmn_eq] + abel, directSumOf_evalE₄E₆_monomial_apply hab] exact ⟨p1 * discriminantPoly + MvPolynomial.C c * (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b), by rw [map_add, map_mul, hp1, evalE₄E₆_discriminantPoly, cuspForm_eq_discriminant_mul (f - c • mn) hg_cusp, map_mul, @@ -345,16 +345,14 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), (show E₆ ≠ 0 from E_ne_zero (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f · exact absurd hk_odd (by decide) · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) - (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₄ - (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨2, rfl⟩)) + (mul_ne_zero E₄ E₄ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) (MvPolynomial.X 0 ^ 2) ?_ f rw [map_pow, evalE₄E₆_X0, pow_two, DirectSum.of_mul_of] apply DirectSum.of_eq_of_gradedMonoid_eq exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 4 : ℤ) = 8 by norm_num).symm rfl · exact absurd hk_odd (by decide) · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) - (mul_modularForm_ne_zero_of_qExpansion_coeff_zero_eq_one E₄ E₆ - (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨3, rfl⟩)) + (mul_ne_zero E₄ E₆ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) (MvPolynomial.X 0 * MvPolynomial.X 1) ?_ f rw [map_mul, evalE₄E₆_X0, evalE₄E₆_X1, DirectSum.of_mul_of] apply DirectSum.of_eq_of_gradedMonoid_eq @@ -371,8 +369,6 @@ theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by ← AlgHom.mem_range] exact Subalgebra.sum_mem _ fun k _ => surj_of_weight k (x k) -/-! ### Injectivity of `evalE₄E₆` -/ - private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d = d 0 * 4 + d 1 * 6 := by rw [Finsupp.weight_apply, @@ -385,9 +381,6 @@ private lemma weight_fin2_cast (d : Fin 2 →₀ ℕ) : push_cast ring -private lemma finsupp_of_fin2 (a b : ℕ) : ∃ d : Fin 2 →₀ ℕ, d 0 = a ∧ d 1 = b := - ⟨Finsupp.equivFunOnFinite.invFun ![a, b], rfl, rfl⟩ - private lemma no_wt_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d ≠ n := by intro h @@ -549,7 +542,8 @@ private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) : p = 0 := by - obtain ⟨d₀, hd0a, hd0b⟩ := finsupp_of_fin2 a b + obtain ⟨d₀, hd0a, hd0b⟩ : ∃ d : Fin 2 →₀ ℕ, d 0 = a ∧ d 1 = b := + ⟨Finsupp.equivFunOnFinite.invFun ![a, b], rfl, rfl⟩ apply per_weight_injective_unique_monomial p hp heval d₀ · intro d hd have h46 := weight_eq_4a_6b d @@ -609,39 +603,26 @@ private lemma discriminantPoly_piece_isWeightedHomogeneous {n : ℕ} (hn12 : 12 omega private lemma discriminantPoly_piece_eq_monomial_sub - (d : Fin 2 →₀ ℕ) (hd_ge : 3 ≤ d 0) (c : ℂ) - (d' : Fin 2 →₀ ℕ) (hd' : d' = Finsupp.single (0 : Fin 2) (d 0 - 3) + - Finsupp.single (1 : Fin 2) (d 1 + 2)) : + (d : Fin 2 →₀ ℕ) (hd_ge : 3 ≤ d 0) (c : ℂ) : MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) = - (MvPolynomial.monomial d) c - (MvPolynomial.monomial d') c := by - subst hd' - have h1728 : (1728 : ℂ) • discriminantPoly = - MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2 := by - simp only [discriminantPoly, smul_smul] - norm_num - have hd_fin : d = Finsupp.single (0 : Fin 2) (d 0) + - Finsupp.single (1 : Fin 2) (d 1) := by - ext i - fin_cases i <;> simp [Finsupp.add_apply] - rw [h1728, show MvPolynomial.C c * ((MvPolynomial.X (0 : Fin 2) ^ 3 - - MvPolynomial.X (1 : Fin 2) ^ 2) * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) = - MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ d 0 * MvPolynomial.X (1 : Fin 2) ^ d 1) - - MvPolynomial.C c * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * - MvPolynomial.X (1 : Fin 2) ^ (d 1 + 2)) by - rw [show (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ d 0 = - MvPolynomial.X (0 : Fin 2) ^ 3 * MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) from by - rw [← pow_add, show 3 + (d 0 - 3) = d 0 from by omega], - show (MvPolynomial.X (1 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ (d 1 + 2) = - MvPolynomial.X (1 : Fin 2) ^ d 1 * MvPolynomial.X (1 : Fin 2) ^ 2 from by rw [pow_add]] - ring] - congr 1 - · rw [MvPolynomial.X_pow_eq_monomial, MvPolynomial.X_pow_eq_monomial, - MvPolynomial.monomial_mul, one_mul, MvPolynomial.C_mul_monomial, mul_one] - exact congrArg (· c) (congrArg MvPolynomial.monomial hd_fin.symm) - rw [MvPolynomial.X_pow_eq_monomial, MvPolynomial.X_pow_eq_monomial, - MvPolynomial.monomial_mul, one_mul, MvPolynomial.C_mul_monomial, mul_one] + MvPolynomial.monomial d c - MvPolynomial.monomial + (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) c := by + rw [show (1728 : ℂ) • discriminantPoly = + MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2 by + simp only [discriminantPoly, smul_smul] + norm_num, + monomial_fin2_eq, monomial_fin2_eq, + show (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) 0 + = d 0 - 3 from by simp [Finsupp.add_apply], + show (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) 1 + = d 1 + 2 from by simp [Finsupp.add_apply], + show (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ d 0 = + MvPolynomial.X 0 ^ 3 * MvPolynomial.X 0 ^ (d 0 - 3) by + rw [← pow_add, show 3 + (d 0 - 3) = d 0 from by omega], + show (MvPolynomial.X (1 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ (d 1 + 2) = + MvPolynomial.X 1 ^ d 1 * MvPolynomial.X 1 ^ 2 by rw [pow_add]] + ring private lemma sum_lt_sum_of_replace {α : Type*} [DecidableEq α] (S S' : Finset α) (f : α → ℕ) (d d' : α) @@ -746,8 +727,9 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 omega have hdp_mono : δ_piece = - (MvPolynomial.monomial d) c - (MvPolynomial.monomial d') c := - discriminantPoly_piece_eq_monomial_sub d hd_ge c d' hd'_def + (MvPolynomial.monomial d) c - (MvPolynomial.monomial d') c := by + rw [hd'_def] + exact discriminantPoly_piece_eq_monomial_sub d hd_ge c obtain ⟨hd_not, hsupp⟩ := hdp_mono ▸ mvpoly_support_after_reduction p d d' c hdd' rfl refine sum_lt_sum_of_replace p.support p'.support (· 0) d d' hd_mem hd_not hsupp ?_ simp [hd'_def, Finsupp.add_apply] From 7781063c067736b4139edde230702bf0c9fe7c64 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:10:44 +0100 Subject: [PATCH 44/61] chore(NumberTheory/ModularForms): break down `reduced_part_eq_zero` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract two helpers from the proof: * `reduced_isWeightedHomogeneous_eq_monomial`: a reduced (`d 0 < 3` for all support `d`) weighted-homogeneous polynomial of weight `n` equals the monomial at any of its support points. * `evalE₄E₆_monomial_qExpansion_coeff_zero`: the q-expansion-coeff-0 of `evalE₄E₆ (monomial d c)` evaluated at the matching weight equals `c`. `reduced_part_eq_zero` is now 36 lines instead of 62. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 80 ++++++++++--------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 57f281aa9eb4c8..13d07610a06a71 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -741,6 +741,40 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) rw [hp_eq, hδ_eq, hp'_eq, mul_add] ring +private lemma reduced_isWeightedHomogeneous_eq_monomial {n : ℕ} + (r : MvPolynomial (Fin 2) ℂ) (hr : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n) + (hr_red : ∀ d ∈ r.support, d 0 < 3) {d₀ : Fin 2 →₀ ℕ} (hd₀ : d₀ ∈ r.support) : + r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by + have hwd₀ := hr (MvPolynomial.mem_support_iff.mp hd₀) + ext d + rw [MvPolynomial.coeff_monomial] + by_cases hd : d = d₀ + · simp [hd] + rw [if_neg (Ne.symm hd)] + by_cases hd_supp : d ∈ r.support + · have h1 := weight_eq_4a_6b d + rw [hr (MvPolynomial.mem_support_iff.mp hd_supp)] at h1 + have h2 := weight_eq_4a_6b d₀ + rw [hwd₀] at h2 + obtain ⟨ha, hb⟩ := unique_small_weight_soln (hr_red d hd_supp) (hr_red d₀ hd₀) + (show d 0 * 4 + d 1 * 6 = d₀ 0 * 4 + d₀ 1 * 6 by omega) + exact absurd (Finsupp.ext fun i => by fin_cases i <;> [exact ha; exact hb]) hd + · rwa [MvPolynomial.mem_support_iff, not_not] at hd_supp + +private lemma evalE₄E₆_monomial_qExpansion_coeff_zero {n : ℕ} {d₀ : Fin 2 →₀ ℕ} + (hd₀_weight : 4 * d₀ 0 + 6 * d₀ 1 = n) (c : ℂ) : + (qExpansion 1 ↑((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c := by + rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, + smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply, + show (↑(c • ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ))) : ℍ → ℂ) = + c • (↑((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ)) : ℍ → ℂ) from rfl, + UpperHalfPlane.qExpansion_smul (ModularFormClass.analyticAt_cuspFunction_zero _ + one_pos one_mem_strictPeriods_SL) c, PowerSeries.coeff_smul, + monomial_qExpansion_coeff_zero_eq_one hd₀_weight] + simp + private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (r s : MvPolynomial (Fin 2) ℂ) (hr : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n) @@ -751,28 +785,13 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) by_cases hr_empty : r.support = ∅ · rwa [MvPolynomial.support_eq_empty] at hr_empty obtain ⟨d₀, hd₀⟩ := Finset.nonempty_of_ne_empty hr_empty - have hwd₀ := hr (MvPolynomial.mem_support_iff.mp hd₀) - have hr_mono : r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by - ext d - rw [MvPolynomial.coeff_monomial] - by_cases hd : d = d₀ - · simp [hd] - rw [if_neg (Ne.symm hd)] - by_cases hd_supp : d ∈ r.support - · have h1 := weight_eq_4a_6b d - rw [hr (MvPolynomial.mem_support_iff.mp hd_supp)] at h1 - have h2 := weight_eq_4a_6b d₀ - rw [hwd₀] at h2 - obtain ⟨ha, hb⟩ := unique_small_weight_soln (hr_red d hd_supp) (hr_red d₀ hd₀) - (show d 0 * 4 + d 1 * 6 = d₀ 0 * 4 + d₀ 1 * 6 by omega) - exact absurd (Finsupp.ext fun i => by fin_cases i <;> [exact ha; exact hb]) hd - · rwa [MvPolynomial.mem_support_iff, not_not] at hd_supp + have hr_mono := reduced_isWeightedHomogeneous_eq_monomial r hr hr_red hd₀ set c := MvPolynomial.coeff d₀ r suffices hc : c = 0 by rw [hr_mono, hc, MvPolynomial.monomial_zero] - rw [hr_mono, map_add] at heval have hd₀_weight : 4 * d₀ 0 + 6 * d₀ 1 = n := by - have := (weight_eq_4a_6b d₀).symm.trans hwd₀ + have := (weight_eq_4a_6b d₀).symm.trans (hr (MvPolynomial.mem_support_iff.mp hd₀)) omega + rw [hr_mono, map_add] at heval set Q := ModularForm.qExpansionAddHom (h := 1) one_pos one_mem_strictPeriods_SL (↑n : ℤ) have hQ_zero : Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ)) = 0 := by @@ -782,26 +801,15 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) from rfl, heval] exact map_zero Q rw [map_add] at hQ_zero - have h_coeff_sum : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 + + have hQ : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 + (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by simpa using congr_arg (fun (p : PowerSeries ℂ) => p.coeff 0) hQ_zero - have h_Δ_term : (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := - evalE₄E₆_discriminantPoly_mul_coeff_zero hn12 s hs - rw [h_Δ_term, add_zero] at h_coeff_sum - have h_mono_term : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c := by - change (qExpansion 1 ↑((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c - rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, - smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply, - show (↑(c • ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ))) : ℍ → ℂ) = - c • (↑((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ)) : ℍ → ℂ) from rfl, - UpperHalfPlane.qExpansion_smul (ModularFormClass.analyticAt_cuspFunction_zero _ - one_pos one_mem_strictPeriods_SL) c, PowerSeries.coeff_smul] - rw [monomial_qExpansion_coeff_zero_eq_one hd₀_weight] - simp - rw [h_mono_term] at h_coeff_sum - exact h_coeff_sum + rw [show (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 from + evalE₄E₆_discriminantPoly_mul_coeff_zero hn12 s hs, + add_zero, + show (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 = c from + evalE₄E₆_monomial_qExpansion_coeff_zero hd₀_weight c] at hQ + exact hQ private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) From d825b52cb267eac5242d2535c9994452bd65c050 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:13:54 +0100 Subject: [PATCH 45/61] chore(NumberTheory/ModularForms): break down `whomog_poly_Delta_decomp` and `surj_of_weight` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Extract `support_sum_lt_after_sub_δ_piece` from `whomog_poly_Delta_decomp` (the support-sum-decreases sub-proof, ~16 lines). * Extract `evalE₄E₆_X_sq` and `evalE₄E₆_X0_X1` simp-style API lemmas, used in the weight-8 and weight-10 base cases of `surj_of_weight`. `whomog_poly_Delta_decomp`: 67 → 52 lines. `surj_of_weight`: 51 → 45 lines. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 68 +++++++++++-------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 13d07610a06a71..5783441a522281 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -141,6 +141,19 @@ lemma evalE₄E₆_monomial (a b : ℕ) : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by simp [map_mul, map_pow] +private lemma evalE₄E₆_X_sq : + evalE₄E₆ (MvPolynomial.X 0 ^ 2) = DirectSum.of (ModularForm 𝒮ℒ) 8 (E₄.mul E₄) := by + rw [map_pow, evalE₄E₆_X0, pow_two, DirectSum.of_mul_of] + exact DirectSum.of_eq_of_gradedMonoid_eq + (ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 4 : ℤ) = 8 by norm_num).symm rfl) + +private lemma evalE₄E₆_X0_X1 : + evalE₄E₆ (MvPolynomial.X 0 * MvPolynomial.X 1) = + DirectSum.of (ModularForm 𝒮ℒ) 10 (E₄.mul E₆) := by + rw [map_mul, evalE₄E₆_X0, evalE₄E₆_X1, DirectSum.of_mul_of] + exact DirectSum.of_eq_of_gradedMonoid_eq + (ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 6 : ℤ) = 10 by norm_num).symm rfl) + private lemma exists_monomial_weight {k : ℕ} (hk : 4 ≤ k) (hkeven : Even k) : ∃ a b : ℕ, 4 * a + 6 * b = k := by obtain ⟨m, rfl⟩ := hkeven @@ -344,19 +357,13 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one (show E₆ ≠ 0 from E_ne_zero (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f · exact absurd hk_odd (by decide) - · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) + · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) (mul_ne_zero E₄ E₄ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) - (MvPolynomial.X 0 ^ 2) ?_ f - rw [map_pow, evalE₄E₆_X0, pow_two, DirectSum.of_mul_of] - apply DirectSum.of_eq_of_gradedMonoid_eq - exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 4 : ℤ) = 8 by norm_num).symm rfl + (MvPolynomial.X 0 ^ 2) evalE₄E₆_X_sq f · exact absurd hk_odd (by decide) - · refine surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) + · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) (mul_ne_zero E₄ E₆ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) - (MvPolynomial.X 0 * MvPolynomial.X 1) ?_ f - rw [map_mul, evalE₄E₆_X0, evalE₄E₆_X1, DirectSum.of_mul_of] - apply DirectSum.of_eq_of_gradedMonoid_eq - exact ModularForm.gradedMonoid_eq_of_cast (show ((4 : ℤ) + 6 : ℤ) = 10 by norm_num).symm rfl + (MvPolynomial.X 0 * MvPolynomial.X 1) evalE₄E₆_X0_X1 f · exact absurd hk_odd (by decide) · push Not at hn12 exact surj_at_weight_inductive hn12 hk_odd ih f @@ -674,6 +681,24 @@ private lemma mvpoly_support_after_reduction {σ R : Type*} [CommRing R] [Decida · exact absurd h2 (Finset.notMem_empty _) exact Finset.mem_union_right _ (by rwa [Finset.mem_singleton] at h2 ⊢) +private lemma support_sum_lt_after_sub_δ_piece (p : MvPolynomial (Fin 2) ℂ) + {d : Fin 2 →₀ ℕ} (hd_mem : d ∈ p.support) (hd_ge : 3 ≤ d 0) : + ∑ d' ∈ (p - MvPolynomial.C (MvPolynomial.coeff d p) * ((1728 : ℂ) • discriminantPoly * + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * + MvPolynomial.X (1 : Fin 2) ^ d 1))).support, d' 0 < + ∑ d' ∈ p.support, d' 0 := by + set d' := Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2) + have hdd' : d ≠ d' := fun heq => by + have h0 := Finsupp.ext_iff.mp heq (0 : Fin 2) + simp only [Fin.isValue, d', Finsupp.add_apply, Finsupp.single_eq_same, + ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 + omega + obtain ⟨hd_not, hsupp⟩ := (discriminantPoly_piece_eq_monomial_sub d hd_ge _ : _ = _) ▸ + mvpoly_support_after_reduction p d d' _ hdd' rfl + refine sum_lt_sum_of_replace p.support _ (· 0) d d' hd_mem hd_not hsupp ?_ + simp [d', Finsupp.add_apply] + omega + private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : @@ -704,7 +729,7 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) omega set c := MvPolynomial.coeff d p set δ_piece := MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1))) + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) with hδ_def set p' := p - δ_piece with hp'_def have hp_eq : p = p' + δ_piece := by simp [p'] have hp'_wh : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p' n := @@ -714,28 +739,13 @@ private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n δ_piece).mpr (discriminantPoly_piece_isWeightedHomogeneous hn12 d hd_ge hwd c))) set q₁ := MvPolynomial.C (c * 1728) * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1)) + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) have hδ_eq : δ_piece = discriminantPoly * q₁ := by simp only [δ_piece, q₁, MvPolynomial.smul_eq_C_mul, map_mul] ring - have hM_lt : ∑ d' ∈ p'.support, d' 0 < ∑ d' ∈ p.support, d' 0 := by - set d' := Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2) - with hd'_def - have hdd' : d ≠ d' := fun heq => by - have h0 := Finsupp.ext_iff.mp heq (0 : Fin 2) - simp only [Fin.isValue, hd'_def, Finsupp.add_apply, Finsupp.single_eq_same, - ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 - omega - have hdp_mono : δ_piece = - (MvPolynomial.monomial d) c - (MvPolynomial.monomial d') c := by - rw [hd'_def] - exact discriminantPoly_piece_eq_monomial_sub d hd_ge c - obtain ⟨hd_not, hsupp⟩ := hdp_mono ▸ mvpoly_support_after_reduction p d d' c hdd' rfl - refine sum_lt_sum_of_replace p.support p'.support (· 0) d d' hd_mem hd_not hsupp ?_ - simp [hd'_def, Finsupp.add_apply] - omega obtain ⟨r, s', hr_wh, hs'_wh, hp'_eq, hr_red⟩ := - ih (∑ d' ∈ p'.support, d' 0) (by omega) p' hp'_wh le_rfl + ih (∑ d' ∈ p'.support, d' 0) + ((support_sum_lt_after_sub_δ_piece p hd_mem hd_ge).trans_le _hM) p' hp'_wh le_rfl refine ⟨r, s' + q₁, hr_wh, hs'_wh.add (.C_mul (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) _), ?_, hr_red⟩ rw [hp_eq, hδ_eq, hp'_eq, mul_add] From 0fae9775d409ec037a7f0bdffc501463fb8ee156 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:17:57 +0100 Subject: [PATCH 46/61] chore(NumberTheory/ModularForms): naming abbreviations + initial line-length fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rename `whomog_*` → `weightedHomogeneous_*` * Rename `mvpoly_*` → `mvPolynomial_*` * Rename `eval_discriminantPoly_mul_zero_imp` → `eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero` * Rename `unique_small_weight_soln` → `unique_small_weight_solution` * Rename `no_wt_monomial_*` → `no_weight_monomial_*` * Remove the `Δ = (E₄³ - E₆²) / 1728` section header * Reformat a few long signatures. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 5783441a522281..13df1dbc364685 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -40,8 +40,6 @@ open UpperHalfPlane ModularForm ModularFormClass MatrixGroups EisensteinSeries namespace ModularForm -/-! ### `Δ = (E₄³ - E₆²) / 1728` -/ - /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - @@ -183,8 +181,8 @@ private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : Modu subst hk rfl -private lemma cast_modularForm_apply {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) (z : ℍ) : - (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by +private lemma cast_modularForm_apply {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) + (z : ℍ) : (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by subst heq rfl @@ -256,7 +254,7 @@ private lemma evalE₄E₆_discriminantPoly : private lemma discriminant_mem_range_evalE₄E₆ : DirectSum.of (ModularForm 𝒮ℒ) 12 ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ Set.range evalE₄E₆ := - ⟨discriminantPoly, evalE₄E₆_discriminantPoly⟩ + ⟨_, evalE₄E₆_discriminantPoly⟩ private lemma sub_smul_qExpansion_coeff_zero_isCuspForm {k : ℤ} (f g : ModularForm 𝒮ℒ k) (hg : (qExpansion 1 g).coeff 0 = 1) : @@ -300,9 +298,10 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev set h' := CuspForm.discriminantEquiv (ModularForm.toCuspForm (f - c • mn) ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp)) - obtain ⟨p1, hp1⟩ : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by + obtain ⟨p1, hp1⟩ : + DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by rw [directSumOf_cast_eq hcast] - exact ih (n - 12) (by omega) (hcast ▸ h') + exact ih _ (by omega) (hcast ▸ h') rw [show DirectSum.of _ (↑n : ℤ) f = DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn by rw [← DirectSum.of_smul, ← map_add] @@ -388,28 +387,28 @@ private lemma weight_fin2_cast (d : Fin 2 →₀ ℕ) : push_cast ring -private lemma no_wt_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ ℕ) : +private lemma no_weight_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d ≠ n := by intro h rw [weight_eq_4a_6b] at h exact Nat.not_odd_iff_even.mpr ⟨d 0 * 2 + d 1 * 3, by omega⟩ hn -private lemma no_wt_monomial_of_two (d : Fin 2 →₀ ℕ) : +private lemma no_weight_monomial_of_two (d : Fin 2 →₀ ℕ) : Finsupp.weight E₄E₆Weight d ≠ 2 := by intro h rw [weight_eq_4a_6b] at h omega -private lemma whomog_eq_zero_of_no_monomials {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) +private lemma weightedHomogeneous_eq_zero_of_no_monomials {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (hno : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d ≠ n) : p = 0 := by rw [← MvPolynomial.support_eq_empty, ← Finset.not_nonempty_iff_eq_empty] rintro ⟨d, hd⟩ exact hno _ (hp (MvPolynomial.mem_support_iff.mp hd)) -private lemma whomog_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) - (d₀ : Fin 2 →₀ ℕ) (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) : +private lemma weightedHomogeneous_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (d₀ : Fin 2 →₀ ℕ) + (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) : p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by ext d rw [MvPolynomial.coeff_monomial] @@ -418,7 +417,7 @@ private lemma whomog_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) rw [if_neg (Ne.symm hd)] exact hp.coeff_eq_zero d (fun h => hd (huniq d h)) -private lemma unique_small_weight_soln {a₁ b₁ a₂ b₂ : ℕ} +private lemma unique_small_weight_solution {a₁ b₁ a₂ b₂ : ℕ} (ha₁ : a₁ < 3) (ha₂ : a₂ < 3) (h : a₁ * 4 + b₁ * 6 = a₂ * 4 + b₂ * 6) : a₁ = a₂ ∧ b₁ = b₂ := ⟨by interval_cases a₁ <;> interval_cases a₂ <;> omega, by omega⟩ @@ -536,7 +535,7 @@ private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial ( (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) (hmf_ne : (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ) ≠ 0) : p = 0 := by - have hpc := whomog_unique_monomial p hp d₀ huniq + have hpc := weightedHomogeneous_unique_monomial p hp d₀ huniq rw [hpc] at heval ⊢ rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply] at heval @@ -555,7 +554,7 @@ private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn · intro d hd have h46 := weight_eq_4a_6b d rw [hd] at h46 - obtain ⟨hda, hdb⟩ := unique_small_weight_soln (by omega : d 0 < 3) ha + obtain ⟨hda, hdb⟩ := unique_small_weight_solution (by omega : d 0 < 3) ha (show d 0 * 4 + d 1 * 6 = a * 4 + b * 6 by omega) ext i fin_cases i <;> [exact hda ▸ hd0a.symm; exact hdb ▸ hd0b.symm] @@ -656,7 +655,7 @@ private lemma sum_lt_sum_of_replace {α : Type*} [DecidableEq α] _ = ∑ x ∈ S, f x := Finset.sum_erase_add S f hd_mem open Classical in -private lemma mvpoly_support_after_reduction {σ R : Type*} [CommRing R] [DecidableEq σ] +private lemma mvPolynomial_support_after_reduction {σ R : Type*} [CommRing R] [DecidableEq σ] (p : MvPolynomial σ R) (d d' : σ →₀ ℕ) (c : R) (hdd' : d ≠ d') (hc : MvPolynomial.coeff d p = c) : let δ := MvPolynomial.monomial d c - MvPolynomial.monomial d' c @@ -694,12 +693,12 @@ private lemma support_sum_lt_after_sub_δ_piece (p : MvPolynomial (Fin 2) ℂ) ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 omega obtain ⟨hd_not, hsupp⟩ := (discriminantPoly_piece_eq_monomial_sub d hd_ge _ : _ = _) ▸ - mvpoly_support_after_reduction p d d' _ hdd' rfl + mvPolynomial_support_after_reduction p d d' _ hdd' rfl refine sum_lt_sum_of_replace p.support _ (· 0) d d' hd_mem hd_not hsupp ?_ simp [d', Finsupp.add_apply] omega -private lemma whomog_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) +private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : ∃ r s : MvPolynomial (Fin 2) ℂ, @@ -766,7 +765,7 @@ private lemma reduced_isWeightedHomogeneous_eq_monomial {n : ℕ} rw [hr (MvPolynomial.mem_support_iff.mp hd_supp)] at h1 have h2 := weight_eq_4a_6b d₀ rw [hwd₀] at h2 - obtain ⟨ha, hb⟩ := unique_small_weight_soln (hr_red d hd_supp) (hr_red d₀ hd₀) + obtain ⟨ha, hb⟩ := unique_small_weight_solution (hr_red d hd_supp) (hr_red d₀ hd₀) (show d 0 * 4 + d 1 * 6 = d₀ 0 * 4 + d₀ 1 * 6 by omega) exact absurd (Finsupp.ext fun i => by fin_cases i <;> [exact ha; exact hb]) hd · rwa [MvPolynomial.mem_support_iff, not_not] at hd_supp @@ -821,7 +820,7 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) evalE₄E₆_monomial_qExpansion_coeff_zero hd₀_weight c] at hQ exact hQ -private lemma eval_discriminantPoly_mul_zero_imp {n : ℕ} (hn12 : 12 ≤ n) +private lemma eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) (hds : (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) = 0) : @@ -843,11 +842,11 @@ private lemma per_weight_injective_inductive_step (n : ℕ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) (hn12 : 12 ≤ n) : p = 0 := by - obtain ⟨r, s, hr_wh, hs_wh, hp_eq, hr_red⟩ := whomog_poly_Delta_decomp hn12 p hp + obtain ⟨r, s, hr_wh, hs_wh, hp_eq, hr_red⟩ := weightedHomogeneous_poly_Delta_decomp hn12 p hp have hr0 : r = 0 := reduced_part_eq_zero hn12 r s hr_wh hs_wh hr_red (hp_eq ▸ heval) rw [hp_eq, hr0, zero_add] at heval ⊢ rw [ih (n - 12) (by omega) s hs_wh - (eval_discriminantPoly_mul_zero_imp hn12 s hs_wh heval), mul_zero] + (eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero hn12 s hs_wh heval), mul_zero] private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ), MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n → @@ -856,7 +855,7 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ induction n using Nat.strong_induction_on with | _ n ih => ?_ intro p hp heval by_cases hk_odd : Odd n - · exact whomog_eq_zero_of_no_monomials p hp (no_wt_monomial_of_odd hk_odd) + · exact weightedHomogeneous_eq_zero_of_no_monomials p hp (no_weight_monomial_of_odd hk_odd) rw [Nat.not_odd_iff_even] at hk_odd by_cases hn4 : n < 4 · have hn02 : n = 0 ∨ n = 2 := by @@ -864,7 +863,7 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ omega rcases hn02 with rfl | rfl · exact per_weight_injective_zero p hp heval - · exact whomog_eq_zero_of_no_monomials p hp no_wt_monomial_of_two + · exact weightedHomogeneous_eq_zero_of_no_monomials p hp no_weight_monomial_of_two push Not at hn4 by_cases hn12 : n < 12 · have hn_cases : n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by From 0ed59e6d3c6f2e8fe5963cdeddc9758d6ecebbc8 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:20:20 +0100 Subject: [PATCH 47/61] chore(NumberTheory/ModularForms): more line-length and signature fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reformat declaration signatures and proof terms that exceeded the 100-char linter limit; reformat the `surj_of_weight` weight-{4,6,8,10} branches and the `E₄E₆_generate` proof header. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 13df1dbc364685..543bb69103ecc4 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -117,16 +117,19 @@ def E₄E₆Weight : Fin 2 → ℕ := ![4, 6] /-- Evaluation homomorphism sending `ℂ[X₀, X₁]` to the graded ring of level 1 modular forms via `X₀ ↦ E₄` and `X₁ ↦ E₆`. -/ -noncomputable def evalE₄E₆ : MvPolynomial (Fin 2) ℂ →ₐ[ℂ] DirectSum ℤ (ModularForm 𝒮ℒ) := +noncomputable def evalE₄E₆ : + MvPolynomial (Fin 2) ℂ →ₐ[ℂ] DirectSum ℤ (ModularForm 𝒮ℒ) := MvPolynomial.aeval ![DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, DirectSum.of (ModularForm 𝒮ℒ) 6 E₆] @[simp] -lemma evalE₄E₆_X0 : evalE₄E₆ (MvPolynomial.X 0) = DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ := by +lemma evalE₄E₆_X0 : + evalE₄E₆ (MvPolynomial.X 0) = DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ := by simp [evalE₄E₆] @[simp] -lemma evalE₄E₆_X1 : evalE₄E₆ (MvPolynomial.X 1) = DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ := by +lemma evalE₄E₆_X1 : + evalE₄E₆ (MvPolynomial.X 1) = DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ := by simp [evalE₄E₆] lemma evalE₄E₆_C (c : ℂ) : @@ -165,9 +168,9 @@ private lemma surj_of_rank_one {k : ℤ} DirectSum.of _ k f ∈ Set.range evalE₄E₆ := by obtain ⟨c, rfl⟩ := (finrank_eq_one_iff_of_nonzero' g hg).mp (Module.rank_eq_one_iff_finrank_eq_one.mp hrank) f - exact ⟨MvPolynomial.C c * p, by - rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, - smul_mul_assoc, one_mul, ← DirectSum.of_smul]⟩ + refine ⟨MvPolynomial.C c * p, ?_⟩ + rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, + smul_mul_assoc, one_mul, ← DirectSum.of_smul] private lemma mul_ne_zero {k₁ k₂ : ℤ} (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) (hf : f ≠ 0) (hg : g ≠ 0) : f.mul g ≠ 0 := by @@ -351,17 +354,21 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), exact ⟨0, map_zero _⟩ · exact absurd hk_odd (by decide) · exact surj_of_rank_one ModularForm.levelOne_weight_four_rank_one - (show E₄ ≠ 0 from E_ne_zero (by norm_num) ⟨2, rfl⟩) (MvPolynomial.X 0) evalE₄E₆_X0 f + (E_ne_zero (k := 4) (by norm_num) ⟨2, rfl⟩) + (MvPolynomial.X 0) evalE₄E₆_X0 f · exact absurd hk_odd (by decide) · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one - (show E₆ ≠ 0 from E_ne_zero (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f + (E_ne_zero (k := 6) (by norm_num) ⟨3, rfl⟩) + (MvPolynomial.X 1) evalE₄E₆_X1 f · exact absurd hk_odd (by decide) · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) - (mul_ne_zero E₄ E₄ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) + (mul_ne_zero E₄ E₄ (E_ne_zero (by norm_num) ⟨2, rfl⟩) + (E_ne_zero (by norm_num) ⟨2, rfl⟩)) (MvPolynomial.X 0 ^ 2) evalE₄E₆_X_sq f · exact absurd hk_odd (by decide) · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) - (mul_ne_zero E₄ E₆ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) + (mul_ne_zero E₄ E₆ (E_ne_zero (by norm_num) ⟨2, rfl⟩) + (E_ne_zero (by norm_num) ⟨3, rfl⟩)) (MvPolynomial.X 0 * MvPolynomial.X 1) evalE₄E₆_X0_X1 f · exact absurd hk_odd (by decide) · push Not at hn12 @@ -897,8 +904,10 @@ noncomputable def modularFormsEquivMvPolynomial : `ℂ`-algebra. -/ theorem E₄E₆_generate : Algebra.adjoin ℂ ({DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆} : Set (DirectSum ℤ (ModularForm 𝒮ℒ))) = ⊤ := by - rw [show ({DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, DirectSum.of (ModularForm 𝒮ℒ) 6 E₆} : Set _) = + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆} : + Set (DirectSum ℤ (ModularForm 𝒮ℒ))) = ⊤ := by + rw [show ({DirectSum.of (ModularForm 𝒮ℒ) 4 E₄, + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆} : Set _) = Set.range (![DirectSum.of _ 4 E₄, DirectSum.of _ 6 E₆] : Fin 2 → _) from (Matrix.range_cons_cons_empty _ _ _).symm, Algebra.adjoin_range_eq_range_aeval] From 82eedef64b13caa21055f53abd80cd51caebb9e6 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:21:44 +0100 Subject: [PATCH 48/61] chore(NumberTheory/ModularForms): collapse odd-weight dismissals in `surj_of_weight` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace `interval_cases n` (12 sub-goals, half of which only dismiss odd n) with a single `obtain rfl | rfl | rfl | rfl | rfl | rfl : n = 0 ∨ ... ∨ n = 10` so the proof has 6 branches instead of 12. `surj_of_weight`: 51 → 47 lines. Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/NumberTheory/ModularForms/GradedRing.lean | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 543bb69103ecc4..b22e1be8db1b17 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -344,33 +344,31 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), exact ⟨0, map_zero _⟩ rw [Int.not_odd_iff_even] at hk_odd by_cases hn12 : n < 12 - · interval_cases n + · obtain rfl | rfl | rfl | rfl | rfl | rfl : + n = 0 ∨ n = 2 ∨ n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by + rcases hk_odd with ⟨m, hm⟩ + omega · refine surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one one_ne_zero_modularForm 1 ?_ f rw [map_one] rfl - · exact absurd hk_odd (by decide) - · rw [(rank_zero_iff_forall_zero.mp ModularForm.levelOne_weight_two_rank_zero) f, map_zero] + · rw [(rank_zero_iff_forall_zero.mp ModularForm.levelOne_weight_two_rank_zero) f, + map_zero] exact ⟨0, map_zero _⟩ - · exact absurd hk_odd (by decide) · exact surj_of_rank_one ModularForm.levelOne_weight_four_rank_one (E_ne_zero (k := 4) (by norm_num) ⟨2, rfl⟩) (MvPolynomial.X 0) evalE₄E₆_X0 f - · exact absurd hk_odd (by decide) · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one (E_ne_zero (k := 6) (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f - · exact absurd hk_odd (by decide) · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) (mul_ne_zero E₄ E₄ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) (MvPolynomial.X 0 ^ 2) evalE₄E₆_X_sq f - · exact absurd hk_odd (by decide) · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) (mul_ne_zero E₄ E₆ (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) (MvPolynomial.X 0 * MvPolynomial.X 1) evalE₄E₆_X0_X1 f - · exact absurd hk_odd (by decide) · push Not at hn12 exact surj_at_weight_inductive hn12 hk_odd ih f From c3629b1f4491d4b07398711d98d07dbf1d79808c Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:25:05 +0100 Subject: [PATCH 49/61] chore(NumberTheory/ModularForms): more line-length fixes + tighten `cuspForm_eq_discriminant_mul` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Reformat `mul_ne_zero`, `directSumOf_cast_eq`, `cast_modularForm_apply`, `discriminant_mem_range_evalE₄E₆`, `directSumOf_evalE₄E₆_monomial_apply`, and `evalE₄E₆_whc_grade` to fit within 100 chars. * Use `refine ... <| ... ?_` to merge the four `apply`/`refine` lines at the top of `cuspForm_eq_discriminant_mul` (28 → 24 lines). Down to 3 lines (all 103–105 chars) over the linter limit. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index b22e1be8db1b17..5798b6486533fa 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -172,15 +172,17 @@ private lemma surj_of_rank_one {k : ℤ} rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, ← DirectSum.of_smul] -private lemma mul_ne_zero {k₁ k₂ : ℤ} (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) - (hf : f ≠ 0) (hg : g ≠ 0) : f.mul g ≠ 0 := by +private lemma mul_ne_zero {k₁ k₂ : ℤ} + (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) (hf : f ≠ 0) (hg : g ≠ 0) : + f.mul g ≠ 0 := by rw [Ne, ← ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL, mul_eq_zero, not_or] exact ⟨(ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hf, (ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hg⟩ private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : - DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by + DirectSum.of (ModularForm 𝒮ℒ) k₁ x = + DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by subst hk rfl @@ -194,7 +196,8 @@ private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (n : ℤ))).coeff 0 = 1 := by set R := ModularForm.qExpansionRingHom (1 : ℝ) one_pos one_mem_strictPeriods_SL with hR_def - set prod := DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b + set prod := + DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b with hprod_def have hweight : (a • (4 : ℤ) + b • (6 : ℤ)) = (n : ℤ) := by simp only [Int.nsmul_eq_mul] @@ -229,19 +232,16 @@ private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := by rw [DirectSum.of_mul_of] symm - apply DirectSum.of_eq_of_gradedMonoid_eq - refine ModularForm.gradedMonoid_eq_of_cast ?_ ?_ - · change (↑n - 12 + 12 : ℤ) = ↑n - ring + refine DirectSum.of_eq_of_gradedMonoid_eq <| + ModularForm.gradedMonoid_eq_of_cast (by change (↑n - 12 + 12 : ℤ) = ↑n; ring) ?_ ext z set hcusp := (ModularForm.isCuspForm_iff_coeffZero_eq_zero g).mp hg change ((CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)).mul ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12)) z = g z - have hdiv : (CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)) z = - g z / ModularForm.discriminant z := - CuspForm.divDiscriminant_apply (ModularForm.toCuspForm g hcusp) z - rw [ModularForm.coe_mul, Pi.mul_apply, hdiv] - change g z / ModularForm.discriminant z * ModularForm.discriminant z = g z + rw [ModularForm.coe_mul, Pi.mul_apply, + show (CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)) z = + g z / ModularForm.discriminant z from + CuspForm.divDiscriminant_apply (ModularForm.toCuspForm g hcusp) z] exact div_mul_cancel₀ _ (discriminant_ne_zero z) private noncomputable def discriminantPoly : MvPolynomial (Fin 2) ℂ := @@ -256,7 +256,8 @@ private lemma evalE₄E₆_discriminantPoly : private lemma discriminant_mem_range_evalE₄E₆ : DirectSum.of (ModularForm 𝒮ℒ) 12 - ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ Set.range evalE₄E₆ := + ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) ∈ + Set.range evalE₄E₆ := ⟨_, evalE₄E₆_discriminantPoly⟩ private lemma sub_smul_qExpansion_coeff_zero_isCuspForm {k : ℤ} (f g : ModularForm 𝒮ℒ k) @@ -273,11 +274,13 @@ private lemma sub_smul_qExpansion_coeff_zero_isCuspForm {k : ℤ} (f g : Modular map_sub, PowerSeries.coeff_smul] simp [hg, c] -private lemma directSumOf_evalE₄E₆_monomial_apply {a b n : ℕ} (hab : 4 * a + 6 * b = n) : +private lemma directSumOf_evalE₄E₆_monomial_apply {a b n : ℕ} + (hab : 4 * a + 6 * b = n) : DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (↑n : ℤ)) = - DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by + DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by rw [DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of, show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) by simp only [Int.nsmul_eq_mul] @@ -452,10 +455,13 @@ private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (k : ℤ) (hk : k ≠ ↑n) : (evalE₄E₆ p) k = 0 := by rw [← MvPolynomial.support_sum_monomial_coeff p, map_sum, - show (∑ x ∈ p.support, evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k = - ∑ x ∈ p.support, (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k from + show (∑ x ∈ p.support, + evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k = + ∑ x ∈ p.support, + (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k from map_sum (DFinsupp.evalAddMonoidHom k) _ _] - refine Finset.sum_eq_zero fun d hd => evalE₄E₆_monomial_grade _ _ _ fun heq => hk ?_ + refine Finset.sum_eq_zero fun d hd => + evalE₄E₆_monomial_grade _ _ _ fun heq => hk ?_ rw [heq, ← weight_fin2_cast d, hp (MvPolynomial.mem_support_iff.mp hd)] private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ) From 49f2fd28cc8e9a20921e2f35c4e0b5c3b1b479b7 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:34:51 +0100 Subject: [PATCH 50/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20inlin?= =?UTF-8?q?e=20`E=E2=82=84E=E2=82=86Weight`=20as=20`(![4,=206]=20:=20Fin?= =?UTF-8?q?=202=20=E2=86=92=20=E2=84=95)`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the standalone `E₄E₆Weight` definition (a junk one-liner with no API) and inline it at each use site as `(![4, 6] : Fin 2 → ℕ)`. The type ascription is necessary: without it, `![4, 6]` elaborates to different `M`'s in `Finsupp.weight (w : σ → M)` depending on the surrounding context (`Fin 2 → ℕ` vs `Fin 2 → ℤ`), which breaks rewrites between sibling lemmas. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 103 +++++++++--------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 5798b6486533fa..204eb42662317a 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -16,7 +16,6 @@ level-1 modular forms. ## Main definitions -* `ModularForm.E₄E₆Weight`: the weight function `Fin 2 → ℕ` mapping `0 ↦ 4`, `1 ↦ 6`. * `ModularForm.evalE₄E₆`: the evaluation homomorphism `ℂ[X₀, X₁] →ₐ[ℂ] ⨁ k, ModularForm 𝒮ℒ k` sending `X₀ ↦ E₄`, `X₁ ↦ E₆`. @@ -112,9 +111,6 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) grind [discriminant_eq_E₄_cube_sub_E₆_sq z] -/-- Weight function assigning weight 4 to E₄ (variable 0) and weight 6 to E₆ (variable 1). -/ -def E₄E₆Weight : Fin 2 → ℕ := ![4, 6] - /-- Evaluation homomorphism sending `ℂ[X₀, X₁]` to the graded ring of level 1 modular forms via `X₀ ↦ E₄` and `X₁ ↦ E₆`. -/ noncomputable def evalE₄E₆ : @@ -384,39 +380,39 @@ theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by exact Subalgebra.sum_mem _ fun k _ => surj_of_weight k (x k) private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : - Finsupp.weight E₄E₆Weight d = d 0 * 4 + d 1 * 6 := by + Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = d 0 * 4 + d 1 * 6 := by rw [Finsupp.weight_apply, - d.sum_fintype (fun i c => c • E₄E₆Weight i) fun _ => zero_smul _ _] - simp [Fin.sum_univ_two, E₄E₆Weight, mul_comm] + d.sum_fintype (fun i c => c • (![4, 6] : Fin 2 → ℕ) i) fun _ => zero_smul _ _] + simp [Fin.sum_univ_two, mul_comm] private lemma weight_fin2_cast (d : Fin 2 →₀ ℕ) : - (Finsupp.weight E₄E₆Weight d : ℤ) = ↑(d 0) * 4 + ↑(d 1) * 6 := by + (Finsupp.weight (![4, 6] : Fin 2 → ℕ) d : ℤ) = ↑(d 0) * 4 + ↑(d 1) * 6 := by rw [weight_eq_4a_6b] push_cast ring private lemma no_weight_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ ℕ) : - Finsupp.weight E₄E₆Weight d ≠ n := by + Finsupp.weight (![4, 6] : Fin 2 → ℕ) d ≠ n := by intro h rw [weight_eq_4a_6b] at h exact Nat.not_odd_iff_even.mpr ⟨d 0 * 2 + d 1 * 3, by omega⟩ hn private lemma no_weight_monomial_of_two (d : Fin 2 →₀ ℕ) : - Finsupp.weight E₄E₆Weight d ≠ 2 := by + Finsupp.weight (![4, 6] : Fin 2 → ℕ) d ≠ 2 := by intro h rw [weight_eq_4a_6b] at h omega private lemma weightedHomogeneous_eq_zero_of_no_monomials {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) - (hno : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d ≠ n) : p = 0 := by + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) + (hno : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight (![4, 6] : Fin 2 → ℕ) d ≠ n) : p = 0 := by rw [← MvPolynomial.support_eq_empty, ← Finset.not_nonempty_iff_eq_empty] rintro ⟨d, hd⟩ exact hno _ (hp (MvPolynomial.mem_support_iff.mp hd)) private lemma weightedHomogeneous_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (d₀ : Fin 2 →₀ ℕ) - (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) : + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (d₀ : Fin 2 →₀ ℕ) + (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = n → d = d₀) : p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by ext d rw [MvPolynomial.coeff_monomial] @@ -452,7 +448,7 @@ private lemma evalE₄E₆_monomial_grade (d : Fin 2 →₀ ℕ) (c : ℂ) (k : evalE₄E₆_mono_grade (d 0) (d 1) k hk, smul_zero] private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) (k : ℤ) (hk : k ≠ ↑n) : + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (k : ℤ) (hk : k ≠ ↑n) : (evalE₄E₆ p) k = 0 := by rw [← MvPolynomial.support_sum_monomial_coeff p, map_sum, show (∑ x ∈ p.support, @@ -465,7 +461,7 @@ private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) rw [heq, ← weight_fin2_cast d, hp (MvPolynomial.mem_support_iff.mp hd)] private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) : evalE₄E₆ p = DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) ((evalE₄E₆ p) ↑n) := by refine DFinsupp.ext fun k : ℤ => ?_ by_cases hk : k = (↑n : ℤ) @@ -474,15 +470,15 @@ private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ · rw [DirectSum.of_eq_of_ne _ _ _ hk, evalE₄E₆_whc_grade p hp k hk] private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) : - (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p)) (↑n : ℤ) = + (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) (↑n : ℤ) = (evalE₄E₆ p) (↑n : ℤ) := by - set q := p - MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p with hq_def - have hdecomp : p = MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p + q := by + set q := p - MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p with hq_def + have hdecomp : p = MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p + q := by simp [q] conv_rhs => rw [hdecomp, map_add] - rw [show (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p) + + rw [show (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p) + evalE₄E₆ q) (↑n : ℤ) = - (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent E₄E₆Weight n p)) (↑n : ℤ) + + (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) (↑n : ℤ) + (evalE₄E₆ q) (↑n : ℤ) from rfl] suffices h : (evalE₄E₆ q) (↑n : ℤ) = 0 by rw [h, add_zero] rw [← MvPolynomial.support_sum_monomial_coeff q, map_sum, @@ -499,32 +495,32 @@ private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) omega private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 + b * 6 = n) : - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) (MvPolynomial.X (0 : Fin 2) ^ a * MvPolynomial.X (1 : Fin 2) ^ b : MvPolynomial (Fin 2) ℂ) n := by - convert ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (0 : Fin 2)).pow a).mul - ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow b) using 1 - simp only [E₄E₆Weight, Matrix.cons_val_zero, Matrix.cons_val_one, smul_eq_mul] + convert ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow a).mul + ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow b) using 1 + simp only [Matrix.cons_val_zero, Matrix.cons_val_one, smul_eq_mul] omega private lemma discriminantPoly_isWeightedHomogeneous : - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight discriminantPoly 12 := by + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) discriminantPoly 12 := by rw [discriminantPoly, MvPolynomial.smul_eq_C_mul] intro d hd simp only [MvPolynomial.coeff_C_mul, MvPolynomial.coeff_sub] at hd by_cases hd3 : MvPolynomial.coeff d (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) ≠ 0 - · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (0 : Fin 2)).pow 3) hd3 + · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow 3) hd3 push Not at hd3 by_cases hd6 : MvPolynomial.coeff d (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 - · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ E₄E₆Weight (1 : Fin 2)).pow 2) hd6 + · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow 2) hd6 push Not at hd6 simp [hd3, hd6] at hd private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) - (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) : + (hs : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12)) : (qExpansion 1 ↑((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by rw [map_mul, evalE₄E₆_discriminantPoly, evalE₄E₆_whc_eq_single (n - 12) s hs, DirectSum.of_mul_of] @@ -540,10 +536,10 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩] private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) (d₀ : Fin 2 →₀ ℕ) - (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight E₄E₆Weight d = n → d = d₀) + (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = n → d = d₀) (hmf_ne : (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ) ≠ 0) : p = 0 := by have hpc := weightedHomogeneous_unique_monomial p hp d₀ huniq @@ -557,7 +553,7 @@ private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial ( private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn : n < 12) (hab : 4 * a + 6 * b = n) (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) : p = 0 := by obtain ⟨d₀, hd0a, hd0b⟩ : ∃ d : Fin 2 →₀ ℕ, d 0 = a ∧ d 1 = b := ⟨Finsupp.equivFunOnFinite.invFun ![a, b], rfl, rfl⟩ @@ -577,7 +573,7 @@ private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn private lemma per_weight_injective_zero (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p 0) + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p 0) (heval : (evalE₄E₆ p) (0 : ℤ) = 0) : p = 0 := by have hpc : p = MvPolynomial.C (MvPolynomial.coeff 0 p) := by ext d' @@ -602,7 +598,7 @@ private lemma per_weight_injective_zero private lemma discriminantPoly_piece_isWeightedHomogeneous {n : ℕ} (hn12 : 12 ≤ n) (d : Fin 2 →₀ ℕ) (hd_ge : 3 ≤ d 0) (hwd : d 0 * 4 + d 1 * 6 = n) (c : ℂ) : - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) (MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ (d 1)))) n := by @@ -711,18 +707,18 @@ private lemma support_sum_lt_after_sub_δ_piece (p : MvPolynomial (Fin 2) ℂ) private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) : + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) : ∃ r s : MvPolynomial (Fin 2) ℂ, - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n ∧ - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12) ∧ + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n ∧ + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12) ∧ p = r + discriminantPoly * s ∧ (∀ d ∈ r.support, d 0 < 3) := by suffices key : ∀ (M : ℕ) (p : MvPolynomial (Fin 2) ℂ), - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n → + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n → (∑ d ∈ p.support, d 0) ≤ M → ∃ r s : MvPolynomial (Fin 2) ℂ, - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n ∧ - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12) ∧ + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n ∧ + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12) ∧ p = r + discriminantPoly * s ∧ (∀ d ∈ r.support, d 0 < 3) from key _ p hp le_rfl @@ -730,7 +726,7 @@ private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) induction M using Nat.strong_induction_on with | _ M ih => ?_ intro p hp _hM by_cases hall : ∀ d ∈ p.support, d 0 < 3 - · exact ⟨p, 0, hp, MvPolynomial.isWeightedHomogeneous_zero ℂ E₄E₆Weight (n - 12), + · exact ⟨p, 0, hp, MvPolynomial.isWeightedHomogeneous_zero ℂ (![4, 6] : Fin 2 → ℕ) (n - 12), by simp only [mul_zero, add_zero], hall⟩ push Not at hall obtain ⟨d, hd_mem, hd_ge⟩ := hall @@ -742,11 +738,11 @@ private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) with hδ_def set p' := p - δ_piece with hp'_def have hp_eq : p = p' + δ_piece := by simp [p'] - have hp'_wh : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p' n := - (MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n _).mp + have hp'_wh : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p' n := + (MvPolynomial.mem_weightedHomogeneousSubmodule ℂ (![4, 6] : Fin 2 → ℕ) n _).mp (Submodule.sub_mem _ - ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n p).mpr hp) - ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ E₄E₆Weight n + ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ (![4, 6] : Fin 2 → ℕ) n p).mpr hp) + ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ (![4, 6] : Fin 2 → ℕ) n δ_piece).mpr (discriminantPoly_piece_isWeightedHomogeneous hn12 d hd_ge hwd c))) set q₁ := MvPolynomial.C (c * 1728) * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) @@ -762,7 +758,7 @@ private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) ring private lemma reduced_isWeightedHomogeneous_eq_monomial {n : ℕ} - (r : MvPolynomial (Fin 2) ℂ) (hr : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n) + (r : MvPolynomial (Fin 2) ℂ) (hr : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n) (hr_red : ∀ d ∈ r.support, d 0 < 3) {d₀ : Fin 2 →₀ ℕ} (hd₀ : d₀ ∈ r.support) : r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by have hwd₀ := hr (MvPolynomial.mem_support_iff.mp hd₀) @@ -797,8 +793,8 @@ private lemma evalE₄E₆_monomial_qExpansion_coeff_zero {n : ℕ} {d₀ : Fin private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (r s : MvPolynomial (Fin 2) ℂ) - (hr : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight r n) - (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) + (hr : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n) + (hs : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12)) (hr_red : ∀ d ∈ r.support, d 0 < 3) (heval : (evalE₄E₆ (r + discriminantPoly * s)) (↑n : ℤ) = 0) : r = 0 := by @@ -833,7 +829,7 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) private lemma eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) - (hs : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight s (n - 12)) + (hs : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12)) (hds : (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) = 0) : (evalE₄E₆ s) (↑(n - 12) : ℤ) = 0 := by rw [map_mul, evalE₄E₆_discriminantPoly, @@ -847,10 +843,10 @@ private lemma eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero {n : ℕ} (hn12 private lemma per_weight_injective_inductive_step (n : ℕ) (ih : ∀ m < n, ∀ (p : MvPolynomial (Fin 2) ℂ), - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p m → + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p m → (evalE₄E₆ p) (↑m : ℤ) = 0 → p = 0) (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n) + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) (hn12 : 12 ≤ n) : p = 0 := by obtain ⟨r, s, hr_wh, hs_wh, hp_eq, hr_red⟩ := weightedHomogeneous_poly_Delta_decomp hn12 p hp @@ -860,7 +856,7 @@ private lemma per_weight_injective_inductive_step (n : ℕ) (eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero hn12 s hs_wh heval), mul_zero] private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ), - MvPolynomial.IsWeightedHomogeneous E₄E₆Weight p n → + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n → (evalE₄E₆ p) (↑n : ℤ) = 0 → p = 0 := by intro n induction n using Nat.strong_induction_on with | _ n ih => ?_ @@ -892,7 +888,8 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ independent. -/ theorem evalE₄E₆_injective : Function.Injective evalE₄E₆ := by intro p q hpq - rw [← sub_eq_zero, ← MvPolynomial.sum_weightedHomogeneousComponent (E₄E₆Weight) (p - q)] + rw [← sub_eq_zero, + ← MvPolynomial.sum_weightedHomogeneousComponent ((![4, 6] : Fin 2 → ℕ)) (p - q)] refine finsum_eq_zero_of_forall_eq_zero fun n => per_weight_injective n _ (MvPolynomial.weightedHomogeneousComponent_isWeightedHomogeneous _ _) ?_ rw [evalE₄E₆_component_eq, map_sub, hpq, sub_self] From 41e6040687d7629bed81aa76dde8241383407521 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:50:17 +0100 Subject: [PATCH 51/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20mathl?= =?UTF-8?q?ib-style=20pass=20=E2=80=94=20line=20lengths=20and=20tactic=20s?= =?UTF-8?q?plit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Split the surviving `;`-chained tactic in `cuspForm_eq_discriminant_mul` (`change ...; ring` → two-line bullet). * Reformat declaration signatures and proof bodies that exceeded the 100-char linter limit (mostly induced by the inlined `(![4, 6] : Fin 2 → ℕ)`). No remaining lines exceed 100 chars. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 63 ++++++++++++------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 204eb42662317a..a1ac5ee9187eb4 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -176,14 +176,16 @@ private lemma mul_ne_zero {k₁ k₂ : ℤ} exact ⟨(ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hf, (ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hg⟩ -private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) (x : ModularForm 𝒮ℒ k₁) : +private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) + (x : ModularForm 𝒮ℒ k₁) : DirectSum.of (ModularForm 𝒮ℒ) k₁ x = DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by subst hk rfl -private lemma cast_modularForm_apply {k₁ k₂ : ℤ} (heq : k₁ = k₂) (h : ModularForm 𝒮ℒ k₁) - (z : ℍ) : (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by +private lemma cast_modularForm_apply {k₁ k₂ : ℤ} (heq : k₁ = k₂) + (h : ModularForm 𝒮ℒ k₁) (z : ℍ) : + (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by subst heq rfl @@ -229,7 +231,9 @@ private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ rw [DirectSum.of_mul_of] symm refine DirectSum.of_eq_of_gradedMonoid_eq <| - ModularForm.gradedMonoid_eq_of_cast (by change (↑n - 12 + 12 : ℤ) = ↑n; ring) ?_ + ModularForm.gradedMonoid_eq_of_cast ?_ ?_ + · change (↑n - 12 + 12 : ℤ) = ↑n + ring ext z set hcusp := (ModularForm.isCuspForm_iff_coeffZero_eq_zero g).mp hg change ((CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)).mul @@ -291,7 +295,8 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev DirectSum.of _ (↑n : ℤ) f ∈ Set.range evalE₄E₆ := by obtain ⟨a, b, hab⟩ : ∃ a b : ℕ, 4 * a + 6 * b = n := exists_monomial_weight (by omega) (by exact_mod_cast hk_even) - set mo := DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b + set mo := + DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b set mn := mo (↑n : ℤ) set c := (qExpansion 1 f).coeff 0 have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := @@ -411,8 +416,10 @@ private lemma weightedHomogeneous_eq_zero_of_no_monomials {n : ℕ} (p : MvPolyn exact hno _ (hp (MvPolynomial.mem_support_iff.mp hd)) private lemma weightedHomogeneous_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (d₀ : Fin 2 →₀ ℕ) - (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = n → d = d₀) : + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) + (d₀ : Fin 2 →₀ ℕ) + (huniq : ∀ d : Fin 2 →₀ ℕ, + Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = n → d = d₀) : p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by ext d rw [MvPolynomial.coeff_monomial] @@ -448,7 +455,8 @@ private lemma evalE₄E₆_monomial_grade (d : Fin 2 →₀ ℕ) (c : ℂ) (k : evalE₄E₆_mono_grade (d 0) (d 1) k hk, smul_zero] private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (k : ℤ) (hk : k ≠ ↑n) : + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) + (k : ℤ) (hk : k ≠ ↑n) : (evalE₄E₆ p) k = 0 := by rw [← MvPolynomial.support_sum_monomial_coeff p, map_sum, show (∑ x ∈ p.support, @@ -470,16 +478,21 @@ private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ · rw [DirectSum.of_eq_of_ne _ _ _ hk, evalE₄E₆_whc_grade p hp k hk] private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) : - (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) (↑n : ℤ) = - (evalE₄E₆ p) (↑n : ℤ) := by - set q := p - MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p with hq_def - have hdecomp : p = MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p + q := by + (evalE₄E₆ + (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) (↑n : ℤ) = + (evalE₄E₆ p) (↑n : ℤ) := by + set q := p - MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p + with hq_def + have hdecomp : + p = MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p + q := by simp [q] conv_rhs => rw [hdecomp, map_add] - rw [show (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p) + - evalE₄E₆ q) (↑n : ℤ) = - (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) (↑n : ℤ) + - (evalE₄E₆ q) (↑n : ℤ) from rfl] + rw [show + (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p) + + evalE₄E₆ q) (↑n : ℤ) = + (evalE₄E₆ + (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) + (↑n : ℤ) + (evalE₄E₆ q) (↑n : ℤ) from rfl] suffices h : (evalE₄E₆ q) (↑n : ℤ) = 0 by rw [h, add_zero] rw [← MvPolynomial.support_sum_monomial_coeff q, map_sum, show (∑ x ∈ q.support, evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x q))) @@ -498,8 +511,10 @@ private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) (MvPolynomial.X (0 : Fin 2) ^ a * MvPolynomial.X (1 : Fin 2) ^ b : MvPolynomial (Fin 2) ℂ) n := by - convert ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow a).mul - ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow b) using 1 + convert + ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow a).mul + ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow b) + using 1 simp only [Matrix.cons_val_zero, Matrix.cons_val_one, smul_eq_mul] omega @@ -510,11 +525,13 @@ private lemma discriminantPoly_isWeightedHomogeneous : simp only [MvPolynomial.coeff_C_mul, MvPolynomial.coeff_sub] at hd by_cases hd3 : MvPolynomial.coeff d (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) ≠ 0 - · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow 3) hd3 + · exact + ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow 3) hd3 push Not at hd3 by_cases hd6 : MvPolynomial.coeff d (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 - · exact ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow 2) hd6 + · exact + ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow 2) hd6 push Not at hd6 simp [hd3, hd6] at hd @@ -726,7 +743,8 @@ private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) induction M using Nat.strong_induction_on with | _ M ih => ?_ intro p hp _hM by_cases hall : ∀ d ∈ p.support, d 0 < 3 - · exact ⟨p, 0, hp, MvPolynomial.isWeightedHomogeneous_zero ℂ (![4, 6] : Fin 2 → ℕ) (n - 12), + · exact ⟨p, 0, hp, + MvPolynomial.isWeightedHomogeneous_zero ℂ (![4, 6] : Fin 2 → ℕ) (n - 12), by simp only [mul_zero, add_zero], hall⟩ push Not at hall obtain ⟨d, hd_mem, hd_ge⟩ := hall @@ -758,7 +776,8 @@ private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) ring private lemma reduced_isWeightedHomogeneous_eq_monomial {n : ℕ} - (r : MvPolynomial (Fin 2) ℂ) (hr : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n) + (r : MvPolynomial (Fin 2) ℂ) + (hr : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n) (hr_red : ∀ d ∈ r.support, d 0 < 3) {d₀ : Fin 2 →₀ ℕ} (hd₀ : d₀ ∈ r.support) : r = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ r) := by have hwd₀ := hr (MvPolynomial.mem_support_iff.mp hd₀) From ce9cbd5b75c0021fb22edee6a99bd8ecca5b9ae8 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:56:43 +0100 Subject: [PATCH 52/61] chore(NumberTheory/ModularForms): generalize movable helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make several helpers ready to be lifted to mathlib core in a separate PR: * `mul_ne_zero` → `modularForm_mul_ne_zero`: generalize from `𝒮ℒ` to any `Γ` with `[HasDetPlusMinusOne]` and any `(hh : 0 < h)` (`hΓ : h ∈ Γ.strictPeriods`). * `directSumOf_cast_eq` → `directSum_of_eq_cast`: generalize from `ModularForm 𝒮ℒ` to any indexed family `β : ι → Type*` of `AddCommMonoid`s. * `cast_modularForm_apply` → `modularForm_cast_apply`: generalize from `𝒮ℒ` to any `Γ`. * `weightedHomogeneous_eq_zero_of_no_monomials`, `weightedHomogeneous_unique_monomial`: generalize from `(![4, 6] : Fin 2 → ℕ)` to any weight function `w : σ → M` and any `CommSemiring R`. Plus another `surj_of_weight` golf: weight-0 case 4 → 3 lines. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index a1ac5ee9187eb4..46a146514ce88f 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -168,24 +168,24 @@ private lemma surj_of_rank_one {k : ℤ} rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, ← DirectSum.of_smul] -private lemma mul_ne_zero {k₁ k₂ : ℤ} - (f : ModularForm 𝒮ℒ k₁) (g : ModularForm 𝒮ℒ k₂) (hf : f ≠ 0) (hg : g ≠ 0) : +private lemma modularForm_mul_ne_zero {Γ : Subgroup (GL (Fin 2) ℝ)} + [Γ.HasDetPlusMinusOne] {h : ℝ} (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) {k₁ k₂ : ℤ} + (f : ModularForm Γ k₁) (g : ModularForm Γ k₂) (hf : f ≠ 0) (hg : g ≠ 0) : f.mul g ≠ 0 := by - rw [Ne, ← ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL, mul_eq_zero, not_or] - exact ⟨(ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hf, - (ModularForm.qExpansion_eq_zero_iff one_pos one_mem_strictPeriods_SL _).not.mpr hg⟩ - -private lemma directSumOf_cast_eq {k₁ k₂ : ℤ} (hk : k₁ = k₂) - (x : ModularForm 𝒮ℒ k₁) : - DirectSum.of (ModularForm 𝒮ℒ) k₁ x = - DirectSum.of (ModularForm 𝒮ℒ) k₂ (hk ▸ x) := by + rw [Ne, ← ModularForm.qExpansion_eq_zero_iff hh hΓ, + ModularForm.qExpansion_mul hh hΓ, mul_eq_zero, not_or] + exact ⟨(ModularForm.qExpansion_eq_zero_iff hh hΓ _).not.mpr hf, + (ModularForm.qExpansion_eq_zero_iff hh hΓ _).not.mpr hg⟩ + +private lemma directSum_of_eq_cast {ι : Type*} [DecidableEq ι] + {β : ι → Type*} [(i : ι) → AddCommMonoid (β i)] {i j : ι} (hk : i = j) (x : β i) : + DirectSum.of β i x = DirectSum.of β j (hk ▸ x) := by subst hk rfl -private lemma cast_modularForm_apply {k₁ k₂ : ℤ} (heq : k₁ = k₂) - (h : ModularForm 𝒮ℒ k₁) (z : ℍ) : - (heq ▸ h : ModularForm 𝒮ℒ k₂) z = h z := by +private lemma modularForm_cast_apply {Γ : Subgroup (GL (Fin 2) ℝ)} {k₁ k₂ : ℤ} + (heq : k₁ = k₂) (h : ModularForm Γ k₁) (z : ℍ) : + (heq ▸ h : ModularForm Γ k₂) z = h z := by subst heq rfl @@ -307,7 +307,7 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp)) obtain ⟨p1, hp1⟩ : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by - rw [directSumOf_cast_eq hcast] + rw [directSum_of_eq_cast hcast] exact ih _ (by omega) (hcast ▸ h') rw [show DirectSum.of _ (↑n : ℤ) f = DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn by @@ -352,10 +352,9 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), n = 0 ∨ n = 2 ∨ n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by rcases hk_odd with ⟨m, hm⟩ omega - · refine surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one - one_ne_zero_modularForm 1 ?_ f - rw [map_one] - rfl + · exact surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one + one_ne_zero_modularForm 1 + ((map_one _).trans (DirectSum.of_zero_one _).symm) f · rw [(rank_zero_iff_forall_zero.mp ModularForm.levelOne_weight_two_rank_zero) f, map_zero] exact ⟨0, map_zero _⟩ @@ -366,12 +365,12 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), (E_ne_zero (k := 6) (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) - (mul_ne_zero E₄ E₄ (E_ne_zero (by norm_num) ⟨2, rfl⟩) - (E_ne_zero (by norm_num) ⟨2, rfl⟩)) + (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₄ + (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) (MvPolynomial.X 0 ^ 2) evalE₄E₆_X_sq f · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) - (mul_ne_zero E₄ E₆ (E_ne_zero (by norm_num) ⟨2, rfl⟩) - (E_ne_zero (by norm_num) ⟨3, rfl⟩)) + (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₆ + (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) (MvPolynomial.X 0 * MvPolynomial.X 1) evalE₄E₆_X0_X1 f · push Not at hn12 exact surj_at_weight_inductive hn12 hk_odd ih f @@ -408,19 +407,21 @@ private lemma no_weight_monomial_of_two (d : Fin 2 →₀ ℕ) : rw [weight_eq_4a_6b] at h omega -private lemma weightedHomogeneous_eq_zero_of_no_monomials {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) - (hno : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight (![4, 6] : Fin 2 → ℕ) d ≠ n) : p = 0 := by +private lemma weightedHomogeneous_eq_zero_of_no_monomials + {σ R : Type*} [CommSemiring R] {M : Type*} [AddCommMonoid M] {w : σ → M} {n : M} + (p : MvPolynomial σ R) (hp : MvPolynomial.IsWeightedHomogeneous w p n) + (hno : ∀ d : σ →₀ ℕ, Finsupp.weight w d ≠ n) : p = 0 := by rw [← MvPolynomial.support_eq_empty, ← Finset.not_nonempty_iff_eq_empty] rintro ⟨d, hd⟩ exact hno _ (hp (MvPolynomial.mem_support_iff.mp hd)) -private lemma weightedHomogeneous_unique_monomial {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) - (d₀ : Fin 2 →₀ ℕ) - (huniq : ∀ d : Fin 2 →₀ ℕ, - Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = n → d = d₀) : +private lemma weightedHomogeneous_unique_monomial + {σ R : Type*} [CommSemiring R] {M : Type*} [AddCommMonoid M] + {w : σ → M} {n : M} + (p : MvPolynomial σ R) (hp : MvPolynomial.IsWeightedHomogeneous w p n) + (d₀ : σ →₀ ℕ) (huniq : ∀ d, Finsupp.weight w d = n → d = d₀) : p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by + classical ext d rw [MvPolynomial.coeff_monomial] by_cases hd : d = d₀ @@ -547,7 +548,7 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) rw [show ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ) = ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ) from - funext fun z => cast_modularForm_apply hcast _ z, + funext fun z => modularForm_cast_apply hcast _ z, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, PowerSeries.coeff_mul] simp [Finset.antidiagonal_zero, (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩] @@ -857,7 +858,7 @@ private lemma eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero {n : ℕ} (hn12 rw [DirectSum.of_apply, dif_pos hcast] at hds ext z have hpw := DFunLike.congr_fun hds z - simp only [ModularForm.zero_apply, cast_modularForm_apply hcast] at hpw ⊢ + simp only [ModularForm.zero_apply, modularForm_cast_apply hcast] at hpw ⊢ exact (mul_eq_zero.mp hpw).resolve_left (discriminant_ne_zero z) private lemma per_weight_injective_inductive_step (n : ℕ) From eb7308c1a7ca8dabfb404d82dc7ab54b466f1cab Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 07:59:05 +0100 Subject: [PATCH 53/61] chore(NumberTheory/ModularForms): more generalizations of helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `monomial_fin2_eq`: generalize from `ℂ` to any `CommSemiring R`. * Extract `weight_fin2 : Finsupp.weight w d = d 0 * w 0 + d 1 * w 1` (general Fin-2 weight identity) and let `weight_eq_4a_6b` be a one-line specialization. These continue to prepare helpers for migration to mathlib core in the forthcoming Group-A / Group-B PR splits. Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/NumberTheory/ModularForms/GradedRing.lean | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 46a146514ce88f..7c1bda2c18ff00 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -383,11 +383,15 @@ theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by ← AlgHom.mem_range] exact Subalgebra.sum_mem _ fun k _ => surj_of_weight k (x k) +private lemma weight_fin2 (w : Fin 2 → ℕ) (d : Fin 2 →₀ ℕ) : + Finsupp.weight w d = d 0 * w 0 + d 1 * w 1 := by + rw [Finsupp.weight_apply, d.sum_fintype (fun i c => c • w i) fun _ => zero_smul _ _] + simp [Fin.sum_univ_two, mul_comm] + private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = d 0 * 4 + d 1 * 6 := by - rw [Finsupp.weight_apply, - d.sum_fintype (fun i c => c • (![4, 6] : Fin 2 → ℕ) i) fun _ => zero_smul _ _] - simp [Fin.sum_univ_two, mul_comm] + rw [weight_fin2] + rfl private lemma weight_fin2_cast (d : Fin 2 →₀ ℕ) : (Finsupp.weight (![4, 6] : Fin 2 → ℕ) d : ℤ) = ↑(d 0) * 4 + ↑(d 1) * 6 := by @@ -434,7 +438,7 @@ private lemma unique_small_weight_solution {a₁ b₁ a₂ b₂ : ℕ} (h : a₁ * 4 + b₁ * 6 = a₂ * 4 + b₂ * 6) : a₁ = a₂ ∧ b₁ = b₂ := ⟨by interval_cases a₁ <;> interval_cases a₂ <;> omega, by omega⟩ -private lemma monomial_fin2_eq (d : Fin 2 →₀ ℕ) (c : ℂ) : +private lemma monomial_fin2_eq {R : Type*} [CommSemiring R] (d : Fin 2 →₀ ℕ) (c : R) : MvPolynomial.monomial d c = MvPolynomial.C c * MvPolynomial.X 0 ^ d 0 * MvPolynomial.X 1 ^ d 1 := by rw [MvPolynomial.monomial_eq, mul_assoc, d.prod_fintype _ fun _ => pow_zero _] From 2a59e8950f10597110bb02c3c3643d0afbaa1190 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 09:25:54 +0100 Subject: [PATCH 54/61] =?UTF-8?q?chore(NumberTheory/ModularForms):=20mathl?= =?UTF-8?q?ib-style=20pass=20=E2=80=94=20naming,=20helpers,=20proof=20tigh?= =?UTF-8?q?tening?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Naming (no abbreviations): - evalE₄E₆_whc_grade → evalE₄E₆_apply_eq_zero_of_ne - evalE₄E₆_whc_eq_single → evalE₄E₆_eq_of_apply - evalE₄E₆_mono_grade → evalE₄E₆_X_pow_mul_apply_eq_zero_of_ne - evalE₄E₆_monomial_grade → evalE₄E₆_monomial_apply_eq_zero_of_ne - directSumOf_evalE₄E₆_monomial_apply → directSum_of_E₄_pow_mul_E₆_pow_apply New general helpers (candidates for upstream PRs): - weightedHomogeneous_sub: sub of weighted-homogeneous polys - directSum_of_eq_sub_add_smul: of i f = of i (f - c•g) + c • of i g Proof simplifications: - monomial_qExpansion_coeff_zero_eq_one: factor through qExpansionRingHom_apply directly - discriminantPoly_isWeightedHomogeneous: use weightedHomogeneous_sub - evalE₄E₆_apply_eq_zero_of_ne / evalE₄E₆_component_eq: DirectSum.sum_apply, DirectSum.add_apply - discriminantPoly_piece_eq_monomial_sub: clean up inline show chains - per_weight_injective_zero: use weightedHomogeneous_unique_monomial - reduced_part_eq_zero: collapse two-step Q.map_add → coeff into one rewrite - surj_at_weight_inductive: use directSum_of_eq_sub_add_smul helper Co-Authored-By: Claude Opus 4.7 (1M context) --- .../NumberTheory/ModularForms/GradedRing.lean | 398 ++++++++---------- 1 file changed, 175 insertions(+), 223 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 7c1bda2c18ff00..b4af2b5298310f 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -189,34 +189,36 @@ private lemma modularForm_cast_apply {Γ : Subgroup (GL (Fin 2) ℝ)} {k₁ k₂ subst heq rfl +private lemma directSum_of_eq_sub_add_smul {ι : Type*} [DecidableEq ι] {β : ι → Type*} + [(i : ι) → AddCommGroup (β i)] {R : Type*} [Semiring R] [(i : ι) → Module R (β i)] {k : ι} + (f g : β k) (c : R) : + DirectSum.of β k f = DirectSum.of β k (f - c • g) + c • DirectSum.of β k g := by + rw [← DirectSum.of_smul, ← map_add] + congr 1 + abel + +private lemma directSum_of_E₄_pow_mul_E₆_pow_apply {a b n : ℕ} + (hab : 4 * a + 6 * b = n) : + DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) + ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (↑n : ℤ)) = + DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by + rw [DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of, + show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) by + simp only [Int.nsmul_eq_mul] + push_cast [← hab] + ring, + DirectSum.of_eq_same] + private lemma monomial_qExpansion_coeff_zero_eq_one {n a b : ℕ} (hab : 4 * a + 6 * b = n) : (qExpansion 1 ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (n : ℤ))).coeff 0 = 1 := by - set R := ModularForm.qExpansionRingHom (1 : ℝ) one_pos one_mem_strictPeriods_SL with hR_def - set prod := - DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b - with hprod_def - have hweight : (a • (4 : ℤ) + b • (6 : ℤ)) = (n : ℤ) := by - simp only [Int.nsmul_eq_mul] - push_cast [← hab] - ring - have hprod_eq : prod = DirectSum.of (ModularForm 𝒮ℒ) (n : ℤ) (prod (n : ℤ)) := by - refine DFinsupp.ext fun k : ℤ => ?_ - by_cases hk : k = (n : ℤ) - · subst hk - simp - rw [DirectSum.of_eq_of_ne _ _ _ hk, hprod_def, DirectSum.ofPow, DirectSum.ofPow, - DirectSum.of_mul_of] - exact DirectSum.of_eq_of_ne _ _ _ (hweight ▸ hk) - have hR_eval : R prod = qExpansion 1 E₄ ^ a * qExpansion 1 E₆ ^ b := by - rw [hprod_def, hR_def, map_mul, map_pow, map_pow, - ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL, - ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL] - have hR_concentrated : R prod = qExpansion 1 (prod (n : ℤ)) := by - conv_lhs => rw [hprod_eq, hR_def] - exact ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL _ _ - rw [← hR_concentrated, hR_eval, PowerSeries.coeff_mul] + rw [← ModularForm.qExpansionRingHom_apply (h := 1) one_pos one_mem_strictPeriods_SL, + directSum_of_E₄_pow_mul_E₆_pow_apply hab, map_mul, map_pow, map_pow, + ModularForm.qExpansionRingHom_apply, ModularForm.qExpansionRingHom_apply, + PowerSeries.coeff_mul] simp [Finset.antidiagonal_zero, PowerSeries.coeff_pow, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] @@ -230,12 +232,10 @@ private lemma cuspForm_eq_discriminant_mul {n : ℕ} (g : ModularForm 𝒮ℒ ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) := by rw [DirectSum.of_mul_of] symm - refine DirectSum.of_eq_of_gradedMonoid_eq <| - ModularForm.gradedMonoid_eq_of_cast ?_ ?_ - · change (↑n - 12 + 12 : ℤ) = ↑n - ring + refine DirectSum.of_eq_of_gradedMonoid_eq + (ModularForm.gradedMonoid_eq_of_cast (by change (↑n - 12 + 12 : ℤ) = ↑n; ring) ?_) ext z - set hcusp := (ModularForm.isCuspForm_iff_coeffZero_eq_zero g).mp hg + let hcusp := (ModularForm.isCuspForm_iff_coeffZero_eq_zero g).mp hg change ((CuspForm.discriminantEquiv (ModularForm.toCuspForm g hcusp)).mul ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12)) z = g z rw [ModularForm.coe_mul, Pi.mul_apply, @@ -274,20 +274,6 @@ private lemma sub_smul_qExpansion_coeff_zero_isCuspForm {k : ℤ} (f g : Modular map_sub, PowerSeries.coeff_smul] simp [hg, c] -private lemma directSumOf_evalE₄E₆_monomial_apply {a b n : ℕ} - (hab : 4 * a + 6 * b = n) : - DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) - ((DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (↑n : ℤ)) = - DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * - DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b := by - rw [DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of, - show (↑n : ℤ) = a • (4 : ℤ) + b • (6 : ℤ) by - simp only [Int.nsmul_eq_mul] - push_cast [← hab] - ring, - DirectSum.of_eq_same] - private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Even (n : ℤ)) (ih : ∀ m < n, ∀ (f : ModularForm 𝒮ℒ ↑m), DirectSum.of _ (↑m : ℤ) f ∈ Set.range evalE₄E₆) @@ -295,25 +281,19 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev DirectSum.of _ (↑n : ℤ) f ∈ Set.range evalE₄E₆ := by obtain ⟨a, b, hab⟩ : ∃ a b : ℕ, 4 * a + 6 * b = n := exists_monomial_weight (by omega) (by exact_mod_cast hk_even) - set mo := - DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b - set mn := mo (↑n : ℤ) + set mn := (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * + DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (↑n : ℤ) set c := (qExpansion 1 f).coeff 0 have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := sub_smul_qExpansion_coeff_zero_isCuspForm f mn (monomial_qExpansion_coeff_zero_eq_one hab) have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by omega - set h' := CuspForm.discriminantEquiv - (ModularForm.toCuspForm (f - c • mn) - ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp)) - obtain ⟨p1, hp1⟩ : - DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) h' ∈ Set.range evalE₄E₆ := by + obtain ⟨p1, hp1⟩ : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) + (CuspForm.discriminantEquiv (ModularForm.toCuspForm (f - c • mn) + ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp))) ∈ + Set.range evalE₄E₆ := by rw [directSum_of_eq_cast hcast] - exact ih _ (by omega) (hcast ▸ h') - rw [show DirectSum.of _ (↑n : ℤ) f = - DirectSum.of _ (↑n : ℤ) (f - c • mn) + c • DirectSum.of _ (↑n : ℤ) mn by - rw [← DirectSum.of_smul, ← map_add] - congr 1 - abel, directSumOf_evalE₄E₆_monomial_apply hab] + exact ih _ (by omega) _ + rw [directSum_of_eq_sub_add_smul f mn c, directSum_of_E₄_pow_mul_E₆_pow_apply hab] exact ⟨p1 * discriminantPoly + MvPolynomial.C c * (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b), by rw [map_add, map_mul, hp1, evalE₄E₆_discriminantPoly, cuspForm_eq_discriminant_mul (f - c • mn) hg_cusp, map_mul, @@ -330,13 +310,45 @@ private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := fun one_ne_zero (α := ℂ) (congr_fun (congr_arg (DFunLike.coe (F := ModularForm 𝒮ℒ 0)) h) UpperHalfPlane.I) +private lemma surj_of_zero_form {k : ℤ} (h : ∀ f : ModularForm 𝒮ℒ k, f = 0) + (f : ModularForm 𝒮ℒ k) : + DirectSum.of (ModularForm 𝒮ℒ) k f ∈ Set.range evalE₄E₆ := by + rw [h f, map_zero] + exact ⟨0, map_zero _⟩ + +private lemma surj_at_small_weight {n : ℕ} (hn12 : n < 12) (hk_even : Even (n : ℤ)) + (f : ModularForm 𝒮ℒ ↑n) : + DirectSum.of _ (↑n : ℤ) f ∈ Set.range evalE₄E₆ := by + obtain rfl | rfl | rfl | rfl | rfl | rfl : + n = 0 ∨ n = 2 ∨ n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by + rcases hk_even with ⟨m, hm⟩ + omega + · exact surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one + one_ne_zero_modularForm 1 + ((map_one _).trans (DirectSum.of_zero_one _).symm) f + · exact surj_of_zero_form (rank_zero_iff_forall_zero.mp + ModularForm.levelOne_weight_two_rank_zero) f + · exact surj_of_rank_one ModularForm.levelOne_weight_four_rank_one + (E_ne_zero (k := 4) (by norm_num) ⟨2, rfl⟩) + (MvPolynomial.X 0) evalE₄E₆_X0 f + · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one + (E_ne_zero (k := 6) (by norm_num) ⟨3, rfl⟩) + (MvPolynomial.X 1) evalE₄E₆_X1 f + · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) + (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₄ + (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) + (MvPolynomial.X 0 ^ 2) evalE₄E₆_X_sq f + · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) + (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₆ + (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) + (MvPolynomial.X 0 * MvPolynomial.X 1) evalE₄E₆_X0_X1 f + private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), DirectSum.of (ModularForm 𝒮ℒ) k f ∈ Set.range evalE₄E₆ := by intro k f by_cases hk_neg : k < 0 - · rw [(rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero hk_neg)) f, - map_zero] - exact ⟨0, map_zero _⟩ + · exact surj_of_zero_form + (rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero hk_neg)) f push Not at hk_neg obtain ⟨n, rfl⟩ : ∃ n : ℕ, k = (n : ℤ) := ⟨k.toNat, by omega⟩ clear hk_neg @@ -344,36 +356,12 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), induction n using Nat.strong_induction_on with | _ n ih => ?_ intro f by_cases hk_odd : Odd (n : ℤ) - · rw [ModularForm.levelOne_odd_weight_eq_zero hk_odd f, map_zero] - exact ⟨0, map_zero _⟩ + · exact surj_of_zero_form (fun f => ModularForm.levelOne_odd_weight_eq_zero hk_odd f) f rw [Int.not_odd_iff_even] at hk_odd by_cases hn12 : n < 12 - · obtain rfl | rfl | rfl | rfl | rfl | rfl : - n = 0 ∨ n = 2 ∨ n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by - rcases hk_odd with ⟨m, hm⟩ - omega - · exact surj_of_rank_one ModularForm.levelOne_weight_zero_rank_one - one_ne_zero_modularForm 1 - ((map_one _).trans (DirectSum.of_zero_one _).symm) f - · rw [(rank_zero_iff_forall_zero.mp ModularForm.levelOne_weight_two_rank_zero) f, - map_zero] - exact ⟨0, map_zero _⟩ - · exact surj_of_rank_one ModularForm.levelOne_weight_four_rank_one - (E_ne_zero (k := 4) (by norm_num) ⟨2, rfl⟩) - (MvPolynomial.X 0) evalE₄E₆_X0 f - · exact surj_of_rank_one ModularForm.levelOne_weight_six_rank_one - (E_ne_zero (k := 6) (by norm_num) ⟨3, rfl⟩) - (MvPolynomial.X 1) evalE₄E₆_X1 f - · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) - (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₄ - (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) - (MvPolynomial.X 0 ^ 2) evalE₄E₆_X_sq f - · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) - (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₆ - (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) - (MvPolynomial.X 0 * MvPolynomial.X 1) evalE₄E₆_X0_X1 f - · push Not at hn12 - exact surj_at_weight_inductive hn12 hk_odd ih f + · exact surj_at_small_weight hn12 hk_odd f + push Not at hn12 + exact surj_at_weight_inductive hn12 hk_odd ih f /-- The evaluation homomorphism `evalE₄E₆` is surjective. -/ theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by @@ -433,6 +421,14 @@ private lemma weightedHomogeneous_unique_monomial rw [if_neg (Ne.symm hd)] exact hp.coeff_eq_zero d (fun h => hd (huniq d h)) +private lemma weightedHomogeneous_sub + {σ R : Type*} [CommRing R] {M : Type*} [AddCommMonoid M] {w : σ → M} {n : M} + {p q : MvPolynomial σ R} + (hp : MvPolynomial.IsWeightedHomogeneous w p n) + (hq : MvPolynomial.IsWeightedHomogeneous w q n) : + MvPolynomial.IsWeightedHomogeneous w (p - q) n := + (MvPolynomial.weightedHomogeneousSubmodule R w n).sub_mem hp hq + private lemma unique_small_weight_solution {a₁ b₁ a₂ b₂ : ℕ} (ha₁ : a₁ < 3) (ha₂ : a₂ < 3) (h : a₁ * 4 + b₁ * 6 = a₂ * 4 + b₂ * 6) : a₁ = a₂ ∧ b₁ = b₂ := @@ -444,7 +440,7 @@ private lemma monomial_fin2_eq {R : Type*} [CommSemiring R] (d : Fin 2 →₀ rw [MvPolynomial.monomial_eq, mul_assoc, d.prod_fintype _ fun _ => pow_zero _] simp [Fin.prod_univ_two] -private lemma evalE₄E₆_mono_grade (a b : ℕ) (k : ℤ) +private lemma evalE₄E₆_X_pow_mul_apply_eq_zero_of_ne (a b : ℕ) (k : ℤ) (hk : k ≠ (↑a * 4 + ↑b * 6 : ℤ)) : (evalE₄E₆ (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b)) k = 0 := by rw [evalE₄E₆_monomial, DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of] @@ -452,61 +448,44 @@ private lemma evalE₄E₆_mono_grade (a b : ℕ) (k : ℤ) simp only [Int.nsmul_eq_mul] at heq omega -private lemma evalE₄E₆_monomial_grade (d : Fin 2 →₀ ℕ) (c : ℂ) (k : ℤ) +private lemma evalE₄E₆_monomial_apply_eq_zero_of_ne (d : Fin 2 →₀ ℕ) (c : ℂ) (k : ℤ) (hk : k ≠ (↑(d 0) * 4 + ↑(d 1) * 6 : ℤ)) : (evalE₄E₆ (MvPolynomial.monomial d c)) k = 0 := by rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, DirectSum.smul_apply, - evalE₄E₆_mono_grade (d 0) (d 1) k hk, smul_zero] + evalE₄E₆_X_pow_mul_apply_eq_zero_of_ne (d 0) (d 1) k hk, smul_zero] -private lemma evalE₄E₆_whc_grade {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) +private lemma evalE₄E₆_apply_eq_zero_of_ne {n : ℕ} (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) (k : ℤ) (hk : k ≠ ↑n) : (evalE₄E₆ p) k = 0 := by - rw [← MvPolynomial.support_sum_monomial_coeff p, map_sum, - show (∑ x ∈ p.support, - evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k = - ∑ x ∈ p.support, - (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x p))) k from - map_sum (DFinsupp.evalAddMonoidHom k) _ _] + rw [← MvPolynomial.support_sum_monomial_coeff p, map_sum, DirectSum.sum_apply] refine Finset.sum_eq_zero fun d hd => - evalE₄E₆_monomial_grade _ _ _ fun heq => hk ?_ + evalE₄E₆_monomial_apply_eq_zero_of_ne _ _ _ fun heq => hk ?_ rw [heq, ← weight_fin2_cast d, hp (MvPolynomial.mem_support_iff.mp hd)] -private lemma evalE₄E₆_whc_eq_single (n : ℕ) (p : MvPolynomial (Fin 2) ℂ) +private lemma evalE₄E₆_eq_of_apply (n : ℕ) (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) : evalE₄E₆ p = DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) ((evalE₄E₆ p) ↑n) := by refine DFinsupp.ext fun k : ℤ => ?_ by_cases hk : k = (↑n : ℤ) · subst hk simp - · rw [DirectSum.of_eq_of_ne _ _ _ hk, evalE₄E₆_whc_grade p hp k hk] + · rw [DirectSum.of_eq_of_ne _ _ _ hk, evalE₄E₆_apply_eq_zero_of_ne p hp k hk] private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) : (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) (↑n : ℤ) = (evalE₄E₆ p) (↑n : ℤ) := by - set q := p - MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p - with hq_def + set q := p - MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p with hq_def have hdecomp : p = MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p + q := by simp [q] - conv_rhs => rw [hdecomp, map_add] - rw [show - (evalE₄E₆ (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p) + - evalE₄E₆ q) (↑n : ℤ) = - (evalE₄E₆ - (MvPolynomial.weightedHomogeneousComponent (![4, 6] : Fin 2 → ℕ) n p)) - (↑n : ℤ) + (evalE₄E₆ q) (↑n : ℤ) from rfl] + conv_rhs => rw [hdecomp, map_add, DirectSum.add_apply] suffices h : (evalE₄E₆ q) (↑n : ℤ) = 0 by rw [h, add_zero] - rw [← MvPolynomial.support_sum_monomial_coeff q, map_sum, - show (∑ x ∈ q.support, evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x q))) - (↑n : ℤ) = - ∑ x ∈ q.support, - (evalE₄E₆ ((MvPolynomial.monomial x) (MvPolynomial.coeff x q))) (↑n : ℤ) from - map_sum (DFinsupp.evalAddMonoidHom (↑n : ℤ)) _ _] + rw [← MvPolynomial.support_sum_monomial_coeff q, map_sum, DirectSum.sum_apply] refine Finset.sum_eq_zero fun d hd => - evalE₄E₆_monomial_grade _ _ _ fun heq => MvPolynomial.mem_support_iff.mp hd ?_ + evalE₄E₆_monomial_apply_eq_zero_of_ne _ _ _ fun heq => MvPolynomial.mem_support_iff.mp hd ?_ rw [hq_def, MvPolynomial.coeff_sub, MvPolynomial.coeff_weightedHomogeneousComponent, if_pos ?_, sub_self] rw [weight_eq_4a_6b] @@ -526,26 +505,16 @@ private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 private lemma discriminantPoly_isWeightedHomogeneous : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) discriminantPoly 12 := by rw [discriminantPoly, MvPolynomial.smul_eq_C_mul] - intro d hd - simp only [MvPolynomial.coeff_C_mul, MvPolynomial.coeff_sub] at hd - by_cases hd3 : MvPolynomial.coeff d - (MvPolynomial.X (0 : Fin 2) ^ 3 : MvPolynomial (Fin 2) ℂ) ≠ 0 - · exact - ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow 3) hd3 - push Not at hd3 - by_cases hd6 : MvPolynomial.coeff d - (MvPolynomial.X (1 : Fin 2) ^ 2 : MvPolynomial (Fin 2) ℂ) ≠ 0 - · exact - ((MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow 2) hd6 - push Not at hd6 - simp [hd3, hd6] at hd + refine MvPolynomial.IsWeightedHomogeneous.C_mul (weightedHomogeneous_sub ?_ ?_) _ + · convert (MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow 3 using 1 + · convert (MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow 2 using 1 private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 ≤ n) (s : MvPolynomial (Fin 2) ℂ) (hs : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12)) : (qExpansion 1 ↑((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by rw [map_mul, evalE₄E₆_discriminantPoly, - evalE₄E₆_whc_eq_single (n - 12) s hs, DirectSum.of_mul_of] + evalE₄E₆_eq_of_apply (n - 12) s hs, DirectSum.of_mul_of] have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega rw [DirectSum.of_apply, dif_pos hcast] set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) @@ -597,25 +566,18 @@ private lemma per_weight_injective_zero (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p 0) (heval : (evalE₄E₆ p) (0 : ℤ) = 0) : p = 0 := by - have hpc : p = MvPolynomial.C (MvPolynomial.coeff 0 p) := by - ext d' - rw [MvPolynomial.coeff_C] - by_cases hd' : 0 = d' - · simp [hd'] - rw [if_neg hd'] - exact hp.coeff_eq_zero d' (fun hw => hd' (by - have h46' := weight_eq_4a_6b d' - rw [hw] at h46' - symm + have hpc : p = MvPolynomial.monomial (0 : Fin 2 →₀ ℕ) (MvPolynomial.coeff 0 p) := + weightedHomogeneous_unique_monomial p hp 0 (fun d hd => by + rw [weight_eq_4a_6b] at hd ext i - fin_cases i <;> simp [Finsupp.coe_zero] <;> omega)) - rw [hpc] at heval ⊢ + fin_cases i <;> simp <;> omega) + rw [hpc, MvPolynomial.monomial_zero'] at heval ⊢ rw [evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, DirectSum.smul_apply, show (1 : DirectSum ℤ (ModularForm 𝒮ℒ)) (0 : ℤ) = (1 : ModularForm 𝒮ℒ 0) from by conv_lhs => rw [← DirectSum.of_zero_one (ModularForm 𝒮ℒ)] exact DirectSum.of_eq_same _ _] at heval rcases smul_eq_zero.mp heval with hc | h1z - · rw [hc, map_zero] + · simp [hc] · exact absurd h1z one_ne_zero_modularForm private lemma discriminantPoly_piece_isWeightedHomogeneous {n : ℕ} (hn12 : 12 ≤ n) @@ -643,20 +605,21 @@ private lemma discriminantPoly_piece_eq_monomial_sub (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) = MvPolynomial.monomial d c - MvPolynomial.monomial (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) c := by - rw [show (1728 : ℂ) • discriminantPoly = - MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2 by + have h1728 : (1728 : ℂ) • discriminantPoly = + MvPolynomial.X (0 : Fin 2) ^ 3 - MvPolynomial.X (1 : Fin 2) ^ 2 := by simp only [discriminantPoly, smul_smul] - norm_num, - monomial_fin2_eq, monomial_fin2_eq, - show (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) 0 - = d 0 - 3 from by simp [Finsupp.add_apply], - show (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) 1 - = d 1 + 2 from by simp [Finsupp.add_apply], - show (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ d 0 = - MvPolynomial.X 0 ^ 3 * MvPolynomial.X 0 ^ (d 0 - 3) by - rw [← pow_add, show 3 + (d 0 - 3) = d 0 from by omega], - show (MvPolynomial.X (1 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ (d 1 + 2) = - MvPolynomial.X 1 ^ d 1 * MvPolynomial.X 1 ^ 2 by rw [pow_add]] + norm_num + have hX0 : (MvPolynomial.X (0 : Fin 2) : MvPolynomial (Fin 2) ℂ) ^ d 0 = + MvPolynomial.X 0 ^ 3 * MvPolynomial.X 0 ^ (d 0 - 3) := by + rw [← pow_add] + congr 1 + omega + have h0 : (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) 0 + = d 0 - 3 := by simp + have h1 : (Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2)) 1 + = d 1 + 2 := by simp + rw [h1728, monomial_fin2_eq, monomial_fin2_eq, h0, h1, hX0, + pow_add (MvPolynomial.X (1 : Fin 2)) (d 1) 2] ring private lemma sum_lt_sum_of_replace {α : Type*} [DecidableEq α] @@ -727,57 +690,54 @@ private lemma support_sum_lt_after_sub_δ_piece (p : MvPolynomial (Fin 2) ℂ) simp [d', Finsupp.add_apply] omega -private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) +private lemma weightedHomogeneous_poly_Delta_decomp_step {n : ℕ} (hn12 : 12 ≤ n) (p : MvPolynomial (Fin 2) ℂ) - (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) : - ∃ r s : MvPolynomial (Fin 2) ℂ, - MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n ∧ - MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12) ∧ - p = r + discriminantPoly * s ∧ - (∀ d ∈ r.support, d 0 < 3) := by - suffices key : ∀ (M : ℕ) (p : MvPolynomial (Fin 2) ℂ), - MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n → - (∑ d ∈ p.support, d 0) ≤ M → - ∃ r s : MvPolynomial (Fin 2) ℂ, - MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n ∧ - MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12) ∧ - p = r + discriminantPoly * s ∧ - (∀ d ∈ r.support, d 0 < 3) from - key _ p hp le_rfl - intro M - induction M using Nat.strong_induction_on with | _ M ih => ?_ - intro p hp _hM - by_cases hall : ∀ d ∈ p.support, d 0 < 3 - · exact ⟨p, 0, hp, - MvPolynomial.isWeightedHomogeneous_zero ℂ (![4, 6] : Fin 2 → ℕ) (n - 12), - by simp only [mul_zero, add_zero], hall⟩ - push Not at hall - obtain ⟨d, hd_mem, hd_ge⟩ := hall + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) + (hnotall : ¬ ∀ d ∈ p.support, d 0 < 3) : + ∃ p' q₁ : MvPolynomial (Fin 2) ℂ, + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p' n ∧ + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) q₁ (n - 12) ∧ + p = p' + discriminantPoly * q₁ ∧ + ∑ d ∈ p'.support, d 0 < ∑ d ∈ p.support, d 0 := by + push Not at hnotall + obtain ⟨d, hd_mem, hd_ge⟩ := hnotall have hwd : d 0 * 4 + d 1 * 6 = n := by have := (weight_eq_4a_6b d).symm.trans <| hp <| MvPolynomial.mem_support_iff.mp hd_mem omega set c := MvPolynomial.coeff d p set δ_piece := MvPolynomial.C c * ((1728 : ℂ) • discriminantPoly * - (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) with hδ_def - set p' := p - δ_piece with hp'_def - have hp_eq : p = p' + δ_piece := by simp [p'] - have hp'_wh : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p' n := - (MvPolynomial.mem_weightedHomogeneousSubmodule ℂ (![4, 6] : Fin 2 → ℕ) n _).mp - (Submodule.sub_mem _ - ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ (![4, 6] : Fin 2 → ℕ) n p).mpr hp) - ((MvPolynomial.mem_weightedHomogeneousSubmodule ℂ (![4, 6] : Fin 2 → ℕ) n - δ_piece).mpr (discriminantPoly_piece_isWeightedHomogeneous hn12 d hd_ge hwd c))) + (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1)) set q₁ := MvPolynomial.C (c * 1728) * (MvPolynomial.X (0 : Fin 2) ^ (d 0 - 3) * MvPolynomial.X (1 : Fin 2) ^ d 1) have hδ_eq : δ_piece = discriminantPoly * q₁ := by simp only [δ_piece, q₁, MvPolynomial.smul_eq_C_mul, map_mul] ring + refine ⟨p - δ_piece, q₁, weightedHomogeneous_sub hp + (discriminantPoly_piece_isWeightedHomogeneous hn12 d hd_ge hwd c), + .C_mul (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) _, ?_, + support_sum_lt_after_sub_δ_piece p hd_mem hd_ge⟩ + rw [← hδ_eq] + ring + +private lemma weightedHomogeneous_poly_Delta_decomp {n : ℕ} (hn12 : 12 ≤ n) + (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) : + ∃ r s : MvPolynomial (Fin 2) ℂ, + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) r n ∧ + MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) s (n - 12) ∧ + p = r + discriminantPoly * s ∧ + (∀ d ∈ r.support, d 0 < 3) := by + generalize hM : ∑ d ∈ p.support, d 0 = M + induction M using Nat.strong_induction_on generalizing p with | _ M ih => ?_ + by_cases hall : ∀ d ∈ p.support, d 0 < 3 + · exact ⟨p, 0, hp, MvPolynomial.isWeightedHomogeneous_zero ℂ _ _, + by simp only [mul_zero, add_zero], hall⟩ + obtain ⟨p', q₁, hp'_wh, hq₁_wh, hp_eq, hlt⟩ := + weightedHomogeneous_poly_Delta_decomp_step hn12 p hp hall obtain ⟨r, s', hr_wh, hs'_wh, hp'_eq, hr_red⟩ := - ih (∑ d' ∈ p'.support, d' 0) - ((support_sum_lt_after_sub_δ_piece p hd_mem hd_ge).trans_le _hM) p' hp'_wh le_rfl - refine ⟨r, s' + q₁, hr_wh, hs'_wh.add (.C_mul - (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) _), ?_, hr_red⟩ - rw [hp_eq, hδ_eq, hp'_eq, mul_add] + ih _ (hM ▸ hlt) p' hp'_wh rfl + refine ⟨r, s' + q₁, hr_wh, hs'_wh.add hq₁_wh, ?_, hr_red⟩ + rw [hp_eq, hp'_eq, mul_add] ring private lemma reduced_isWeightedHomogeneous_eq_monomial {n : ℕ} @@ -831,19 +791,11 @@ private lemma reduced_part_eq_zero {n : ℕ} (hn12 : 12 ≤ n) have hd₀_weight : 4 * d₀ 0 + 6 * d₀ 1 = n := by have := (weight_eq_4a_6b d₀).symm.trans (hr (MvPolynomial.mem_support_iff.mp hd₀)) omega - rw [hr_mono, map_add] at heval + rw [hr_mono, map_add, DirectSum.add_apply] at heval set Q := ModularForm.qExpansionAddHom (h := 1) one_pos one_mem_strictPeriods_SL (↑n : ℤ) - have hQ_zero : Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + - (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ)) = 0 := by - rw [show (evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ) + - (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) = - (evalE₄E₆ (MvPolynomial.monomial d₀ c) + - evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) from rfl, heval] - exact map_zero Q - rw [map_add] at hQ_zero have hQ : (Q ((evalE₄E₆ (MvPolynomial.monomial d₀ c)) (↑n : ℤ))).coeff 0 + (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by - simpa using congr_arg (fun (p : PowerSeries ℂ) => p.coeff 0) hQ_zero + rw [← LinearMap.map_add, ← Q.map_add, heval, map_zero, map_zero] rw [show (Q ((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 from evalE₄E₆_discriminantPoly_mul_coeff_zero hn12 s hs, add_zero, @@ -857,7 +809,7 @@ private lemma eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero {n : ℕ} (hn12 (hds : (evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ) = 0) : (evalE₄E₆ s) (↑(n - 12) : ℤ) = 0 := by rw [map_mul, evalE₄E₆_discriminantPoly, - evalE₄E₆_whc_eq_single (n - 12) s hs, DirectSum.of_mul_of] at hds + evalE₄E₆_eq_of_apply (n - 12) s hs, DirectSum.of_mul_of] at hds have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega rw [DirectSum.of_apply, dif_pos hcast] at hds ext z @@ -879,6 +831,21 @@ private lemma per_weight_injective_inductive_step (n : ℕ) rw [ih (n - 12) (by omega) s hs_wh (eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero hn12 s hs_wh heval), mul_zero] +private lemma per_weight_injective_at_small_weight {n : ℕ} (hn12 : n < 12) (hk_even : Even n) + (p : MvPolynomial (Fin 2) ℂ) + (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) + (heval : (evalE₄E₆ p) (↑n : ℤ) = 0) : p = 0 := by + obtain rfl | rfl | rfl | rfl | rfl | rfl : + n = 0 ∨ n = 2 ∨ n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by + rcases hk_even with ⟨m, hm⟩ + omega + · exact per_weight_injective_zero p hp heval + · exact weightedHomogeneous_eq_zero_of_no_monomials p hp no_weight_monomial_of_two + · exact per_weight_injective_small 1 0 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_small 0 1 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_small 2 0 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_small 1 1 (by omega) (by omega) rfl p hp heval + private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ), MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n → (evalE₄E₆ p) (↑n : ℤ) = 0 → p = 0 := by @@ -888,23 +855,8 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ by_cases hk_odd : Odd n · exact weightedHomogeneous_eq_zero_of_no_monomials p hp (no_weight_monomial_of_odd hk_odd) rw [Nat.not_odd_iff_even] at hk_odd - by_cases hn4 : n < 4 - · have hn02 : n = 0 ∨ n = 2 := by - obtain ⟨m, rfl⟩ := hk_odd - omega - rcases hn02 with rfl | rfl - · exact per_weight_injective_zero p hp heval - · exact weightedHomogeneous_eq_zero_of_no_monomials p hp no_weight_monomial_of_two - push Not at hn4 by_cases hn12 : n < 12 - · have hn_cases : n = 4 ∨ n = 6 ∨ n = 8 ∨ n = 10 := by - obtain ⟨m, rfl⟩ := hk_odd - omega - rcases hn_cases with rfl | rfl | rfl | rfl - · exact per_weight_injective_small 1 0 (by omega) (by omega) rfl p hp heval - · exact per_weight_injective_small 0 1 (by omega) (by omega) rfl p hp heval - · exact per_weight_injective_small 2 0 (by omega) (by omega) rfl p hp heval - · exact per_weight_injective_small 1 1 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_at_small_weight hn12 hk_odd p hp heval push Not at hn12 exact per_weight_injective_inductive_step n ih p hp heval hn12 From 94142565e594158979bc7846e8d4c2f53d933efd Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 10:39:54 +0100 Subject: [PATCH 55/61] review: address loefflerd's review comments on PR #38806 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Discriminant.lean: convert single `simp` for `discriminant_qExpansion_coeff_one` to a 3-step `calc` proof for robustness. - Basic.lean: add `ModularForm.pow` (with `coe_pow` simp lemma). - QExpansion.lean: add `ModularForm.qExpansion_pow`. - GradedRing.lean: use `pow` and `qExpansion_pow` in the `E₄³ - E₆²` def. - QExpansion.lean: move `cuspFunction_smul/neg/add/sub` and `qExpansion_smul/neg/add/sub` from `ModularFormClass` to `ModularForm` namespace, per the convention that lemmas about `Foo` go in the `Foo` namespace even when their input is class-generic. Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/NumberTheory/ModularForms/Basic.lean | 17 ++++++++++ .../DimensionFormulas/LevelOne.lean | 8 ++--- .../ModularForms/Discriminant.lean | 17 ++++++---- .../NumberTheory/ModularForms/GradedRing.lean | 24 +++++++------- .../NumberTheory/ModularForms/QExpansion.lean | 31 ++++++++++++------- 5 files changed, 63 insertions(+), 34 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index cfb4abba9ed314..e687391fa631f6 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -571,6 +571,23 @@ theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMo cases h exact congr_arg _ h2 +/-- The `n`-th power of a modular form, as a modular form of weight `n * k`. -/ +def pow {Γ : Subgroup (GL (Fin 2) ℝ)} [Γ.HasDetPlusMinusOne] {k : ℤ} (f : ModularForm Γ k) : + ∀ (n : ℕ), ModularForm Γ ((n : ℤ) * k) + | 0 => mcast (by simp) (1 : ModularForm Γ 0) + | n + 1 => mcast (by push_cast; ring) ((f.pow n).mul f) + +@[simp] +lemma coe_pow {Γ : Subgroup (GL (Fin 2) ℝ)} [Γ.HasDetPlusMinusOne] {k : ℤ} + (f : ModularForm Γ k) (n : ℕ) : ⇑(f.pow n) = (⇑f) ^ n := by + induction n with + | zero => + change (1 : ℍ → ℂ) = _ + rw [pow_zero] + | succ n ih => + change ((f.pow n).mul f : ℍ → ℂ) = _ + rw [coe_mul, ih, pow_succ] + instance (Γ : Subgroup (GL (Fin 2) ℝ)) [Γ.HasDetPlusMinusOne] : GradedMonoid.GOne (ModularForm Γ) where one := 1 diff --git a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean index 0ddf7a000f7e55..dd37aa7f69b6b1 100644 --- a/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean +++ b/Mathlib/NumberTheory/ModularForms/DimensionFormulas/LevelOne.lean @@ -136,8 +136,8 @@ lemma ModularForm.rank_eq_one_add_rank_cuspForm {k : ℕ} (hk : 3 ≤ k) (hk2 : exact one_ne_zero <| hE.symm.trans <| (isCuspForm_iff_coeffZero_eq_zero _).mp h · refine (Submodule.Quotient.forall _).mpr fun f ↦ ⟨(qExpansion 1 f).coeff 0, ?_⟩ rw [← Submodule.Quotient.mk_smul, Submodule.Quotient.eq, mem_cuspFormSubmodule_iff, - isCuspForm_iff_coeffZero_eq_zero, ModularForm.coe_sub, ModularFormClass.qExpansion_sub, - IsGLPos.coe_smul, ModularFormClass.qExpansion_smul, map_sub, + isCuspForm_iff_coeffZero_eq_zero, ModularForm.coe_sub, ModularForm.qExpansion_sub, + IsGLPos.coe_smul, ModularForm.qExpansion_smul, map_sub, PowerSeries.coeff_smul, E_qExpansion_coeff_zero hk hk2, smul_eq_mul, mul_one, sub_self] all_goals simp @@ -187,12 +187,12 @@ private lemma weight_two_qExpansion_eq_zero (f : ModularForm 𝒮ℒ 2) : qExpan (Module.rank_eq_one_iff_finrank_eq_one.mp levelOne_weight_six_rank_one) _ have hqc4 : c4 • qExpansion 1 (E₄ : ℍ → ℂ) = qExpansion 1 (f : ℍ → ℂ) ^ 2 := by rw [pow_two, ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, - ← ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, + ← ModularForm.qExpansion_smul one_pos one_mem_strictPeriods_SL c4 E₄, show (c4 • E₄ : ℍ → ℂ) = (f.mul f) from congrArg DFunLike.coe hc4] have hqc6 : c6 • qExpansion 1 E₆ = qExpansion 1 (f : ℍ → ℂ) ^ 3 := by rw [pow_succ, pow_two, ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f f, ← ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (f.mul f) f, - ← ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆, + ← ModularForm.qExpansion_smul one_pos one_mem_strictPeriods_SL c6 E₆, show (c6 • E₆ : ℍ → ℂ) = (f.mul f).mul f from congrArg DFunLike.coe hc6] exact eq_zero_of_pow_eq_smul (E_qExpansion_coeff_zero _ ⟨2, rfl⟩) (E_qExpansion_coeff_zero _ ⟨3, rfl⟩) E₄_qExpansion_coeff_one E₆_qExpansion_coeff_one hqc4 hqc6 diff --git a/Mathlib/NumberTheory/ModularForms/Discriminant.lean b/Mathlib/NumberTheory/ModularForms/Discriminant.lean index 627a7139ddaa04..5bec8502b02a13 100644 --- a/Mathlib/NumberTheory/ModularForms/Discriminant.lean +++ b/Mathlib/NumberTheory/ModularForms/Discriminant.lean @@ -209,12 +209,17 @@ private lemma discriminant_cuspFunction_eqOn : Set.EqOn (cuspFunction 1 Δ) /-- The first q-expansion coefficient of the modular discriminant is 1. -/ lemma discriminant_qExpansion_coeff_one : (qExpansion 1 Δ).coeff 1 = 1 := by have hmem : (0 : ℂ) ∈ Metric.ball (0 : ℂ) 1 := Metric.mem_ball_self one_pos - simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, - ← derivWithin_of_isOpen Metric.isOpen_ball hmem, - derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem), - derivWithin_fun_mul (s := Metric.ball 0 1) differentiableWithinAt_id' - (differentiableOn_tprod_one_sub_pow_pow 24 _ hmem), - derivWithin_id' _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + calc (qExpansion 1 Δ).coeff 1 + = derivWithin (cuspFunction 1 Δ) (Metric.ball 0 1) 0 := by + simp [qExpansion_coeff, iteratedDeriv_succ, iteratedDeriv_zero, + ← derivWithin_of_isOpen Metric.isOpen_ball hmem] + _ = derivWithin (fun q ↦ q * ∏' i, (1 - q ^ (i + 1)) ^ 24) (Metric.ball 0 1) 0 := + derivWithin_congr discriminant_cuspFunction_eqOn (discriminant_cuspFunction_eqOn hmem) + _ = 1 := by + rw [derivWithin_fun_mul (s := Metric.ball 0 1) differentiableWithinAt_id' + (differentiableOn_tprod_one_sub_pow_pow 24 _ hmem), + derivWithin_id' _ _ (Metric.isOpen_ball.uniqueDiffWithinAt hmem)] + simp end diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index b4af2b5298310f..3915bb05eba486 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -41,25 +41,25 @@ namespace ModularForm /-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄) - - ModularForm.mcast (by norm_num) (E₆.mul E₆) + ModularForm.mcast (by decide) (E₄.pow 3) - ModularForm.mcast (by decide) (E₆.pow 2) private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by - change E₄ z * E₄ z * E₄ z - E₆ z * E₆ z = _ - ring + change ⇑(E₄.pow 3) z - ⇑(E₆.pow 2) z = _ + rw [coe_pow, coe_pow] + rfl private lemma E₄CubeSubE₆SqForm_qExpansion_eq : qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - qExpansion 1 E₆ * qExpansion 1 E₆ := by rw [show qExpansion 1 E₄CubeSubE₆SqForm = - qExpansion 1 ((E₄.mul E₄).mul E₄) - qExpansion 1 (E₆.mul E₆) from - ModularFormClass.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by norm_num) ((E₄.mul E₄).mul E₄)) - (ModularForm.mcast (by norm_num) (E₆.mul E₆)), - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL (E₄.mul E₄) E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₄ E₄, - ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL E₆ E₆] + qExpansion 1 (E₄.pow 3) - qExpansion 1 (E₆.pow 2) from + ModularForm.qExpansion_sub one_pos one_mem_strictPeriods_SL + (ModularForm.mcast (by decide) (E₄.pow 3)) + (ModularForm.mcast (by decide) (E₆.pow 2)), + ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₄ 3, + ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₆ 2] + ring private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ @@ -82,7 +82,7 @@ theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg have hc_eq : c = 1728 := by have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc - have hgΔ := ModularFormClass.qExpansion_smul one_pos one_mem_strictPeriods_SL c + have hgΔ := ModularForm.qExpansion_smul one_pos one_mem_strictPeriods_SL c CuspForm.discriminant rw [hcΔ, hgE] at hgΔ simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, diff --git a/Mathlib/NumberTheory/ModularForms/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/QExpansion.lean index 06ff2fd364d9a0..0dec76a41cf843 100644 --- a/Mathlib/NumberTheory/ModularForms/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/QExpansion.lean @@ -522,7 +522,7 @@ lemma qExpansion_one (h) : qExpansion h (1 : ℍ → ℂ) = 1 := by end UpperHalfPlane -namespace ModularFormClass +namespace ModularForm protected lemma cuspFunction_smul (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) (a : ℂ) (f : F) [ModularFormClass F Γ k] : cuspFunction h (a • f) = a • cuspFunction h f := @@ -544,6 +544,12 @@ protected lemma cuspFunction_sub {G : Type*} [FunLike G ℍ ℂ] (hh : 0 < h) cuspFunction_sub (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ).continuousAt (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ).continuousAt +protected lemma cuspFunction_mul [Γ.HasDetPlusMinusOne] (hh : 0 < h) + (hΓ : h ∈ Γ.strictPeriods) {a b : ℤ} (f : ModularForm Γ a) (g : ModularForm Γ b) : + cuspFunction h (f.mul g) = cuspFunction h f * cuspFunction h g := + cuspFunction_mul (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ).continuousAt + (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ).continuousAt + protected lemma qExpansion_smul (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) (a : ℂ) (f : F) [ModularFormClass F Γ k] : qExpansion h (a • f) = a • qExpansion h f := qExpansion_smul (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ) a @@ -564,16 +570,6 @@ protected lemma qExpansion_sub {G : Type*} [FunLike G ℍ ℂ] (hh : 0 < h) qExpansion_sub (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ) (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ) -end ModularFormClass - -namespace ModularForm - -protected lemma cuspFunction_mul [Γ.HasDetPlusMinusOne] (hh : 0 < h) - (hΓ : h ∈ Γ.strictPeriods) {a b : ℤ} (f : ModularForm Γ a) (g : ModularForm Γ b) : - cuspFunction h (f.mul g) = cuspFunction h f * cuspFunction h g := - cuspFunction_mul (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ).continuousAt - (ModularFormClass.analyticAt_cuspFunction_zero g hh hΓ).continuousAt - protected lemma qExpansion_mul [Γ.HasDetPlusMinusOne] (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) {a b : ℤ} (f : ModularForm Γ a) (g : ModularForm Γ b) : qExpansion h (f.mul g) = qExpansion h f * qExpansion h g := @@ -589,12 +585,23 @@ protected lemma qExpansion_one [Γ.HasDetPlusMinusOne] : qExpansion h (1 : ModularForm Γ 0) = 1 := by simp [qExpansion_one] +protected lemma qExpansion_pow [Γ.HasDetPlusMinusOne] (hh : 0 < h) + (hΓ : h ∈ Γ.strictPeriods) (f : ModularForm Γ k) (n : ℕ) : + qExpansion h (f.pow n) = (qExpansion h f) ^ n := by + induction n with + | zero => + change qExpansion h (1 : ModularForm Γ 0) = _ + rw [pow_zero, ModularForm.qExpansion_one] + | succ n ih => + change qExpansion h ((f.pow n).mul f) = _ + rw [ModularForm.qExpansion_mul hh hΓ, ih, pow_succ] + /-- The qExpansion map as an additive group hom. to power series over `ℂ`. -/ def qExpansionAddHom (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) (k : ℤ) : ModularForm Γ k →+ PowerSeries ℂ where toFun f := qExpansion h f map_zero' := qExpansion_zero h - map_add' f g := ModularFormClass.qExpansion_add hh hΓ f g + map_add' f g := ModularForm.qExpansion_add hh hΓ f g open scoped DirectSum in /-- The qExpansion map as a map from the graded ring of modular forms to power series over `ℂ`. -/ From 036c15bec99de2d89af61bb0f12302453c5e43bc Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Sun, 3 May 2026 10:49:26 +0100 Subject: [PATCH 56/61] review: also rename remaining ModularFormClass.qExpansion_smul in GradedRing This was missed by the cherry-pick because the graded-ring branch has an extra usage in `sub_smul_qExpansion_coeff_zero_isCuspForm` that wasn't on the discriminant branch. Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/NumberTheory/ModularForms/GradedRing.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 3915bb05eba486..786d042a3b1a05 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -269,7 +269,7 @@ private lemma sub_smul_qExpansion_coeff_zero_isCuspForm {k : ℤ} (f g : Modular qExpansion 1 ⇑f - qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) from (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL k).map_sub f (c • g), show qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) = c • qExpansion 1 ⇑g from - ModularFormClass.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := k) + ModularForm.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := k) one_pos one_mem_strictPeriods_SL c g, map_sub, PowerSeries.coeff_smul] simp [hg, c] From 993f681de27a8643cecafb13b14d4841ef80c004 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 4 May 2026 10:32:25 +0100 Subject: [PATCH 57/61] feat(NumberTheory/ModularForms): add API lemmas needed for level-1 graded ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds five lemmas extracted from the upcoming graded-ring PR (#38813), so that that PR can be reviewed in smaller pieces: * `DirectSum.of_eq_of_eq` (Algebra/DirectSum/Basic): cast indices in `of`. * `DirectSum.of_eq_sub_add_smul` (Algebra/DirectSum/Module): the identity `of i f = of i (f - c•g) + c • of i g`. * `ModularForm.cast_apply` (NumberTheory/ModularForms/Basic): a ModularForm cast through a weight equality has the same pointwise values. * `ModularForm.mul_ne_zero` (NumberTheory/ModularForms/QExpansion): the product of two non-zero modular forms is non-zero (via integral domain structure of `PowerSeries ℂ`). * `ModularForm.sub_smul_isCuspForm` (NumberTheory/ModularForms/CuspFormSubmodule): for level-1 forms `f, g` with `(qExpansion 1 g).coeff 0 = 1`, the form `f - (qExpansion 1 f).coeff 0 • g` is a cusp form. Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/Algebra/DirectSum/Basic.lean | 3 +++ Mathlib/Algebra/DirectSum/Module.lean | 7 +++++++ Mathlib/NumberTheory/ModularForms/Basic.lean | 6 ++++++ .../ModularForms/CuspFormSubmodule.lean | 16 ++++++++++++++++ .../NumberTheory/ModularForms/QExpansion.lean | 9 +++++++++ 5 files changed, 41 insertions(+) diff --git a/Mathlib/Algebra/DirectSum/Basic.lean b/Mathlib/Algebra/DirectSum/Basic.lean index c491917e5820ee..9fb48b916557fc 100644 --- a/Mathlib/Algebra/DirectSum/Basic.lean +++ b/Mathlib/Algebra/DirectSum/Basic.lean @@ -139,6 +139,9 @@ theorem of_eq_of_ne (i j : ι) (x : β i) (h : j ≠ i) : (of _ i x) j = 0 := lemma of_apply {i : ι} (j : ι) (x : β i) : of β i x j = if h : i = j then Eq.recOn h x else 0 := DFinsupp.single_apply +theorem of_eq_of_eq {i j : ι} (h : i = j) (x : β i) : of β i x = of β j (h ▸ x) := by + subst h; rfl + theorem mk_apply_of_mem {s : Finset ι} {f : ∀ i : (↑s : Set ι), β i.val} {n : ι} (hn : n ∈ s) : mk β s f n = f ⟨n, hn⟩ := DFinsupp.mk_of_mem hn diff --git a/Mathlib/Algebra/DirectSum/Module.lean b/Mathlib/Algebra/DirectSum/Module.lean index e10dff85371f95..b04e1be4e680e4 100644 --- a/Mathlib/Algebra/DirectSum/Module.lean +++ b/Mathlib/Algebra/DirectSum/Module.lean @@ -93,6 +93,13 @@ theorem mk_smul (s : Finset ι) (c : R) (x) : mk M s (c • x) = c • mk M s x theorem of_smul (i : ι) (c : R) (x) : of M i (c • x) = c • of M i x := (lof R ι M i).map_smul c x +theorem of_eq_sub_add_smul {M : ι → Type*} [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] + {i : ι} (f g : M i) (c : R) : + of M i f = of M i (f - c • g) + c • of M i g := by + rw [← of_smul, ← map_add] + congr 1 + abel + variable {R} theorem support_smul [∀ (i : ι) (x : M i), Decidable (x ≠ 0)] (c : R) (v : ⨁ i, M i) : diff --git a/Mathlib/NumberTheory/ModularForms/Basic.lean b/Mathlib/NumberTheory/ModularForms/Basic.lean index e687391fa631f6..2bd129fef3f22b 100644 --- a/Mathlib/NumberTheory/ModularForms/Basic.lean +++ b/Mathlib/NumberTheory/ModularForms/Basic.lean @@ -564,6 +564,12 @@ def mcast {a b : ℤ} {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : a = b) (f : Modu holo' := f.holo' bdd_at_cusps' hc := h ▸ f.bdd_at_cusps' (hΓ ▸ hc) +theorem cast_apply {Γ : Subgroup (GL (Fin 2) ℝ)} {k₁ k₂ : ℤ} + (heq : k₁ = k₂) (f : ModularForm Γ k₁) (z : ℍ) : + (heq ▸ f : ModularForm Γ k₂) z = f z := by + subst heq + rfl + @[ext (iff := false)] theorem gradedMonoid_eq_of_cast {Γ : Subgroup (GL (Fin 2) ℝ)} {a b : GradedMonoid (ModularForm Γ)} (h : a.fst = b.fst) (h2 : mcast h a.snd = b.snd) : a = b := by diff --git a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean index 5d38f28dbec919..cfcec35f759233 100644 --- a/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean +++ b/Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean @@ -136,6 +136,22 @@ lemma isCuspForm_iff_coeffZero_eq_zero (f : ModularForm 𝒮ℒ k) : (periodic_comp_ofComplex _ one_mem_strictPeriods_SL)] exact (CuspFormClass.zero_at_infty g).valueAtInfty_eq_zero +/-- Subtracting `(qExpansion 1 f).coeff 0 • g` from `f` (where `g` has constant qExpansion 1) +gives a cusp form. -/ +lemma sub_smul_isCuspForm (f g : ModularForm 𝒮ℒ k) + (hg : (qExpansion 1 g).coeff 0 = 1) : + ModularForm.IsCuspForm (f - (qExpansion 1 f).coeff 0 • g) := by + set c := (qExpansion 1 f).coeff 0 + rw [ModularForm.isCuspForm_iff_coeffZero_eq_zero, + show qExpansion 1 ⇑(f - c • g : ModularForm 𝒮ℒ k) = + qExpansion 1 ⇑f - qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) from + (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL k).map_sub f (c • g), + show qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) = c • qExpansion 1 ⇑g from + ModularForm.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := k) + one_pos one_mem_strictPeriods_SL c g, + map_sub, PowerSeries.coeff_smul] + simp [hg, c] + end SL2Z end ModularForm diff --git a/Mathlib/NumberTheory/ModularForms/QExpansion.lean b/Mathlib/NumberTheory/ModularForms/QExpansion.lean index 0dec76a41cf843..4c7fba913e3e65 100644 --- a/Mathlib/NumberTheory/ModularForms/QExpansion.lean +++ b/Mathlib/NumberTheory/ModularForms/QExpansion.lean @@ -10,6 +10,7 @@ public import Mathlib.Analysis.Complex.UpperHalfPlane.Exp public import Mathlib.NumberTheory.ModularForms.Basic public import Mathlib.NumberTheory.ModularForms.Identities public import Mathlib.RingTheory.PowerSeries.Basic +public import Mathlib.RingTheory.PowerSeries.NoZeroDivisors /-! # q-expansions of functions on the upper half plane @@ -596,6 +597,14 @@ protected lemma qExpansion_pow [Γ.HasDetPlusMinusOne] (hh : 0 < h) change qExpansion h ((f.pow n).mul f) = _ rw [ModularForm.qExpansion_mul hh hΓ, ih, pow_succ] +protected lemma mul_ne_zero [Γ.HasDetPlusMinusOne] (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) + {a b : ℤ} {f : ModularForm Γ a} {g : ModularForm Γ b} (hf : f ≠ 0) (hg : g ≠ 0) : + f.mul g ≠ 0 := by + rw [Ne, ← ModularForm.qExpansion_eq_zero_iff hh hΓ, + ModularForm.qExpansion_mul hh hΓ, mul_eq_zero, not_or] + exact ⟨(ModularForm.qExpansion_eq_zero_iff hh hΓ _).not.mpr hf, + (ModularForm.qExpansion_eq_zero_iff hh hΓ _).not.mpr hg⟩ + /-- The qExpansion map as an additive group hom. to power series over `ℂ`. -/ def qExpansionAddHom (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) (k : ℤ) : ModularForm Γ k →+ PowerSeries ℂ where From c56a0bcfae958a71894028b88128cf3043d99ca7 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 4 May 2026 10:34:32 +0100 Subject: [PATCH 58/61] feat(RingTheory/MvPolynomial/WeightedHomogeneous): add sub, eq_zero_of_no_monomials, eq_monomial_of_unique_weight MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds three weighted-homogeneous API lemmas extracted from the upcoming graded-ring PR (#38813): * `IsWeightedHomogeneous.sub`: difference of weighted-homogeneous polynomials of degree `n` is weighted-homogeneous of degree `n` (mirrors `add`, requires `CommRing R`). * `IsWeightedHomogeneous.eq_zero_of_no_monomials`: a weighted-homogeneous polynomial of degree `n` is zero if no monomial has weight `n`. * `IsWeightedHomogeneous.eq_monomial_of_unique_weight`: a weighted-homogeneous polynomial of degree `n` whose support is concentrated at a single `d₀` equals `monomial d₀ (coeff d₀ φ)`. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../MvPolynomial/WeightedHomogeneous.lean | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean index e9b69b061fa3cc..15b91becb257a0 100644 --- a/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean +++ b/Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean @@ -245,6 +245,32 @@ theorem add {w : σ → M} (hφ : IsWeightedHomogeneous w φ n) (hψ : IsWeighte IsWeightedHomogeneous w (φ + ψ) n := (weightedHomogeneousSubmodule R w n).add_mem hφ hψ +/-- The difference of two weighted homogeneous polynomials of degree `n` is weighted homogeneous + of weighted degree `n`. -/ +theorem sub {R : Type*} [CommRing R] {w : σ → M} {φ ψ : MvPolynomial σ R} + (hφ : IsWeightedHomogeneous w φ n) (hψ : IsWeightedHomogeneous w ψ n) : + IsWeightedHomogeneous w (φ - ψ) n := + (weightedHomogeneousSubmodule R w n).sub_mem hφ hψ + +/-- A weighted homogeneous polynomial of degree `n` is zero if no monomial has weight `n`. -/ +theorem eq_zero_of_no_monomials {w : σ → M} (hφ : IsWeightedHomogeneous w φ n) + (hno : ∀ d : σ →₀ ℕ, weight w d ≠ n) : φ = 0 := by + rw [← support_eq_empty, ← Finset.not_nonempty_iff_eq_empty] + rintro ⟨d, hd⟩ + exact hno _ (hφ (mem_support_iff.mp hd)) + +/-- A weighted homogeneous polynomial of degree `n` whose support degrees are all equal to a +fixed `d₀` is a single monomial. -/ +theorem eq_monomial_of_unique_weight {w : σ → M} (hφ : IsWeightedHomogeneous w φ n) (d₀ : σ →₀ ℕ) + (huniq : ∀ d, weight w d = n → d = d₀) : φ = monomial d₀ (coeff d₀ φ) := by + classical + ext d + rw [coeff_monomial] + by_cases hd : d = d₀ + · simp [hd] + rw [if_neg (Ne.symm hd)] + exact hφ.coeff_eq_zero d (fun h => hd (huniq d h)) + /-- The sum of weighted homogeneous polynomials of degree `n` is weighted homogeneous of weighted degree `n`. -/ theorem sum {ι : Type*} (s : Finset ι) (φ : ι → MvPolynomial σ R) (n : M) {w : σ → M} From 3d562381cd42da1b7098c8811a86bff6aa7341c2 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Mon, 4 May 2026 10:52:47 +0100 Subject: [PATCH 59/61] refactor: use mathlib API from prereq PRs, drop local helpers Removes ~70 lines of local API helpers from GradedRing.lean now that they are added to the appropriate mathlib files via the two prerequisite PRs: * From `Mathlib/NumberTheory/ModularForms/Basic.lean`: `ModularForm.cast_apply`. * From `Mathlib/Algebra/DirectSum/Basic.lean`: `DirectSum.of_eq_of_eq`. * From `Mathlib/Algebra/DirectSum/Module.lean`: `DirectSum.of_eq_sub_add_smul`. * From `Mathlib/NumberTheory/ModularForms/QExpansion.lean`: `ModularForm.mul_ne_zero`. * From `Mathlib/NumberTheory/ModularForms/CuspFormSubmodule.lean`: `ModularForm.sub_smul_isCuspForm`. * From `Mathlib/RingTheory/MvPolynomial/WeightedHomogeneous.lean`: `IsWeightedHomogeneous.sub`, `eq_zero_of_no_monomials`, `eq_monomial_of_unique_weight`. Also fixes the proof of `DirectSum.of_eq_sub_add_smul` to avoid an instance ambiguity between `AddCommMonoid` and `AddCommGroup` from the section variables; the proof now uses an explicit `M` declaration. Co-Authored-By: Claude Opus 4.7 (1M context) --- Mathlib/Algebra/DirectSum/Module.lean | 6 +- .../NumberTheory/ModularForms/GradedRing.lean | 99 +++---------------- 2 files changed, 16 insertions(+), 89 deletions(-) diff --git a/Mathlib/Algebra/DirectSum/Module.lean b/Mathlib/Algebra/DirectSum/Module.lean index b04e1be4e680e4..a3a8c724d0e7e5 100644 --- a/Mathlib/Algebra/DirectSum/Module.lean +++ b/Mathlib/Algebra/DirectSum/Module.lean @@ -93,12 +93,12 @@ theorem mk_smul (s : Finset ι) (c : R) (x) : mk M s (c • x) = c • mk M s x theorem of_smul (i : ι) (c : R) (x) : of M i (c • x) = c • of M i x := (lof R ι M i).map_smul c x -theorem of_eq_sub_add_smul {M : ι → Type*} [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] +theorem of_eq_sub_add_smul {ι : Type*} [DecidableEq ι] {M : ι → Type*} + [∀ i, AddCommGroup (M i)] {R : Type*} [Semiring R] [∀ i, Module R (M i)] {i : ι} (f g : M i) (c : R) : of M i f = of M i (f - c • g) + c • of M i g := by rw [← of_smul, ← map_add] - congr 1 - abel + exact (congr_arg (of M i) (sub_add_cancel f (c • g))).symm variable {R} diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 786d042a3b1a05..6ff9dcc84d57fa 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -168,35 +168,6 @@ private lemma surj_of_rank_one {k : ℤ} rw [map_mul, evalE₄E₆_C, hp, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, ← DirectSum.of_smul] -private lemma modularForm_mul_ne_zero {Γ : Subgroup (GL (Fin 2) ℝ)} - [Γ.HasDetPlusMinusOne] {h : ℝ} (hh : 0 < h) (hΓ : h ∈ Γ.strictPeriods) {k₁ k₂ : ℤ} - (f : ModularForm Γ k₁) (g : ModularForm Γ k₂) (hf : f ≠ 0) (hg : g ≠ 0) : - f.mul g ≠ 0 := by - rw [Ne, ← ModularForm.qExpansion_eq_zero_iff hh hΓ, - ModularForm.qExpansion_mul hh hΓ, mul_eq_zero, not_or] - exact ⟨(ModularForm.qExpansion_eq_zero_iff hh hΓ _).not.mpr hf, - (ModularForm.qExpansion_eq_zero_iff hh hΓ _).not.mpr hg⟩ - -private lemma directSum_of_eq_cast {ι : Type*} [DecidableEq ι] - {β : ι → Type*} [(i : ι) → AddCommMonoid (β i)] {i j : ι} (hk : i = j) (x : β i) : - DirectSum.of β i x = DirectSum.of β j (hk ▸ x) := by - subst hk - rfl - -private lemma modularForm_cast_apply {Γ : Subgroup (GL (Fin 2) ℝ)} {k₁ k₂ : ℤ} - (heq : k₁ = k₂) (h : ModularForm Γ k₁) (z : ℍ) : - (heq ▸ h : ModularForm Γ k₂) z = h z := by - subst heq - rfl - -private lemma directSum_of_eq_sub_add_smul {ι : Type*} [DecidableEq ι] {β : ι → Type*} - [(i : ι) → AddCommGroup (β i)] {R : Type*} [Semiring R] [(i : ι) → Module R (β i)] {k : ι} - (f g : β k) (c : R) : - DirectSum.of β k f = DirectSum.of β k (f - c • g) + c • DirectSum.of β k g := by - rw [← DirectSum.of_smul, ← map_add] - congr 1 - abel - private lemma directSum_of_E₄_pow_mul_E₆_pow_apply {a b n : ℕ} (hab : 4 * a + 6 * b = n) : DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) @@ -260,20 +231,6 @@ private lemma discriminant_mem_range_evalE₄E₆ : Set.range evalE₄E₆ := ⟨_, evalE₄E₆_discriminantPoly⟩ -private lemma sub_smul_qExpansion_coeff_zero_isCuspForm {k : ℤ} (f g : ModularForm 𝒮ℒ k) - (hg : (qExpansion 1 g).coeff 0 = 1) : - ModularForm.IsCuspForm (f - (qExpansion 1 f).coeff 0 • g) := by - set c := (qExpansion 1 f).coeff 0 - rw [ModularForm.isCuspForm_iff_coeffZero_eq_zero, - show qExpansion 1 ⇑(f - c • g : ModularForm 𝒮ℒ k) = - qExpansion 1 ⇑f - qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) from - (ModularForm.qExpansionAddHom one_pos one_mem_strictPeriods_SL k).map_sub f (c • g), - show qExpansion 1 ⇑(c • g : ModularForm 𝒮ℒ k) = c • qExpansion 1 ⇑g from - ModularForm.qExpansion_smul (h := 1) (Γ := 𝒮ℒ) (k := k) - one_pos one_mem_strictPeriods_SL c g, - map_sub, PowerSeries.coeff_smul] - simp [hg, c] - private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Even (n : ℤ)) (ih : ∀ m < n, ∀ (f : ModularForm 𝒮ℒ ↑m), DirectSum.of _ (↑m : ℤ) f ∈ Set.range evalE₄E₆) @@ -285,15 +242,15 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (↑n : ℤ) set c := (qExpansion 1 f).coeff 0 have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := - sub_smul_qExpansion_coeff_zero_isCuspForm f mn (monomial_qExpansion_coeff_zero_eq_one hab) + ModularForm.sub_smul_isCuspForm f mn (monomial_qExpansion_coeff_zero_eq_one hab) have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by omega obtain ⟨p1, hp1⟩ : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) (CuspForm.discriminantEquiv (ModularForm.toCuspForm (f - c • mn) ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp))) ∈ Set.range evalE₄E₆ := by - rw [directSum_of_eq_cast hcast] + rw [DirectSum.of_eq_of_eq hcast] exact ih _ (by omega) _ - rw [directSum_of_eq_sub_add_smul f mn c, directSum_of_E₄_pow_mul_E₆_pow_apply hab] + rw [DirectSum.of_eq_sub_add_smul f mn c, directSum_of_E₄_pow_mul_E₆_pow_apply hab] exact ⟨p1 * discriminantPoly + MvPolynomial.C c * (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b), by rw [map_add, map_mul, hp1, evalE₄E₆_discriminantPoly, cuspForm_eq_discriminant_mul (f - c • mn) hg_cusp, map_mul, @@ -335,11 +292,11 @@ private lemma surj_at_small_weight {n : ℕ} (hn12 : n < 12) (hk_even : Even (n (E_ne_zero (k := 6) (by norm_num) ⟨3, rfl⟩) (MvPolynomial.X 1) evalE₄E₆_X1 f · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨4, rfl⟩ (by norm_num)) - (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₄ + (ModularForm.mul_ne_zero one_pos one_mem_strictPeriods_SL (f := E₄) (g := E₄) (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨2, rfl⟩)) (MvPolynomial.X 0 ^ 2) evalE₄E₆_X_sq f · exact surj_of_rank_one (rank_one_of_lt_twelve (by norm_num) ⟨5, rfl⟩ (by norm_num)) - (modularForm_mul_ne_zero one_pos one_mem_strictPeriods_SL E₄ E₆ + (ModularForm.mul_ne_zero one_pos one_mem_strictPeriods_SL (f := E₄) (g := E₆) (E_ne_zero (by norm_num) ⟨2, rfl⟩) (E_ne_zero (by norm_num) ⟨3, rfl⟩)) (MvPolynomial.X 0 * MvPolynomial.X 1) evalE₄E₆_X0_X1 f @@ -399,36 +356,6 @@ private lemma no_weight_monomial_of_two (d : Fin 2 →₀ ℕ) : rw [weight_eq_4a_6b] at h omega -private lemma weightedHomogeneous_eq_zero_of_no_monomials - {σ R : Type*} [CommSemiring R] {M : Type*} [AddCommMonoid M] {w : σ → M} {n : M} - (p : MvPolynomial σ R) (hp : MvPolynomial.IsWeightedHomogeneous w p n) - (hno : ∀ d : σ →₀ ℕ, Finsupp.weight w d ≠ n) : p = 0 := by - rw [← MvPolynomial.support_eq_empty, ← Finset.not_nonempty_iff_eq_empty] - rintro ⟨d, hd⟩ - exact hno _ (hp (MvPolynomial.mem_support_iff.mp hd)) - -private lemma weightedHomogeneous_unique_monomial - {σ R : Type*} [CommSemiring R] {M : Type*} [AddCommMonoid M] - {w : σ → M} {n : M} - (p : MvPolynomial σ R) (hp : MvPolynomial.IsWeightedHomogeneous w p n) - (d₀ : σ →₀ ℕ) (huniq : ∀ d, Finsupp.weight w d = n → d = d₀) : - p = MvPolynomial.monomial d₀ (MvPolynomial.coeff d₀ p) := by - classical - ext d - rw [MvPolynomial.coeff_monomial] - by_cases hd : d = d₀ - · simp [hd] - rw [if_neg (Ne.symm hd)] - exact hp.coeff_eq_zero d (fun h => hd (huniq d h)) - -private lemma weightedHomogeneous_sub - {σ R : Type*} [CommRing R] {M : Type*} [AddCommMonoid M] {w : σ → M} {n : M} - {p q : MvPolynomial σ R} - (hp : MvPolynomial.IsWeightedHomogeneous w p n) - (hq : MvPolynomial.IsWeightedHomogeneous w q n) : - MvPolynomial.IsWeightedHomogeneous w (p - q) n := - (MvPolynomial.weightedHomogeneousSubmodule R w n).sub_mem hp hq - private lemma unique_small_weight_solution {a₁ b₁ a₂ b₂ : ℕ} (ha₁ : a₁ < 3) (ha₂ : a₂ < 3) (h : a₁ * 4 + b₁ * 6 = a₂ * 4 + b₂ * 6) : a₁ = a₂ ∧ b₁ = b₂ := @@ -505,7 +432,7 @@ private lemma X0_pow_mul_X1_pow_isWeightedHomogeneous (a b n : ℕ) (hab : a * 4 private lemma discriminantPoly_isWeightedHomogeneous : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) discriminantPoly 12 := by rw [discriminantPoly, MvPolynomial.smul_eq_C_mul] - refine MvPolynomial.IsWeightedHomogeneous.C_mul (weightedHomogeneous_sub ?_ ?_) _ + refine MvPolynomial.IsWeightedHomogeneous.C_mul (.sub ?_ ?_) _ · convert (MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (0 : Fin 2)).pow 3 using 1 · convert (MvPolynomial.isWeightedHomogeneous_X ℂ (![4, 6] : Fin 2 → ℕ) (1 : Fin 2)).pow 2 using 1 @@ -521,7 +448,7 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) rw [show ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ) = ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ) from - funext fun z => modularForm_cast_apply hcast _ z, + funext fun z => ModularForm.cast_apply hcast _ z, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, PowerSeries.coeff_mul] simp [Finset.antidiagonal_zero, (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩] @@ -533,7 +460,7 @@ private lemma per_weight_injective_unique_monomial {n : ℕ} (p : MvPolynomial ( (huniq : ∀ d : Fin 2 →₀ ℕ, Finsupp.weight (![4, 6] : Fin 2 → ℕ) d = n → d = d₀) (hmf_ne : (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ d₀ 0 * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ d₀ 1) (↑n : ℤ) ≠ 0) : p = 0 := by - have hpc := weightedHomogeneous_unique_monomial p hp d₀ huniq + have hpc := hp.eq_monomial_of_unique_weight d₀ huniq rw [hpc] at heval ⊢ rw [monomial_fin2_eq, mul_assoc, map_mul, evalE₄E₆_C, Algebra.algebraMap_eq_smul_one, smul_mul_assoc, one_mul, evalE₄E₆_monomial, DirectSum.smul_apply] at heval @@ -567,7 +494,7 @@ private lemma per_weight_injective_zero (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p 0) (heval : (evalE₄E₆ p) (0 : ℤ) = 0) : p = 0 := by have hpc : p = MvPolynomial.monomial (0 : Fin 2 →₀ ℕ) (MvPolynomial.coeff 0 p) := - weightedHomogeneous_unique_monomial p hp 0 (fun d hd => by + hp.eq_monomial_of_unique_weight 0 (fun d hd => by rw [weight_eq_4a_6b] at hd ext i fin_cases i <;> simp <;> omega) @@ -712,7 +639,7 @@ private lemma weightedHomogeneous_poly_Delta_decomp_step {n : ℕ} (hn12 : 12 have hδ_eq : δ_piece = discriminantPoly * q₁ := by simp only [δ_piece, q₁, MvPolynomial.smul_eq_C_mul, map_mul] ring - refine ⟨p - δ_piece, q₁, weightedHomogeneous_sub hp + refine ⟨p - δ_piece, q₁, hp.sub (discriminantPoly_piece_isWeightedHomogeneous hn12 d hd_ge hwd c), .C_mul (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) _, ?_, support_sum_lt_after_sub_δ_piece p hd_mem hd_ge⟩ @@ -814,7 +741,7 @@ private lemma eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero {n : ℕ} (hn12 rw [DirectSum.of_apply, dif_pos hcast] at hds ext z have hpw := DFunLike.congr_fun hds z - simp only [ModularForm.zero_apply, modularForm_cast_apply hcast] at hpw ⊢ + simp only [ModularForm.zero_apply, ModularForm.cast_apply hcast] at hpw ⊢ exact (mul_eq_zero.mp hpw).resolve_left (discriminant_ne_zero z) private lemma per_weight_injective_inductive_step (n : ℕ) @@ -840,7 +767,7 @@ private lemma per_weight_injective_at_small_weight {n : ℕ} (hn12 : n < 12) (hk rcases hk_even with ⟨m, hm⟩ omega · exact per_weight_injective_zero p hp heval - · exact weightedHomogeneous_eq_zero_of_no_monomials p hp no_weight_monomial_of_two + · exact hp.eq_zero_of_no_monomials no_weight_monomial_of_two · exact per_weight_injective_small 1 0 (by omega) (by omega) rfl p hp heval · exact per_weight_injective_small 0 1 (by omega) (by omega) rfl p hp heval · exact per_weight_injective_small 2 0 (by omega) (by omega) rfl p hp heval @@ -853,7 +780,7 @@ private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ induction n using Nat.strong_induction_on with | _ n ih => ?_ intro p hp heval by_cases hk_odd : Odd n - · exact weightedHomogeneous_eq_zero_of_no_monomials p hp (no_weight_monomial_of_odd hk_odd) + · exact hp.eq_zero_of_no_monomials (no_weight_monomial_of_odd hk_odd) rw [Nat.not_odd_iff_even] at hk_odd by_cases hn12 : n < 12 · exact per_weight_injective_at_small_weight hn12 hk_odd p hp heval From 786fd497d6ea5a06640679900f418484d34fb1e0 Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Tue, 12 May 2026 15:35:39 +0100 Subject: [PATCH 60/61] fix: drop duplicate discriminant identity (now in LevelOne/GradedRing) --- .../NumberTheory/ModularForms/GradedRing.lean | 78 +------------------ 1 file changed, 1 insertion(+), 77 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 08f863b161a864..37f378669aeed6 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -5,7 +5,7 @@ Authors: Chris Birkbeck -/ module -public import Mathlib.NumberTheory.ModularForms.LevelOne.DimensionFormula +public import Mathlib.NumberTheory.ModularForms.LevelOne.GradedRing public import Mathlib.RingTheory.MvPolynomial.WeightedHomogeneous /-! @@ -21,10 +21,6 @@ level-1 modular forms. ## Main results -* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq`: the pointwise identity - `Δ = (E₄³ - E₆²) / 1728`. -* `ModularForm.discriminant_eq_E₄_cube_sub_E₆_sq_graded`: the same identity in the graded - ring `⨁ k, ModularForm 𝒮ℒ k`. * `ModularForm.evalE₄E₆_surjective`: `evalE₄E₆` is surjective. * `ModularForm.evalE₄E₆_injective`: `evalE₄E₆` is injective (E₄ and E₆ are algebraically independent). @@ -39,78 +35,6 @@ open UpperHalfPlane ModularForm ModularFormClass MatrixGroups EisensteinSeries namespace ModularForm -/-- The combination `E₄³ - E₆²` viewed as a level-1 modular form of weight 12. -/ -private noncomputable def E₄CubeSubE₆SqForm : ModularForm 𝒮ℒ 12 := - ModularForm.mcast (by decide) (E₄.pow 3) - ModularForm.mcast (by decide) (E₆.pow 2) - -private lemma E₄CubeSubE₆SqForm_apply (z : ℍ) : - E₄CubeSubE₆SqForm z = E₄ z ^ 3 - E₆ z ^ 2 := by - change ⇑(E₄.pow 3) z - ⇑(E₆.pow 2) z = _ - rw [coe_pow, coe_pow] - rfl - -private lemma E₄CubeSubE₆SqForm_qExpansion_eq : - qExpansion 1 E₄CubeSubE₆SqForm = qExpansion 1 E₄ * qExpansion 1 E₄ * qExpansion 1 E₄ - - qExpansion 1 E₆ * qExpansion 1 E₆ := by - rw [show qExpansion 1 E₄CubeSubE₆SqForm = - qExpansion 1 (E₄.pow 3) - qExpansion 1 (E₆.pow 2) from - ModularForm.qExpansion_sub one_pos one_mem_strictPeriods_SL - (ModularForm.mcast (by decide) (E₄.pow 3)) - (ModularForm.mcast (by decide) (E₆.pow 2)), - ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₄ 3, - ModularForm.qExpansion_pow one_pos one_mem_strictPeriods_SL E₆ 2] - ring - -private lemma E₄CubeSubE₆SqForm_isCuspForm : IsCuspForm E₄CubeSubE₆SqForm := by - refine (isCuspForm_iff_coeffZero_eq_zero _).mpr ?_ - rw [E₄CubeSubE₆SqForm_qExpansion_eq] - simp [PowerSeries.coeff_mul, -PowerSeries.coeff_zero_eq_constantCoeff, - E_qExpansion_coeff_zero _ ⟨2, rfl⟩, E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - -private lemma E₄CubeSubE₆SqForm_qExpansion_coeff_one : - (qExpansion 1 E₄CubeSubE₆SqForm).coeff 1 = 1728 := by - rw [E₄CubeSubE₆SqForm_qExpansion_eq] - norm_num [PowerSeries.coeff_mul, Finset.Nat.antidiagonal_succ, E₄_qExpansion_coeff_one, - E₆_qExpansion_coeff_one, E_qExpansion_coeff_zero _ ⟨2, rfl⟩, - E_qExpansion_coeff_zero _ ⟨3, rfl⟩] - -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728`. -/ -theorem discriminant_eq_E₄_cube_sub_E₆_sq (z : ℍ) : - discriminant z = (1 / 1728) * (E₄ z ^ 3 - E₆ z ^ 2) := by - obtain ⟨g, hg⟩ := E₄CubeSubE₆SqForm_isCuspForm - obtain ⟨c, hc⟩ := CuspForm.exists_smul_discriminant_of_weight_eq_twelve g - have hgE : (g : ℍ → ℂ) = E₄CubeSubE₆SqForm := congrArg DFunLike.coe hg - have hc_eq : c = 1728 := by - have hcΔ : (c • CuspForm.discriminant : ℍ → ℂ) = g := congrArg DFunLike.coe hc - have hgΔ := ModularForm.qExpansion_smul one_pos one_mem_strictPeriods_SL c - CuspForm.discriminant - rw [hcΔ, hgE] at hgΔ - simpa [PowerSeries.coeff_smul, discriminant_qExpansion_coeff_one, - E₄CubeSubE₆SqForm_qExpansion_coeff_one] using (congr_arg (·.coeff 1) hgΔ).symm - have h1728 : (1728 : ℂ) * discriminant z = E₄ z ^ 3 - E₆ z ^ 2 := by - rw [← hc_eq, show c * discriminant z = (c • CuspForm.discriminant) z from rfl, hc, - congr_fun hgE z, E₄CubeSubE₆SqForm_apply] - linear_combination h1728 / 1728 - -/-- The modular discriminant equals `(E₄³ - E₆²) / 1728` in the graded ring -`⨁ k, ModularForm 𝒮ℒ k`. -/ -theorem discriminant_eq_E₄_cube_sub_E₆_sq_graded : - DirectSum.of (ModularForm 𝒮ℒ) 12 CuspForm.discriminant = - (1 / 1728 : ℂ) • (.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 - .of (ModularForm 𝒮ℒ) 6 E₆ ^ 2) := by - have hE4 : DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ 3 = DirectSum.of (ModularForm 𝒮ℒ) 12 - (ModularForm.mcast (by decide) ((E₄.mul E₄).mul E₄)) := by - rw [pow_succ (n := 2), pow_two, DirectSum.of_mul_of, DirectSum.of_mul_of] - rfl - have hE6 : DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ 2 = - DirectSum.of (ModularForm 𝒮ℒ) 12 (ModularForm.mcast (by decide) (E₆.mul E₆)) := by - rw [pow_two, DirectSum.of_mul_of] - rfl - rw [hE4, hE6, ← map_sub (DirectSum.of (ModularForm 𝒮ℒ) 12), ← DirectSum.of_smul] - congr 1 - ext z - change ModularForm.discriminant z = (1 / 1728 : ℂ) * (E₄ z * E₄ z * E₄ z - E₆ z * E₆ z) - grind [discriminant_eq_E₄_cube_sub_E₆_sq z] - /-- Evaluation homomorphism sending `ℂ[X₀, X₁]` to the graded ring of level 1 modular forms via `X₀ ↦ E₄` and `X₁ ↦ E₆`. -/ noncomputable def evalE₄E₆ : From bf642222fdf1cd0bd71e82857be2b49fca6f54af Mon Sep 17 00:00:00 2001 From: Chris Birkbeck Date: Tue, 12 May 2026 15:36:50 +0100 Subject: [PATCH 61/61] =?UTF-8?q?cleanup:=20omega=20=E2=86=92=20lia,=20=3D?= =?UTF-8?q?>=20=E2=86=92=20=E2=86=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NumberTheory/ModularForms/GradedRing.lean | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/Mathlib/NumberTheory/ModularForms/GradedRing.lean b/Mathlib/NumberTheory/ModularForms/GradedRing.lean index 37f378669aeed6..bd71a173028c19 100644 --- a/Mathlib/NumberTheory/ModularForms/GradedRing.lean +++ b/Mathlib/NumberTheory/ModularForms/GradedRing.lean @@ -79,7 +79,7 @@ private lemma exists_monomial_weight {k : ℕ} (hk : 4 ≤ k) (hkeven : Even k) ∃ a b : ℕ, 4 * a + 6 * b = k := by obtain ⟨m, rfl⟩ := hkeven rcases Nat.even_or_odd m with ⟨n, hn⟩ | ⟨n, hn⟩ - exacts [⟨n, 0, by omega⟩, ⟨n - 1, 1, by omega⟩] + exacts [⟨n, 0, by lia⟩, ⟨n - 1, 1, by lia⟩] private lemma surj_of_rank_one {k : ℤ} (hrank : Module.rank ℂ (ModularForm 𝒮ℒ k) = 1) {g : ModularForm 𝒮ℒ k} (hg : g ≠ 0) @@ -161,19 +161,19 @@ private lemma surj_at_weight_inductive {n : ℕ} (hn12 : 12 ≤ n) (hk_even : Ev (f : ModularForm 𝒮ℒ ↑n) : DirectSum.of _ (↑n : ℤ) f ∈ Set.range evalE₄E₆ := by obtain ⟨a, b, hab⟩ : ∃ a b : ℕ, 4 * a + 6 * b = n := - exists_monomial_weight (by omega) (by exact_mod_cast hk_even) + exists_monomial_weight (by lia) (by exact_mod_cast hk_even) set mn := (DirectSum.of (ModularForm 𝒮ℒ) 4 E₄ ^ a * DirectSum.of (ModularForm 𝒮ℒ) 6 E₆ ^ b) (↑n : ℤ) set c := (qExpansion 1 f).coeff 0 have hg_cusp : ModularForm.IsCuspForm (f - c • mn) := ModularForm.sub_smul_isCuspForm f mn (monomial_qExpansion_coeff_zero_eq_one hab) - have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by omega + have hcast : ((↑n : ℤ) - 12 : ℤ) = ((n - 12 : ℕ) : ℤ) := by lia obtain ⟨p1, hp1⟩ : DirectSum.of (ModularForm 𝒮ℒ) ((↑n : ℤ) - 12) (CuspForm.discriminantEquiv (ModularForm.toCuspForm (f - c • mn) ((ModularForm.isCuspForm_iff_coeffZero_eq_zero _).mp hg_cusp))) ∈ Set.range evalE₄E₆ := by rw [DirectSum.of_eq_of_eq hcast] - exact ih _ (by omega) _ + exact ih _ (by lia) _ rw [DirectSum.of_eq_sub_add_smul f mn c, directSum_of_E₄_pow_mul_E₆_pow_apply hab] exact ⟨p1 * discriminantPoly + MvPolynomial.C c * (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b), by rw [map_add, map_mul, hp1, evalE₄E₆_discriminantPoly, @@ -187,7 +187,7 @@ private lemma rank_one_of_lt_twelve {k : ℕ} (hk3 : 3 ≤ k) (hk2 : Even k) (hk CuspForm.rank_eq_zero_of_weight_lt_twelve (mod_cast hk12 : (↑k : ℤ) < 12)] norm_cast -private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := fun h => +private lemma one_ne_zero_modularForm : (1 : ModularForm 𝒮ℒ 0) ≠ 0 := fun h ↦ one_ne_zero (α := ℂ) (congr_fun (congr_arg (DFunLike.coe (F := ModularForm 𝒮ℒ 0)) h) UpperHalfPlane.I) @@ -231,13 +231,13 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), · exact surj_of_zero_form (rank_zero_iff_forall_zero.mp (ModularForm.levelOne_neg_weight_rank_zero hk_neg)) f push Not at hk_neg - obtain ⟨n, rfl⟩ : ∃ n : ℕ, k = (n : ℤ) := ⟨k.toNat, by omega⟩ + obtain ⟨n, rfl⟩ : ∃ n : ℕ, k = (n : ℤ) := ⟨k.toNat, by lia⟩ clear hk_neg revert f induction n using Nat.strong_induction_on with | _ n ih => ?_ intro f by_cases hk_odd : Odd (n : ℤ) - · exact surj_of_zero_form (fun f => ModularForm.levelOne_odd_weight_eq_zero hk_odd f) f + · exact surj_of_zero_form (fun f ↦ ModularForm.levelOne_odd_weight_eq_zero hk_odd f) f rw [Int.not_odd_iff_even] at hk_odd by_cases hn12 : n < 12 · exact surj_at_small_weight hn12 hk_odd f @@ -248,13 +248,13 @@ private lemma surj_of_weight : ∀ (k : ℤ) (f : ModularForm 𝒮ℒ k), theorem evalE₄E₆_surjective : Function.Surjective evalE₄E₆ := by classical intro x - rw [show x = x.sum (fun i m => DirectSum.of _ i m) from (DFinsupp.sum_single (f := x)).symm, + rw [show x = x.sum (fun i m ↦ DirectSum.of _ i m) from (DFinsupp.sum_single (f := x)).symm, ← AlgHom.mem_range] - exact Subalgebra.sum_mem _ fun k _ => surj_of_weight k (x k) + exact Subalgebra.sum_mem _ fun k _ ↦ surj_of_weight k (x k) private lemma weight_fin2 (w : Fin 2 → ℕ) (d : Fin 2 →₀ ℕ) : Finsupp.weight w d = d 0 * w 0 + d 1 * w 1 := by - rw [Finsupp.weight_apply, d.sum_fintype (fun i c => c • w i) fun _ => zero_smul _ _] + rw [Finsupp.weight_apply, d.sum_fintype (fun i c ↦ c • w i) fun _ ↦ zero_smul _ _] simp [Fin.sum_univ_two, mul_comm] private lemma weight_eq_4a_6b (d : Fin 2 →₀ ℕ) : @@ -272,7 +272,7 @@ private lemma no_weight_monomial_of_odd {n : ℕ} (hn : Odd n) (d : Fin 2 →₀ Finsupp.weight (![4, 6] : Fin 2 → ℕ) d ≠ n := by intro h rw [weight_eq_4a_6b] at h - exact Nat.not_odd_iff_even.mpr ⟨d 0 * 2 + d 1 * 3, by omega⟩ hn + exact Nat.not_odd_iff_even.mpr ⟨d 0 * 2 + d 1 * 3, by lia⟩ hn private lemma no_weight_monomial_of_two (d : Fin 2 →₀ ℕ) : Finsupp.weight (![4, 6] : Fin 2 → ℕ) d ≠ 2 := by @@ -283,19 +283,19 @@ private lemma no_weight_monomial_of_two (d : Fin 2 →₀ ℕ) : private lemma unique_small_weight_solution {a₁ b₁ a₂ b₂ : ℕ} (ha₁ : a₁ < 3) (ha₂ : a₂ < 3) (h : a₁ * 4 + b₁ * 6 = a₂ * 4 + b₂ * 6) : a₁ = a₂ ∧ b₁ = b₂ := - ⟨by interval_cases a₁ <;> interval_cases a₂ <;> omega, by omega⟩ + ⟨by interval_cases a₁ <;> interval_cases a₂ <;> omega, by lia⟩ private lemma monomial_fin2_eq {R : Type*} [CommSemiring R] (d : Fin 2 →₀ ℕ) (c : R) : MvPolynomial.monomial d c = MvPolynomial.C c * MvPolynomial.X 0 ^ d 0 * MvPolynomial.X 1 ^ d 1 := by - rw [MvPolynomial.monomial_eq, mul_assoc, d.prod_fintype _ fun _ => pow_zero _] + rw [MvPolynomial.monomial_eq, mul_assoc, d.prod_fintype _ fun _ ↦ pow_zero _] simp [Fin.prod_univ_two] private lemma evalE₄E₆_X_pow_mul_apply_eq_zero_of_ne (a b : ℕ) (k : ℤ) (hk : k ≠ (↑a * 4 + ↑b * 6 : ℤ)) : (evalE₄E₆ (MvPolynomial.X 0 ^ a * MvPolynomial.X 1 ^ b)) k = 0 := by rw [evalE₄E₆_monomial, DirectSum.ofPow, DirectSum.ofPow, DirectSum.of_mul_of] - refine DirectSum.of_eq_of_ne _ _ _ fun heq => hk ?_ + refine DirectSum.of_eq_of_ne _ _ _ fun heq ↦ hk ?_ simp only [Int.nsmul_eq_mul] at heq omega @@ -311,14 +311,14 @@ private lemma evalE₄E₆_apply_eq_zero_of_ne {n : ℕ} (p : MvPolynomial (Fin (k : ℤ) (hk : k ≠ ↑n) : (evalE₄E₆ p) k = 0 := by rw [← MvPolynomial.support_sum_monomial_coeff p, map_sum, DirectSum.sum_apply] - refine Finset.sum_eq_zero fun d hd => - evalE₄E₆_monomial_apply_eq_zero_of_ne _ _ _ fun heq => hk ?_ + refine Finset.sum_eq_zero fun d hd ↦ + evalE₄E₆_monomial_apply_eq_zero_of_ne _ _ _ fun heq ↦ hk ?_ rw [heq, ← weight_fin2_cast d, hp (MvPolynomial.mem_support_iff.mp hd)] private lemma evalE₄E₆_eq_of_apply (n : ℕ) (p : MvPolynomial (Fin 2) ℂ) (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n) : evalE₄E₆ p = DirectSum.of (ModularForm 𝒮ℒ) (↑n : ℤ) ((evalE₄E₆ p) ↑n) := by - refine DFinsupp.ext fun k : ℤ => ?_ + refine DFinsupp.ext fun k : ℤ ↦ ?_ by_cases hk : k = (↑n : ℤ) · subst hk simp @@ -335,8 +335,8 @@ private lemma evalE₄E₆_component_eq (p : MvPolynomial (Fin 2) ℂ) (n : ℕ) conv_rhs => rw [hdecomp, map_add, DirectSum.add_apply] suffices h : (evalE₄E₆ q) (↑n : ℤ) = 0 by rw [h, add_zero] rw [← MvPolynomial.support_sum_monomial_coeff q, map_sum, DirectSum.sum_apply] - refine Finset.sum_eq_zero fun d hd => - evalE₄E₆_monomial_apply_eq_zero_of_ne _ _ _ fun heq => MvPolynomial.mem_support_iff.mp hd ?_ + refine Finset.sum_eq_zero fun d hd ↦ + evalE₄E₆_monomial_apply_eq_zero_of_ne _ _ _ fun heq ↦ MvPolynomial.mem_support_iff.mp hd ?_ rw [hq_def, MvPolynomial.coeff_sub, MvPolynomial.coeff_weightedHomogeneousComponent, if_pos ?_, sub_self] rw [weight_eq_4a_6b] @@ -366,13 +366,13 @@ private lemma evalE₄E₆_discriminantPoly_mul_coeff_zero {n : ℕ} (hn12 : 12 (qExpansion 1 ↑((evalE₄E₆ (discriminantPoly * s)) (↑n : ℤ))).coeff 0 = 0 := by rw [map_mul, evalE₄E₆_discriminantPoly, evalE₄E₆_eq_of_apply (n - 12) s hs, DirectSum.of_mul_of] - have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega + have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by lia rw [DirectSum.of_apply, dif_pos hcast] set f := ((CuspForm.discriminant : CuspForm 𝒮ℒ 12) : ModularForm 𝒮ℒ 12) set g := (evalE₄E₆ s) ((n - 12 : ℕ) : ℤ) rw [show ((hcast ▸ GradedMonoid.GMul.mul f g : ModularForm 𝒮ℒ ↑n) : ℍ → ℂ) = ((f.mul g : ModularForm 𝒮ℒ (12 + ((n - 12 : ℕ) : ℤ))) : ℍ → ℂ) from - funext fun z => ModularForm.cast_apply hcast _ z, + funext fun z ↦ ModularForm.cast_apply hcast _ z, ModularForm.qExpansion_mul one_pos one_mem_strictPeriods_SL f g, PowerSeries.coeff_mul] simp [Finset.antidiagonal_zero, (ModularForm.isCuspForm_iff_coeffZero_eq_zero f).mp ⟨CuspForm.discriminant, rfl⟩] @@ -403,13 +403,13 @@ private lemma per_weight_injective_small {n : ℕ} (a b : ℕ) (ha : a < 3) (hn · intro d hd have h46 := weight_eq_4a_6b d rw [hd] at h46 - obtain ⟨hda, hdb⟩ := unique_small_weight_solution (by omega : d 0 < 3) ha - (show d 0 * 4 + d 1 * 6 = a * 4 + b * 6 by omega) + obtain ⟨hda, hdb⟩ := unique_small_weight_solution (by lia : d 0 < 3) ha + (show d 0 * 4 + d 1 * 6 = a * 4 + b * 6 by lia) ext i fin_cases i <;> [exact hda ▸ hd0a.symm; exact hdb ▸ hd0b.symm] · rw [hd0a, hd0b] intro habs - have hcz := monomial_qExpansion_coeff_zero_eq_one (n := n) (a := a) (b := b) (by omega) + have hcz := monomial_qExpansion_coeff_zero_eq_one (n := n) (a := a) (b := b) (by lia) rw [habs] at hcz simp [UpperHalfPlane.qExpansion_zero] at hcz @@ -418,7 +418,7 @@ private lemma per_weight_injective_zero (hp : MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p 0) (heval : (evalE₄E₆ p) (0 : ℤ) = 0) : p = 0 := by have hpc : p = MvPolynomial.monomial (0 : Fin 2 →₀ ℕ) (MvPolynomial.coeff 0 p) := - hp.eq_monomial_of_unique_weight 0 (fun d hd => by + hp.eq_monomial_of_unique_weight 0 (fun d hd ↦ by rw [weight_eq_4a_6b] at hd ext i fin_cases i <;> simp <;> omega) @@ -446,7 +446,7 @@ private lemma discriminantPoly_piece_isWeightedHomogeneous {n : ℕ} (hn12 : 12 MvPolynomial.X (1 : Fin 2) ^ d 1)) from by ring] apply MvPolynomial.IsWeightedHomogeneous.C_mul convert discriminantPoly_isWeightedHomogeneous.mul - (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) + (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by lia)) using 1 omega @@ -481,19 +481,19 @@ private lemma sum_lt_sum_of_replace {α : Type*} [DecidableEq α] ∑ x ∈ S', f x < ∑ x ∈ S, f x := by by_cases hd'S : d' ∈ S · calc ∑ x ∈ S', f x - ≤ ∑ x ∈ S.erase d, f x := Finset.sum_le_sum_of_subset (fun x hx => - Finset.mem_erase.mpr ⟨fun h => hd_not (h ▸ hx), + ≤ ∑ x ∈ S.erase d, f x := Finset.sum_le_sum_of_subset (fun x hx ↦ + Finset.mem_erase.mpr ⟨fun h ↦ hd_not (h ▸ hx), match Finset.mem_union.mp (hS' hx) with | .inl h => Finset.mem_of_mem_erase h | .inr h => Finset.mem_singleton.mp h ▸ hd'S⟩) _ < ∑ x ∈ S.erase d, f x + f d := - Nat.lt_add_of_pos_right (Nat.pos_of_ne_zero (by omega)) + Nat.lt_add_of_pos_right (Nat.pos_of_ne_zero (by lia)) _ = ∑ x ∈ S, f x := Finset.sum_erase_add S f hd_mem · calc ∑ x ∈ S', f x ≤ ∑ x ∈ S.erase d ∪ {d'}, f x := Finset.sum_le_sum_of_subset hS' _ = ∑ x ∈ S.erase d, f x + f d' := by rw [Finset.sum_union (Finset.disjoint_singleton_right.mpr - (fun h => hd'S (Finset.mem_of_mem_erase h))), Finset.sum_singleton] + (fun h ↦ hd'S (Finset.mem_of_mem_erase h))), Finset.sum_singleton] _ < ∑ x ∈ S.erase d, f x + f d := Nat.add_lt_add_left hlt _ _ = ∑ x ∈ S, f x := Finset.sum_erase_add S f hd_mem @@ -508,7 +508,7 @@ private lemma mvPolynomial_support_after_reduction {σ R : Type*} [CommRing R] [ rw [MvPolynomial.notMem_support_iff, MvPolynomial.coeff_sub, MvPolynomial.coeff_sub, MvPolynomial.coeff_monomial, MvPolynomial.coeff_monomial, if_pos rfl, if_neg hdd'.symm, sub_zero, hc, sub_self] - refine ⟨hd_not, fun x hx => ?_⟩ + refine ⟨hd_not, fun x hx ↦ ?_⟩ rcases Finset.mem_union.mp (MvPolynomial.support_sub σ p _ hx) with hp | hdelta · by_cases hxd : x = d · exact absurd (hxd ▸ hx) hd_not @@ -530,7 +530,7 @@ private lemma support_sum_lt_after_sub_δ_piece (p : MvPolynomial (Fin 2) ℂ) MvPolynomial.X (1 : Fin 2) ^ d 1))).support, d' 0 < ∑ d' ∈ p.support, d' 0 := by set d' := Finsupp.single (0 : Fin 2) (d 0 - 3) + Finsupp.single (1 : Fin 2) (d 1 + 2) - have hdd' : d ≠ d' := fun heq => by + have hdd' : d ≠ d' := fun heq ↦ by have h0 := Finsupp.ext_iff.mp heq (0 : Fin 2) simp only [Fin.isValue, d', Finsupp.add_apply, Finsupp.single_eq_same, ne_eq, zero_ne_one, not_false_eq_true, Finsupp.single_eq_of_ne, add_zero] at h0 @@ -565,7 +565,7 @@ private lemma weightedHomogeneous_poly_Delta_decomp_step {n : ℕ} (hn12 : 12 ring refine ⟨p - δ_piece, q₁, hp.sub (discriminantPoly_piece_isWeightedHomogeneous hn12 d hd_ge hwd c), - .C_mul (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by omega)) _, ?_, + .C_mul (X0_pow_mul_X1_pow_isWeightedHomogeneous (d 0 - 3) (d 1) (n - 12) (by lia)) _, ?_, support_sum_lt_after_sub_δ_piece p hd_mem hd_ge⟩ rw [← hδ_eq] ring @@ -608,8 +608,8 @@ private lemma reduced_isWeightedHomogeneous_eq_monomial {n : ℕ} have h2 := weight_eq_4a_6b d₀ rw [hwd₀] at h2 obtain ⟨ha, hb⟩ := unique_small_weight_solution (hr_red d hd_supp) (hr_red d₀ hd₀) - (show d 0 * 4 + d 1 * 6 = d₀ 0 * 4 + d₀ 1 * 6 by omega) - exact absurd (Finsupp.ext fun i => by fin_cases i <;> [exact ha; exact hb]) hd + (show d 0 * 4 + d 1 * 6 = d₀ 0 * 4 + d₀ 1 * 6 by lia) + exact absurd (Finsupp.ext fun i ↦ by fin_cases i <;> [exact ha; exact hb]) hd · rwa [MvPolynomial.mem_support_iff, not_not] at hd_supp private lemma evalE₄E₆_monomial_qExpansion_coeff_zero {n : ℕ} {d₀ : Fin 2 →₀ ℕ} @@ -661,7 +661,7 @@ private lemma eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero {n : ℕ} (hn12 (evalE₄E₆ s) (↑(n - 12) : ℤ) = 0 := by rw [map_mul, evalE₄E₆_discriminantPoly, evalE₄E₆_eq_of_apply (n - 12) s hs, DirectSum.of_mul_of] at hds - have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by omega + have hcast : (12 : ℤ) + ((n - 12 : ℕ) : ℤ) = (↑n : ℤ) := by lia rw [DirectSum.of_apply, dif_pos hcast] at hds ext z have hpw := DFunLike.congr_fun hds z @@ -679,7 +679,7 @@ private lemma per_weight_injective_inductive_step (n : ℕ) obtain ⟨r, s, hr_wh, hs_wh, hp_eq, hr_red⟩ := weightedHomogeneous_poly_Delta_decomp hn12 p hp have hr0 : r = 0 := reduced_part_eq_zero hn12 r s hr_wh hs_wh hr_red (hp_eq ▸ heval) rw [hp_eq, hr0, zero_add] at heval ⊢ - rw [ih (n - 12) (by omega) s hs_wh + rw [ih (n - 12) (by lia) s hs_wh (eval_discriminantPoly_mul_eq_zero_imp_eval_eq_zero hn12 s hs_wh heval), mul_zero] private lemma per_weight_injective_at_small_weight {n : ℕ} (hn12 : n < 12) (hk_even : Even n) @@ -692,10 +692,10 @@ private lemma per_weight_injective_at_small_weight {n : ℕ} (hn12 : n < 12) (hk omega · exact per_weight_injective_zero p hp heval · exact hp.eq_zero_of_no_monomials no_weight_monomial_of_two - · exact per_weight_injective_small 1 0 (by omega) (by omega) rfl p hp heval - · exact per_weight_injective_small 0 1 (by omega) (by omega) rfl p hp heval - · exact per_weight_injective_small 2 0 (by omega) (by omega) rfl p hp heval - · exact per_weight_injective_small 1 1 (by omega) (by omega) rfl p hp heval + · exact per_weight_injective_small 1 0 (by lia) (by lia) rfl p hp heval + · exact per_weight_injective_small 0 1 (by lia) (by lia) rfl p hp heval + · exact per_weight_injective_small 2 0 (by lia) (by lia) rfl p hp heval + · exact per_weight_injective_small 1 1 (by lia) (by lia) rfl p hp heval private lemma per_weight_injective : ∀ (n : ℕ) (p : MvPolynomial (Fin 2) ℂ), MvPolynomial.IsWeightedHomogeneous (![4, 6] : Fin 2 → ℕ) p n → @@ -717,7 +717,7 @@ theorem evalE₄E₆_injective : Function.Injective evalE₄E₆ := by intro p q hpq rw [← sub_eq_zero, ← MvPolynomial.sum_weightedHomogeneousComponent ((![4, 6] : Fin 2 → ℕ)) (p - q)] - refine finsum_eq_zero_of_forall_eq_zero fun n => per_weight_injective n _ + refine finsum_eq_zero_of_forall_eq_zero fun n ↦ per_weight_injective n _ (MvPolynomial.weightedHomogeneousComponent_isWeightedHomogeneous _ _) ?_ rw [evalE₄E₆_component_eq, map_sub, hpq, sub_self] rfl