From 835433a2e425c3a65a2dfa2ce48a89b9f68c76c4 Mon Sep 17 00:00:00 2001 From: SmwYin Date: Mon, 29 Jun 2026 01:12:03 +0100 Subject: [PATCH 1/5] Experiments on issues --- .../LeanModularForms/Experiments/Issue34.lean | 0 .../LeanModularForms/Experiments/Issue50.lean | 125 +++++ .../LeanModularForms/Experiments/Issue54.lean | 47 ++ .../LeanModularForms/Experiments/Issue55.lean | 478 ++++++++++++++++++ .../LeanModularForms/Experiments/Issue56.lean | 142 ++++++ 5 files changed, 792 insertions(+) create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean new file mode 100644 index 000000000..e69de29bb diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean new file mode 100644 index 000000000..88c7c4ec9 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean @@ -0,0 +1,125 @@ +import Mathlib.Analysis.SpecialFunctions.Log.Basic +import Mathlib.RingTheory.Radical.NatInt +import Mathlib.Tactic + +/-! +# LeanBridge issue #50: abc quality + +This file uses mathlib's integer radical and defines the associated real-valued abc quality. +-/ + +open scoped BigOperators + +namespace XYin.Experiments.Issue50 + +open UniqueFactorizationMonoid + +private lemma isRelPrime_int_of_gcd_eq_one {a b : ℤ} (h : Int.gcd a b = 1) : + IsRelPrime a b := by + intro d hda hdb + rw [Int.isUnit_iff_natAbs_eq] + have hda' : ((d.natAbs : ℕ) : ℤ) ∣ a := (Int.natAbs_dvd).mpr hda + have hdb' : ((d.natAbs : ℕ) : ℤ) ∣ b := (Int.natAbs_dvd).mpr hdb + have hg : d.natAbs ∣ Int.gcd a b := Int.dvd_gcd hda' hdb' + rw [h] at hg + exact Nat.dvd_one.mp hg + +private lemma radical_two : radical (2 : ℤ) = 2 := by + rw [radical_of_prime (show Prime (2 : ℤ) by norm_num)] + rfl + +private lemma radical_three : radical (3 : ℤ) = 3 := by + rw [radical_of_prime (show Prime (3 : ℤ) by norm_num)] + rfl + +private lemma radical_five : radical (5 : ℤ) = 5 := by + rw [radical_of_prime (show Prime (5 : ℤ) by norm_num)] + rfl + +lemma radical_dvd_int (n : ℤ) : radical n ∣ n := + radical_dvd_self + +/-- The height appearing in the numerator of the abc quality. -/ +def abcHeight (a b c : ℤ) : ℕ := + max a.natAbs (max b.natAbs c.natAbs) + +/-- The abc quality `log(max(|a|, |b|, |c|)) / log(rad(abc))`. -/ +noncomputable def abcQuality (a b c : ℤ) : ℝ := + Real.log (abcHeight a b c : ℝ) / Real.log (((radical (a * b * c : ℤ) : ℤ) : ℝ)) + +/-- A pairwise coprime integer triple satisfying `a + b = c`. -/ +structure CoprimeTriple (a b c : ℤ) : Prop where + sum_eq : a + b = c + coprime_ab : Nat.Coprime a.natAbs b.natAbs + coprime_ac : Nat.Coprime a.natAbs c.natAbs + coprime_bc : Nat.Coprime b.natAbs c.natAbs + +lemma abcQuality_pos_of_one_lt_height_radical {a b c : ℤ} + (hH : 1 < abcHeight a b c) (hR : 1 < radical (a * b * c : ℤ)) : + 0 < abcQuality a b c := by + exact div_pos (Real.log_pos (by exact_mod_cast hH)) (Real.log_pos (by exact_mod_cast hR)) + +lemma one_lt_abcQuality_of_radical_lt_height {a b c : ℤ} + (hR : 1 < radical (a * b * c : ℤ)) + (hRH : radical (a * b * c : ℤ) < (abcHeight a b c : ℤ)) : + 1 < abcQuality a b c := by + rw [abcQuality] + have hlogR : 0 < Real.log (((radical (a * b * c : ℤ) : ℤ) : ℝ)) := + Real.log_pos (by exact_mod_cast hR) + exact (one_lt_div hlogR).2 <| + Real.log_lt_log (by exact_mod_cast Int.radical_pos (a * b * c : ℤ)) + (by exact_mod_cast hRH) + +lemma one_eight_nine_coprimeTriple : CoprimeTriple 1 8 9 where + sum_eq := by norm_num + coprime_ab := by norm_num + coprime_ac := by norm_num + coprime_bc := by norm_num + +lemma five_twentyseven_thirtytwo_coprimeTriple : CoprimeTriple 5 27 32 where + sum_eq := by norm_num + coprime_ab := by norm_num + coprime_ac := by norm_num + coprime_bc := by norm_num + +lemma radical_one_eight_nine : radical (1 * 8 * 9 : ℤ) = 6 := by + rw [show (1 * 8 * 9 : ℤ) = (2 : ℤ) ^ 3 * (3 : ℤ) ^ 2 by norm_num] + rw [radical_mul (isRelPrime_int_of_gcd_eq_one (by norm_num))] + rw [radical_pow, radical_pow] + · rw [radical_two, radical_three] + norm_num + · norm_num + · norm_num + +lemma abcHeight_one_eight_nine : abcHeight 1 8 9 = 9 := by + norm_num [abcHeight] + +lemma one_lt_abcQuality_one_eight_nine : 1 < abcQuality 1 8 9 := by + rw [abcQuality, abcHeight_one_eight_nine, radical_one_eight_nine] + have hlog6 : 0 < Real.log (6 : ℝ) := Real.log_pos (by norm_num) + exact (one_lt_div hlog6).2 <| by + simpa using + (Real.log_lt_log (by norm_num : (0 : ℝ) < 6) (by norm_num : (6 : ℝ) < 9)) + +lemma radical_five_twentyseven_thirtytwo : radical (5 * 27 * 32 : ℤ) = 30 := by + rw [show (5 * 27 * 32 : ℤ) = ((2 : ℤ) ^ 5 * (3 : ℤ) ^ 3) * 5 by norm_num] + rw [radical_mul (isRelPrime_int_of_gcd_eq_one (by norm_num))] + rw [radical_mul (isRelPrime_int_of_gcd_eq_one (by norm_num))] + rw [radical_pow, radical_pow] + · rw [radical_two, radical_three, radical_five] + norm_num + · norm_num + · norm_num + +lemma abcHeight_five_twentyseven_thirtytwo : abcHeight 5 27 32 = 32 := by + norm_num [abcHeight] + +lemma one_lt_abcQuality_five_twentyseven_thirtytwo : 1 < abcQuality 5 27 32 := by + rw [abcQuality, abcHeight_five_twentyseven_thirtytwo, + radical_five_twentyseven_thirtytwo] + have hlog30 : 0 < Real.log (30 : ℝ) := Real.log_pos (by norm_num) + exact (one_lt_div hlog30).2 <| by + simpa using + (Real.log_lt_log (by norm_num : (0 : ℝ) < 30) (by norm_num : (30 : ℝ) < 32)) + +end XYin.Experiments.Issue50 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean new file mode 100644 index 000000000..12a71e36e --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean @@ -0,0 +1,47 @@ +import Mathlib.Data.Nat.Factorization.Basic +import Mathlib.Tactic + +/-! +# LeanBridge issue #54: bad primes + +The bad primes of level `N` are exactly the prime factors of `N`. +-/ + +namespace XYin.Experiments.Issue54 + +/-- The finite set of primes dividing the level. -/ +def badPrimes (N : ℕ) : Finset ℕ := + N.primeFactors + +@[simp] +lemma mem_badPrimes {N p : ℕ} : p ∈ badPrimes N ↔ p.Prime ∧ p ∣ N ∧ N ≠ 0 := by + simp [badPrimes] + +lemma prime_mem_badPrimes_iff_dvd {N p : ℕ} (hp : p.Prime) (hN : N ≠ 0) : + p ∈ badPrimes N ↔ p ∣ N := by + simp [badPrimes, hp, hN] + +lemma badPrimes_finite (N : ℕ) : {p | p ∈ badPrimes N}.Finite := + (badPrimes N).finite_toSet + +example : badPrimes 11 = {11} := by + ext p + simp only [mem_badPrimes, Finset.mem_singleton] + constructor + · rintro ⟨hp, hdvd, _⟩ + exact (Nat.dvd_prime (by norm_num : Nat.Prime 11)).mp hdvd |>.resolve_left hp.ne_one + · intro h + subst h + norm_num + +example : badPrimes 12 = ({2, 3} : Finset ℕ) := by + ext p + simp only [mem_badPrimes, Finset.mem_insert, Finset.mem_singleton] + constructor + · rintro ⟨hp, hdvd, _⟩ + have hle : p ≤ 12 := Nat.le_of_dvd (by norm_num) hdvd + have hpos : 0 < p := hp.pos + interval_cases p <;> norm_num [Nat.Prime] at * + · rintro (rfl | rfl) <;> norm_num + +end XYin.Experiments.Issue54 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean new file mode 100644 index 000000000..990b30c18 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean @@ -0,0 +1,478 @@ +import LeanModularForms.HeckeRIngs.GL2.Newforms.Newform +import Mathlib.Tactic + +/-! +# LeanBridge issue #55: dual and self-dual cusp forms + +This file defines the conjugate-coefficient dual of a cusp form in the +Nebentypus ambient space `S_k(N, χ)`, represented in this repository as the +`χ`-eigenspace inside cusp forms for `Γ₁(N)`. + +The construction is the slash action by the reflection +`J = [-1, 0; 0, 1]`, which sends `τ` to `-conj τ`. The form `dualForm f` +is a bundled cusp form, its `∞`-Fourier coefficients are the complex +conjugates of those of `f`, and it sends the `χ`-character subspace to the +pointwise conjugate character subspace. +-/ + +noncomputable section + +namespace HeckeRing.GL2 + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex +open scoped ComplexConjugate MatrixGroups ModularForm Pointwise + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +/-- The canonical Fourier coefficient `aₙ(f)` of a cusp form at the cusp `∞`. -/ +noncomputable def fourierCoeffAtInfinity (f : CuspForm Γ k) (n : ℕ) : ℂ := + (UpperHalfPlane.qExpansion Γ.strictWidthInfty f).coeff n + +@[simp] +lemma fourierCoeffAtInfinity_apply (f : CuspForm Γ k) (n : ℕ) : + fourierCoeffAtInfinity f n = + (UpperHalfPlane.qExpansion Γ.strictWidthInfty f).coeff n := + rfl + +/-- `g` has the `∞`-coefficients expected of the conjugate-coefficient dual of `f`. -/ +def HasConjugateCoefficientsAtInfinity (f g : CuspForm Γ k) : Prop := + ∀ n : ℕ, fourierCoeffAtInfinity g n = conj (fourierCoeffAtInfinity f n) + +@[symm] +lemma HasConjugateCoefficientsAtInfinity.symm {f g : CuspForm Γ k} + (h : HasConjugateCoefficientsAtInfinity f g) : + HasConjugateCoefficientsAtInfinity g f := by + intro n + have hn := congrArg conj (h n) + simpa using hn.symm + +lemma hasConjugateCoefficientsAtInfinity_comm (f g : CuspForm Γ k) : + HasConjugateCoefficientsAtInfinity f g ↔ HasConjugateCoefficientsAtInfinity g f := + ⟨HasConjugateCoefficientsAtInfinity.symm, HasConjugateCoefficientsAtInfinity.symm⟩ + +/-- +A cusp form is self-dual, for its L-function, when all canonical Fourier +coefficients at `∞` are real. +-/ +def IsSelfDual (f : CuspForm Γ k) : Prop := + ∀ n : ℕ, (fourierCoeffAtInfinity f n).im = 0 + +lemma isSelfDual_iff_self_hasConjugateCoefficientsAtInfinity + (f : CuspForm Γ k) : + IsSelfDual f ↔ HasConjugateCoefficientsAtInfinity f f := by + constructor + · intro hf n + exact ((Complex.conj_eq_iff_im).mpr (hf n)).symm + · intro h n + exact (Complex.conj_eq_iff_im).mp (h n).symm + +namespace LFunction + +/-- +Self-duality of the L-function attached to a cusp form, expressed at the +coefficient-sequence level: the Dirichlet-series coefficients are real. +-/ +def IsSelfDual (f : CuspForm Γ k) : Prop := + ∀ n : ℕ, (ModularForms.lCoeff f n).im = 0 + +end LFunction + +lemma lCoeff_eq_fourierCoeffAtInfinity (f : CuspForm Γ k) (n : ℕ) : + ModularForms.lCoeff f n = fourierCoeffAtInfinity f n := by + rfl + +lemma isSelfDual_iff_lFunction_selfDual + (f : CuspForm Γ k) : + IsSelfDual f ↔ LFunction.IsSelfDual f := by + simp [IsSelfDual, LFunction.IsSelfDual] + +variable {N : ℕ} [NeZero N] + +section CongruenceSubgroup + +/-- Reflection of an integral determinant-one matrix by `J`. -/ +def reflectSL (A : SL(2, ℤ)) : SL(2, ℤ) where + val := !![A 0 0, -A 0 1; -A 1 0, A 1 1] + property := by + rw [Matrix.det_fin_two] + have hdet := A.property + rw [Matrix.det_fin_two] at hdet + simpa [mul_comm, mul_left_comm, mul_assoc] using hdet + +lemma reflectSL_mem_Gamma1 {N : ℕ} (A : SL(2, ℤ)) (hA : A ∈ Gamma1 N) : + reflectSL A ∈ Gamma1 N := by + rw [Gamma1_mem] at hA ⊢ + simpa [reflectSL] using hA + +lemma J_inv_eq_J : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := by + rw [inv_eq_iff_mul_eq_one] + simpa [sq] using UpperHalfPlane.J_sq + +lemma reflectSL_mapGL_eq_J_mul (A : SL(2, ℤ)) : + (mapGL ℝ (reflectSL A) : GL (Fin 2) ℝ) = + UpperHalfPlane.J * (mapGL ℝ A : GL (Fin 2) ℝ) * UpperHalfPlane.J⁻¹ := by + rw [J_inv_eq_J] + ext i j + fin_cases i <;> fin_cases j <;> + simp [reflectSL, UpperHalfPlane.J, Matrix.mul_apply, Matrix.vecMul, Fin.sum_univ_two, + Matrix.vecHead, Matrix.vecTail] + +lemma Gamma1_map_conj_J_le (N : ℕ) : + (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • ((Gamma1 N).map (mapGL ℝ)) ≤ + (Gamma1 N).map (mapGL ℝ) := by + intro x hx + rw [Subgroup.mem_pointwise_smul_iff_inv_smul_mem] at hx + rcases hx with ⟨A, hA, hAeq⟩ + refine ⟨reflectSL A, reflectSL_mem_Gamma1 A hA, ?_⟩ + have hJJ : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by + simpa [sq] using UpperHalfPlane.J_sq + rw [reflectSL_mapGL_eq_J_mul, hAeq] + simp [J_inv_eq_J, ConjAct.smul_def] + calc + UpperHalfPlane.J * (UpperHalfPlane.J * x * UpperHalfPlane.J) * UpperHalfPlane.J = + (UpperHalfPlane.J * UpperHalfPlane.J) * x * + (UpperHalfPlane.J * UpperHalfPlane.J) := by + group + _ = x := by simp [hJJ] + +lemma Gamma1_map_le_conj_J (N : ℕ) : + (Gamma1 N).map (mapGL ℝ) ≤ + (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • ((Gamma1 N).map (mapGL ℝ)) := by + rw [Subgroup.subset_pointwise_smul_iff] + rw [← ConjAct.toConjAct_inv] + simpa [J_inv_eq_J] using Gamma1_map_conj_J_le N + +/-- +Conjugating the image of `Γ₁(N)` in `GL₂(ℝ)` by `J` gives back the same subgroup. +-/ +lemma Gamma1_map_conj_J_eq (N : ℕ) : + (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • ((Gamma1 N).map (mapGL ℝ)) = + (Gamma1 N).map (mapGL ℝ) := + le_antisymm (Gamma1_map_conj_J_le N) (Gamma1_map_le_conj_J N) + +end CongruenceSubgroup + +/-- +The conjugate-coefficient dual cusp form. + +Concretely, this is the slash action by `J = [-1,0;0,1]`, bundled back as a +cusp form for `Γ₁(N)`. +-/ +noncomputable def dualForm (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : + CuspForm ((Gamma1 N).map (mapGL ℝ)) k := + (Gamma1_map_conj_J_eq N) ▸ CuspForm.translate f UpperHalfPlane.J + +/- +Previous inclusion-based definition: + +noncomputable def dualForm (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : + CuspForm ((Gamma1 N).map (mapGL ℝ)) k := + CuspForm.restrictSubgroup (Gamma1_map_le_conj_J N) (CuspForm.translate f UpperHalfPlane.J) +-/ + +lemma cuspForm_cast_coe {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') + (f : CuspForm Γ k) : + ⇑(h ▸ f : CuspForm Γ' k) = ⇑f := by + cases h + rfl + +omit [NeZero N] in +lemma dualForm_coe (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : + ⇑(dualForm f) = ⇑f ∣[k] UpperHalfPlane.J := by + unfold dualForm + rw [cuspForm_cast_coe] + rfl + +omit [NeZero N] in +lemma slash_J_apply (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (τ : UpperHalfPlane) : + (⇑f ∣[k] UpperHalfPlane.J) τ = conj (f (UpperHalfPlane.J • τ)) := by + simp [ModularForm.slash_apply] + +/-- The `q`-parameter at `J • τ` is the complex conjugate of the `q`-parameter at `τ`. -/ +lemma qParam_J_eq_conj (τ : UpperHalfPlane) : + Function.Periodic.qParam (1 : ℝ) (↑(UpperHalfPlane.J • τ) : ℂ) = + conj (Function.Periodic.qParam (1 : ℝ) (τ : ℂ)) := by + have harg : 2 * ↑Real.pi * I * (↑(UpperHalfPlane.J • τ) : ℂ) / (↑(1 : ℝ) : ℂ) = + conj (2 * ↑Real.pi * I * (τ : ℂ) / (↑(1 : ℝ) : ℂ)) := by + simp only [UpperHalfPlane.coe_J_smul, div_eq_mul_inv, map_mul, map_inv₀, map_ofNat, + Complex.conj_ofReal, Complex.conj_I] + ring + rw [Function.Periodic.qParam, Function.Periodic.qParam, harg, Complex.exp_conj] + +lemma qParam_J_pow_conj (τ : UpperHalfPlane) (m : ℕ) : + Function.Periodic.qParam (1 : ℝ) (↑(UpperHalfPlane.J • τ) : ℂ) ^ m = + conj (Function.Periodic.qParam (1 : ℝ) (τ : ℂ) ^ m) := by + rw [qParam_J_eq_conj] + simp + +omit [NeZero N] in +lemma dualForm_hasSum_conj_coeff + (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (τ : UpperHalfPlane) : + HasSum + (fun m : ℕ ↦ conj ((UpperHalfPlane.qExpansion (1 : ℝ) f).coeff m) • + Function.Periodic.qParam (1 : ℝ) (τ : ℂ) ^ m) + (dualForm f τ) := by + have h_period := one_mem_strictPeriods_Gamma1_map N + haveI : Fact (IsCusp OnePoint.infty ((Gamma1 N).map (mapGL ℝ))) := + ⟨((Gamma1 N).map (mapGL ℝ)).isCusp_of_mem_strictPeriods one_pos h_period⟩ + have hf_sum : HasSum + (fun m : ℕ ↦ (UpperHalfPlane.qExpansion (1 : ℝ) f).coeff m • + Function.Periodic.qParam (1 : ℝ) (↑(UpperHalfPlane.J • τ) : ℂ) ^ m) + (f (UpperHalfPlane.J • τ)) := by + exact UpperHalfPlane.hasSum_qExpansion one_pos + (SlashInvariantFormClass.periodic_comp_ofComplex f h_period) + (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) + (UpperHalfPlane.J • τ) + have hconj := (Complex.hasSum_conj').mpr hf_sum + rw [dualForm_coe, slash_J_apply] + simpa [smul_eq_mul, qParam_J_pow_conj τ, mul_comm, mul_left_comm, mul_assoc] using hconj + +omit [NeZero N] in +/-- The `∞`-Fourier coefficients of `dualForm f` are the conjugates of those of `f`. -/ +lemma dualForm_coeffAtInfinity_eq_conj + (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (n : ℕ) : + fourierCoeffAtInfinity (dualForm f) n = conj (fourierCoeffAtInfinity f n) := by + have hcoeff := ModularFormClass.qExpansion_coeff_unique + (F := CuspForm ((Gamma1 N).map (mapGL ℝ)) k) + (Γ := ((Gamma1 N).map (mapGL ℝ))) (k := k) + (c := fun m : ℕ ↦ conj ((UpperHalfPlane.qExpansion (1 : ℝ) f).coeff m)) + one_pos (one_mem_strictPeriods_Gamma1_map N) + (f := dualForm f) (dualForm_hasSum_conj_coeff f) n + rw [fourierCoeffAtInfinity, fourierCoeffAtInfinity, + ModularForms.strictWidthInfty_Gamma1_mapGL] + exact hcoeff.symm + +omit [NeZero N] in +lemma dualForm_hasConjugateCoefficientsAtInfinity + (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : + HasConjugateCoefficientsAtInfinity f (dualForm f) := + dualForm_coeffAtInfinity_eq_conj f + +omit [NeZero N] in +lemma dualForm_lCoeff_eq_conj + (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (n : ℕ) : + ModularForms.lCoeff (dualForm f) n = conj (ModularForms.lCoeff f n) := by + rw [lCoeff_eq_fourierCoeffAtInfinity, lCoeff_eq_fourierCoeffAtInfinity] + exact dualForm_coeffAtInfinity_eq_conj f n + +section Involution + +omit [NeZero N] in +lemma cuspForm_Gamma1_ext_of_forall_fourierCoeffAtInfinity_eq + {f g : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} + (h : ∀ n : ℕ, fourierCoeffAtInfinity f n = fourierCoeffAtInfinity g n) : + f = g := by + refine DFunLike.coe_injective ?_ + show (⇑f : UpperHalfPlane → ℂ) = ⇑g + have h_period := one_mem_strictPeriods_Gamma1_map N + have h_qExp_eq : ∀ n : ℕ, + (UpperHalfPlane.qExpansion (1 : ℝ) f.toModularForm').coeff n = + (UpperHalfPlane.qExpansion (1 : ℝ) g.toModularForm').coeff n := by + intro n + change (UpperHalfPlane.qExpansion (1 : ℝ) (⇑f : UpperHalfPlane → ℂ)).coeff n = + (UpperHalfPlane.qExpansion (1 : ℝ) (⇑g : UpperHalfPlane → ℂ)).coeff n + simpa [fourierCoeffAtInfinity, ModularForms.strictWidthInfty_Gamma1_mapGL] using h n + have h_diff_qExp_zero : + UpperHalfPlane.qExpansion (1 : ℝ) (f.toModularForm' - g.toModularForm') = 0 := by + rw [ModularForm.qExpansion_sub one_pos h_period f.toModularForm' g.toModularForm'] + ext n + simp [h_qExp_eq n] + have h_diff_zero : f.toModularForm' - g.toModularForm' = 0 := + (ModularForm.qExpansion_eq_zero_iff one_pos h_period + (f := f.toModularForm' - g.toModularForm')).mp h_diff_qExp_zero + funext z + have hz := DFunLike.congr_fun h_diff_zero z + exact sub_eq_zero.mp hz + +omit [NeZero N] in +/-- The dualForm map is an involution. -/ +lemma dualForm_dualForm (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : + dualForm (dualForm f) = f := by + apply cuspForm_Gamma1_ext_of_forall_fourierCoeffAtInfinity_eq + intro n + rw [dualForm_coeffAtInfinity_eq_conj, dualForm_coeffAtInfinity_eq_conj] + simp + +omit [NeZero N] in +lemma isSelfDual_of_dualForm_eq_self + {f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} (h : dualForm f = f) : + IsSelfDual f := by + intro n + have hcoeff := congrArg (fun g : CuspForm ((Gamma1 N).map (mapGL ℝ)) k ↦ + fourierCoeffAtInfinity g n) h + rw [dualForm_coeffAtInfinity_eq_conj] at hcoeff + exact Complex.conj_eq_iff_im.mp hcoeff + +omit [NeZero N] in +lemma dualForm_eq_self_of_isSelfDual + (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (hf : IsSelfDual f) : + dualForm f = f := by + apply cuspForm_Gamma1_ext_of_forall_fourierCoeffAtInfinity_eq + intro n + have hreal : conj (fourierCoeffAtInfinity f n) = fourierCoeffAtInfinity f n := + (Complex.conj_eq_iff_im).mpr (hf n) + rw [dualForm_coeffAtInfinity_eq_conj, hreal] + +omit [NeZero N] in +/-- A cusp form is fixed by `dualForm` if and only if all of its `∞`-coefficients are real. -/ +lemma dualForm_eq_self_iff (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : + dualForm f = f ↔ IsSelfDual f := + ⟨isSelfDual_of_dualForm_eq_self, dualForm_eq_self_of_isSelfDual f⟩ + +end Involution + +section Character + +/-- Pointwise conjugation of a Nebentypus character. -/ +def conjNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : (ZMod N)ˣ →* ℂˣ where + toFun d := star (χ d) + map_one' := by simp + map_mul' d e := by + ext + simp [map_mul] + +omit [NeZero N] in +@[simp] +lemma conjNebentypus_apply_coe (χ : (ZMod N)ˣ →* ℂˣ) (d : (ZMod N)ˣ) : + ((conjNebentypus χ d : ℂ)) = conj ((χ d : ℂ)) := by + rfl + +lemma reflectSL_mem_Gamma0 {N : ℕ} (A : SL(2, ℤ)) (hA : A ∈ Gamma0 N) : + reflectSL A ∈ Gamma0 N := by + rw [Gamma0_mem] at hA ⊢ + simpa [reflectSL] using hA + +lemma J_mul_mapGL_eq_reflectSL_mul_J (A : SL(2, ℤ)) : + UpperHalfPlane.J * (mapGL ℝ A : GL (Fin 2) ℝ) = + (mapGL ℝ (reflectSL A) : GL (Fin 2) ℝ) * UpperHalfPlane.J := by + rw [reflectSL_mapGL_eq_J_mul, J_inv_eq_J] + rw [mul_assoc (UpperHalfPlane.J * (mapGL ℝ A : GL (Fin 2) ℝ)) + UpperHalfPlane.J UpperHalfPlane.J] + simp [show UpperHalfPlane.J * UpperHalfPlane.J = 1 by + simpa [sq] using UpperHalfPlane.J_sq] + +omit [NeZero N] in +lemma Gamma0MapUnits_reflectSL (g : ↥(Gamma0 N)) : + Gamma0MapUnits + ⟨reflectSL (g : SL(2, ℤ)), reflectSL_mem_Gamma0 (g : SL(2, ℤ)) g.property⟩ = + Gamma0MapUnits g := by + ext + simp [Gamma0MapUnits_val, Gamma0Map, reflectSL] + +/-- +The dual form sends the `χ`-Nebentypus subspace to the subspace for the pointwise +conjugate character. +-/ +lemma dualForm_mem_conjNebentypus {χ : (ZMod N)ˣ →* ℂˣ} + {f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} + (hfχ : f ∈ cuspFormCharSpace k χ) : + dualForm f ∈ cuspFormCharSpace k (conjNebentypus χ) := by + rw [cuspFormCharSpace_iff_nebentypus] + intro g + have hf_neb := (cuspFormCharSpace_iff_nebentypus k χ f).mp hfχ + let gJ : ↥(Gamma0 N) := + ⟨reflectSL (g : SL(2, ℤ)), reflectSL_mem_Gamma0 (g : SL(2, ℤ)) g.property⟩ + have hunit : Gamma0MapUnits gJ = Gamma0MapUnits g := Gamma0MapUnits_reflectSL g + calc + (⇑(dualForm f) ∣[k] mapGL ℝ (g : SL(2, ℤ))) + = ((⇑f ∣[k] UpperHalfPlane.J) ∣[k] mapGL ℝ (g : SL(2, ℤ))) := by + rw [dualForm_coe] + _ = ⇑f ∣[k] (UpperHalfPlane.J * mapGL ℝ (g : SL(2, ℤ))) := by + rw [← SlashAction.slash_mul] + _ = ⇑f ∣[k] (mapGL ℝ (reflectSL (g : SL(2, ℤ))) * UpperHalfPlane.J) := by + rw [J_mul_mapGL_eq_reflectSL_mul_J] + _ = (⇑f ∣[k] mapGL ℝ (reflectSL (g : SL(2, ℤ)))) ∣[k] UpperHalfPlane.J := by + rw [SlashAction.slash_mul] + _ = (((χ (Gamma0MapUnits g) : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) := by + rw [← hunit] + exact congrArg (fun F : UpperHalfPlane → ℂ => F ∣[k] UpperHalfPlane.J) (hf_neb gJ) + _ = (↑(conjNebentypus χ (Gamma0MapUnits g)) : ℂ) • ⇑(dualForm f) := by + rw [dualForm_coe] + simp [ModularForm.smul_slash] + +/-- A Nebentypus character is real-valued when all of its values have zero imaginary part. -/ +def HasRealNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : Prop := + ∀ d : (ZMod N)ˣ, ((χ d : ℂ).im = 0) + +omit [NeZero N] in +/-- A real-valued Nebentypus character is unchanged by pointwise complex conjugation. -/ +lemma conjNebentypus_eq_of_hasRealNebentypus {χ : (ZMod N)ˣ →* ℂˣ} + (hχ : HasRealNebentypus χ) : + conjNebentypus χ = χ := by + ext d + rw [conjNebentypus_apply_coe] + exact (Complex.conj_eq_iff_im).mpr (hχ d) + +omit [NeZero N] in +@[simp] +lemma hasRealNebentypus_one : HasRealNebentypus (N := N) 1 := by + intro d + simp + +/-- A character is quadratic if all values are `±1`. -/ +def IsQuadraticNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : Prop := + ∀ d : (ZMod N)ˣ, χ d = 1 ∨ χ d = -1 + +omit [NeZero N] in +lemma IsQuadraticNebentypus.hasRealNebentypus {χ : (ZMod N)ˣ →* ℂˣ} + (hχ : IsQuadraticNebentypus χ) : HasRealNebentypus χ := by + intro d + rcases hχ d with hd | hd <;> simp [hd] + +lemma HasRealNebentypus.isQuadratic {χ : (ZMod N)ˣ →* ℂˣ} + (hχ : HasRealNebentypus χ) : IsQuadraticNebentypus χ := by + intro d + let x : ℝ := (χ d : ℂ).re + have hx_complex : (x : ℂ) = (χ d : ℂ) := by + apply Complex.ext + · simp [x] + · simp [x, hχ d] + have hpow_units : χ d ^ Fintype.card (ZMod N)ˣ = 1 := by + rw [← map_pow, pow_card_eq_one, map_one] + have hpow_complex : (x : ℂ) ^ Fintype.card (ZMod N)ˣ = (1 : ℂ) := by + rw [hx_complex] + simpa using congrArg Units.val hpow_units + have hpow_real : x ^ Fintype.card (ZMod N)ˣ = 1 := by + exact Complex.ofReal_injective (by simpa using hpow_complex) + have hx_fin : IsOfFinOrder x := + isOfFinOrder_iff_pow_eq_one.mpr + ⟨Fintype.card (ZMod N)ˣ, Fintype.card_pos_iff.mpr ⟨(1 : (ZMod N)ˣ)⟩, hpow_real⟩ + rcases le_total 0 x with hx_nonneg | hx_nonpos + · left + apply Units.ext + change (χ d : ℂ) = (1 : ℂ) + rw [← hx_complex, IsOfFinOrder.eq_one hx_nonneg hx_fin] + norm_num + · right + apply Units.ext + change (χ d : ℂ) = (-1 : ℂ) + rw [← hx_complex, IsOfFinOrder.eq_neg_one hx_nonpos hx_fin] + norm_num + +/-- For Nebentypus characters, being real-valued is equivalent to being quadratic. -/ +lemma hasRealNebentypus_iff_isQuadraticNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : + HasRealNebentypus χ ↔ IsQuadraticNebentypus χ := + ⟨HasRealNebentypus.isQuadratic, IsQuadraticNebentypus.hasRealNebentypus⟩ + +end Character + +section TestCases + +/-- Test case: a real Nebentypus space is preserved by the dual form. -/ +lemma dualForm_mem_realNebentypus {χ : (ZMod N)ˣ →* ℂˣ} + {f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} + (hfχ : f ∈ cuspFormCharSpace k χ) (hχ : HasRealNebentypus χ) : + dualForm f ∈ cuspFormCharSpace k χ := by + simpa [conjNebentypus_eq_of_hasRealNebentypus hχ] using + dualForm_mem_conjNebentypus (χ := χ) (f := f) hfχ + +/-- Test case: a newform with a non-real coefficient is not self-dual. -/ +lemma newform_not_selfDual_of_nonreal_coeff (f : Newform N k) {n : ℕ} + (hn : (fourierCoeffAtInfinity f.toCuspForm n).im ≠ 0) : + ¬ IsSelfDual f.toCuspForm := by + intro h + exact hn (h n) + +end TestCases + +end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean new file mode 100644 index 000000000..34be83b51 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean @@ -0,0 +1,142 @@ +import Mathlib.NumberTheory.NumberField.InfinitePlace.TotallyRealComplex +import Mathlib.Algebra.QuadraticAlgebra.Basic +import Mathlib.NumberTheory.Real.Irrational +import Mathlib.Tactic + +/-! +# LeanBridge issue #56: totally positive elements + +The definition is stated using the infinite-place API: every real infinite place sends the element +to a positive real number. +-/ + +namespace NumberField + +variable {K : Type*} [Field K] + +/-- An element is totally positive if it is positive under every real infinite place. -/ +def IsTotallyPositive (x : K) : Prop := + ∀ (w : InfinitePlace K) (hw : w.IsReal), 0 < InfinitePlace.embedding_of_isReal hw x + +lemma isTotallyPositive_iff {x : K} : + IsTotallyPositive x ↔ + ∀ (w : InfinitePlace K) (hw : w.IsReal), 0 < InfinitePlace.embedding_of_isReal hw x := + Iff.rfl + +namespace IsTotallyPositive + +lemma add {x y : K} (hx : IsTotallyPositive x) (hy : IsTotallyPositive y) : + IsTotallyPositive (x + y) := by + intro w hw + simpa using add_pos (hx w hw) (hy w hw) + +lemma mul {x y : K} (hx : IsTotallyPositive x) (hy : IsTotallyPositive y) : + IsTotallyPositive (x * y) := by + intro w hw + simpa using mul_pos (hx w hw) (hy w hw) + +lemma pow_two {x : K} (hx : x ≠ 0) : IsTotallyPositive (x ^ 2) := by + intro w hw + have hxw : InfinitePlace.embedding_of_isReal hw x ≠ 0 := by + exact (map_ne_zero (InfinitePlace.embedding_of_isReal hw)).mpr hx + simpa [pow_two] using sq_pos_of_ne_zero hxw + +lemma inv {x : K} (hx : IsTotallyPositive x) : IsTotallyPositive x⁻¹ := by + intro w hw + simpa using inv_pos.mpr (hx w hw) + +lemma div {x y : K} (hx : IsTotallyPositive x) (hy : IsTotallyPositive y) : + IsTotallyPositive (x / y) := by + simpa [div_eq_mul_inv] using hx.mul hy.inv + +end IsTotallyPositive + +lemma isTotallyPositive_unit_square (u : Kˣ) : IsTotallyPositive ((u : K) ^ 2) := + IsTotallyPositive.pow_two u.ne_zero + +noncomputable section + +open scoped QuadraticAlgebra + +namespace Issue56Examples + +abbrev Qsqrt2 := QuadraticAlgebra ℚ (2 : ℚ) 0 + +lemma qsqrt2_no_rat_root : ∀ r : ℚ, r ^ 2 ≠ (2 : ℚ) + 0 * r := by + intro r hr + norm_num at hr + have hreal : ((r : ℝ) ^ 2) = (2 : ℝ) := by exact_mod_cast hr + have hsq : ((r : ℝ) ^ 2) = (Real.sqrt 2) ^ 2 := by + rw [hreal, Real.sq_sqrt (by norm_num)] + rcases (sq_eq_sq_iff_eq_or_eq_neg.mp hsq) with h | h + · exact irrational_sqrt_two ⟨r, h⟩ + · exact irrational_sqrt_two ⟨-r, by simp [h]⟩ + +local instance : Fact (∀ r : ℚ, r ^ 2 ≠ (2 : ℚ) + 0 * r) := + ⟨qsqrt2_no_rat_root⟩ + +abbrev sqrtTwo : Qsqrt2 := + QuadraticAlgebra.omega + +abbrev threePlusTwoSqrtTwo : Qsqrt2 := + ⟨3, 2⟩ + +lemma one_add_sqrtTwo_sq : (1 + sqrtTwo) ^ 2 = threePlusTwoSqrtTwo := by + ext <;> norm_num [sqrtTwo, threePlusTwoSqrtTwo, pow_two] + +lemma threePlusTwoSqrtTwo_eq_one_add_sq : + threePlusTwoSqrtTwo = (1 + sqrtTwo) ^ 2 := + one_add_sqrtTwo_sq.symm + +example : IsTotallyPositive threePlusTwoSqrtTwo := by + rw [threePlusTwoSqrtTwo_eq_one_add_sq] + exact IsTotallyPositive.pow_two (by + intro h + have him := congrArg QuadraticAlgebra.im h + norm_num [sqrtTwo] at him) + +noncomputable def negSqrt2AlgHom : Qsqrt2 →ₐ[ℚ] ℝ := + QuadraticAlgebra.lift ⟨-Real.sqrt 2, by + rw [neg_mul_neg, ← pow_two (Real.sqrt 2), Real.sq_sqrt (by norm_num)] + norm_num⟩ + +lemma negSqrt2AlgHom_sqrtTwo : negSqrt2AlgHom sqrtTwo = -Real.sqrt 2 := by + dsimp [negSqrt2AlgHom, sqrtTwo, QuadraticAlgebra.lift] + change (QuadraticAlgebra.omega : Qsqrt2).re • (1 : ℝ) + + (QuadraticAlgebra.omega : Qsqrt2).im • (-Real.sqrt 2) = -Real.sqrt 2 + norm_num + +noncomputable def negSqrt2Embedding : Qsqrt2 →+* ℂ := + Complex.ofRealHom.comp negSqrt2AlgHom.toRingHom + +lemma negSqrt2Embedding_isReal : ComplexEmbedding.IsReal negSqrt2Embedding := by + rw [ComplexEmbedding.isReal_iff] + ext x + simp [negSqrt2Embedding] + +lemma neg_place_sqrtTwo : + let w := InfinitePlace.mk negSqrt2Embedding + let hw : w.IsReal := InfinitePlace.isReal_mk_iff.mpr negSqrt2Embedding_isReal + InfinitePlace.embedding_of_isReal hw sqrtTwo = -Real.sqrt 2 := by + dsimp only + apply Complex.ofReal_injective + rw [InfinitePlace.embedding_of_isReal_apply, + InfinitePlace.embedding_mk_eq_of_isReal negSqrt2Embedding_isReal] + simp [negSqrt2Embedding, negSqrt2AlgHom_sqrtTwo] + +example : ¬ IsTotallyPositive sqrtTwo := by + intro h + let w := InfinitePlace.mk negSqrt2Embedding + let hw : w.IsReal := InfinitePlace.isReal_mk_iff.mpr negSqrt2Embedding_isReal + have hω : InfinitePlace.embedding_of_isReal hw sqrtTwo = -Real.sqrt 2 := neg_place_sqrtTwo + have hsqrt_pos : 0 < Real.sqrt 2 := by positivity + have hnot : ¬ 0 < InfinitePlace.embedding_of_isReal hw sqrtTwo := by + rw [hω] + linarith + exact hnot (h w hw) + +end Issue56Examples + +end + +end NumberField From 524b8556418d08bb668c4f8bc80fd3c0dd14827a Mon Sep 17 00:00:00 2001 From: SmwYin Date: Tue, 30 Jun 2026 13:53:21 +0100 Subject: [PATCH 2/5] SelfDual --- .../LeanModularForms/Experiments/Issue34.lean | 54 ++ .../LeanModularForms/Experiments/Issue55.lean | 478 ------------------ .../Experiments/SelfDual/Basic.lean | 111 ++++ .../Experiments/SelfDual/Version1.lean | 107 ++++ .../Experiments/SelfDual/Version2.lean | 88 ++++ .../LeanModularForms/Issues/SelfDual'.lean | 38 ++ .../LeanModularForms/Issues/SelfDual.lean | 38 ++ .../Issues/SelfDual/Basic.lean | 111 ++++ .../Issues/SelfDual/Version1.lean | 107 ++++ .../Issues/SelfDual/Version2.lean | 88 ++++ 10 files changed, 742 insertions(+), 478 deletions(-) delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual'.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean index e69de29bb..76f9981b0 100644 --- a/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean +++ b/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean @@ -0,0 +1,54 @@ +import LeanModularForms.Experiments.Issue55 +import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic +import Mathlib.NumberTheory.NumberField.CMField + +/-! +# LeanBridge issue #34: coefficient fields of newforms + +This file states the key coefficient-field targets for newforms. +-/ + +noncomputable section + +namespace HeckeRing.GL2 + +variable {N : ℕ} [NeZero N] {k : ℤ} + +namespace Newform + +/-- The coefficient field `ℚ(a_n : n ≥ 1)` of a newform. -/ +noncomputable def coefficientField (f : Newform N k) : IntermediateField ℚ ℂ := + IntermediateField.adjoin ℚ + (Set.range fun n : ℕ+ => fourierCoeffAtInfinity f.toCuspForm n.val) + +/-- The coefficient field of a newform is finite-dimensional over `ℚ`. -/ +theorem coefficientField_finiteDimensional (f : Newform N k) : + FiniteDimensional ℚ f.coefficientField := by + sorry + +/-- The coefficient field of a newform is a number field. -/ +theorem coefficientField_numberField (f : Newform N k) : + NumberField f.coefficientField := by + sorry + +/-- The relative dimension attached to a newform. -/ +noncomputable def relativeDimension (f : Newform N k) : ℕ := + Module.finrank ℚ f.coefficientField + +theorem coefficientField_degree_eq_relativeDimension (f : Newform N k) : + Module.finrank ℚ f.coefficientField = f.relativeDimension := by + sorry + +/-- A newform's coefficient field is totally real if and only if the newform is self-dual. -/ +theorem coefficientField_isTotallyReal_iff_isSelfDual (f : Newform N k) : + NumberField.IsTotallyReal f.coefficientField ↔ IsSelfDual f.toCuspForm := by + sorry + +/-- A newform's coefficient field is CM if and only if the newform is not self-dual. -/ +theorem coefficientField_isCM_iff_not_isSelfDual (f : Newform N k) : + NumberField.IsCMField f.coefficientField ↔ ¬ IsSelfDual f.toCuspForm := by + sorry + +end Newform + +end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean deleted file mode 100644 index 990b30c18..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/Issue55.lean +++ /dev/null @@ -1,478 +0,0 @@ -import LeanModularForms.HeckeRIngs.GL2.Newforms.Newform -import Mathlib.Tactic - -/-! -# LeanBridge issue #55: dual and self-dual cusp forms - -This file defines the conjugate-coefficient dual of a cusp form in the -Nebentypus ambient space `S_k(N, χ)`, represented in this repository as the -`χ`-eigenspace inside cusp forms for `Γ₁(N)`. - -The construction is the slash action by the reflection -`J = [-1, 0; 0, 1]`, which sends `τ` to `-conj τ`. The form `dualForm f` -is a bundled cusp form, its `∞`-Fourier coefficients are the complex -conjugates of those of `f`, and it sends the `χ`-character subspace to the -pointwise conjugate character subspace. --/ - -noncomputable section - -namespace HeckeRing.GL2 - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex -open scoped ComplexConjugate MatrixGroups ModularForm Pointwise - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -/-- The canonical Fourier coefficient `aₙ(f)` of a cusp form at the cusp `∞`. -/ -noncomputable def fourierCoeffAtInfinity (f : CuspForm Γ k) (n : ℕ) : ℂ := - (UpperHalfPlane.qExpansion Γ.strictWidthInfty f).coeff n - -@[simp] -lemma fourierCoeffAtInfinity_apply (f : CuspForm Γ k) (n : ℕ) : - fourierCoeffAtInfinity f n = - (UpperHalfPlane.qExpansion Γ.strictWidthInfty f).coeff n := - rfl - -/-- `g` has the `∞`-coefficients expected of the conjugate-coefficient dual of `f`. -/ -def HasConjugateCoefficientsAtInfinity (f g : CuspForm Γ k) : Prop := - ∀ n : ℕ, fourierCoeffAtInfinity g n = conj (fourierCoeffAtInfinity f n) - -@[symm] -lemma HasConjugateCoefficientsAtInfinity.symm {f g : CuspForm Γ k} - (h : HasConjugateCoefficientsAtInfinity f g) : - HasConjugateCoefficientsAtInfinity g f := by - intro n - have hn := congrArg conj (h n) - simpa using hn.symm - -lemma hasConjugateCoefficientsAtInfinity_comm (f g : CuspForm Γ k) : - HasConjugateCoefficientsAtInfinity f g ↔ HasConjugateCoefficientsAtInfinity g f := - ⟨HasConjugateCoefficientsAtInfinity.symm, HasConjugateCoefficientsAtInfinity.symm⟩ - -/-- -A cusp form is self-dual, for its L-function, when all canonical Fourier -coefficients at `∞` are real. --/ -def IsSelfDual (f : CuspForm Γ k) : Prop := - ∀ n : ℕ, (fourierCoeffAtInfinity f n).im = 0 - -lemma isSelfDual_iff_self_hasConjugateCoefficientsAtInfinity - (f : CuspForm Γ k) : - IsSelfDual f ↔ HasConjugateCoefficientsAtInfinity f f := by - constructor - · intro hf n - exact ((Complex.conj_eq_iff_im).mpr (hf n)).symm - · intro h n - exact (Complex.conj_eq_iff_im).mp (h n).symm - -namespace LFunction - -/-- -Self-duality of the L-function attached to a cusp form, expressed at the -coefficient-sequence level: the Dirichlet-series coefficients are real. --/ -def IsSelfDual (f : CuspForm Γ k) : Prop := - ∀ n : ℕ, (ModularForms.lCoeff f n).im = 0 - -end LFunction - -lemma lCoeff_eq_fourierCoeffAtInfinity (f : CuspForm Γ k) (n : ℕ) : - ModularForms.lCoeff f n = fourierCoeffAtInfinity f n := by - rfl - -lemma isSelfDual_iff_lFunction_selfDual - (f : CuspForm Γ k) : - IsSelfDual f ↔ LFunction.IsSelfDual f := by - simp [IsSelfDual, LFunction.IsSelfDual] - -variable {N : ℕ} [NeZero N] - -section CongruenceSubgroup - -/-- Reflection of an integral determinant-one matrix by `J`. -/ -def reflectSL (A : SL(2, ℤ)) : SL(2, ℤ) where - val := !![A 0 0, -A 0 1; -A 1 0, A 1 1] - property := by - rw [Matrix.det_fin_two] - have hdet := A.property - rw [Matrix.det_fin_two] at hdet - simpa [mul_comm, mul_left_comm, mul_assoc] using hdet - -lemma reflectSL_mem_Gamma1 {N : ℕ} (A : SL(2, ℤ)) (hA : A ∈ Gamma1 N) : - reflectSL A ∈ Gamma1 N := by - rw [Gamma1_mem] at hA ⊢ - simpa [reflectSL] using hA - -lemma J_inv_eq_J : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := by - rw [inv_eq_iff_mul_eq_one] - simpa [sq] using UpperHalfPlane.J_sq - -lemma reflectSL_mapGL_eq_J_mul (A : SL(2, ℤ)) : - (mapGL ℝ (reflectSL A) : GL (Fin 2) ℝ) = - UpperHalfPlane.J * (mapGL ℝ A : GL (Fin 2) ℝ) * UpperHalfPlane.J⁻¹ := by - rw [J_inv_eq_J] - ext i j - fin_cases i <;> fin_cases j <;> - simp [reflectSL, UpperHalfPlane.J, Matrix.mul_apply, Matrix.vecMul, Fin.sum_univ_two, - Matrix.vecHead, Matrix.vecTail] - -lemma Gamma1_map_conj_J_le (N : ℕ) : - (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • ((Gamma1 N).map (mapGL ℝ)) ≤ - (Gamma1 N).map (mapGL ℝ) := by - intro x hx - rw [Subgroup.mem_pointwise_smul_iff_inv_smul_mem] at hx - rcases hx with ⟨A, hA, hAeq⟩ - refine ⟨reflectSL A, reflectSL_mem_Gamma1 A hA, ?_⟩ - have hJJ : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by - simpa [sq] using UpperHalfPlane.J_sq - rw [reflectSL_mapGL_eq_J_mul, hAeq] - simp [J_inv_eq_J, ConjAct.smul_def] - calc - UpperHalfPlane.J * (UpperHalfPlane.J * x * UpperHalfPlane.J) * UpperHalfPlane.J = - (UpperHalfPlane.J * UpperHalfPlane.J) * x * - (UpperHalfPlane.J * UpperHalfPlane.J) := by - group - _ = x := by simp [hJJ] - -lemma Gamma1_map_le_conj_J (N : ℕ) : - (Gamma1 N).map (mapGL ℝ) ≤ - (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • ((Gamma1 N).map (mapGL ℝ)) := by - rw [Subgroup.subset_pointwise_smul_iff] - rw [← ConjAct.toConjAct_inv] - simpa [J_inv_eq_J] using Gamma1_map_conj_J_le N - -/-- -Conjugating the image of `Γ₁(N)` in `GL₂(ℝ)` by `J` gives back the same subgroup. --/ -lemma Gamma1_map_conj_J_eq (N : ℕ) : - (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • ((Gamma1 N).map (mapGL ℝ)) = - (Gamma1 N).map (mapGL ℝ) := - le_antisymm (Gamma1_map_conj_J_le N) (Gamma1_map_le_conj_J N) - -end CongruenceSubgroup - -/-- -The conjugate-coefficient dual cusp form. - -Concretely, this is the slash action by `J = [-1,0;0,1]`, bundled back as a -cusp form for `Γ₁(N)`. --/ -noncomputable def dualForm (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : - CuspForm ((Gamma1 N).map (mapGL ℝ)) k := - (Gamma1_map_conj_J_eq N) ▸ CuspForm.translate f UpperHalfPlane.J - -/- -Previous inclusion-based definition: - -noncomputable def dualForm (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : - CuspForm ((Gamma1 N).map (mapGL ℝ)) k := - CuspForm.restrictSubgroup (Gamma1_map_le_conj_J N) (CuspForm.translate f UpperHalfPlane.J) --/ - -lemma cuspForm_cast_coe {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') - (f : CuspForm Γ k) : - ⇑(h ▸ f : CuspForm Γ' k) = ⇑f := by - cases h - rfl - -omit [NeZero N] in -lemma dualForm_coe (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : - ⇑(dualForm f) = ⇑f ∣[k] UpperHalfPlane.J := by - unfold dualForm - rw [cuspForm_cast_coe] - rfl - -omit [NeZero N] in -lemma slash_J_apply (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (τ : UpperHalfPlane) : - (⇑f ∣[k] UpperHalfPlane.J) τ = conj (f (UpperHalfPlane.J • τ)) := by - simp [ModularForm.slash_apply] - -/-- The `q`-parameter at `J • τ` is the complex conjugate of the `q`-parameter at `τ`. -/ -lemma qParam_J_eq_conj (τ : UpperHalfPlane) : - Function.Periodic.qParam (1 : ℝ) (↑(UpperHalfPlane.J • τ) : ℂ) = - conj (Function.Periodic.qParam (1 : ℝ) (τ : ℂ)) := by - have harg : 2 * ↑Real.pi * I * (↑(UpperHalfPlane.J • τ) : ℂ) / (↑(1 : ℝ) : ℂ) = - conj (2 * ↑Real.pi * I * (τ : ℂ) / (↑(1 : ℝ) : ℂ)) := by - simp only [UpperHalfPlane.coe_J_smul, div_eq_mul_inv, map_mul, map_inv₀, map_ofNat, - Complex.conj_ofReal, Complex.conj_I] - ring - rw [Function.Periodic.qParam, Function.Periodic.qParam, harg, Complex.exp_conj] - -lemma qParam_J_pow_conj (τ : UpperHalfPlane) (m : ℕ) : - Function.Periodic.qParam (1 : ℝ) (↑(UpperHalfPlane.J • τ) : ℂ) ^ m = - conj (Function.Periodic.qParam (1 : ℝ) (τ : ℂ) ^ m) := by - rw [qParam_J_eq_conj] - simp - -omit [NeZero N] in -lemma dualForm_hasSum_conj_coeff - (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (τ : UpperHalfPlane) : - HasSum - (fun m : ℕ ↦ conj ((UpperHalfPlane.qExpansion (1 : ℝ) f).coeff m) • - Function.Periodic.qParam (1 : ℝ) (τ : ℂ) ^ m) - (dualForm f τ) := by - have h_period := one_mem_strictPeriods_Gamma1_map N - haveI : Fact (IsCusp OnePoint.infty ((Gamma1 N).map (mapGL ℝ))) := - ⟨((Gamma1 N).map (mapGL ℝ)).isCusp_of_mem_strictPeriods one_pos h_period⟩ - have hf_sum : HasSum - (fun m : ℕ ↦ (UpperHalfPlane.qExpansion (1 : ℝ) f).coeff m • - Function.Periodic.qParam (1 : ℝ) (↑(UpperHalfPlane.J • τ) : ℂ) ^ m) - (f (UpperHalfPlane.J • τ)) := by - exact UpperHalfPlane.hasSum_qExpansion one_pos - (SlashInvariantFormClass.periodic_comp_ofComplex f h_period) - (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) - (UpperHalfPlane.J • τ) - have hconj := (Complex.hasSum_conj').mpr hf_sum - rw [dualForm_coe, slash_J_apply] - simpa [smul_eq_mul, qParam_J_pow_conj τ, mul_comm, mul_left_comm, mul_assoc] using hconj - -omit [NeZero N] in -/-- The `∞`-Fourier coefficients of `dualForm f` are the conjugates of those of `f`. -/ -lemma dualForm_coeffAtInfinity_eq_conj - (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (n : ℕ) : - fourierCoeffAtInfinity (dualForm f) n = conj (fourierCoeffAtInfinity f n) := by - have hcoeff := ModularFormClass.qExpansion_coeff_unique - (F := CuspForm ((Gamma1 N).map (mapGL ℝ)) k) - (Γ := ((Gamma1 N).map (mapGL ℝ))) (k := k) - (c := fun m : ℕ ↦ conj ((UpperHalfPlane.qExpansion (1 : ℝ) f).coeff m)) - one_pos (one_mem_strictPeriods_Gamma1_map N) - (f := dualForm f) (dualForm_hasSum_conj_coeff f) n - rw [fourierCoeffAtInfinity, fourierCoeffAtInfinity, - ModularForms.strictWidthInfty_Gamma1_mapGL] - exact hcoeff.symm - -omit [NeZero N] in -lemma dualForm_hasConjugateCoefficientsAtInfinity - (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : - HasConjugateCoefficientsAtInfinity f (dualForm f) := - dualForm_coeffAtInfinity_eq_conj f - -omit [NeZero N] in -lemma dualForm_lCoeff_eq_conj - (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (n : ℕ) : - ModularForms.lCoeff (dualForm f) n = conj (ModularForms.lCoeff f n) := by - rw [lCoeff_eq_fourierCoeffAtInfinity, lCoeff_eq_fourierCoeffAtInfinity] - exact dualForm_coeffAtInfinity_eq_conj f n - -section Involution - -omit [NeZero N] in -lemma cuspForm_Gamma1_ext_of_forall_fourierCoeffAtInfinity_eq - {f g : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} - (h : ∀ n : ℕ, fourierCoeffAtInfinity f n = fourierCoeffAtInfinity g n) : - f = g := by - refine DFunLike.coe_injective ?_ - show (⇑f : UpperHalfPlane → ℂ) = ⇑g - have h_period := one_mem_strictPeriods_Gamma1_map N - have h_qExp_eq : ∀ n : ℕ, - (UpperHalfPlane.qExpansion (1 : ℝ) f.toModularForm').coeff n = - (UpperHalfPlane.qExpansion (1 : ℝ) g.toModularForm').coeff n := by - intro n - change (UpperHalfPlane.qExpansion (1 : ℝ) (⇑f : UpperHalfPlane → ℂ)).coeff n = - (UpperHalfPlane.qExpansion (1 : ℝ) (⇑g : UpperHalfPlane → ℂ)).coeff n - simpa [fourierCoeffAtInfinity, ModularForms.strictWidthInfty_Gamma1_mapGL] using h n - have h_diff_qExp_zero : - UpperHalfPlane.qExpansion (1 : ℝ) (f.toModularForm' - g.toModularForm') = 0 := by - rw [ModularForm.qExpansion_sub one_pos h_period f.toModularForm' g.toModularForm'] - ext n - simp [h_qExp_eq n] - have h_diff_zero : f.toModularForm' - g.toModularForm' = 0 := - (ModularForm.qExpansion_eq_zero_iff one_pos h_period - (f := f.toModularForm' - g.toModularForm')).mp h_diff_qExp_zero - funext z - have hz := DFunLike.congr_fun h_diff_zero z - exact sub_eq_zero.mp hz - -omit [NeZero N] in -/-- The dualForm map is an involution. -/ -lemma dualForm_dualForm (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : - dualForm (dualForm f) = f := by - apply cuspForm_Gamma1_ext_of_forall_fourierCoeffAtInfinity_eq - intro n - rw [dualForm_coeffAtInfinity_eq_conj, dualForm_coeffAtInfinity_eq_conj] - simp - -omit [NeZero N] in -lemma isSelfDual_of_dualForm_eq_self - {f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} (h : dualForm f = f) : - IsSelfDual f := by - intro n - have hcoeff := congrArg (fun g : CuspForm ((Gamma1 N).map (mapGL ℝ)) k ↦ - fourierCoeffAtInfinity g n) h - rw [dualForm_coeffAtInfinity_eq_conj] at hcoeff - exact Complex.conj_eq_iff_im.mp hcoeff - -omit [NeZero N] in -lemma dualForm_eq_self_of_isSelfDual - (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) (hf : IsSelfDual f) : - dualForm f = f := by - apply cuspForm_Gamma1_ext_of_forall_fourierCoeffAtInfinity_eq - intro n - have hreal : conj (fourierCoeffAtInfinity f n) = fourierCoeffAtInfinity f n := - (Complex.conj_eq_iff_im).mpr (hf n) - rw [dualForm_coeffAtInfinity_eq_conj, hreal] - -omit [NeZero N] in -/-- A cusp form is fixed by `dualForm` if and only if all of its `∞`-coefficients are real. -/ -lemma dualForm_eq_self_iff (f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k) : - dualForm f = f ↔ IsSelfDual f := - ⟨isSelfDual_of_dualForm_eq_self, dualForm_eq_self_of_isSelfDual f⟩ - -end Involution - -section Character - -/-- Pointwise conjugation of a Nebentypus character. -/ -def conjNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : (ZMod N)ˣ →* ℂˣ where - toFun d := star (χ d) - map_one' := by simp - map_mul' d e := by - ext - simp [map_mul] - -omit [NeZero N] in -@[simp] -lemma conjNebentypus_apply_coe (χ : (ZMod N)ˣ →* ℂˣ) (d : (ZMod N)ˣ) : - ((conjNebentypus χ d : ℂ)) = conj ((χ d : ℂ)) := by - rfl - -lemma reflectSL_mem_Gamma0 {N : ℕ} (A : SL(2, ℤ)) (hA : A ∈ Gamma0 N) : - reflectSL A ∈ Gamma0 N := by - rw [Gamma0_mem] at hA ⊢ - simpa [reflectSL] using hA - -lemma J_mul_mapGL_eq_reflectSL_mul_J (A : SL(2, ℤ)) : - UpperHalfPlane.J * (mapGL ℝ A : GL (Fin 2) ℝ) = - (mapGL ℝ (reflectSL A) : GL (Fin 2) ℝ) * UpperHalfPlane.J := by - rw [reflectSL_mapGL_eq_J_mul, J_inv_eq_J] - rw [mul_assoc (UpperHalfPlane.J * (mapGL ℝ A : GL (Fin 2) ℝ)) - UpperHalfPlane.J UpperHalfPlane.J] - simp [show UpperHalfPlane.J * UpperHalfPlane.J = 1 by - simpa [sq] using UpperHalfPlane.J_sq] - -omit [NeZero N] in -lemma Gamma0MapUnits_reflectSL (g : ↥(Gamma0 N)) : - Gamma0MapUnits - ⟨reflectSL (g : SL(2, ℤ)), reflectSL_mem_Gamma0 (g : SL(2, ℤ)) g.property⟩ = - Gamma0MapUnits g := by - ext - simp [Gamma0MapUnits_val, Gamma0Map, reflectSL] - -/-- -The dual form sends the `χ`-Nebentypus subspace to the subspace for the pointwise -conjugate character. --/ -lemma dualForm_mem_conjNebentypus {χ : (ZMod N)ˣ →* ℂˣ} - {f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} - (hfχ : f ∈ cuspFormCharSpace k χ) : - dualForm f ∈ cuspFormCharSpace k (conjNebentypus χ) := by - rw [cuspFormCharSpace_iff_nebentypus] - intro g - have hf_neb := (cuspFormCharSpace_iff_nebentypus k χ f).mp hfχ - let gJ : ↥(Gamma0 N) := - ⟨reflectSL (g : SL(2, ℤ)), reflectSL_mem_Gamma0 (g : SL(2, ℤ)) g.property⟩ - have hunit : Gamma0MapUnits gJ = Gamma0MapUnits g := Gamma0MapUnits_reflectSL g - calc - (⇑(dualForm f) ∣[k] mapGL ℝ (g : SL(2, ℤ))) - = ((⇑f ∣[k] UpperHalfPlane.J) ∣[k] mapGL ℝ (g : SL(2, ℤ))) := by - rw [dualForm_coe] - _ = ⇑f ∣[k] (UpperHalfPlane.J * mapGL ℝ (g : SL(2, ℤ))) := by - rw [← SlashAction.slash_mul] - _ = ⇑f ∣[k] (mapGL ℝ (reflectSL (g : SL(2, ℤ))) * UpperHalfPlane.J) := by - rw [J_mul_mapGL_eq_reflectSL_mul_J] - _ = (⇑f ∣[k] mapGL ℝ (reflectSL (g : SL(2, ℤ)))) ∣[k] UpperHalfPlane.J := by - rw [SlashAction.slash_mul] - _ = (((χ (Gamma0MapUnits g) : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) := by - rw [← hunit] - exact congrArg (fun F : UpperHalfPlane → ℂ => F ∣[k] UpperHalfPlane.J) (hf_neb gJ) - _ = (↑(conjNebentypus χ (Gamma0MapUnits g)) : ℂ) • ⇑(dualForm f) := by - rw [dualForm_coe] - simp [ModularForm.smul_slash] - -/-- A Nebentypus character is real-valued when all of its values have zero imaginary part. -/ -def HasRealNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : Prop := - ∀ d : (ZMod N)ˣ, ((χ d : ℂ).im = 0) - -omit [NeZero N] in -/-- A real-valued Nebentypus character is unchanged by pointwise complex conjugation. -/ -lemma conjNebentypus_eq_of_hasRealNebentypus {χ : (ZMod N)ˣ →* ℂˣ} - (hχ : HasRealNebentypus χ) : - conjNebentypus χ = χ := by - ext d - rw [conjNebentypus_apply_coe] - exact (Complex.conj_eq_iff_im).mpr (hχ d) - -omit [NeZero N] in -@[simp] -lemma hasRealNebentypus_one : HasRealNebentypus (N := N) 1 := by - intro d - simp - -/-- A character is quadratic if all values are `±1`. -/ -def IsQuadraticNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : Prop := - ∀ d : (ZMod N)ˣ, χ d = 1 ∨ χ d = -1 - -omit [NeZero N] in -lemma IsQuadraticNebentypus.hasRealNebentypus {χ : (ZMod N)ˣ →* ℂˣ} - (hχ : IsQuadraticNebentypus χ) : HasRealNebentypus χ := by - intro d - rcases hχ d with hd | hd <;> simp [hd] - -lemma HasRealNebentypus.isQuadratic {χ : (ZMod N)ˣ →* ℂˣ} - (hχ : HasRealNebentypus χ) : IsQuadraticNebentypus χ := by - intro d - let x : ℝ := (χ d : ℂ).re - have hx_complex : (x : ℂ) = (χ d : ℂ) := by - apply Complex.ext - · simp [x] - · simp [x, hχ d] - have hpow_units : χ d ^ Fintype.card (ZMod N)ˣ = 1 := by - rw [← map_pow, pow_card_eq_one, map_one] - have hpow_complex : (x : ℂ) ^ Fintype.card (ZMod N)ˣ = (1 : ℂ) := by - rw [hx_complex] - simpa using congrArg Units.val hpow_units - have hpow_real : x ^ Fintype.card (ZMod N)ˣ = 1 := by - exact Complex.ofReal_injective (by simpa using hpow_complex) - have hx_fin : IsOfFinOrder x := - isOfFinOrder_iff_pow_eq_one.mpr - ⟨Fintype.card (ZMod N)ˣ, Fintype.card_pos_iff.mpr ⟨(1 : (ZMod N)ˣ)⟩, hpow_real⟩ - rcases le_total 0 x with hx_nonneg | hx_nonpos - · left - apply Units.ext - change (χ d : ℂ) = (1 : ℂ) - rw [← hx_complex, IsOfFinOrder.eq_one hx_nonneg hx_fin] - norm_num - · right - apply Units.ext - change (χ d : ℂ) = (-1 : ℂ) - rw [← hx_complex, IsOfFinOrder.eq_neg_one hx_nonpos hx_fin] - norm_num - -/-- For Nebentypus characters, being real-valued is equivalent to being quadratic. -/ -lemma hasRealNebentypus_iff_isQuadraticNebentypus (χ : (ZMod N)ˣ →* ℂˣ) : - HasRealNebentypus χ ↔ IsQuadraticNebentypus χ := - ⟨HasRealNebentypus.isQuadratic, IsQuadraticNebentypus.hasRealNebentypus⟩ - -end Character - -section TestCases - -/-- Test case: a real Nebentypus space is preserved by the dual form. -/ -lemma dualForm_mem_realNebentypus {χ : (ZMod N)ˣ →* ℂˣ} - {f : CuspForm ((Gamma1 N).map (mapGL ℝ)) k} - (hfχ : f ∈ cuspFormCharSpace k χ) (hχ : HasRealNebentypus χ) : - dualForm f ∈ cuspFormCharSpace k χ := by - simpa [conjNebentypus_eq_of_hasRealNebentypus hχ] using - dualForm_mem_conjNebentypus (χ := χ) (f := f) hfχ - -/-- Test case: a newform with a non-real coefficient is not self-dual. -/ -lemma newform_not_selfDual_of_nonreal_coeff (f : Newform N k) {n : ℕ} - (hn : (fourierCoeffAtInfinity f.toCuspForm n).im ≠ 0) : - ¬ IsSelfDual f.toCuspForm := by - intro h - exact hn (h n) - -end TestCases - -end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean new file mode 100644 index 000000000..e248cec50 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean @@ -0,0 +1,111 @@ +import Mathlib + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex Function MatrixGroups ModularForm Pointwise +open UpperHalfPlane hiding I +open scoped ComplexConjugate + +local notation "𝕢" => Periodic.qParam + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := + (ConjAct.toConjAct J⁻¹) • Γ + +class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where + self_dual : Subgroup.dual Γ = Γ + +noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := + ModularForm.translate f J + +@[simp] +theorem ModularForm.coe_dual (f : ModularForm Γ k) : + ⇑(ModularForm.dual f) = ⇑f ∣[k] J := + ModularForm.coe_translate f J + +@[simp] +theorem ModularForm.dual_apply (f : ModularForm Γ k) (z : ℍ) : + ModularForm.dual f z = (⇑f ∣[k] J) z := + rfl + +@[simp] +theorem ModularForm.dual_zero : + ModularForm.dual (0 : ModularForm Γ k) = 0 := by + ext z + simp + +@[simp] +theorem ModularForm.dual_add (f g : ModularForm Γ k) : + ModularForm.dual (f + g) = ModularForm.dual f + ModularForm.dual g := by + ext z + simp + +@[simp] +theorem ModularForm.dual_neg (f : ModularForm Γ k) : + ModularForm.dual (-f) = -ModularForm.dual f := by + ext z + simp + +@[simp] +theorem ModularForm.dual_sub (f g : ModularForm Γ k) : + ModularForm.dual (f - g) = ModularForm.dual f - ModularForm.dual g := by + ext z + simp [sub_eq_add_neg] + +@[simp] +theorem ModularForm.dual_smul_real (c : ℝ) (f : ModularForm Γ k) : + ModularForm.dual (c • f) = c • ModularForm.dual f := by + ext z + change (((c : ℂ) • ⇑f) ∣[k] J) z = (c : ℂ) * ModularForm.dual f z + rw [smul_slash, σ_ofReal J c] + rfl + +theorem ModularForm.dual_apply_conj (f : ModularForm Γ k) (z : ℍ) : + ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by + simp [ModularForm.slash_def, J_smul] + +private theorem qParam_neg_conj (h : ℝ) (z : ℂ) : + 𝕢 h (-(conj z)) = conj (𝕢 h z) := by + simp [Periodic.qParam, ← Complex.exp_conj, map_ofNat] + +theorem ModularForm.hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) : + ∀ z : ℍ, HasSum (fun m : ℕ ↦ conj ((qExpansion Γ.strictWidthInfty f).coeff m) • 𝕢 Γ.strictWidthInfty (z : ℂ) ^ m) + (ModularForm.dual f z) := by + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓ : h ∈ Γ.strictPeriods := by + simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ + haveI : Fact (IsCusp OnePoint.infty Γ) := ⟨Subgroup.isCusp_of_mem_strictPeriods hh hΓ⟩ + intro z + let z' : ℍ := ofComplex (-(conj (z : ℂ))) + have hz' : 0 < (-(conj (z : ℂ))).im := by simpa using z.im_pos + have hcoe : (z' : ℂ) = -(conj (z : ℂ)) := by + simp [z', ofComplex_apply_of_im_pos hz'] + have hq : 𝕢 h (z' : ℂ) = conj (𝕢 h (z : ℂ)) := by + rw [hcoe] + exact qParam_neg_conj h (z : ℂ) + have hval : (⇑f ∣[k] J) z = conj (f z') := by + simpa [ModularForm.dual_apply, z'] using ModularForm.dual_apply_conj f z + have hs1 : HasSum (fun m : ℕ ↦ conj ((qExpansion h f).coeff m • 𝕢 h (z' : ℂ) ^ m)) (conj (f z')) := + (RCLike.hasSum_conj ℂ).mpr (by + simpa using hasSum_qExpansion hh (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ) + (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) z') + simpa [h, ModularForm.dual_apply, hval, hq, Complex.conj_conj, map_mul, map_pow, smul_eq_mul] using hs1 + +theorem ModularForm.qExpansion_dual_coeff [Γ.IsSelfDual] [Γ.IsArithmetic] + (f : ModularForm Γ k) (n : ℕ) : + (qExpansion Γ.strictWidthInfty (ModularForm.dual f)).coeff n = + conj ((qExpansion Γ.strictWidthInfty f).coeff n) := by + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓdual : h ∈ (Subgroup.dual Γ).strictPeriods := by + simpa [h, Subgroup.IsSelfDual.self_dual (Γ := Γ)] using + Subgroup.strictWidthInfty_mem_strictPeriods Γ + simpa [h] using (ModularFormClass.qExpansion_coeff_unique + (Γ := Subgroup.dual Γ) (F := ModularForm (Subgroup.dual Γ) k) + (h := h) (hh := hh) (hΓ := hΓdual) (f := ModularForm.dual f) + (by simpa [h] using ModularForm.hasSum_qExpansion_dual (Γ := Γ) (k := k) f) n).symm + +theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} + (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by + cases h + rfl diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean new file mode 100644 index 000000000..51a0a1608 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean @@ -0,0 +1,107 @@ +import LeanModularForms.Experiments.SelfDual.Basic + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := + (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f + +theorem ModularForm.isSelfDual_iff_coe_dual_eq [Γ.IsSelfDual] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ ⇑(ModularForm.dual f) = ⇑f := by + constructor + · intro h + calc + ⇑(ModularForm.dual f) = + ⇑(‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f : ModularForm Γ k) := by + rw [ModularForm.coe_cast_group] + _ = ⇑f := by rw [h] + · intro h + apply ModularForm.ext + intro z + rw [ModularForm.coe_cast_group] + exact congrFun h z + +theorem ModularForm.isSelfDual_iff_apply [Γ.IsSelfDual] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ ∀ z, ModularForm.dual f z = f z := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] + exact ⟨fun h z => congrFun h z, fun h => funext h⟩ + +@[simp] +theorem ModularForm.isSelfDual_zero [Γ.IsSelfDual] : + ModularForm.isSelfDual (0 : ModularForm Γ k) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] + ext z + simp + +theorem ModularForm.isSelfDual_add [Γ.IsSelfDual] {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : + ModularForm.isSelfDual (f + g) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf hg ⊢ + ext z + simpa [ModularForm.dual_apply] using congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) + +theorem ModularForm.isSelfDual_neg [Γ.IsSelfDual] {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) : + ModularForm.isSelfDual (-f) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ + ext z + simpa [ModularForm.dual_apply] using congrArg Neg.neg (congrFun hf z) + +theorem ModularForm.isSelfDual_sub [Γ.IsSelfDual] {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : + ModularForm.isSelfDual (f - g) := by + simpa [sub_eq_add_neg] using ModularForm.isSelfDual_add hf (ModularForm.isSelfDual_neg hg) + +theorem ModularForm.isSelfDual_smul_real [Γ.IsSelfDual] (c : ℝ) {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) : + ModularForm.isSelfDual (c • f) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ + ext z + have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := + UpperHalfPlane.σ_ofReal UpperHalfPlane.J c + change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z + rw [smul_slash, hsigma] + simpa [Pi.smul_apply, smul_eq_mul] using + congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) + +theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ + ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓ : h ∈ Γ.strictPeriods := by + simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ + constructor + · intro hfd n + have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [hfd] + have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [← ModularForm.qExpansion_dual_coeff f n, hq] + simpa [h] using (Complex.conj_eq_iff_im.mp hstar) + · intro hcoeff + let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) + have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by + dsimp [fd] + rw [ModularForm.coe_cast_group] + have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by + apply PowerSeries.ext + intro n + rw [show (UpperHalfPlane.qExpansion h fd).coeff n = + (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] + rw [ModularForm.qExpansion_dual_coeff f n] + exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) + have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by + rw [show UpperHalfPlane.qExpansion h (fd - f) = + UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] + rw [ModularForm.qExpansion_sub hh hΓ fd f] + simp [hq] + have hzero_form : fd - f = 0 := + (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q + have hfd_eq : fd = f := sub_eq_zero.mp hzero_form + calc + ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm + _ = ⇑f := by rw [hfd_eq] diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean new file mode 100644 index 000000000..48aaaba10 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean @@ -0,0 +1,88 @@ +import LeanModularForms.Experiments.SelfDual.Basic + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +def ModularForm.isSelfDual' (f : ModularForm Γ k) : Prop := + ⇑(ModularForm.dual f) = ⇑f + +theorem ModularForm.isSelfDual'_iff_apply (f : ModularForm Γ k) : + ModularForm.isSelfDual' f ↔ ∀ z, ModularForm.dual f z = f z := + ⟨fun h z => congrFun h z, fun h => funext h⟩ + +@[simp] +theorem ModularForm.isSelfDual'_zero : + ModularForm.isSelfDual' (0 : ModularForm Γ k) := by + ext z + simp + +theorem ModularForm.isSelfDual'_add {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : + ModularForm.isSelfDual' (f + g) := by + ext z + simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using + congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) + +theorem ModularForm.isSelfDual'_neg {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) : + ModularForm.isSelfDual' (-f) := by + ext z + simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using + congrArg Neg.neg (congrFun hf z) + +theorem ModularForm.isSelfDual'_sub {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : + ModularForm.isSelfDual' (f - g) := by + simpa [sub_eq_add_neg] using ModularForm.isSelfDual'_add hf (ModularForm.isSelfDual'_neg hg) + +theorem ModularForm.isSelfDual'_smul_real (c : ℝ) {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) : + ModularForm.isSelfDual' (c • f) := by + ext z + have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := + UpperHalfPlane.σ_ofReal UpperHalfPlane.J c + change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z + rw [smul_slash, hsigma] + simpa [Pi.smul_apply, smul_eq_mul] using + congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) + +theorem ModularForm.isSelfDual_iff' [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : + ModularForm.isSelfDual' f ↔ + ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓ : h ∈ Γ.strictPeriods := by + simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ + constructor + · intro hfd n + have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [hfd] + have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [← ModularForm.qExpansion_dual_coeff f n, hq] + simpa [h] using (Complex.conj_eq_iff_im.mp hstar) + · intro hcoeff + let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) + have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by + dsimp [fd] + rw [ModularForm.coe_cast_group] + have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by + apply PowerSeries.ext + intro n + rw [show (UpperHalfPlane.qExpansion h fd).coeff n = + (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] + rw [ModularForm.qExpansion_dual_coeff f n] + exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) + have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by + rw [show UpperHalfPlane.qExpansion h (fd - f) = + UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] + rw [ModularForm.qExpansion_sub hh hΓ fd f] + simp [hq] + have hzero_form : fd - f = 0 := + (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q + have hfd_eq : fd = f := sub_eq_zero.mp hzero_form + calc + ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm + _ = ⇑f := by rw [hfd_eq] diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual'.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual'.lean new file mode 100644 index 000000000..d6e32d429 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual'.lean @@ -0,0 +1,38 @@ +import Mathlib + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := + (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ + +/- +def Subgroup.isSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop := + Subgroup.dual Γ = Γ + +noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := + ModularForm.translate f UpperHalfPlane.J + +def ModularForm.isSelfDual [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : Prop := + ((Fact.out : Subgroup.isSelfDual Γ) ▸ ModularForm.dual f) = f + +theorem ModularForm.isSelfDual_iff [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + sorry +-/ + +/-- `Γ` is self-dual when it is fixed by conjugation by `J`. -/ +class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where + self_dual : Subgroup.dual Γ = Γ + +noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := + ModularForm.translate f UpperHalfPlane.J + +def ModularForm.isSelfDual' (f : ModularForm Γ k) : Prop := + ⇑(ModularForm.dual f) = ⇑f + +theorem ModularForm.isSelfDual_iff' [Γ.IsSelfDual] (f : ModularForm Γ k) : + ModularForm.isSelfDual' f ↔ + ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean new file mode 100644 index 000000000..f320f4323 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean @@ -0,0 +1,38 @@ +import Mathlib + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := + (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ + +/- +def Subgroup.isSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop := + Subgroup.dual Γ = Γ + +noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := + ModularForm.translate f UpperHalfPlane.J + +def ModularForm.isSelfDual [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : Prop := + ((Fact.out : Subgroup.isSelfDual Γ) ▸ ModularForm.dual f) = f + +theorem ModularForm.isSelfDual_iff [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + sorry +-/ + +/-- `Γ` is self-dual when it is fixed by conjugation by `J`. -/ +class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where + self_dual : Subgroup.dual Γ = Γ + +noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := + ModularForm.translate f UpperHalfPlane.J + +def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := + (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f + +theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ + ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean new file mode 100644 index 000000000..e248cec50 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean @@ -0,0 +1,111 @@ +import Mathlib + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex Function MatrixGroups ModularForm Pointwise +open UpperHalfPlane hiding I +open scoped ComplexConjugate + +local notation "𝕢" => Periodic.qParam + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := + (ConjAct.toConjAct J⁻¹) • Γ + +class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where + self_dual : Subgroup.dual Γ = Γ + +noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := + ModularForm.translate f J + +@[simp] +theorem ModularForm.coe_dual (f : ModularForm Γ k) : + ⇑(ModularForm.dual f) = ⇑f ∣[k] J := + ModularForm.coe_translate f J + +@[simp] +theorem ModularForm.dual_apply (f : ModularForm Γ k) (z : ℍ) : + ModularForm.dual f z = (⇑f ∣[k] J) z := + rfl + +@[simp] +theorem ModularForm.dual_zero : + ModularForm.dual (0 : ModularForm Γ k) = 0 := by + ext z + simp + +@[simp] +theorem ModularForm.dual_add (f g : ModularForm Γ k) : + ModularForm.dual (f + g) = ModularForm.dual f + ModularForm.dual g := by + ext z + simp + +@[simp] +theorem ModularForm.dual_neg (f : ModularForm Γ k) : + ModularForm.dual (-f) = -ModularForm.dual f := by + ext z + simp + +@[simp] +theorem ModularForm.dual_sub (f g : ModularForm Γ k) : + ModularForm.dual (f - g) = ModularForm.dual f - ModularForm.dual g := by + ext z + simp [sub_eq_add_neg] + +@[simp] +theorem ModularForm.dual_smul_real (c : ℝ) (f : ModularForm Γ k) : + ModularForm.dual (c • f) = c • ModularForm.dual f := by + ext z + change (((c : ℂ) • ⇑f) ∣[k] J) z = (c : ℂ) * ModularForm.dual f z + rw [smul_slash, σ_ofReal J c] + rfl + +theorem ModularForm.dual_apply_conj (f : ModularForm Γ k) (z : ℍ) : + ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by + simp [ModularForm.slash_def, J_smul] + +private theorem qParam_neg_conj (h : ℝ) (z : ℂ) : + 𝕢 h (-(conj z)) = conj (𝕢 h z) := by + simp [Periodic.qParam, ← Complex.exp_conj, map_ofNat] + +theorem ModularForm.hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) : + ∀ z : ℍ, HasSum (fun m : ℕ ↦ conj ((qExpansion Γ.strictWidthInfty f).coeff m) • 𝕢 Γ.strictWidthInfty (z : ℂ) ^ m) + (ModularForm.dual f z) := by + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓ : h ∈ Γ.strictPeriods := by + simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ + haveI : Fact (IsCusp OnePoint.infty Γ) := ⟨Subgroup.isCusp_of_mem_strictPeriods hh hΓ⟩ + intro z + let z' : ℍ := ofComplex (-(conj (z : ℂ))) + have hz' : 0 < (-(conj (z : ℂ))).im := by simpa using z.im_pos + have hcoe : (z' : ℂ) = -(conj (z : ℂ)) := by + simp [z', ofComplex_apply_of_im_pos hz'] + have hq : 𝕢 h (z' : ℂ) = conj (𝕢 h (z : ℂ)) := by + rw [hcoe] + exact qParam_neg_conj h (z : ℂ) + have hval : (⇑f ∣[k] J) z = conj (f z') := by + simpa [ModularForm.dual_apply, z'] using ModularForm.dual_apply_conj f z + have hs1 : HasSum (fun m : ℕ ↦ conj ((qExpansion h f).coeff m • 𝕢 h (z' : ℂ) ^ m)) (conj (f z')) := + (RCLike.hasSum_conj ℂ).mpr (by + simpa using hasSum_qExpansion hh (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ) + (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) z') + simpa [h, ModularForm.dual_apply, hval, hq, Complex.conj_conj, map_mul, map_pow, smul_eq_mul] using hs1 + +theorem ModularForm.qExpansion_dual_coeff [Γ.IsSelfDual] [Γ.IsArithmetic] + (f : ModularForm Γ k) (n : ℕ) : + (qExpansion Γ.strictWidthInfty (ModularForm.dual f)).coeff n = + conj ((qExpansion Γ.strictWidthInfty f).coeff n) := by + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓdual : h ∈ (Subgroup.dual Γ).strictPeriods := by + simpa [h, Subgroup.IsSelfDual.self_dual (Γ := Γ)] using + Subgroup.strictWidthInfty_mem_strictPeriods Γ + simpa [h] using (ModularFormClass.qExpansion_coeff_unique + (Γ := Subgroup.dual Γ) (F := ModularForm (Subgroup.dual Γ) k) + (h := h) (hh := hh) (hΓ := hΓdual) (f := ModularForm.dual f) + (by simpa [h] using ModularForm.hasSum_qExpansion_dual (Γ := Γ) (k := k) f) n).symm + +theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} + (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by + cases h + rfl diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean new file mode 100644 index 000000000..93098dd93 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean @@ -0,0 +1,107 @@ +import LeanModularForms.Issues.SelfDual.Basic + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := + (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f + +theorem ModularForm.isSelfDual_iff_coe_dual_eq [Γ.IsSelfDual] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ ⇑(ModularForm.dual f) = ⇑f := by + constructor + · intro h + calc + ⇑(ModularForm.dual f) = + ⇑(‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f : ModularForm Γ k) := by + rw [ModularForm.coe_cast_group] + _ = ⇑f := by rw [h] + · intro h + apply ModularForm.ext + intro z + rw [ModularForm.coe_cast_group] + exact congrFun h z + +theorem ModularForm.isSelfDual_iff_apply [Γ.IsSelfDual] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ ∀ z, ModularForm.dual f z = f z := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] + exact ⟨fun h z => congrFun h z, fun h => funext h⟩ + +@[simp] +theorem ModularForm.isSelfDual_zero [Γ.IsSelfDual] : + ModularForm.isSelfDual (0 : ModularForm Γ k) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] + ext z + simp + +theorem ModularForm.isSelfDual_add [Γ.IsSelfDual] {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : + ModularForm.isSelfDual (f + g) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf hg ⊢ + ext z + simpa [ModularForm.dual_apply] using congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) + +theorem ModularForm.isSelfDual_neg [Γ.IsSelfDual] {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) : + ModularForm.isSelfDual (-f) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ + ext z + simpa [ModularForm.dual_apply] using congrArg Neg.neg (congrFun hf z) + +theorem ModularForm.isSelfDual_sub [Γ.IsSelfDual] {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : + ModularForm.isSelfDual (f - g) := by + simpa [sub_eq_add_neg] using ModularForm.isSelfDual_add hf (ModularForm.isSelfDual_neg hg) + +theorem ModularForm.isSelfDual_smul_real [Γ.IsSelfDual] (c : ℝ) {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual f) : + ModularForm.isSelfDual (c • f) := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ + ext z + have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := + UpperHalfPlane.σ_ofReal UpperHalfPlane.J c + change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z + rw [smul_slash, hsigma] + simpa [Pi.smul_apply, smul_eq_mul] using + congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) + +theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ + ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + rw [ModularForm.isSelfDual_iff_coe_dual_eq] + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓ : h ∈ Γ.strictPeriods := by + simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ + constructor + · intro hfd n + have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [hfd] + have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [← ModularForm.qExpansion_dual_coeff f n, hq] + simpa [h] using (Complex.conj_eq_iff_im.mp hstar) + · intro hcoeff + let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) + have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by + dsimp [fd] + rw [ModularForm.coe_cast_group] + have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by + apply PowerSeries.ext + intro n + rw [show (UpperHalfPlane.qExpansion h fd).coeff n = + (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] + rw [ModularForm.qExpansion_dual_coeff f n] + exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) + have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by + rw [show UpperHalfPlane.qExpansion h (fd - f) = + UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] + rw [ModularForm.qExpansion_sub hh hΓ fd f] + simp [hq] + have hzero_form : fd - f = 0 := + (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q + have hfd_eq : fd = f := sub_eq_zero.mp hzero_form + calc + ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm + _ = ⇑f := by rw [hfd_eq] diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean new file mode 100644 index 000000000..6365b1b3b --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean @@ -0,0 +1,88 @@ +import LeanModularForms.Issues.SelfDual.Basic + +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +def ModularForm.isSelfDual' (f : ModularForm Γ k) : Prop := + ⇑(ModularForm.dual f) = ⇑f + +theorem ModularForm.isSelfDual'_iff_apply (f : ModularForm Γ k) : + ModularForm.isSelfDual' f ↔ ∀ z, ModularForm.dual f z = f z := + ⟨fun h z => congrFun h z, fun h => funext h⟩ + +@[simp] +theorem ModularForm.isSelfDual'_zero : + ModularForm.isSelfDual' (0 : ModularForm Γ k) := by + ext z + simp + +theorem ModularForm.isSelfDual'_add {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : + ModularForm.isSelfDual' (f + g) := by + ext z + simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using + congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) + +theorem ModularForm.isSelfDual'_neg {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) : + ModularForm.isSelfDual' (-f) := by + ext z + simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using + congrArg Neg.neg (congrFun hf z) + +theorem ModularForm.isSelfDual'_sub {f g : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : + ModularForm.isSelfDual' (f - g) := by + simpa [sub_eq_add_neg] using ModularForm.isSelfDual'_add hf (ModularForm.isSelfDual'_neg hg) + +theorem ModularForm.isSelfDual'_smul_real (c : ℝ) {f : ModularForm Γ k} + (hf : ModularForm.isSelfDual' f) : + ModularForm.isSelfDual' (c • f) := by + ext z + have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := + UpperHalfPlane.σ_ofReal UpperHalfPlane.J c + change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z + rw [smul_slash, hsigma] + simpa [Pi.smul_apply, smul_eq_mul] using + congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) + +theorem ModularForm.isSelfDual_iff' [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : + ModularForm.isSelfDual' f ↔ + ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + let h := Γ.strictWidthInfty + have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ + have hΓ : h ∈ Γ.strictPeriods := by + simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ + constructor + · intro hfd n + have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [hfd] + have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = + (UpperHalfPlane.qExpansion h f).coeff n := by + rw [← ModularForm.qExpansion_dual_coeff f n, hq] + simpa [h] using (Complex.conj_eq_iff_im.mp hstar) + · intro hcoeff + let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) + have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by + dsimp [fd] + rw [ModularForm.coe_cast_group] + have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by + apply PowerSeries.ext + intro n + rw [show (UpperHalfPlane.qExpansion h fd).coeff n = + (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] + rw [ModularForm.qExpansion_dual_coeff f n] + exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) + have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by + rw [show UpperHalfPlane.qExpansion h (fd - f) = + UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] + rw [ModularForm.qExpansion_sub hh hΓ fd f] + simp [hq] + have hzero_form : fd - f = 0 := + (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q + have hfd_eq : fd = f := sub_eq_zero.mp hzero_form + calc + ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm + _ = ⇑f := by rw [hfd_eq] From ab84d530258c6c28d92c08e9b36aa8e15374e4fe Mon Sep 17 00:00:00 2001 From: SmwYin Date: Tue, 30 Jun 2026 14:13:04 +0100 Subject: [PATCH 3/5] More on SelfDual --- .../Issues/SelfDual/Basic.lean | 63 +++------------ .../Issues/SelfDual/Version1.lean | 81 +++---------------- .../Issues/SelfDual/Version2.lean | 62 +++----------- 3 files changed, 35 insertions(+), 171 deletions(-) diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean index e248cec50..a5017d4bc 100644 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean @@ -30,82 +30,45 @@ theorem ModularForm.dual_apply (f : ModularForm Γ k) (z : ℍ) : @[simp] theorem ModularForm.dual_zero : ModularForm.dual (0 : ModularForm Γ k) = 0 := by - ext z - simp + sorry @[simp] theorem ModularForm.dual_add (f g : ModularForm Γ k) : ModularForm.dual (f + g) = ModularForm.dual f + ModularForm.dual g := by - ext z - simp + sorry @[simp] theorem ModularForm.dual_neg (f : ModularForm Γ k) : ModularForm.dual (-f) = -ModularForm.dual f := by - ext z - simp + sorry @[simp] theorem ModularForm.dual_sub (f g : ModularForm Γ k) : ModularForm.dual (f - g) = ModularForm.dual f - ModularForm.dual g := by - ext z - simp [sub_eq_add_neg] + sorry @[simp] theorem ModularForm.dual_smul_real (c : ℝ) (f : ModularForm Γ k) : ModularForm.dual (c • f) = c • ModularForm.dual f := by - ext z - change (((c : ℂ) • ⇑f) ∣[k] J) z = (c : ℂ) * ModularForm.dual f z - rw [smul_slash, σ_ofReal J c] - rfl + sorry theorem ModularForm.dual_apply_conj (f : ModularForm Γ k) (z : ℍ) : ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by - simp [ModularForm.slash_def, J_smul] + sorry private theorem qParam_neg_conj (h : ℝ) (z : ℂ) : 𝕢 h (-(conj z)) = conj (𝕢 h z) := by - simp [Periodic.qParam, ← Complex.exp_conj, map_ofNat] + sorry theorem ModularForm.hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) : ∀ z : ℍ, HasSum (fun m : ℕ ↦ conj ((qExpansion Γ.strictWidthInfty f).coeff m) • 𝕢 Γ.strictWidthInfty (z : ℂ) ^ m) (ModularForm.dual f z) := by - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓ : h ∈ Γ.strictPeriods := by - simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ - haveI : Fact (IsCusp OnePoint.infty Γ) := ⟨Subgroup.isCusp_of_mem_strictPeriods hh hΓ⟩ - intro z - let z' : ℍ := ofComplex (-(conj (z : ℂ))) - have hz' : 0 < (-(conj (z : ℂ))).im := by simpa using z.im_pos - have hcoe : (z' : ℂ) = -(conj (z : ℂ)) := by - simp [z', ofComplex_apply_of_im_pos hz'] - have hq : 𝕢 h (z' : ℂ) = conj (𝕢 h (z : ℂ)) := by - rw [hcoe] - exact qParam_neg_conj h (z : ℂ) - have hval : (⇑f ∣[k] J) z = conj (f z') := by - simpa [ModularForm.dual_apply, z'] using ModularForm.dual_apply_conj f z - have hs1 : HasSum (fun m : ℕ ↦ conj ((qExpansion h f).coeff m • 𝕢 h (z' : ℂ) ^ m)) (conj (f z')) := - (RCLike.hasSum_conj ℂ).mpr (by - simpa using hasSum_qExpansion hh (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ) - (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) z') - simpa [h, ModularForm.dual_apply, hval, hq, Complex.conj_conj, map_mul, map_pow, smul_eq_mul] using hs1 - -theorem ModularForm.qExpansion_dual_coeff [Γ.IsSelfDual] [Γ.IsArithmetic] - (f : ModularForm Γ k) (n : ℕ) : - (qExpansion Γ.strictWidthInfty (ModularForm.dual f)).coeff n = - conj ((qExpansion Γ.strictWidthInfty f).coeff n) := by - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓdual : h ∈ (Subgroup.dual Γ).strictPeriods := by - simpa [h, Subgroup.IsSelfDual.self_dual (Γ := Γ)] using - Subgroup.strictWidthInfty_mem_strictPeriods Γ - simpa [h] using (ModularFormClass.qExpansion_coeff_unique - (Γ := Subgroup.dual Γ) (F := ModularForm (Subgroup.dual Γ) k) - (h := h) (hh := hh) (hΓ := hΓdual) (f := ModularForm.dual f) - (by simpa [h] using ModularForm.hasSum_qExpansion_dual (Γ := Γ) (k := k) f) n).symm + sorry + +theorem ModularForm.qExpansion_dual_coeff [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) (n : ℕ) : + (qExpansion Γ.strictWidthInfty (ModularForm.dual f)).coeff n = conj ((qExpansion Γ.strictWidthInfty f).coeff n) := by + sorry theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by - cases h - rfl + sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean index 93098dd93..ef6810e10 100644 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean @@ -9,99 +9,42 @@ def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := theorem ModularForm.isSelfDual_iff_coe_dual_eq [Γ.IsSelfDual] (f : ModularForm Γ k) : ModularForm.isSelfDual f ↔ ⇑(ModularForm.dual f) = ⇑f := by - constructor - · intro h - calc - ⇑(ModularForm.dual f) = - ⇑(‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f : ModularForm Γ k) := by - rw [ModularForm.coe_cast_group] - _ = ⇑f := by rw [h] - · intro h - apply ModularForm.ext - intro z - rw [ModularForm.coe_cast_group] - exact congrFun h z + sorry theorem ModularForm.isSelfDual_iff_apply [Γ.IsSelfDual] (f : ModularForm Γ k) : ModularForm.isSelfDual f ↔ ∀ z, ModularForm.dual f z = f z := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] - exact ⟨fun h z => congrFun h z, fun h => funext h⟩ + sorry @[simp] theorem ModularForm.isSelfDual_zero [Γ.IsSelfDual] : ModularForm.isSelfDual (0 : ModularForm Γ k) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] - ext z - simp + sorry +@[simp] theorem ModularForm.isSelfDual_add [Γ.IsSelfDual] {f g : ModularForm Γ k} (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : ModularForm.isSelfDual (f + g) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf hg ⊢ - ext z - simpa [ModularForm.dual_apply] using congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) + sorry +@[simp] theorem ModularForm.isSelfDual_neg [Γ.IsSelfDual] {f : ModularForm Γ k} (hf : ModularForm.isSelfDual f) : ModularForm.isSelfDual (-f) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ - ext z - simpa [ModularForm.dual_apply] using congrArg Neg.neg (congrFun hf z) + sorry +@[simp] theorem ModularForm.isSelfDual_sub [Γ.IsSelfDual] {f g : ModularForm Γ k} (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : ModularForm.isSelfDual (f - g) := by - simpa [sub_eq_add_neg] using ModularForm.isSelfDual_add hf (ModularForm.isSelfDual_neg hg) + sorry +@[simp] theorem ModularForm.isSelfDual_smul_real [Γ.IsSelfDual] (c : ℝ) {f : ModularForm Γ k} (hf : ModularForm.isSelfDual f) : ModularForm.isSelfDual (c • f) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ - ext z - have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := - UpperHalfPlane.σ_ofReal UpperHalfPlane.J c - change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z - rw [smul_slash, hsigma] - simpa [Pi.smul_apply, smul_eq_mul] using - congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) + sorry theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : ModularForm.isSelfDual f ↔ ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓ : h ∈ Γ.strictPeriods := by - simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ - constructor - · intro hfd n - have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [hfd] - have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [← ModularForm.qExpansion_dual_coeff f n, hq] - simpa [h] using (Complex.conj_eq_iff_im.mp hstar) - · intro hcoeff - let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) - have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by - dsimp [fd] - rw [ModularForm.coe_cast_group] - have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by - apply PowerSeries.ext - intro n - rw [show (UpperHalfPlane.qExpansion h fd).coeff n = - (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] - rw [ModularForm.qExpansion_dual_coeff f n] - exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) - have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by - rw [show UpperHalfPlane.qExpansion h (fd - f) = - UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] - rw [ModularForm.qExpansion_sub hh hΓ fd f] - simp [hq] - have hzero_form : fd - f = 0 := - (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q - have hfd_eq : fd = f := sub_eq_zero.mp hzero_form - calc - ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm - _ = ⇑f := by rw [hfd_eq] + sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean index 6365b1b3b..f902f61c2 100644 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean @@ -14,75 +14,33 @@ theorem ModularForm.isSelfDual'_iff_apply (f : ModularForm Γ k) : @[simp] theorem ModularForm.isSelfDual'_zero : ModularForm.isSelfDual' (0 : ModularForm Γ k) := by - ext z - simp + sorry +@[simp] theorem ModularForm.isSelfDual'_add {f g : ModularForm Γ k} (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : ModularForm.isSelfDual' (f + g) := by - ext z - simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using - congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) + sorry +@[simp] theorem ModularForm.isSelfDual'_neg {f : ModularForm Γ k} (hf : ModularForm.isSelfDual' f) : ModularForm.isSelfDual' (-f) := by - ext z - simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using - congrArg Neg.neg (congrFun hf z) + sorry +@[simp] theorem ModularForm.isSelfDual'_sub {f g : ModularForm Γ k} (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : ModularForm.isSelfDual' (f - g) := by - simpa [sub_eq_add_neg] using ModularForm.isSelfDual'_add hf (ModularForm.isSelfDual'_neg hg) + sorry +@[simp] theorem ModularForm.isSelfDual'_smul_real (c : ℝ) {f : ModularForm Γ k} (hf : ModularForm.isSelfDual' f) : ModularForm.isSelfDual' (c • f) := by - ext z - have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := - UpperHalfPlane.σ_ofReal UpperHalfPlane.J c - change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z - rw [smul_slash, hsigma] - simpa [Pi.smul_apply, smul_eq_mul] using - congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) + sorry theorem ModularForm.isSelfDual_iff' [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : ModularForm.isSelfDual' f ↔ ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓ : h ∈ Γ.strictPeriods := by - simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ - constructor - · intro hfd n - have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [hfd] - have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [← ModularForm.qExpansion_dual_coeff f n, hq] - simpa [h] using (Complex.conj_eq_iff_im.mp hstar) - · intro hcoeff - let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) - have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by - dsimp [fd] - rw [ModularForm.coe_cast_group] - have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by - apply PowerSeries.ext - intro n - rw [show (UpperHalfPlane.qExpansion h fd).coeff n = - (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] - rw [ModularForm.qExpansion_dual_coeff f n] - exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) - have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by - rw [show UpperHalfPlane.qExpansion h (fd - f) = - UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] - rw [ModularForm.qExpansion_sub hh hΓ fd f] - simp [hq] - have hzero_form : fd - f = 0 := - (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q - have hfd_eq : fd = f := sub_eq_zero.mp hzero_form - calc - ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm - _ = ⇑f := by rw [hfd_eq] + sorry From a5f8d097454c0c2ea2335c09d1fec5c8acfa4c77 Mon Sep 17 00:00:00 2001 From: SmwYin Date: Thu, 2 Jul 2026 22:23:05 +0100 Subject: [PATCH 4/5] Sorry-free --- .../.mathlib-quality/learnings.jsonl | 2 + .../.mathlib-quality/renames.jsonl | 0 .../LeanModularForms/Issues/SelfDual.lean | 33 +- .../Issues/SelfDual/Basic copy.lean | 338 +++++++++++++++++ .../Issues/SelfDual/Basic.lean | 354 +++++++++++++++--- .../{SelfDual'.lean => SelfDual_old.lean} | 13 +- 6 files changed, 672 insertions(+), 68 deletions(-) create mode 100644 projects/LeanModularForms/.mathlib-quality/learnings.jsonl create mode 100644 projects/LeanModularForms/.mathlib-quality/renames.jsonl create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic copy.lean rename projects/LeanModularForms/LeanModularForms/Issues/{SelfDual'.lean => SelfDual_old.lean} (77%) diff --git a/projects/LeanModularForms/.mathlib-quality/learnings.jsonl b/projects/LeanModularForms/.mathlib-quality/learnings.jsonl new file mode 100644 index 000000000..98764da59 --- /dev/null +++ b/projects/LeanModularForms/.mathlib-quality/learnings.jsonl @@ -0,0 +1,2 @@ +{"type":"style_correction","date":"2026-07-02","file":"Issues/SelfDual/Basic.lean","summary":"Per-declaration cleanup workers cannot catch cross-declaration proof-block duplication; the Phase-6.5 /simplify holistic pass found the `hdualΓ` (strictWidthInfty ∈ (dual Γ).strictPeriods) block copy-pasted across two declarations and extracted it into a shared private helper `strictWidthInfty_mem_dual_strictPeriods`.","lesson":"Always run the holistic simplify pass after per-decl golf; it is where cross-cutting DRY wins surface."} +{"type":"mathlib_discovery","date":"2026-07-02","file":"Issues/SelfDual/Basic.lean","summary":"`Subgroup.strictWidthInfty` is a bare `dite` on `DiscreteTopology _.strictPeriods` with no congruence lemma, so `Subgroup.dual_width_eq` must reconstruct the def body under `congrArg` (rw/simp fail with 'motive is not type correct' / 'failed to synthesize Decidable'). A `strictWidthInfty_congr (h : Γ₁.strictPeriods = Γ₂.strictPeriods) : strictWidthInfty Γ₁ = strictWidthInfty Γ₂` is the missing API (upstream/dev-ticket candidate)."} diff --git a/projects/LeanModularForms/.mathlib-quality/renames.jsonl b/projects/LeanModularForms/.mathlib-quality/renames.jsonl new file mode 100644 index 000000000..e69de29bb diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean index f320f4323..a482afef4 100644 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean @@ -1,38 +1,35 @@ import Mathlib open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise + Subgroup +open UpperHalfPlane hiding I variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ -/- -def Subgroup.isSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop := - Subgroup.dual Γ = Γ +/-- `Γ` is self-dual when it is fixed by conjugation by `J`. -/ +class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where + self_dual : Subgroup.dual Γ = Γ noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := ModularForm.translate f UpperHalfPlane.J -def ModularForm.isSelfDual [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : Prop := - ((Fact.out : Subgroup.isSelfDual Γ) ▸ ModularForm.dual f) = f +def ModularForm.isSelfDual (f : ModularForm Γ k) : Prop := + ⇑(ModularForm.dual f) = ⇑f + -theorem ModularForm.isSelfDual_iff [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - sorry --/ -/-- `Γ` is self-dual when it is fixed by conjugation by `J`. -/ -class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where - self_dual : Subgroup.dual Γ = Γ -noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := - ModularForm.translate f UpperHalfPlane.J -def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := - (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f -theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] (f : ModularForm Γ k) : + +theorem Subgroup.dual_width_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : + strictWidthInfty (Subgroup.dual Γ) = strictWidthInfty Γ := by + sorry + +theorem ModularForm.isSelfDual_iff (f : ModularForm Γ k) : ModularForm.isSelfDual f ↔ - ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by + ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := by sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic copy.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic copy.lean new file mode 100644 index 000000000..e3573a51b --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic copy.lean @@ -0,0 +1,338 @@ +import Mathlib +import LeanModularForms.HeckeRIngs.GL2.Gamma1Pair +import LeanModularForms.HeckeRIngs.GL2.Newforms + +open ModularForm UpperHalfPlane MatrixGroups ComplexConjugate +open CongruenceSubgroup Pointwise Subgroup + +variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} + +/-- The dual of a subgroup of `GL (Fin 2) ℝ` is its conjugate by `J⁻¹`. -/ +noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := + (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ + +namespace Subgroup + +open Matrix.GeneralLinearGroup + +/-- Conjugation by `J` sends `upperRightHom x` to `upperRightHom (-x)`. -/ +theorem dual_upperRightHom (x : ℝ) : + ConjAct.toConjAct UpperHalfPlane.J • upperRightHom x = upperRightHom (-x) := by + have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := + inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq + rw [ConjAct.toConjAct_smul, hJinv] + ext i j + fin_cases i <;> fin_cases j <;> + norm_num [UpperHalfPlane.J, Matrix.GeneralLinearGroup.upperRightHom, Matrix.mul_apply, + Fin.sum_univ_two] + +/-- Dualising a subgroup preserves its strict periods. -/ +theorem dual_strictPeriods_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : + (Subgroup.dual Γ).strictPeriods = Γ.strictPeriods := by + ext x + simp only [Subgroup.mem_strictPeriods_iff, Subgroup.dual, + Subgroup.mem_pointwise_smul_iff_inv_smul_mem, map_inv, inv_inv, dual_upperRightHom] + simpa using (Subgroup.inv_mem_iff (H := Γ) (x := upperRightHom x)) + +end Subgroup + +/-- A subgroup is self-dual when it equals its own dual. -/ +class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where + /-- A self-dual subgroup equals its own dual. -/ + isSelfDual : Subgroup.dual Γ = Γ + +instance : Subgroup.IsSelfDual (⊥ : Subgroup (GL (Fin 2) ℝ)) where + isSelfDual := by simp [Subgroup.dual] + +/-- The dual of a modular form is its translate by `J`. -/ +noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := + ModularForm.translate f UpperHalfPlane.J + +/-- A modular form is self-dual when it equals its own dual. -/ +noncomputable def ModularForm.isSelfDual (f : ModularForm Γ k) : Prop := + ⇑(ModularForm.dual f) = ⇑f + +/-- A cusp form is self-dual when its underlying modular form is self-dual. -/ +def IsSelfDual (f : CuspForm Γ k) : Prop := + ModularForm.isSelfDual f.toModularForm' + +theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} + (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by + cases h + rfl + +open Classical in +/-- Dualising a subgroup preserves the strict width of the cusp `∞`. -/ +theorem Subgroup.dual_width_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : + strictWidthInfty (Subgroup.dual Γ) = strictWidthInfty Γ := + congrArg (fun H : AddSubgroup ℝ => + if h : DiscreteTopology H then + |Exists.choose <| H.isAddCyclic_iff_exists_zmultiples_eq_top.mp + <| AddSubgroup.discrete_iff_addCyclic.mpr h| + else 0) (Subgroup.dual_strictPeriods_eq Γ) + +private lemma strictWidthInfty_mem_dual_strictPeriods (Γ : Subgroup (GL (Fin 2) ℝ)) + [Γ.IsArithmetic] : strictWidthInfty Γ ∈ (Subgroup.dual Γ).strictPeriods := by + rw [← Subgroup.dual_width_eq Γ] + exact (Subgroup.dual Γ).strictWidthInfty_mem_strictPeriods + +private lemma qParam_J_smul (h : ℝ) (z : UpperHalfPlane) : + Function.Periodic.qParam h ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) = + conj (Function.Periodic.qParam h (z : ℂ)) := by + simp [Function.Periodic.qParam, UpperHalfPlane.coe_J_smul, ← Complex.exp_conj, map_ofNat] + +/-- `f.dual` at `z` equals the complex conjugate of `f` at `ofComplex (-conj z)`. -/ +theorem ModularForm.dual_explicit (f : ModularForm Γ k) (z : UpperHalfPlane) : + ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by + change (⇑f ∣[(k : ℤ)] UpperHalfPlane.J) z = conj (f (ofComplex (-(conj (z : ℂ))))) + simp [ModularForm.slash_apply, UpperHalfPlane.J_smul] + +private lemma hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) (z : UpperHalfPlane) : + HasSum (fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m) • + Function.Periodic.qParam (strictWidthInfty Γ) (z : ℂ) ^ m) (ModularForm.dual f z) := by + have hf : HasSum (fun m : ℕ ↦ (qExpansion (strictWidthInfty Γ) f).coeff m • + Function.Periodic.qParam (strictWidthInfty Γ) + ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) ^ m) (f (UpperHalfPlane.J • z)) := + UpperHalfPlane.hasSum_qExpansion Γ.strictWidthInfty_pos + (SlashInvariantFormClass.periodic_comp_ofComplex f Γ.strictWidthInfty_mem_strictPeriods) + (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) (UpperHalfPlane.J • z) + convert (Complex.hasSum_conj' (f := fun m : ℕ ↦ + (qExpansion (strictWidthInfty Γ) f).coeff m • Function.Periodic.qParam (strictWidthInfty Γ) + ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) ^ m) + (x := f (UpperHalfPlane.J • z))).mpr hf using 1 + · ext m + simp [qParam_J_smul, smul_eq_mul] + · simp [ModularForm.dual_explicit, UpperHalfPlane.J_smul] + +/-- The `q`-expansion coefficients of the dual are the complex conjugates of the original's. -/ +theorem ModularForm.qExpansion_dual_coefficient [Γ.IsArithmetic] (f : ModularForm Γ k) (n : ℕ) : + (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := by + exact (ModularFormClass.qExpansion_coeff_unique (Γ := Subgroup.dual Γ) + (c := fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m)) + Γ.strictWidthInfty_pos (strictWidthInfty_mem_dual_strictPeriods Γ) + (hasSum_qExpansion_dual f) n).symm + +private lemma im_coeff_eq_zero_of_isSelfDual [Γ.IsArithmetic] (f : ModularForm Γ k) + (hself : ModularForm.isSelfDual f) (n : ℕ) : + ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := by + have hcoeff : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := + ModularForm.qExpansion_dual_coefficient f n + have hsame : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + (qExpansion (strictWidthInfty Γ) f).coeff n := by + simpa [ModularForm.isSelfDual] using + congrArg (fun g : UpperHalfPlane → ℂ ↦ (qExpansion (strictWidthInfty Γ) g).coeff n) hself + rw [hsame] at hcoeff + exact Complex.conj_eq_iff_im.mp hcoeff.symm + +private lemma isSelfDual_of_forall_im_coeff_eq_zero [Γ.IsArithmetic] (f : ModularForm Γ k) + (hreal : ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0) : + ModularForm.isSelfDual f := by + have hh : 0 < strictWidthInfty Γ := Γ.strictWidthInfty_pos + have hΓ : strictWidthInfty Γ ∈ Γ.strictPeriods := Γ.strictWidthInfty_mem_strictPeriods + have hdualΓ : strictWidthInfty Γ ∈ (Subgroup.dual Γ).strictPeriods := + strictWidthInfty_mem_dual_strictPeriods Γ + have hqeq : qExpansion (strictWidthInfty Γ) (ModularForm.dual f) = + qExpansion (strictWidthInfty Γ) f := by + ext n + calc + (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n + = conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := + ModularForm.qExpansion_dual_coefficient f n + _ = (qExpansion (strictWidthInfty Γ) f).coeff n := + Complex.conj_eq_iff_im.mpr (hreal n) + have hqsub : + qExpansion (strictWidthInfty Γ) (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := by + rw [UpperHalfPlane.qExpansion_sub + (ModularFormClass.analyticAt_cuspFunction_zero (ModularForm.dual f) hh hdualΓ) + (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ), hqeq, sub_self] + have hper : Function.Periodic + ((⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) ∘ ofComplex) (strictWidthInfty Γ) := by + intro z + simpa only [Function.comp_apply, Pi.sub_apply] using + congrArg₂ (fun a b : ℂ ↦ a - b) + (SlashInvariantFormClass.periodic_comp_ofComplex (ModularForm.dual f) hdualΓ z) + (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ z) + have hbdd : IsBoundedAtImInfty (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) := by + have : Fact (IsCusp OnePoint.infty (Subgroup.dual Γ)) := + ⟨(Subgroup.dual Γ).isCusp_of_mem_strictPeriods hh hdualΓ⟩ + change Filter.BoundedAtFilter UpperHalfPlane.atImInfty + (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) + simpa [sub_eq_add_neg] using + (ModularFormClass.bdd_at_infty (ModularForm.dual f)).add + (ModularFormClass.bdd_at_infty f).neg + have hzero : (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := + (UpperHalfPlane.qExpansion_eq_zero_iff hh hper + ((ModularFormClass.holo (ModularForm.dual f)).sub (ModularFormClass.holo f)) hbdd).mp hqsub + exact funext fun z ↦ sub_eq_zero.mp (congrFun hzero z) + +/-- A modular form is self-dual iff all its `q`-expansion coefficients are real. -/ +theorem ModularForm.isSelfDual_iff [Γ.IsArithmetic] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ + ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := + ⟨im_coeff_eq_zero_of_isSelfDual f, isSelfDual_of_forall_im_coeff_eq_zero f⟩ + +section Nebentypus + +open Matrix.SpecialLinearGroup HeckeRing.GL2 + +abbrev Γ₁ (N : ℕ): Subgroup (GL (Fin 2) ℝ) := (Gamma1 N).map (mapGL ℝ) + +private def conjugateByJ (γ : SL(2, ℤ)) : SL(2, ℤ) where + val := !![γ 0 0, -γ 0 1; -γ 1 0, γ 1 1] + property := by + have hdet : γ.val.det = 1 := γ.property + rw [Matrix.det_fin_two] at hdet + simpa [Matrix.det_fin_two] using hdet + +private lemma conjugateByJ_mem_Gamma1_iff (γ : SL(2, ℤ)) : + conjugateByJ γ ∈ Gamma1 N ↔ γ ∈ Gamma1 N := by + rw [Gamma1_mem, Gamma1_mem] + simp [conjugateByJ] + +private lemma conjugateByJ_mem_Gamma0 {γ : SL(2, ℤ)} (hγ : γ ∈ Gamma0 N) : + conjugateByJ γ ∈ Gamma0 N := by + rw [Gamma0_mem] at hγ ⊢ + simpa [conjugateByJ] using hγ + +private lemma Gamma0MapUnits_conjugateByJ (γ : ↥(Gamma0 N)) : + Gamma0MapUnits (⟨conjugateByJ (γ : SL(2, ℤ)), + conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ : ↥(Gamma0 N)) = + Gamma0MapUnits γ := by + ext + simp [Gamma0MapUnits_val, Gamma0Map, conjugateByJ] + +private lemma mapGL_conjugateByJ (γ : SL(2, ℤ)) : + mapGL ℝ (conjugateByJ γ) = UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J := by + ext i j + fin_cases i <;> fin_cases j <;> + norm_num [conjugateByJ, UpperHalfPlane.J, Matrix.GeneralLinearGroup.coe_mul, + Matrix.mul_apply, Matrix.vecMul, dotProduct, Matrix.vecHead, Matrix.vecTail, + Fin.sum_univ_two] + +private lemma J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J (γ : SL(2, ℤ)) : + UpperHalfPlane.J * mapGL ℝ γ = mapGL ℝ (conjugateByJ γ) * UpperHalfPlane.J := by + have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by + simpa [sq] using UpperHalfPlane.J_sq + rw [mapGL_conjugateByJ] + calc + UpperHalfPlane.J * mapGL ℝ γ = UpperHalfPlane.J * mapGL ℝ γ * 1 := by rw [mul_one] + _ = UpperHalfPlane.J * mapGL ℝ γ * (UpperHalfPlane.J * UpperHalfPlane.J) := by + rw [hJmul] + _ = (UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J) * UpperHalfPlane.J := by + group + +/-- `Γ₁(N)`, viewed inside `GL(2, ℝ)`, is self-dual. -/ +instance CongruenceSubgroup.isSelfDual_Gamma1_map (N : ℕ) : + Subgroup.IsSelfDual (Γ₁ N) where + isSelfDual := by + have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := + inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq + have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by + simpa [sq] using UpperHalfPlane.J_sq + rw [Subgroup.dual, Γ₁] + ext y + simp only [Subgroup.mem_pointwise_smul_iff_inv_smul_mem, ConjAct.smul_def, + ConjAct.ofConjAct_toConjAct, map_inv, inv_inv, Subgroup.mem_map] + constructor + · rintro ⟨σ, hσ, hσy⟩ + refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ + rw [mapGL_conjugateByJ, hσy] + rw [hJinv] + calc + UpperHalfPlane.J * (UpperHalfPlane.J * y * UpperHalfPlane.J) * UpperHalfPlane.J = + (UpperHalfPlane.J * UpperHalfPlane.J) * y * + (UpperHalfPlane.J * UpperHalfPlane.J) := by group + _ = y := by simp [hJmul] + · rintro ⟨σ, hσ, rfl⟩ + refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ + rw [mapGL_conjugateByJ] + simp [hJinv] + +/-- The complex conjugate of a `ℂˣ`-valued character. -/ +def MonoidHom.conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : G →* ℂˣ := + (Units.map (starRingEnd ℂ).toMonoidHom).comp χ + +@[simp] +theorem MonoidHom.conjChar_conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : + MonoidHom.conjChar (MonoidHom.conjChar χ) = χ := by + ext g + simp [MonoidHom.conjChar] + +namespace ModularForm + +theorem dual_mem_range_modFormCharSpace_inclusion_conjChar {N : ℕ} [NeZero N] + (χ : (ZMod N)ˣ →* ℂˣ) (f : modFormCharSpace (N := N) k χ) : + ((Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ ModularForm.dual f : + ModularForm (Γ₁ N) k)) ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) := by + let F : ModularForm (Γ₁ N) k := + (Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ + ModularForm.dual (f : ModularForm (Γ₁ N) k)) + change F ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) + rw [modFormCharSpace_iff_nebentypus] + intro γ + let γJ : ↥(Gamma0 N) := ⟨conjugateByJ (γ : SL(2, ℤ)), + conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ + have hf := + (modFormCharSpace_iff_nebentypus k χ (f : ModularForm (Γ₁ N) k)).mp f.property γJ + have hF : + ⇑F = ⇑(ModularForm.dual (f : ModularForm (Γ₁ N) k)) := + ModularForm.coe_cast_group _ _ + rw [hF] + change (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) ∣[k] + (mapGL ℝ (γ : SL(2, ℤ))) = + (↑(MonoidHom.conjChar χ (Gamma0MapUnits γ)) : ℂ) • + (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) + rw [← SlashAction.slash_mul, J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J, + SlashAction.slash_mul, hf, Gamma0MapUnits_conjugateByJ, ModularForm.smul_slash] + simp [MonoidHom.conjChar] + +end ModularForm + +end Nebentypus + +variable {N : ℕ} [NeZero N] {k : ℤ} + +open HeckeRing.GL2 + +namespace HeckeRing.GL2 + +namespace Newform + +/-- The coefficient field `ℚ(a_n : n ≥ 1)` of a newform. -/ +noncomputable def coefficientField (f : Newform N k) : IntermediateField ℚ ℂ := + IntermediateField.adjoin ℚ + (Set.range fun n : ℕ+ => (qExpansion (1 : ℝ) f.toCuspForm).coeff n) + +/-- The coefficient field of a newform is finite-dimensional over `ℚ`. -/ +theorem coefficientField_finiteDimensional (f : Newform N k) : + FiniteDimensional ℚ f.coefficientField := by + sorry + +/-- The coefficient field of a newform is a number field. -/ +theorem coefficientField_numberField (f : Newform N k) : + NumberField f.coefficientField := by + sorry + +/-- The relative dimension attached to a newform. -/ +noncomputable def relativeDimension (f : Newform N k) : ℕ := + Module.finrank ℚ f.coefficientField + +theorem coefficientField_degree_eq_relativeDimension (f : Newform N k) : + Module.finrank ℚ f.coefficientField = f.relativeDimension := by + sorry + +/-- A newform's coefficient field is totally real if and only if the newform is self-dual. -/ +theorem coefficientField_isTotallyReal_iff_isSelfDual (f : Newform N k) : + NumberField.IsTotallyReal f.coefficientField ↔ IsSelfDual f.toCuspForm := by + sorry + +/-- A newform's coefficient field is CM if and only if the newform is not self-dual. -/ +theorem coefficientField_isCM_iff_not_isSelfDual (f : Newform N k) : + NumberField.IsCMField f.coefficientField ↔ ¬ IsSelfDual f.toCuspForm := by + sorry + +end Newform + +end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean index a5017d4bc..e3573a51b 100644 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean @@ -1,74 +1,338 @@ import Mathlib +import LeanModularForms.HeckeRIngs.GL2.Gamma1Pair +import LeanModularForms.HeckeRIngs.GL2.Newforms -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex Function MatrixGroups ModularForm Pointwise -open UpperHalfPlane hiding I -open scoped ComplexConjugate - -local notation "𝕢" => Periodic.qParam +open ModularForm UpperHalfPlane MatrixGroups ComplexConjugate +open CongruenceSubgroup Pointwise Subgroup variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} +/-- The dual of a subgroup of `GL (Fin 2) ℝ` is its conjugate by `J⁻¹`. -/ noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := - (ConjAct.toConjAct J⁻¹) • Γ + (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ + +namespace Subgroup + +open Matrix.GeneralLinearGroup + +/-- Conjugation by `J` sends `upperRightHom x` to `upperRightHom (-x)`. -/ +theorem dual_upperRightHom (x : ℝ) : + ConjAct.toConjAct UpperHalfPlane.J • upperRightHom x = upperRightHom (-x) := by + have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := + inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq + rw [ConjAct.toConjAct_smul, hJinv] + ext i j + fin_cases i <;> fin_cases j <;> + norm_num [UpperHalfPlane.J, Matrix.GeneralLinearGroup.upperRightHom, Matrix.mul_apply, + Fin.sum_univ_two] +/-- Dualising a subgroup preserves its strict periods. -/ +theorem dual_strictPeriods_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : + (Subgroup.dual Γ).strictPeriods = Γ.strictPeriods := by + ext x + simp only [Subgroup.mem_strictPeriods_iff, Subgroup.dual, + Subgroup.mem_pointwise_smul_iff_inv_smul_mem, map_inv, inv_inv, dual_upperRightHom] + simpa using (Subgroup.inv_mem_iff (H := Γ) (x := upperRightHom x)) + +end Subgroup + +/-- A subgroup is self-dual when it equals its own dual. -/ class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where - self_dual : Subgroup.dual Γ = Γ + /-- A self-dual subgroup equals its own dual. -/ + isSelfDual : Subgroup.dual Γ = Γ + +instance : Subgroup.IsSelfDual (⊥ : Subgroup (GL (Fin 2) ℝ)) where + isSelfDual := by simp [Subgroup.dual] +/-- The dual of a modular form is its translate by `J`. -/ noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := - ModularForm.translate f J + ModularForm.translate f UpperHalfPlane.J -@[simp] -theorem ModularForm.coe_dual (f : ModularForm Γ k) : - ⇑(ModularForm.dual f) = ⇑f ∣[k] J := - ModularForm.coe_translate f J +/-- A modular form is self-dual when it equals its own dual. -/ +noncomputable def ModularForm.isSelfDual (f : ModularForm Γ k) : Prop := + ⇑(ModularForm.dual f) = ⇑f -@[simp] -theorem ModularForm.dual_apply (f : ModularForm Γ k) (z : ℍ) : - ModularForm.dual f z = (⇑f ∣[k] J) z := +/-- A cusp form is self-dual when its underlying modular form is self-dual. -/ +def IsSelfDual (f : CuspForm Γ k) : Prop := + ModularForm.isSelfDual f.toModularForm' + +theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} + (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by + cases h rfl -@[simp] -theorem ModularForm.dual_zero : - ModularForm.dual (0 : ModularForm Γ k) = 0 := by - sorry +open Classical in +/-- Dualising a subgroup preserves the strict width of the cusp `∞`. -/ +theorem Subgroup.dual_width_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : + strictWidthInfty (Subgroup.dual Γ) = strictWidthInfty Γ := + congrArg (fun H : AddSubgroup ℝ => + if h : DiscreteTopology H then + |Exists.choose <| H.isAddCyclic_iff_exists_zmultiples_eq_top.mp + <| AddSubgroup.discrete_iff_addCyclic.mpr h| + else 0) (Subgroup.dual_strictPeriods_eq Γ) -@[simp] -theorem ModularForm.dual_add (f g : ModularForm Γ k) : - ModularForm.dual (f + g) = ModularForm.dual f + ModularForm.dual g := by - sorry +private lemma strictWidthInfty_mem_dual_strictPeriods (Γ : Subgroup (GL (Fin 2) ℝ)) + [Γ.IsArithmetic] : strictWidthInfty Γ ∈ (Subgroup.dual Γ).strictPeriods := by + rw [← Subgroup.dual_width_eq Γ] + exact (Subgroup.dual Γ).strictWidthInfty_mem_strictPeriods -@[simp] -theorem ModularForm.dual_neg (f : ModularForm Γ k) : - ModularForm.dual (-f) = -ModularForm.dual f := by - sorry +private lemma qParam_J_smul (h : ℝ) (z : UpperHalfPlane) : + Function.Periodic.qParam h ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) = + conj (Function.Periodic.qParam h (z : ℂ)) := by + simp [Function.Periodic.qParam, UpperHalfPlane.coe_J_smul, ← Complex.exp_conj, map_ofNat] -@[simp] -theorem ModularForm.dual_sub (f g : ModularForm Γ k) : - ModularForm.dual (f - g) = ModularForm.dual f - ModularForm.dual g := by - sorry +/-- `f.dual` at `z` equals the complex conjugate of `f` at `ofComplex (-conj z)`. -/ +theorem ModularForm.dual_explicit (f : ModularForm Γ k) (z : UpperHalfPlane) : + ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by + change (⇑f ∣[(k : ℤ)] UpperHalfPlane.J) z = conj (f (ofComplex (-(conj (z : ℂ))))) + simp [ModularForm.slash_apply, UpperHalfPlane.J_smul] + +private lemma hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) (z : UpperHalfPlane) : + HasSum (fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m) • + Function.Periodic.qParam (strictWidthInfty Γ) (z : ℂ) ^ m) (ModularForm.dual f z) := by + have hf : HasSum (fun m : ℕ ↦ (qExpansion (strictWidthInfty Γ) f).coeff m • + Function.Periodic.qParam (strictWidthInfty Γ) + ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) ^ m) (f (UpperHalfPlane.J • z)) := + UpperHalfPlane.hasSum_qExpansion Γ.strictWidthInfty_pos + (SlashInvariantFormClass.periodic_comp_ofComplex f Γ.strictWidthInfty_mem_strictPeriods) + (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) (UpperHalfPlane.J • z) + convert (Complex.hasSum_conj' (f := fun m : ℕ ↦ + (qExpansion (strictWidthInfty Γ) f).coeff m • Function.Periodic.qParam (strictWidthInfty Γ) + ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) ^ m) + (x := f (UpperHalfPlane.J • z))).mpr hf using 1 + · ext m + simp [qParam_J_smul, smul_eq_mul] + · simp [ModularForm.dual_explicit, UpperHalfPlane.J_smul] + +/-- The `q`-expansion coefficients of the dual are the complex conjugates of the original's. -/ +theorem ModularForm.qExpansion_dual_coefficient [Γ.IsArithmetic] (f : ModularForm Γ k) (n : ℕ) : + (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := by + exact (ModularFormClass.qExpansion_coeff_unique (Γ := Subgroup.dual Γ) + (c := fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m)) + Γ.strictWidthInfty_pos (strictWidthInfty_mem_dual_strictPeriods Γ) + (hasSum_qExpansion_dual f) n).symm + +private lemma im_coeff_eq_zero_of_isSelfDual [Γ.IsArithmetic] (f : ModularForm Γ k) + (hself : ModularForm.isSelfDual f) (n : ℕ) : + ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := by + have hcoeff : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := + ModularForm.qExpansion_dual_coefficient f n + have hsame : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + (qExpansion (strictWidthInfty Γ) f).coeff n := by + simpa [ModularForm.isSelfDual] using + congrArg (fun g : UpperHalfPlane → ℂ ↦ (qExpansion (strictWidthInfty Γ) g).coeff n) hself + rw [hsame] at hcoeff + exact Complex.conj_eq_iff_im.mp hcoeff.symm + +private lemma isSelfDual_of_forall_im_coeff_eq_zero [Γ.IsArithmetic] (f : ModularForm Γ k) + (hreal : ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0) : + ModularForm.isSelfDual f := by + have hh : 0 < strictWidthInfty Γ := Γ.strictWidthInfty_pos + have hΓ : strictWidthInfty Γ ∈ Γ.strictPeriods := Γ.strictWidthInfty_mem_strictPeriods + have hdualΓ : strictWidthInfty Γ ∈ (Subgroup.dual Γ).strictPeriods := + strictWidthInfty_mem_dual_strictPeriods Γ + have hqeq : qExpansion (strictWidthInfty Γ) (ModularForm.dual f) = + qExpansion (strictWidthInfty Γ) f := by + ext n + calc + (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n + = conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := + ModularForm.qExpansion_dual_coefficient f n + _ = (qExpansion (strictWidthInfty Γ) f).coeff n := + Complex.conj_eq_iff_im.mpr (hreal n) + have hqsub : + qExpansion (strictWidthInfty Γ) (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := by + rw [UpperHalfPlane.qExpansion_sub + (ModularFormClass.analyticAt_cuspFunction_zero (ModularForm.dual f) hh hdualΓ) + (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ), hqeq, sub_self] + have hper : Function.Periodic + ((⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) ∘ ofComplex) (strictWidthInfty Γ) := by + intro z + simpa only [Function.comp_apply, Pi.sub_apply] using + congrArg₂ (fun a b : ℂ ↦ a - b) + (SlashInvariantFormClass.periodic_comp_ofComplex (ModularForm.dual f) hdualΓ z) + (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ z) + have hbdd : IsBoundedAtImInfty (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) := by + have : Fact (IsCusp OnePoint.infty (Subgroup.dual Γ)) := + ⟨(Subgroup.dual Γ).isCusp_of_mem_strictPeriods hh hdualΓ⟩ + change Filter.BoundedAtFilter UpperHalfPlane.atImInfty + (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) + simpa [sub_eq_add_neg] using + (ModularFormClass.bdd_at_infty (ModularForm.dual f)).add + (ModularFormClass.bdd_at_infty f).neg + have hzero : (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := + (UpperHalfPlane.qExpansion_eq_zero_iff hh hper + ((ModularFormClass.holo (ModularForm.dual f)).sub (ModularFormClass.holo f)) hbdd).mp hqsub + exact funext fun z ↦ sub_eq_zero.mp (congrFun hzero z) + +/-- A modular form is self-dual iff all its `q`-expansion coefficients are real. -/ +theorem ModularForm.isSelfDual_iff [Γ.IsArithmetic] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ + ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := + ⟨im_coeff_eq_zero_of_isSelfDual f, isSelfDual_of_forall_im_coeff_eq_zero f⟩ + +section Nebentypus + +open Matrix.SpecialLinearGroup HeckeRing.GL2 + +abbrev Γ₁ (N : ℕ): Subgroup (GL (Fin 2) ℝ) := (Gamma1 N).map (mapGL ℝ) + +private def conjugateByJ (γ : SL(2, ℤ)) : SL(2, ℤ) where + val := !![γ 0 0, -γ 0 1; -γ 1 0, γ 1 1] + property := by + have hdet : γ.val.det = 1 := γ.property + rw [Matrix.det_fin_two] at hdet + simpa [Matrix.det_fin_two] using hdet + +private lemma conjugateByJ_mem_Gamma1_iff (γ : SL(2, ℤ)) : + conjugateByJ γ ∈ Gamma1 N ↔ γ ∈ Gamma1 N := by + rw [Gamma1_mem, Gamma1_mem] + simp [conjugateByJ] + +private lemma conjugateByJ_mem_Gamma0 {γ : SL(2, ℤ)} (hγ : γ ∈ Gamma0 N) : + conjugateByJ γ ∈ Gamma0 N := by + rw [Gamma0_mem] at hγ ⊢ + simpa [conjugateByJ] using hγ + +private lemma Gamma0MapUnits_conjugateByJ (γ : ↥(Gamma0 N)) : + Gamma0MapUnits (⟨conjugateByJ (γ : SL(2, ℤ)), + conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ : ↥(Gamma0 N)) = + Gamma0MapUnits γ := by + ext + simp [Gamma0MapUnits_val, Gamma0Map, conjugateByJ] + +private lemma mapGL_conjugateByJ (γ : SL(2, ℤ)) : + mapGL ℝ (conjugateByJ γ) = UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J := by + ext i j + fin_cases i <;> fin_cases j <;> + norm_num [conjugateByJ, UpperHalfPlane.J, Matrix.GeneralLinearGroup.coe_mul, + Matrix.mul_apply, Matrix.vecMul, dotProduct, Matrix.vecHead, Matrix.vecTail, + Fin.sum_univ_two] + +private lemma J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J (γ : SL(2, ℤ)) : + UpperHalfPlane.J * mapGL ℝ γ = mapGL ℝ (conjugateByJ γ) * UpperHalfPlane.J := by + have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by + simpa [sq] using UpperHalfPlane.J_sq + rw [mapGL_conjugateByJ] + calc + UpperHalfPlane.J * mapGL ℝ γ = UpperHalfPlane.J * mapGL ℝ γ * 1 := by rw [mul_one] + _ = UpperHalfPlane.J * mapGL ℝ γ * (UpperHalfPlane.J * UpperHalfPlane.J) := by + rw [hJmul] + _ = (UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J) * UpperHalfPlane.J := by + group + +/-- `Γ₁(N)`, viewed inside `GL(2, ℝ)`, is self-dual. -/ +instance CongruenceSubgroup.isSelfDual_Gamma1_map (N : ℕ) : + Subgroup.IsSelfDual (Γ₁ N) where + isSelfDual := by + have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := + inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq + have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by + simpa [sq] using UpperHalfPlane.J_sq + rw [Subgroup.dual, Γ₁] + ext y + simp only [Subgroup.mem_pointwise_smul_iff_inv_smul_mem, ConjAct.smul_def, + ConjAct.ofConjAct_toConjAct, map_inv, inv_inv, Subgroup.mem_map] + constructor + · rintro ⟨σ, hσ, hσy⟩ + refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ + rw [mapGL_conjugateByJ, hσy] + rw [hJinv] + calc + UpperHalfPlane.J * (UpperHalfPlane.J * y * UpperHalfPlane.J) * UpperHalfPlane.J = + (UpperHalfPlane.J * UpperHalfPlane.J) * y * + (UpperHalfPlane.J * UpperHalfPlane.J) := by group + _ = y := by simp [hJmul] + · rintro ⟨σ, hσ, rfl⟩ + refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ + rw [mapGL_conjugateByJ] + simp [hJinv] + +/-- The complex conjugate of a `ℂˣ`-valued character. -/ +def MonoidHom.conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : G →* ℂˣ := + (Units.map (starRingEnd ℂ).toMonoidHom).comp χ @[simp] -theorem ModularForm.dual_smul_real (c : ℝ) (f : ModularForm Γ k) : - ModularForm.dual (c • f) = c • ModularForm.dual f := by - sorry +theorem MonoidHom.conjChar_conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : + MonoidHom.conjChar (MonoidHom.conjChar χ) = χ := by + ext g + simp [MonoidHom.conjChar] -theorem ModularForm.dual_apply_conj (f : ModularForm Γ k) (z : ℍ) : - ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by +namespace ModularForm + +theorem dual_mem_range_modFormCharSpace_inclusion_conjChar {N : ℕ} [NeZero N] + (χ : (ZMod N)ˣ →* ℂˣ) (f : modFormCharSpace (N := N) k χ) : + ((Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ ModularForm.dual f : + ModularForm (Γ₁ N) k)) ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) := by + let F : ModularForm (Γ₁ N) k := + (Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ + ModularForm.dual (f : ModularForm (Γ₁ N) k)) + change F ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) + rw [modFormCharSpace_iff_nebentypus] + intro γ + let γJ : ↥(Gamma0 N) := ⟨conjugateByJ (γ : SL(2, ℤ)), + conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ + have hf := + (modFormCharSpace_iff_nebentypus k χ (f : ModularForm (Γ₁ N) k)).mp f.property γJ + have hF : + ⇑F = ⇑(ModularForm.dual (f : ModularForm (Γ₁ N) k)) := + ModularForm.coe_cast_group _ _ + rw [hF] + change (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) ∣[k] + (mapGL ℝ (γ : SL(2, ℤ))) = + (↑(MonoidHom.conjChar χ (Gamma0MapUnits γ)) : ℂ) • + (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) + rw [← SlashAction.slash_mul, J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J, + SlashAction.slash_mul, hf, Gamma0MapUnits_conjugateByJ, ModularForm.smul_slash] + simp [MonoidHom.conjChar] + +end ModularForm + +end Nebentypus + +variable {N : ℕ} [NeZero N] {k : ℤ} + +open HeckeRing.GL2 + +namespace HeckeRing.GL2 + +namespace Newform + +/-- The coefficient field `ℚ(a_n : n ≥ 1)` of a newform. -/ +noncomputable def coefficientField (f : Newform N k) : IntermediateField ℚ ℂ := + IntermediateField.adjoin ℚ + (Set.range fun n : ℕ+ => (qExpansion (1 : ℝ) f.toCuspForm).coeff n) + +/-- The coefficient field of a newform is finite-dimensional over `ℚ`. -/ +theorem coefficientField_finiteDimensional (f : Newform N k) : + FiniteDimensional ℚ f.coefficientField := by sorry -private theorem qParam_neg_conj (h : ℝ) (z : ℂ) : - 𝕢 h (-(conj z)) = conj (𝕢 h z) := by +/-- The coefficient field of a newform is a number field. -/ +theorem coefficientField_numberField (f : Newform N k) : + NumberField f.coefficientField := by sorry -theorem ModularForm.hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) : - ∀ z : ℍ, HasSum (fun m : ℕ ↦ conj ((qExpansion Γ.strictWidthInfty f).coeff m) • 𝕢 Γ.strictWidthInfty (z : ℂ) ^ m) - (ModularForm.dual f z) := by +/-- The relative dimension attached to a newform. -/ +noncomputable def relativeDimension (f : Newform N k) : ℕ := + Module.finrank ℚ f.coefficientField + +theorem coefficientField_degree_eq_relativeDimension (f : Newform N k) : + Module.finrank ℚ f.coefficientField = f.relativeDimension := by sorry -theorem ModularForm.qExpansion_dual_coeff [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) (n : ℕ) : - (qExpansion Γ.strictWidthInfty (ModularForm.dual f)).coeff n = conj ((qExpansion Γ.strictWidthInfty f).coeff n) := by +/-- A newform's coefficient field is totally real if and only if the newform is self-dual. -/ +theorem coefficientField_isTotallyReal_iff_isSelfDual (f : Newform N k) : + NumberField.IsTotallyReal f.coefficientField ↔ IsSelfDual f.toCuspForm := by sorry -theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} - (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by +/-- A newform's coefficient field is CM if and only if the newform is not self-dual. -/ +theorem coefficientField_isCM_iff_not_isSelfDual (f : Newform N k) : + NumberField.IsCMField f.coefficientField ↔ ¬ IsSelfDual f.toCuspForm := by sorry + +end Newform + +end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual'.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual_old.lean similarity index 77% rename from projects/LeanModularForms/LeanModularForms/Issues/SelfDual'.lean rename to projects/LeanModularForms/LeanModularForms/Issues/SelfDual_old.lean index d6e32d429..c6ccbabd8 100644 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual'.lean +++ b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual_old.lean @@ -1,6 +1,6 @@ import Mathlib -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise +open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise Subgroup variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} @@ -26,13 +26,16 @@ theorem ModularForm.isSelfDual_iff [Fact (Subgroup.isSelfDual Γ)] (f : ModularF class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where self_dual : Subgroup.dual Γ = Γ +instance : Subgroup.IsSelfDual (⊥ : Subgroup (GL (Fin 2) ℝ)) where + self_dual := by simp [Subgroup.dual] + noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := ModularForm.translate f UpperHalfPlane.J -def ModularForm.isSelfDual' (f : ModularForm Γ k) : Prop := - ⇑(ModularForm.dual f) = ⇑f +def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := + (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f -theorem ModularForm.isSelfDual_iff' [Γ.IsSelfDual] (f : ModularForm Γ k) : - ModularForm.isSelfDual' f ↔ +theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] (f : ModularForm Γ k) : + ModularForm.isSelfDual f ↔ ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by sorry From 84c6fc6689f6291e63f03e69b661effadc066a0c Mon Sep 17 00:00:00 2001 From: SmwYin Date: Fri, 3 Jul 2026 13:19:29 +0100 Subject: [PATCH 5/5] Some work on dual forms --- .../.mathlib-quality/learnings.jsonl | 1 + .../LeanModularForms/Experiments/Issue34.lean | 54 --- .../LeanModularForms/Experiments/Issue50.lean | 125 ------- .../LeanModularForms/Experiments/Issue54.lean | 47 --- .../LeanModularForms/Experiments/Issue56.lean | 142 -------- .../Experiments/SelfDual/Basic.lean | 111 ------ .../Experiments/SelfDual/Version1.lean | 107 ------ .../Experiments/SelfDual/Version2.lean | 88 ----- .../LeanModularForms/Issues/Example.lean | 127 +++++++ .../LeanModularForms/Issues/Issue34.lean | 99 +++++ .../Basic copy.lean => Issue55.lean} | 230 +++++------- .../LeanModularForms/Issues/SelfDual.lean | 35 -- .../Issues/SelfDual/Basic.lean | 338 ------------------ .../Issues/SelfDual/Version1.lean | 50 --- .../Issues/SelfDual/Version2.lean | 46 --- .../LeanModularForms/Issues/SelfDual_old.lean | 41 --- 16 files changed, 315 insertions(+), 1326 deletions(-) delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/Example.lean create mode 100644 projects/LeanModularForms/LeanModularForms/Issues/Issue34.lean rename projects/LeanModularForms/LeanModularForms/Issues/{SelfDual/Basic copy.lean => Issue55.lean} (54%) delete mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean delete mode 100644 projects/LeanModularForms/LeanModularForms/Issues/SelfDual_old.lean diff --git a/projects/LeanModularForms/.mathlib-quality/learnings.jsonl b/projects/LeanModularForms/.mathlib-quality/learnings.jsonl index 98764da59..a166ce986 100644 --- a/projects/LeanModularForms/.mathlib-quality/learnings.jsonl +++ b/projects/LeanModularForms/.mathlib-quality/learnings.jsonl @@ -1,2 +1,3 @@ {"type":"style_correction","date":"2026-07-02","file":"Issues/SelfDual/Basic.lean","summary":"Per-declaration cleanup workers cannot catch cross-declaration proof-block duplication; the Phase-6.5 /simplify holistic pass found the `hdualΓ` (strictWidthInfty ∈ (dual Γ).strictPeriods) block copy-pasted across two declarations and extracted it into a shared private helper `strictWidthInfty_mem_dual_strictPeriods`.","lesson":"Always run the holistic simplify pass after per-decl golf; it is where cross-cutting DRY wins surface."} {"type":"mathlib_discovery","date":"2026-07-02","file":"Issues/SelfDual/Basic.lean","summary":"`Subgroup.strictWidthInfty` is a bare `dite` on `DiscreteTopology _.strictPeriods` with no congruence lemma, so `Subgroup.dual_width_eq` must reconstruct the def body under `congrArg` (rw/simp fail with 'motive is not type correct' / 'failed to synthesize Decidable'). A `strictWidthInfty_congr (h : Γ₁.strictPeriods = Γ₂.strictPeriods) : strictWidthInfty Γ₁ = strictWidthInfty Γ₂` is the missing API (upstream/dev-ticket candidate)."} +{"type":"mathlib_discovery","date":"2026-07-03","file":"Issues/Issue34.lean","summary":"To prove a ring hom `σ : IntermediateField ℚ ℂ →+* ℂ` is real on an adjoin (`conjugate σ = σ`), do NOT hand-roll `IntermediateField.adjoin_induction` with per-operation `change`/`rw [map_*, star_*]` closure branches (~22 lines). Instead bundle both ring homs as ℚ-AlgHoms via `RingHom.equivRatAlgHom : (A →+* B) ≃ (A →ₐ[ℚ] B)` and apply `IntermediateField.algHom_ext_of_eq_adjoin (F := ℚ) rfl` (or `adjoin_algHom_ext`), reducing the goal to the generator case (`rintro x ⟨n, rfl⟩; show star (σ ⟨_,_⟩) = σ ⟨_,_⟩; exact Complex.conj_eq_iff_im.mpr (h n)`). ~22 lines → 5.","lesson":"A per-declaration cleanup worker rejected this refactor (feared manual AlgHom bundling); the /simplify holistic pass (3 of 4 angles) found it. `equivRatAlgHom` makes ℚ-linearity free, so the AlgHom ext lemmas apply to any ring hom between ℚ-algebras — the `change`-heavy adjoin_induction is the missing-API smell mathlib warns about."} diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean deleted file mode 100644 index 76f9981b0..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/Issue34.lean +++ /dev/null @@ -1,54 +0,0 @@ -import LeanModularForms.Experiments.Issue55 -import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic -import Mathlib.NumberTheory.NumberField.CMField - -/-! -# LeanBridge issue #34: coefficient fields of newforms - -This file states the key coefficient-field targets for newforms. --/ - -noncomputable section - -namespace HeckeRing.GL2 - -variable {N : ℕ} [NeZero N] {k : ℤ} - -namespace Newform - -/-- The coefficient field `ℚ(a_n : n ≥ 1)` of a newform. -/ -noncomputable def coefficientField (f : Newform N k) : IntermediateField ℚ ℂ := - IntermediateField.adjoin ℚ - (Set.range fun n : ℕ+ => fourierCoeffAtInfinity f.toCuspForm n.val) - -/-- The coefficient field of a newform is finite-dimensional over `ℚ`. -/ -theorem coefficientField_finiteDimensional (f : Newform N k) : - FiniteDimensional ℚ f.coefficientField := by - sorry - -/-- The coefficient field of a newform is a number field. -/ -theorem coefficientField_numberField (f : Newform N k) : - NumberField f.coefficientField := by - sorry - -/-- The relative dimension attached to a newform. -/ -noncomputable def relativeDimension (f : Newform N k) : ℕ := - Module.finrank ℚ f.coefficientField - -theorem coefficientField_degree_eq_relativeDimension (f : Newform N k) : - Module.finrank ℚ f.coefficientField = f.relativeDimension := by - sorry - -/-- A newform's coefficient field is totally real if and only if the newform is self-dual. -/ -theorem coefficientField_isTotallyReal_iff_isSelfDual (f : Newform N k) : - NumberField.IsTotallyReal f.coefficientField ↔ IsSelfDual f.toCuspForm := by - sorry - -/-- A newform's coefficient field is CM if and only if the newform is not self-dual. -/ -theorem coefficientField_isCM_iff_not_isSelfDual (f : Newform N k) : - NumberField.IsCMField f.coefficientField ↔ ¬ IsSelfDual f.toCuspForm := by - sorry - -end Newform - -end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean deleted file mode 100644 index 88c7c4ec9..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/Issue50.lean +++ /dev/null @@ -1,125 +0,0 @@ -import Mathlib.Analysis.SpecialFunctions.Log.Basic -import Mathlib.RingTheory.Radical.NatInt -import Mathlib.Tactic - -/-! -# LeanBridge issue #50: abc quality - -This file uses mathlib's integer radical and defines the associated real-valued abc quality. --/ - -open scoped BigOperators - -namespace XYin.Experiments.Issue50 - -open UniqueFactorizationMonoid - -private lemma isRelPrime_int_of_gcd_eq_one {a b : ℤ} (h : Int.gcd a b = 1) : - IsRelPrime a b := by - intro d hda hdb - rw [Int.isUnit_iff_natAbs_eq] - have hda' : ((d.natAbs : ℕ) : ℤ) ∣ a := (Int.natAbs_dvd).mpr hda - have hdb' : ((d.natAbs : ℕ) : ℤ) ∣ b := (Int.natAbs_dvd).mpr hdb - have hg : d.natAbs ∣ Int.gcd a b := Int.dvd_gcd hda' hdb' - rw [h] at hg - exact Nat.dvd_one.mp hg - -private lemma radical_two : radical (2 : ℤ) = 2 := by - rw [radical_of_prime (show Prime (2 : ℤ) by norm_num)] - rfl - -private lemma radical_three : radical (3 : ℤ) = 3 := by - rw [radical_of_prime (show Prime (3 : ℤ) by norm_num)] - rfl - -private lemma radical_five : radical (5 : ℤ) = 5 := by - rw [radical_of_prime (show Prime (5 : ℤ) by norm_num)] - rfl - -lemma radical_dvd_int (n : ℤ) : radical n ∣ n := - radical_dvd_self - -/-- The height appearing in the numerator of the abc quality. -/ -def abcHeight (a b c : ℤ) : ℕ := - max a.natAbs (max b.natAbs c.natAbs) - -/-- The abc quality `log(max(|a|, |b|, |c|)) / log(rad(abc))`. -/ -noncomputable def abcQuality (a b c : ℤ) : ℝ := - Real.log (abcHeight a b c : ℝ) / Real.log (((radical (a * b * c : ℤ) : ℤ) : ℝ)) - -/-- A pairwise coprime integer triple satisfying `a + b = c`. -/ -structure CoprimeTriple (a b c : ℤ) : Prop where - sum_eq : a + b = c - coprime_ab : Nat.Coprime a.natAbs b.natAbs - coprime_ac : Nat.Coprime a.natAbs c.natAbs - coprime_bc : Nat.Coprime b.natAbs c.natAbs - -lemma abcQuality_pos_of_one_lt_height_radical {a b c : ℤ} - (hH : 1 < abcHeight a b c) (hR : 1 < radical (a * b * c : ℤ)) : - 0 < abcQuality a b c := by - exact div_pos (Real.log_pos (by exact_mod_cast hH)) (Real.log_pos (by exact_mod_cast hR)) - -lemma one_lt_abcQuality_of_radical_lt_height {a b c : ℤ} - (hR : 1 < radical (a * b * c : ℤ)) - (hRH : radical (a * b * c : ℤ) < (abcHeight a b c : ℤ)) : - 1 < abcQuality a b c := by - rw [abcQuality] - have hlogR : 0 < Real.log (((radical (a * b * c : ℤ) : ℤ) : ℝ)) := - Real.log_pos (by exact_mod_cast hR) - exact (one_lt_div hlogR).2 <| - Real.log_lt_log (by exact_mod_cast Int.radical_pos (a * b * c : ℤ)) - (by exact_mod_cast hRH) - -lemma one_eight_nine_coprimeTriple : CoprimeTriple 1 8 9 where - sum_eq := by norm_num - coprime_ab := by norm_num - coprime_ac := by norm_num - coprime_bc := by norm_num - -lemma five_twentyseven_thirtytwo_coprimeTriple : CoprimeTriple 5 27 32 where - sum_eq := by norm_num - coprime_ab := by norm_num - coprime_ac := by norm_num - coprime_bc := by norm_num - -lemma radical_one_eight_nine : radical (1 * 8 * 9 : ℤ) = 6 := by - rw [show (1 * 8 * 9 : ℤ) = (2 : ℤ) ^ 3 * (3 : ℤ) ^ 2 by norm_num] - rw [radical_mul (isRelPrime_int_of_gcd_eq_one (by norm_num))] - rw [radical_pow, radical_pow] - · rw [radical_two, radical_three] - norm_num - · norm_num - · norm_num - -lemma abcHeight_one_eight_nine : abcHeight 1 8 9 = 9 := by - norm_num [abcHeight] - -lemma one_lt_abcQuality_one_eight_nine : 1 < abcQuality 1 8 9 := by - rw [abcQuality, abcHeight_one_eight_nine, radical_one_eight_nine] - have hlog6 : 0 < Real.log (6 : ℝ) := Real.log_pos (by norm_num) - exact (one_lt_div hlog6).2 <| by - simpa using - (Real.log_lt_log (by norm_num : (0 : ℝ) < 6) (by norm_num : (6 : ℝ) < 9)) - -lemma radical_five_twentyseven_thirtytwo : radical (5 * 27 * 32 : ℤ) = 30 := by - rw [show (5 * 27 * 32 : ℤ) = ((2 : ℤ) ^ 5 * (3 : ℤ) ^ 3) * 5 by norm_num] - rw [radical_mul (isRelPrime_int_of_gcd_eq_one (by norm_num))] - rw [radical_mul (isRelPrime_int_of_gcd_eq_one (by norm_num))] - rw [radical_pow, radical_pow] - · rw [radical_two, radical_three, radical_five] - norm_num - · norm_num - · norm_num - -lemma abcHeight_five_twentyseven_thirtytwo : abcHeight 5 27 32 = 32 := by - norm_num [abcHeight] - -lemma one_lt_abcQuality_five_twentyseven_thirtytwo : 1 < abcQuality 5 27 32 := by - rw [abcQuality, abcHeight_five_twentyseven_thirtytwo, - radical_five_twentyseven_thirtytwo] - have hlog30 : 0 < Real.log (30 : ℝ) := Real.log_pos (by norm_num) - exact (one_lt_div hlog30).2 <| by - simpa using - (Real.log_lt_log (by norm_num : (0 : ℝ) < 30) (by norm_num : (30 : ℝ) < 32)) - -end XYin.Experiments.Issue50 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean deleted file mode 100644 index 12a71e36e..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/Issue54.lean +++ /dev/null @@ -1,47 +0,0 @@ -import Mathlib.Data.Nat.Factorization.Basic -import Mathlib.Tactic - -/-! -# LeanBridge issue #54: bad primes - -The bad primes of level `N` are exactly the prime factors of `N`. --/ - -namespace XYin.Experiments.Issue54 - -/-- The finite set of primes dividing the level. -/ -def badPrimes (N : ℕ) : Finset ℕ := - N.primeFactors - -@[simp] -lemma mem_badPrimes {N p : ℕ} : p ∈ badPrimes N ↔ p.Prime ∧ p ∣ N ∧ N ≠ 0 := by - simp [badPrimes] - -lemma prime_mem_badPrimes_iff_dvd {N p : ℕ} (hp : p.Prime) (hN : N ≠ 0) : - p ∈ badPrimes N ↔ p ∣ N := by - simp [badPrimes, hp, hN] - -lemma badPrimes_finite (N : ℕ) : {p | p ∈ badPrimes N}.Finite := - (badPrimes N).finite_toSet - -example : badPrimes 11 = {11} := by - ext p - simp only [mem_badPrimes, Finset.mem_singleton] - constructor - · rintro ⟨hp, hdvd, _⟩ - exact (Nat.dvd_prime (by norm_num : Nat.Prime 11)).mp hdvd |>.resolve_left hp.ne_one - · intro h - subst h - norm_num - -example : badPrimes 12 = ({2, 3} : Finset ℕ) := by - ext p - simp only [mem_badPrimes, Finset.mem_insert, Finset.mem_singleton] - constructor - · rintro ⟨hp, hdvd, _⟩ - have hle : p ≤ 12 := Nat.le_of_dvd (by norm_num) hdvd - have hpos : 0 < p := hp.pos - interval_cases p <;> norm_num [Nat.Prime] at * - · rintro (rfl | rfl) <;> norm_num - -end XYin.Experiments.Issue54 diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean b/projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean deleted file mode 100644 index 34be83b51..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/Issue56.lean +++ /dev/null @@ -1,142 +0,0 @@ -import Mathlib.NumberTheory.NumberField.InfinitePlace.TotallyRealComplex -import Mathlib.Algebra.QuadraticAlgebra.Basic -import Mathlib.NumberTheory.Real.Irrational -import Mathlib.Tactic - -/-! -# LeanBridge issue #56: totally positive elements - -The definition is stated using the infinite-place API: every real infinite place sends the element -to a positive real number. --/ - -namespace NumberField - -variable {K : Type*} [Field K] - -/-- An element is totally positive if it is positive under every real infinite place. -/ -def IsTotallyPositive (x : K) : Prop := - ∀ (w : InfinitePlace K) (hw : w.IsReal), 0 < InfinitePlace.embedding_of_isReal hw x - -lemma isTotallyPositive_iff {x : K} : - IsTotallyPositive x ↔ - ∀ (w : InfinitePlace K) (hw : w.IsReal), 0 < InfinitePlace.embedding_of_isReal hw x := - Iff.rfl - -namespace IsTotallyPositive - -lemma add {x y : K} (hx : IsTotallyPositive x) (hy : IsTotallyPositive y) : - IsTotallyPositive (x + y) := by - intro w hw - simpa using add_pos (hx w hw) (hy w hw) - -lemma mul {x y : K} (hx : IsTotallyPositive x) (hy : IsTotallyPositive y) : - IsTotallyPositive (x * y) := by - intro w hw - simpa using mul_pos (hx w hw) (hy w hw) - -lemma pow_two {x : K} (hx : x ≠ 0) : IsTotallyPositive (x ^ 2) := by - intro w hw - have hxw : InfinitePlace.embedding_of_isReal hw x ≠ 0 := by - exact (map_ne_zero (InfinitePlace.embedding_of_isReal hw)).mpr hx - simpa [pow_two] using sq_pos_of_ne_zero hxw - -lemma inv {x : K} (hx : IsTotallyPositive x) : IsTotallyPositive x⁻¹ := by - intro w hw - simpa using inv_pos.mpr (hx w hw) - -lemma div {x y : K} (hx : IsTotallyPositive x) (hy : IsTotallyPositive y) : - IsTotallyPositive (x / y) := by - simpa [div_eq_mul_inv] using hx.mul hy.inv - -end IsTotallyPositive - -lemma isTotallyPositive_unit_square (u : Kˣ) : IsTotallyPositive ((u : K) ^ 2) := - IsTotallyPositive.pow_two u.ne_zero - -noncomputable section - -open scoped QuadraticAlgebra - -namespace Issue56Examples - -abbrev Qsqrt2 := QuadraticAlgebra ℚ (2 : ℚ) 0 - -lemma qsqrt2_no_rat_root : ∀ r : ℚ, r ^ 2 ≠ (2 : ℚ) + 0 * r := by - intro r hr - norm_num at hr - have hreal : ((r : ℝ) ^ 2) = (2 : ℝ) := by exact_mod_cast hr - have hsq : ((r : ℝ) ^ 2) = (Real.sqrt 2) ^ 2 := by - rw [hreal, Real.sq_sqrt (by norm_num)] - rcases (sq_eq_sq_iff_eq_or_eq_neg.mp hsq) with h | h - · exact irrational_sqrt_two ⟨r, h⟩ - · exact irrational_sqrt_two ⟨-r, by simp [h]⟩ - -local instance : Fact (∀ r : ℚ, r ^ 2 ≠ (2 : ℚ) + 0 * r) := - ⟨qsqrt2_no_rat_root⟩ - -abbrev sqrtTwo : Qsqrt2 := - QuadraticAlgebra.omega - -abbrev threePlusTwoSqrtTwo : Qsqrt2 := - ⟨3, 2⟩ - -lemma one_add_sqrtTwo_sq : (1 + sqrtTwo) ^ 2 = threePlusTwoSqrtTwo := by - ext <;> norm_num [sqrtTwo, threePlusTwoSqrtTwo, pow_two] - -lemma threePlusTwoSqrtTwo_eq_one_add_sq : - threePlusTwoSqrtTwo = (1 + sqrtTwo) ^ 2 := - one_add_sqrtTwo_sq.symm - -example : IsTotallyPositive threePlusTwoSqrtTwo := by - rw [threePlusTwoSqrtTwo_eq_one_add_sq] - exact IsTotallyPositive.pow_two (by - intro h - have him := congrArg QuadraticAlgebra.im h - norm_num [sqrtTwo] at him) - -noncomputable def negSqrt2AlgHom : Qsqrt2 →ₐ[ℚ] ℝ := - QuadraticAlgebra.lift ⟨-Real.sqrt 2, by - rw [neg_mul_neg, ← pow_two (Real.sqrt 2), Real.sq_sqrt (by norm_num)] - norm_num⟩ - -lemma negSqrt2AlgHom_sqrtTwo : negSqrt2AlgHom sqrtTwo = -Real.sqrt 2 := by - dsimp [negSqrt2AlgHom, sqrtTwo, QuadraticAlgebra.lift] - change (QuadraticAlgebra.omega : Qsqrt2).re • (1 : ℝ) + - (QuadraticAlgebra.omega : Qsqrt2).im • (-Real.sqrt 2) = -Real.sqrt 2 - norm_num - -noncomputable def negSqrt2Embedding : Qsqrt2 →+* ℂ := - Complex.ofRealHom.comp negSqrt2AlgHom.toRingHom - -lemma negSqrt2Embedding_isReal : ComplexEmbedding.IsReal negSqrt2Embedding := by - rw [ComplexEmbedding.isReal_iff] - ext x - simp [negSqrt2Embedding] - -lemma neg_place_sqrtTwo : - let w := InfinitePlace.mk negSqrt2Embedding - let hw : w.IsReal := InfinitePlace.isReal_mk_iff.mpr negSqrt2Embedding_isReal - InfinitePlace.embedding_of_isReal hw sqrtTwo = -Real.sqrt 2 := by - dsimp only - apply Complex.ofReal_injective - rw [InfinitePlace.embedding_of_isReal_apply, - InfinitePlace.embedding_mk_eq_of_isReal negSqrt2Embedding_isReal] - simp [negSqrt2Embedding, negSqrt2AlgHom_sqrtTwo] - -example : ¬ IsTotallyPositive sqrtTwo := by - intro h - let w := InfinitePlace.mk negSqrt2Embedding - let hw : w.IsReal := InfinitePlace.isReal_mk_iff.mpr negSqrt2Embedding_isReal - have hω : InfinitePlace.embedding_of_isReal hw sqrtTwo = -Real.sqrt 2 := neg_place_sqrtTwo - have hsqrt_pos : 0 < Real.sqrt 2 := by positivity - have hnot : ¬ 0 < InfinitePlace.embedding_of_isReal hw sqrtTwo := by - rw [hω] - linarith - exact hnot (h w hw) - -end Issue56Examples - -end - -end NumberField diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean deleted file mode 100644 index e248cec50..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Basic.lean +++ /dev/null @@ -1,111 +0,0 @@ -import Mathlib - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex Function MatrixGroups ModularForm Pointwise -open UpperHalfPlane hiding I -open scoped ComplexConjugate - -local notation "𝕢" => Periodic.qParam - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := - (ConjAct.toConjAct J⁻¹) • Γ - -class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where - self_dual : Subgroup.dual Γ = Γ - -noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := - ModularForm.translate f J - -@[simp] -theorem ModularForm.coe_dual (f : ModularForm Γ k) : - ⇑(ModularForm.dual f) = ⇑f ∣[k] J := - ModularForm.coe_translate f J - -@[simp] -theorem ModularForm.dual_apply (f : ModularForm Γ k) (z : ℍ) : - ModularForm.dual f z = (⇑f ∣[k] J) z := - rfl - -@[simp] -theorem ModularForm.dual_zero : - ModularForm.dual (0 : ModularForm Γ k) = 0 := by - ext z - simp - -@[simp] -theorem ModularForm.dual_add (f g : ModularForm Γ k) : - ModularForm.dual (f + g) = ModularForm.dual f + ModularForm.dual g := by - ext z - simp - -@[simp] -theorem ModularForm.dual_neg (f : ModularForm Γ k) : - ModularForm.dual (-f) = -ModularForm.dual f := by - ext z - simp - -@[simp] -theorem ModularForm.dual_sub (f g : ModularForm Γ k) : - ModularForm.dual (f - g) = ModularForm.dual f - ModularForm.dual g := by - ext z - simp [sub_eq_add_neg] - -@[simp] -theorem ModularForm.dual_smul_real (c : ℝ) (f : ModularForm Γ k) : - ModularForm.dual (c • f) = c • ModularForm.dual f := by - ext z - change (((c : ℂ) • ⇑f) ∣[k] J) z = (c : ℂ) * ModularForm.dual f z - rw [smul_slash, σ_ofReal J c] - rfl - -theorem ModularForm.dual_apply_conj (f : ModularForm Γ k) (z : ℍ) : - ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by - simp [ModularForm.slash_def, J_smul] - -private theorem qParam_neg_conj (h : ℝ) (z : ℂ) : - 𝕢 h (-(conj z)) = conj (𝕢 h z) := by - simp [Periodic.qParam, ← Complex.exp_conj, map_ofNat] - -theorem ModularForm.hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) : - ∀ z : ℍ, HasSum (fun m : ℕ ↦ conj ((qExpansion Γ.strictWidthInfty f).coeff m) • 𝕢 Γ.strictWidthInfty (z : ℂ) ^ m) - (ModularForm.dual f z) := by - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓ : h ∈ Γ.strictPeriods := by - simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ - haveI : Fact (IsCusp OnePoint.infty Γ) := ⟨Subgroup.isCusp_of_mem_strictPeriods hh hΓ⟩ - intro z - let z' : ℍ := ofComplex (-(conj (z : ℂ))) - have hz' : 0 < (-(conj (z : ℂ))).im := by simpa using z.im_pos - have hcoe : (z' : ℂ) = -(conj (z : ℂ)) := by - simp [z', ofComplex_apply_of_im_pos hz'] - have hq : 𝕢 h (z' : ℂ) = conj (𝕢 h (z : ℂ)) := by - rw [hcoe] - exact qParam_neg_conj h (z : ℂ) - have hval : (⇑f ∣[k] J) z = conj (f z') := by - simpa [ModularForm.dual_apply, z'] using ModularForm.dual_apply_conj f z - have hs1 : HasSum (fun m : ℕ ↦ conj ((qExpansion h f).coeff m • 𝕢 h (z' : ℂ) ^ m)) (conj (f z')) := - (RCLike.hasSum_conj ℂ).mpr (by - simpa using hasSum_qExpansion hh (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ) - (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) z') - simpa [h, ModularForm.dual_apply, hval, hq, Complex.conj_conj, map_mul, map_pow, smul_eq_mul] using hs1 - -theorem ModularForm.qExpansion_dual_coeff [Γ.IsSelfDual] [Γ.IsArithmetic] - (f : ModularForm Γ k) (n : ℕ) : - (qExpansion Γ.strictWidthInfty (ModularForm.dual f)).coeff n = - conj ((qExpansion Γ.strictWidthInfty f).coeff n) := by - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓdual : h ∈ (Subgroup.dual Γ).strictPeriods := by - simpa [h, Subgroup.IsSelfDual.self_dual (Γ := Γ)] using - Subgroup.strictWidthInfty_mem_strictPeriods Γ - simpa [h] using (ModularFormClass.qExpansion_coeff_unique - (Γ := Subgroup.dual Γ) (F := ModularForm (Subgroup.dual Γ) k) - (h := h) (hh := hh) (hΓ := hΓdual) (f := ModularForm.dual f) - (by simpa [h] using ModularForm.hasSum_qExpansion_dual (Γ := Γ) (k := k) f) n).symm - -theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} - (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by - cases h - rfl diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean deleted file mode 100644 index 51a0a1608..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version1.lean +++ /dev/null @@ -1,107 +0,0 @@ -import LeanModularForms.Experiments.SelfDual.Basic - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := - (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f - -theorem ModularForm.isSelfDual_iff_coe_dual_eq [Γ.IsSelfDual] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ ⇑(ModularForm.dual f) = ⇑f := by - constructor - · intro h - calc - ⇑(ModularForm.dual f) = - ⇑(‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f : ModularForm Γ k) := by - rw [ModularForm.coe_cast_group] - _ = ⇑f := by rw [h] - · intro h - apply ModularForm.ext - intro z - rw [ModularForm.coe_cast_group] - exact congrFun h z - -theorem ModularForm.isSelfDual_iff_apply [Γ.IsSelfDual] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ ∀ z, ModularForm.dual f z = f z := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] - exact ⟨fun h z => congrFun h z, fun h => funext h⟩ - -@[simp] -theorem ModularForm.isSelfDual_zero [Γ.IsSelfDual] : - ModularForm.isSelfDual (0 : ModularForm Γ k) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] - ext z - simp - -theorem ModularForm.isSelfDual_add [Γ.IsSelfDual] {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : - ModularForm.isSelfDual (f + g) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf hg ⊢ - ext z - simpa [ModularForm.dual_apply] using congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) - -theorem ModularForm.isSelfDual_neg [Γ.IsSelfDual] {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) : - ModularForm.isSelfDual (-f) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ - ext z - simpa [ModularForm.dual_apply] using congrArg Neg.neg (congrFun hf z) - -theorem ModularForm.isSelfDual_sub [Γ.IsSelfDual] {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : - ModularForm.isSelfDual (f - g) := by - simpa [sub_eq_add_neg] using ModularForm.isSelfDual_add hf (ModularForm.isSelfDual_neg hg) - -theorem ModularForm.isSelfDual_smul_real [Γ.IsSelfDual] (c : ℝ) {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) : - ModularForm.isSelfDual (c • f) := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] at hf ⊢ - ext z - have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := - UpperHalfPlane.σ_ofReal UpperHalfPlane.J c - change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z - rw [smul_slash, hsigma] - simpa [Pi.smul_apply, smul_eq_mul] using - congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) - -theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ - ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - rw [ModularForm.isSelfDual_iff_coe_dual_eq] - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓ : h ∈ Γ.strictPeriods := by - simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ - constructor - · intro hfd n - have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [hfd] - have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [← ModularForm.qExpansion_dual_coeff f n, hq] - simpa [h] using (Complex.conj_eq_iff_im.mp hstar) - · intro hcoeff - let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) - have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by - dsimp [fd] - rw [ModularForm.coe_cast_group] - have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by - apply PowerSeries.ext - intro n - rw [show (UpperHalfPlane.qExpansion h fd).coeff n = - (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] - rw [ModularForm.qExpansion_dual_coeff f n] - exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) - have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by - rw [show UpperHalfPlane.qExpansion h (fd - f) = - UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] - rw [ModularForm.qExpansion_sub hh hΓ fd f] - simp [hq] - have hzero_form : fd - f = 0 := - (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q - have hfd_eq : fd = f := sub_eq_zero.mp hzero_form - calc - ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm - _ = ⇑f := by rw [hfd_eq] diff --git a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean b/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean deleted file mode 100644 index 48aaaba10..000000000 --- a/projects/LeanModularForms/LeanModularForms/Experiments/SelfDual/Version2.lean +++ /dev/null @@ -1,88 +0,0 @@ -import LeanModularForms.Experiments.SelfDual.Basic - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -def ModularForm.isSelfDual' (f : ModularForm Γ k) : Prop := - ⇑(ModularForm.dual f) = ⇑f - -theorem ModularForm.isSelfDual'_iff_apply (f : ModularForm Γ k) : - ModularForm.isSelfDual' f ↔ ∀ z, ModularForm.dual f z = f z := - ⟨fun h z => congrFun h z, fun h => funext h⟩ - -@[simp] -theorem ModularForm.isSelfDual'_zero : - ModularForm.isSelfDual' (0 : ModularForm Γ k) := by - ext z - simp - -theorem ModularForm.isSelfDual'_add {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : - ModularForm.isSelfDual' (f + g) := by - ext z - simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using - congrArg₂ HAdd.hAdd (congrFun hf z) (congrFun hg z) - -theorem ModularForm.isSelfDual'_neg {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) : - ModularForm.isSelfDual' (-f) := by - ext z - simpa [ModularForm.isSelfDual', ModularForm.dual_apply] using - congrArg Neg.neg (congrFun hf z) - -theorem ModularForm.isSelfDual'_sub {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : - ModularForm.isSelfDual' (f - g) := by - simpa [sub_eq_add_neg] using ModularForm.isSelfDual'_add hf (ModularForm.isSelfDual'_neg hg) - -theorem ModularForm.isSelfDual'_smul_real (c : ℝ) {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) : - ModularForm.isSelfDual' (c • f) := by - ext z - have hsigma : UpperHalfPlane.σ UpperHalfPlane.J (c : ℂ) = c := - UpperHalfPlane.σ_ofReal UpperHalfPlane.J c - change (((c : ℂ) • ⇑f) ∣[k] UpperHalfPlane.J) z = (c : ℂ) * f z - rw [smul_slash, hsigma] - simpa [Pi.smul_apply, smul_eq_mul] using - congrArg (fun x : ℂ => (c : ℂ) * x) (congrFun hf z) - -theorem ModularForm.isSelfDual_iff' [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : - ModularForm.isSelfDual' f ↔ - ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - let h := Γ.strictWidthInfty - have hh : 0 < h := by simpa [h] using Subgroup.strictWidthInfty_pos Γ - have hΓ : h ∈ Γ.strictPeriods := by - simpa [h] using Subgroup.strictWidthInfty_mem_strictPeriods Γ - constructor - · intro hfd n - have hq : (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [hfd] - have hstar : (starRingEnd ℂ) ((UpperHalfPlane.qExpansion h f).coeff n) = - (UpperHalfPlane.qExpansion h f).coeff n := by - rw [← ModularForm.qExpansion_dual_coeff f n, hq] - simpa [h] using (Complex.conj_eq_iff_im.mp hstar) - · intro hcoeff - let fd : ModularForm Γ k := (Subgroup.IsSelfDual.self_dual (Γ := Γ) ▸ ModularForm.dual f) - have hfd_coe : ⇑fd = ⇑(ModularForm.dual f) := by - dsimp [fd] - rw [ModularForm.coe_cast_group] - have hq : UpperHalfPlane.qExpansion h fd = UpperHalfPlane.qExpansion h f := by - apply PowerSeries.ext - intro n - rw [show (UpperHalfPlane.qExpansion h fd).coeff n = - (UpperHalfPlane.qExpansion h (ModularForm.dual f)).coeff n by rw [hfd_coe]] - rw [ModularForm.qExpansion_dual_coeff f n] - exact Complex.conj_eq_iff_im.mpr (by simpa [h] using hcoeff n) - have hzero_q : UpperHalfPlane.qExpansion h (fd - f) = 0 := by - rw [show UpperHalfPlane.qExpansion h (fd - f) = - UpperHalfPlane.qExpansion h (⇑fd - ⇑f : UpperHalfPlane → ℂ) by rfl] - rw [ModularForm.qExpansion_sub hh hΓ fd f] - simp [hq] - have hzero_form : fd - f = 0 := - (ModularForm.qExpansion_eq_zero_iff hh hΓ (fd - f)).mp hzero_q - have hfd_eq : fd = f := sub_eq_zero.mp hzero_form - calc - ⇑(ModularForm.dual f) = ⇑fd := hfd_coe.symm - _ = ⇑f := by rw [hfd_eq] diff --git a/projects/LeanModularForms/LeanModularForms/Issues/Example.lean b/projects/LeanModularForms/LeanModularForms/Issues/Example.lean new file mode 100644 index 000000000..078492785 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/Example.lean @@ -0,0 +1,127 @@ +import LeanModularForms.Issues.Issue55 + +/-! +# A congruence subgroup that is not self-dual, carrying a self-dual form + +This file constructs a concrete example separating three properties of a subgroup of +`SL(2, ℤ)` and a modular form on it. The subgroup `Γ` is the preimage, modulo `3`, of the +stabilizer of the line spanned by `(1, 1)`. It is a congruence subgroup but is not self-dual, +yet the discriminant cusp form `Δ` restricted to it is self-dual. + +## Main definitions + +* `IssueExample.Γ`: the subgroup of `SL(2, ℤ)` whose reduction mod `3` fixes the sum + `γ 0 0 + γ 0 1` and `γ 1 0 + γ 1 1`. +* `IssueExample.Δ`: the discriminant cusp form restricted from `SL(2, ℤ)` to `Γ`. + +## Main results + +* `IssueExample.result`: `Γ` is a congruence subgroup, `Γ` is not self-dual, and `Δ` is + self-dual. +-/ + +open ModularForm UpperHalfPlane MatrixGroups ComplexConjugate +open CongruenceSubgroup Pointwise Subgroup +open Matrix Matrix.SpecialLinearGroup Complex +open scoped MatrixGroups ModularForm Real + +private lemma eta_neg_conj (z : UpperHalfPlane) : + conj (ModularForm.eta (-(conj (z : ℂ)))) = ModularForm.eta (z : ℂ) := by + have hz' : (-(conj (z : ℂ))) ∈ UpperHalfPlane.upperHalfPlaneSet := by + simpa using z.2 + have hprod := (ModularForm.multipliableLocallyUniformlyOn_eta.multipliable hz').map_tprod + (starRingEnd ℂ) Complex.continuous_conj + rw [ModularForm.eta, map_mul, hprod, ModularForm.eta] + simp [ModularForm.eta_q, Function.Periodic.qParam, ← Complex.exp_conj, map_ofNat] + +namespace IssueExample + +/-- The subgroup of `SL(2, ℤ)` whose reduction modulo `3` stabilizes the line +spanned by `(1, 1)`. -/ +def Γ : Subgroup SL(2, ℤ) where + carrier := {γ | (γ 0 0 + γ 0 1 : ZMod 3) = (γ 1 0 + γ 1 1 : ZMod 3)} + one_mem' := by norm_num + mul_mem' := by + intro A B hA hB + change ((A * B) 0 0 + (A * B) 0 1 : ZMod 3) = + ((A * B) 1 0 + (A * B) 1 1 : ZMod 3) + have hA' : (A 0 0 : ZMod 3) + (A 0 1 : ZMod 3) = + (A 1 0 : ZMod 3) + (A 1 1 : ZMod 3) := hA + have hB' : (B 0 0 : ZMod 3) + (B 0 1 : ZMod 3) = + (B 1 0 : ZMod 3) + (B 1 1 : ZMod 3) := hB + simp only [Fin.isValue, Matrix.SpecialLinearGroup.coe_mul, Matrix.mul_apply, + Fin.sum_univ_two, Int.cast_add, Int.cast_mul] + linear_combination ((B 0 0 : ZMod 3) + (B 0 1 : ZMod 3)) * hA' + + ((A 1 1 : ZMod 3) - (A 0 1 : ZMod 3)) * hB' + inv_mem' := by + intro A hA + change ((A⁻¹) 0 0 + (A⁻¹) 0 1 : ZMod 3) = + ((A⁻¹) 1 0 + (A⁻¹) 1 1 : ZMod 3) + have hA' : (A 0 0 : ZMod 3) + (A 0 1 : ZMod 3) = + (A 1 0 : ZMod 3) + (A 1 1 : ZMod 3) := hA + rw [SL2_inv_expl A] + simp only [Fin.isValue, cons_val', cons_val_zero, cons_val_fin_one, cons_val_one, Int.cast_neg] + linear_combination -hA' + +theorem mem_Γ (γ : SL(2, ℤ)) : γ ∈ Γ ↔ (γ 0 0 + γ 0 1 : ZMod 3) = (γ 1 0 + γ 1 1 : ZMod 3) := + Iff.rfl + +theorem Γ_isCongruenceSubgroup : CongruenceSubgroup.IsCongruenceSubgroup Γ := by + refine ⟨3, by norm_num, ?_⟩ + intro γ hγ + rw [CongruenceSubgroup.Gamma_mem] at hγ + change (γ 0 0 + γ 0 1 : ZMod 3) = (γ 1 0 + γ 1 1 : ZMod 3) + simp [hγ] + +theorem Γ_not_isSelfDual : + ¬ Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) := by + let γ : SL(2, ℤ) := ⟨!![0, 1; -1, -1], by norm_num [Matrix.det_fin_two_of]⟩ + let γJ : SL(2, ℤ) := ⟨!![0, -1; 1, -1], by norm_num [Matrix.det_fin_two_of]⟩ + have hγΓ : γ ∈ Γ := by + change ((0 : ZMod 3) + (1 : ZMod 3) = (-1 : ZMod 3) + (-1 : ZMod 3)) + decide + have hγJ_not : γJ ∉ Γ := by + change ¬ ((0 : ZMod 3) + (-1 : ZMod 3) = (1 : ZMod 3) + (-1 : ZMod 3)) + decide + have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := + inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq + have hmapγJ : mapGL ℝ γJ = UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J := by + ext i j + fin_cases i <;> fin_cases j <;> + norm_num [γ, γJ, UpperHalfPlane.J, Matrix.GeneralLinearGroup.coe_mul, + Matrix.mul_apply, Matrix.vecMul, dotProduct, Matrix.vecHead, Matrix.vecTail, + Fin.sum_univ_two] + have hdual_mem : UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J ∈ + Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) := by + rw [Subgroup.dual, hJinv] + simpa [ConjAct.toConjAct_smul, hJinv] using + Subgroup.smul_mem_pointwise_smul (mapGL ℝ γ) (ConjAct.toConjAct UpperHalfPlane.J) + (Γ : Subgroup (GL (Fin 2) ℝ)) (Subgroup.mem_map.mpr ⟨γ, hγΓ, rfl⟩) + have hnot_mem : UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J ∉ + (Γ : Subgroup (GL (Fin 2) ℝ)) := by + intro hmem + obtain ⟨δ, hδΓ, hδ⟩ := Subgroup.mem_map.mp hmem + have hδ_eq : δ = γJ := mapGL_injective (by rw [hδ, ← hmapγJ]) + exact hγJ_not (hδ_eq ▸ hδΓ) + intro hself + exact hnot_mem (by simpa [hself.isSelfDual] using hdual_mem) + +theorem Γ_le_SL : (Γ : Subgroup (GL (Fin 2) ℝ)) ≤ 𝒮ℒ := Subgroup.map_le_range (mapGL ℝ) Γ + +/-- The discriminant cusp form, restricted from the full modular group to `Γ`. -/ +noncomputable def Δ : CuspForm (Γ : Subgroup (GL (Fin 2) ℝ)) 12 := + CuspForm.restrictSubgroup Γ_le_SL CuspForm.discriminant + +theorem Δ_isSelfDual : ModularFormClass.isSelfDual Δ := by + ext z + rw [ModularFormClass.dual_explicit] + change conj (ModularForm.discriminant (ofComplex (-(conj (z : ℂ))))) = + ModularForm.discriminant z + have hz' : 0 < (-(conj (z : ℂ))).im := by simpa using z.2 + simp [ModularForm.discriminant, ofComplex_apply_of_im_pos hz', map_pow, eta_neg_conj] + +/-- The concrete example: `Γ` is congruence and not self-dual, while `Δ` is self-dual. -/ +theorem result : IsCongruenceSubgroup Γ ∧ ¬ Subgroup.IsSelfDual Γ ∧ ModularFormClass.isSelfDual Δ := + ⟨Γ_isCongruenceSubgroup, Γ_not_isSelfDual, Δ_isSelfDual⟩ + +end IssueExample diff --git a/projects/LeanModularForms/LeanModularForms/Issues/Issue34.lean b/projects/LeanModularForms/LeanModularForms/Issues/Issue34.lean new file mode 100644 index 000000000..eb0a33df6 --- /dev/null +++ b/projects/LeanModularForms/LeanModularForms/Issues/Issue34.lean @@ -0,0 +1,99 @@ +import LeanModularForms.Issues.Issue55 + +open ModularForm UpperHalfPlane MatrixGroups ComplexConjugate CongruenceSubgroup Pointwise Subgroup + Matrix.SpecialLinearGroup HeckeRing.GL2 + +variable {N : ℕ} [NeZero N] {k : ℤ} + +namespace HeckeRing.GL2 + +namespace Newform + +/-- The coefficient field `ℚ(a_n : n ≥ 1)` of a newform. -/ +noncomputable def coefficientField (f : Newform N k) : IntermediateField ℚ ℂ := + IntermediateField.adjoin ℚ (Set.range fun n : ℕ+ ↦ (qExpansion 1 f.toCuspForm).coeff n) + +/-- The coefficient field of a newform is finite-dimensional over `ℚ`. -/ +theorem coefficientField_finiteDimensional (f : Newform N k) : + FiniteDimensional ℚ f.coefficientField := by + sorry + +/-- The coefficient field of a newform is a number field. -/ +instance (f : Newform N k) : NumberField f.coefficientField := + {to_finiteDimensional := coefficientField_finiteDimensional f} + +lemma coeff_mem_coefficientField (f : Newform N k) (n : ℕ+) : + (qExpansion 1 f.toCuspForm).coeff n ∈ f.coefficientField := + IntermediateField.subset_adjoin ℚ _ (Set.mem_range_self n) + +lemma isSelfDual_iff_qExpansion_one_coeff_im_eq_zero (f : Newform N k) : + ModularFormClass.isSelfDual f.toCuspForm ↔ + ∀ n : ℕ, ((qExpansion 1 f.toCuspForm).coeff n).im = 0 := by + simpa [CongruenceSubgroup.strictWidthInfty_Gamma1 N] using + ModularFormClass.isSelfDual_iff f.toCuspForm + +lemma qExpansion_one_coeff_im_eq_zero_of_coefficientField_isTotallyReal (f : Newform N k) + (hK : NumberField.IsTotallyReal f.coefficientField) : + ∀ n : ℕ, ((qExpansion 1 f.toCuspForm).coeff n).im = 0 := by + intro n + cases n with + | zero => simp [CuspFormClass.qExpansion_coeff_zero f.toCuspForm one_pos (one_mem_strictPeriods_Gamma1_map N)] + | succ n => + let npos : ℕ+ := ⟨n + 1, n.succ_pos⟩ + simpa [npos] using Complex.conj_eq_iff_im.mp (RingHom.congr_fun + (NumberField.IsTotallyReal.complexEmbedding_isReal (algebraMap f.coefficientField ℂ)) + ⟨(qExpansion 1 f.toCuspForm).coeff npos, coeff_mem_coefficientField f npos⟩) + +/-- +For every embedding σ : K_f ↪ ℂ, the coefficientwise conjugate +f^σ(q) = ∑ n ≥ 1, σ(a_n(f)) q^n +is again a normalized newform. Its dual has coefficients +a_n((f^σ)ᵛ) = overline(σ(a_n(f))). +Galois conjugation commutes with duality: +(f^σ)ᵛ = (fᵛ)^σ. +-/ +theorem exists_selfDual_galoisConjugate_newform_of_isSelfDual (f : Newform N k) + (hself : ModularFormClass.isSelfDual f.toCuspForm) (σ : f.coefficientField →+* ℂ) : + ∃ g : Newform N k, ModularFormClass.isSelfDual g.toCuspForm ∧ + ∀ n : ℕ+, (qExpansion 1 g.toCuspForm).coeff n = + σ ⟨(qExpansion 1 f.toCuspForm).coeff n, coeff_mem_coefficientField f n⟩ := by + sorry + +lemma complexEmbedding_coeff_im_eq_zero_of_isSelfDual (f : Newform N k) + (hself : ModularFormClass.isSelfDual f.toCuspForm) (σ : f.coefficientField →+* ℂ) (n : ℕ+) : + (σ ⟨(qExpansion 1 f.toCuspForm).coeff n, coeff_mem_coefficientField f n⟩).im = 0 := by + obtain ⟨g, hgself, hgcoeff⟩ := exists_selfDual_galoisConjugate_newform_of_isSelfDual f hself σ + rw [← hgcoeff n] + exact (isSelfDual_iff_qExpansion_one_coeff_im_eq_zero g).mp hgself n + +lemma coefficientField_isTotallyReal_of_forall_complexEmbedding_coeff_im_eq_zero + (f : Newform N k) (hσ : ∀ (σ : f.coefficientField →+* ℂ) (n : ℕ+), + (σ ⟨(qExpansion 1 f.toCuspForm).coeff n, coeff_mem_coefficientField f n⟩).im = 0) : + NumberField.IsTotallyReal f.coefficientField := by + unfold coefficientField at hσ ⊢ + refine ⟨fun v ↦ ?_⟩ + rw [NumberField.InfinitePlace.isReal_iff] + let σ := NumberField.InfinitePlace.embedding v + rw [NumberField.ComplexEmbedding.isReal_iff] + apply RingHom.equivRatAlgHom.injective + apply IntermediateField.algHom_ext_of_eq_adjoin (F := ℚ) rfl + rintro x ⟨n, rfl⟩ + change star (σ ⟨_, _⟩) = σ ⟨_, _⟩ + exact Complex.conj_eq_iff_im.mpr (hσ σ n) + +/-- A newform's coefficient field is totally real if and only if the newform is self-dual. -/ +theorem coefficientField_isTotallyReal_iff_isSelfDual (f : Newform N k) : + NumberField.IsTotallyReal f.coefficientField ↔ ModularFormClass.isSelfDual f.toCuspForm := + ⟨fun hK ↦ (isSelfDual_iff_qExpansion_one_coeff_im_eq_zero f).mpr + (qExpansion_one_coeff_im_eq_zero_of_coefficientField_isTotallyReal f hK), + fun hself ↦ coefficientField_isTotallyReal_of_forall_complexEmbedding_coeff_im_eq_zero f + (complexEmbedding_coeff_im_eq_zero_of_isSelfDual f hself)⟩ + +/-- A newform's coefficient field is CM if and only if the newform is not self-dual. -/ +theorem coefficientField_isCM_iff_not_isSelfDual (f : Newform N k) : + NumberField.IsCMField f.coefficientField ↔ ¬ ModularFormClass.isSelfDual f.toCuspForm := by + sorry + +end Newform + +end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic copy.lean b/projects/LeanModularForms/LeanModularForms/Issues/Issue55.lean similarity index 54% rename from projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic copy.lean rename to projects/LeanModularForms/LeanModularForms/Issues/Issue55.lean index e3573a51b..f289a7ab6 100644 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic copy.lean +++ b/projects/LeanModularForms/LeanModularForms/Issues/Issue55.lean @@ -1,9 +1,9 @@ import Mathlib + import LeanModularForms.HeckeRIngs.GL2.Gamma1Pair import LeanModularForms.HeckeRIngs.GL2.Newforms -open ModularForm UpperHalfPlane MatrixGroups ComplexConjugate -open CongruenceSubgroup Pointwise Subgroup +open ModularForm UpperHalfPlane MatrixGroups ComplexConjugate CongruenceSubgroup Pointwise Subgroup variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} @@ -11,6 +11,12 @@ variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ +private lemma J_mul_self : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by + simpa [sq] using UpperHalfPlane.J_sq + +private lemma J_inv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := + inv_eq_of_mul_eq_one_right J_mul_self + namespace Subgroup open Matrix.GeneralLinearGroup @@ -18,9 +24,7 @@ open Matrix.GeneralLinearGroup /-- Conjugation by `J` sends `upperRightHom x` to `upperRightHom (-x)`. -/ theorem dual_upperRightHom (x : ℝ) : ConjAct.toConjAct UpperHalfPlane.J • upperRightHom x = upperRightHom (-x) := by - have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := - inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq - rw [ConjAct.toConjAct_smul, hJinv] + rw [ConjAct.toConjAct_smul, J_inv] ext i j fin_cases i <;> fin_cases j <;> norm_num [UpperHalfPlane.J, Matrix.GeneralLinearGroup.upperRightHom, Matrix.mul_apply, @@ -30,32 +34,31 @@ theorem dual_upperRightHom (x : ℝ) : theorem dual_strictPeriods_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : (Subgroup.dual Γ).strictPeriods = Γ.strictPeriods := by ext x - simp only [Subgroup.mem_strictPeriods_iff, Subgroup.dual, - Subgroup.mem_pointwise_smul_iff_inv_smul_mem, map_inv, inv_inv, dual_upperRightHom] - simpa using (Subgroup.inv_mem_iff (H := Γ) (x := upperRightHom x)) + simp only [mem_strictPeriods_iff, Subgroup.dual, mem_pointwise_smul_iff_inv_smul_mem, + map_inv, inv_inv, dual_upperRightHom] + simpa using (Subgroup.inv_mem_iff Γ (x := upperRightHom x)) end Subgroup /-- A subgroup is self-dual when it equals its own dual. -/ class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where - /-- A self-dual subgroup equals its own dual. -/ isSelfDual : Subgroup.dual Γ = Γ +/-- Example: the trivial subgroup is self-dual. -/ instance : Subgroup.IsSelfDual (⊥ : Subgroup (GL (Fin 2) ℝ)) where isSelfDual := by simp [Subgroup.dual] -/-- The dual of a modular form is its translate by `J`. -/ -noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := +/-- The dual of a modular-form-like object is its translate by `J`. -/ +noncomputable def ModularFormClass.dual {F : Type*} [FunLike F UpperHalfPlane ℂ] + [ModularFormClass F Γ k] (f : F) : ModularForm (Subgroup.dual Γ) k := ModularForm.translate f UpperHalfPlane.J -/-- A modular form is self-dual when it equals its own dual. -/ -noncomputable def ModularForm.isSelfDual (f : ModularForm Γ k) : Prop := - ⇑(ModularForm.dual f) = ⇑f - -/-- A cusp form is self-dual when its underlying modular form is self-dual. -/ -def IsSelfDual (f : CuspForm Γ k) : Prop := - ModularForm.isSelfDual f.toModularForm' +/-- A modular-form-like object is self-dual when it equals its own dual. -/ +def ModularFormClass.isSelfDual {F : Type*} [FunLike F UpperHalfPlane ℂ] + [ModularFormClass F Γ k] (f : F) : Prop := + ⇑(ModularFormClass.dual f) = ⇑f +/-- Transporting a modular form along an equality of subgroups leaves its coercion unchanged. -/ theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by cases h @@ -65,7 +68,7 @@ open Classical in /-- Dualising a subgroup preserves the strict width of the cusp `∞`. -/ theorem Subgroup.dual_width_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : strictWidthInfty (Subgroup.dual Γ) = strictWidthInfty Γ := - congrArg (fun H : AddSubgroup ℝ => + congrArg (fun H : AddSubgroup ℝ ↦ if h : DiscreteTopology H then |Exists.choose <| H.isAddCyclic_iff_exists_zmultiples_eq_top.mp <| AddSubgroup.discrete_iff_addCyclic.mpr h| @@ -82,14 +85,18 @@ private lemma qParam_J_smul (h : ℝ) (z : UpperHalfPlane) : simp [Function.Periodic.qParam, UpperHalfPlane.coe_J_smul, ← Complex.exp_conj, map_ofNat] /-- `f.dual` at `z` equals the complex conjugate of `f` at `ofComplex (-conj z)`. -/ -theorem ModularForm.dual_explicit (f : ModularForm Γ k) (z : UpperHalfPlane) : - ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by - change (⇑f ∣[(k : ℤ)] UpperHalfPlane.J) z = conj (f (ofComplex (-(conj (z : ℂ))))) +theorem ModularFormClass.dual_explicit {F : Type*} [FunLike F UpperHalfPlane ℂ] + [ModularFormClass F Γ k] (f : F) (z : UpperHalfPlane) : + ModularFormClass.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by + change (⇑(f : ModularForm Γ k) ∣[(k : ℤ)] UpperHalfPlane.J) z = + conj (f (ofComplex (-(conj (z : ℂ))))) simp [ModularForm.slash_apply, UpperHalfPlane.J_smul] -private lemma hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) (z : UpperHalfPlane) : +private lemma hasSum_qExpansion_dual [Γ.IsArithmetic] {F : Type*} [FunLike F UpperHalfPlane ℂ] + [ModularFormClass F Γ k] (f : F) (z : UpperHalfPlane) : HasSum (fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m) • - Function.Periodic.qParam (strictWidthInfty Γ) (z : ℂ) ^ m) (ModularForm.dual f z) := by + Function.Periodic.qParam (strictWidthInfty Γ) (z : ℂ) ^ m) + (ModularFormClass.dual f z) := by have hf : HasSum (fun m : ℕ ↦ (qExpansion (strictWidthInfty Γ) f).coeff m • Function.Periodic.qParam (strictWidthInfty Γ) ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) ^ m) (f (UpperHalfPlane.J • z)) := @@ -102,74 +109,78 @@ private lemma hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) (z (x := f (UpperHalfPlane.J • z))).mpr hf using 1 · ext m simp [qParam_J_smul, smul_eq_mul] - · simp [ModularForm.dual_explicit, UpperHalfPlane.J_smul] + · simp [ModularFormClass.dual_explicit, UpperHalfPlane.J_smul] /-- The `q`-expansion coefficients of the dual are the complex conjugates of the original's. -/ -theorem ModularForm.qExpansion_dual_coefficient [Γ.IsArithmetic] (f : ModularForm Γ k) (n : ℕ) : - (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = - conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := by - exact (ModularFormClass.qExpansion_coeff_unique (Γ := Subgroup.dual Γ) +theorem ModularFormClass.qExpansion_dual_coefficient [Γ.IsArithmetic] {F : Type*} + [FunLike F UpperHalfPlane ℂ] [ModularFormClass F Γ k] (f : F) (n : ℕ) : + (qExpansion (strictWidthInfty Γ) (ModularFormClass.dual f)).coeff n = + conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := + (ModularFormClass.qExpansion_coeff_unique (Γ := Subgroup.dual Γ) (c := fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m)) Γ.strictWidthInfty_pos (strictWidthInfty_mem_dual_strictPeriods Γ) (hasSum_qExpansion_dual f) n).symm -private lemma im_coeff_eq_zero_of_isSelfDual [Γ.IsArithmetic] (f : ModularForm Γ k) - (hself : ModularForm.isSelfDual f) (n : ℕ) : +private lemma im_coeff_eq_zero_of_isSelfDual [Γ.IsArithmetic] {F : Type*} + [FunLike F UpperHalfPlane ℂ] [ModularFormClass F Γ k] (f : F) + (hself : ModularFormClass.isSelfDual f) (n : ℕ) : ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := by - have hcoeff : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + have hcoeff : (qExpansion (strictWidthInfty Γ) (ModularFormClass.dual f)).coeff n = conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := - ModularForm.qExpansion_dual_coefficient f n - have hsame : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = + ModularFormClass.qExpansion_dual_coefficient f n + have hsame : (qExpansion (strictWidthInfty Γ) (ModularFormClass.dual f)).coeff n = (qExpansion (strictWidthInfty Γ) f).coeff n := by - simpa [ModularForm.isSelfDual] using + simpa [ModularFormClass.isSelfDual] using congrArg (fun g : UpperHalfPlane → ℂ ↦ (qExpansion (strictWidthInfty Γ) g).coeff n) hself rw [hsame] at hcoeff exact Complex.conj_eq_iff_im.mp hcoeff.symm -private lemma isSelfDual_of_forall_im_coeff_eq_zero [Γ.IsArithmetic] (f : ModularForm Γ k) +private lemma isSelfDual_of_forall_im_coeff_eq_zero [Γ.IsArithmetic] {F : Type*} + [FunLike F UpperHalfPlane ℂ] [ModularFormClass F Γ k] (f : F) (hreal : ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0) : - ModularForm.isSelfDual f := by + ModularFormClass.isSelfDual f := by have hh : 0 < strictWidthInfty Γ := Γ.strictWidthInfty_pos have hΓ : strictWidthInfty Γ ∈ Γ.strictPeriods := Γ.strictWidthInfty_mem_strictPeriods have hdualΓ : strictWidthInfty Γ ∈ (Subgroup.dual Γ).strictPeriods := strictWidthInfty_mem_dual_strictPeriods Γ - have hqeq : qExpansion (strictWidthInfty Γ) (ModularForm.dual f) = + have hqeq : qExpansion (strictWidthInfty Γ) (ModularFormClass.dual f) = qExpansion (strictWidthInfty Γ) f := by ext n - calc - (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n - = conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := - ModularForm.qExpansion_dual_coefficient f n - _ = (qExpansion (strictWidthInfty Γ) f).coeff n := - Complex.conj_eq_iff_im.mpr (hreal n) + exact (ModularFormClass.qExpansion_dual_coefficient f n).trans + (Complex.conj_eq_iff_im.mpr (hreal n)) have hqsub : - qExpansion (strictWidthInfty Γ) (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := by + qExpansion (strictWidthInfty Γ) + (⇑(ModularFormClass.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := by rw [UpperHalfPlane.qExpansion_sub - (ModularFormClass.analyticAt_cuspFunction_zero (ModularForm.dual f) hh hdualΓ) + (ModularFormClass.analyticAt_cuspFunction_zero (ModularFormClass.dual f) hh hdualΓ) (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ), hqeq, sub_self] have hper : Function.Periodic - ((⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) ∘ ofComplex) (strictWidthInfty Γ) := by + ((⇑(ModularFormClass.dual f) - ⇑f : UpperHalfPlane → ℂ) ∘ ofComplex) + (strictWidthInfty Γ) := by intro z simpa only [Function.comp_apply, Pi.sub_apply] using congrArg₂ (fun a b : ℂ ↦ a - b) - (SlashInvariantFormClass.periodic_comp_ofComplex (ModularForm.dual f) hdualΓ z) + (SlashInvariantFormClass.periodic_comp_ofComplex (ModularFormClass.dual f) hdualΓ z) (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ z) - have hbdd : IsBoundedAtImInfty (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) := by + have hbdd : IsBoundedAtImInfty + (⇑(ModularFormClass.dual f) - ⇑f : UpperHalfPlane → ℂ) := by have : Fact (IsCusp OnePoint.infty (Subgroup.dual Γ)) := ⟨(Subgroup.dual Γ).isCusp_of_mem_strictPeriods hh hdualΓ⟩ change Filter.BoundedAtFilter UpperHalfPlane.atImInfty - (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) + (⇑(ModularFormClass.dual f) - ⇑f : UpperHalfPlane → ℂ) simpa [sub_eq_add_neg] using - (ModularFormClass.bdd_at_infty (ModularForm.dual f)).add + (ModularFormClass.bdd_at_infty (ModularFormClass.dual f)).add (ModularFormClass.bdd_at_infty f).neg - have hzero : (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := + have hzero : (⇑(ModularFormClass.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := (UpperHalfPlane.qExpansion_eq_zero_iff hh hper - ((ModularFormClass.holo (ModularForm.dual f)).sub (ModularFormClass.holo f)) hbdd).mp hqsub + ((ModularFormClass.holo (ModularFormClass.dual f)).sub (ModularFormClass.holo f)) + hbdd).mp hqsub exact funext fun z ↦ sub_eq_zero.mp (congrFun hzero z) -/-- A modular form is self-dual iff all its `q`-expansion coefficients are real. -/ -theorem ModularForm.isSelfDual_iff [Γ.IsArithmetic] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ +/-- A modular-form-like object is self-dual iff all its `q`-expansion coefficients are real. -/ +theorem ModularFormClass.isSelfDual_iff [Γ.IsArithmetic] {F : Type*} + [FunLike F UpperHalfPlane ℂ] [ModularFormClass F Γ k] (f : F) : + ModularFormClass.isSelfDual f ↔ ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := ⟨im_coeff_eq_zero_of_isSelfDual f, isSelfDual_of_forall_im_coeff_eq_zero f⟩ @@ -177,7 +188,7 @@ section Nebentypus open Matrix.SpecialLinearGroup HeckeRing.GL2 -abbrev Γ₁ (N : ℕ): Subgroup (GL (Fin 2) ℝ) := (Gamma1 N).map (mapGL ℝ) +abbrev Γ₁ (N : ℕ) : Subgroup (GL (Fin 2) ℝ) := (Gamma1 N).map (mapGL ℝ) private def conjugateByJ (γ : SL(2, ℤ)) : SL(2, ℤ) where val := !![γ 0 0, -γ 0 1; -γ 1 0, γ 1 1] @@ -197,9 +208,8 @@ private lemma conjugateByJ_mem_Gamma0 {γ : SL(2, ℤ)} (hγ : γ ∈ Gamma0 N) simpa [conjugateByJ] using hγ private lemma Gamma0MapUnits_conjugateByJ (γ : ↥(Gamma0 N)) : - Gamma0MapUnits (⟨conjugateByJ (γ : SL(2, ℤ)), - conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ : ↥(Gamma0 N)) = - Gamma0MapUnits γ := by + Gamma0MapUnits (⟨conjugateByJ (γ : SL(2, ℤ)), conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ : + ↥(Gamma0 N)) = Gamma0MapUnits γ := by ext simp [Gamma0MapUnits_val, Gamma0Map, conjugateByJ] @@ -213,24 +223,12 @@ private lemma mapGL_conjugateByJ (γ : SL(2, ℤ)) : private lemma J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J (γ : SL(2, ℤ)) : UpperHalfPlane.J * mapGL ℝ γ = mapGL ℝ (conjugateByJ γ) * UpperHalfPlane.J := by - have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by - simpa [sq] using UpperHalfPlane.J_sq - rw [mapGL_conjugateByJ] - calc - UpperHalfPlane.J * mapGL ℝ γ = UpperHalfPlane.J * mapGL ℝ γ * 1 := by rw [mul_one] - _ = UpperHalfPlane.J * mapGL ℝ γ * (UpperHalfPlane.J * UpperHalfPlane.J) := by - rw [hJmul] - _ = (UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J) * UpperHalfPlane.J := by - group + rw [mapGL_conjugateByJ, mul_assoc, mul_assoc, J_mul_self, mul_one] /-- `Γ₁(N)`, viewed inside `GL(2, ℝ)`, is self-dual. -/ instance CongruenceSubgroup.isSelfDual_Gamma1_map (N : ℕ) : Subgroup.IsSelfDual (Γ₁ N) where isSelfDual := by - have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := - inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq - have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by - simpa [sq] using UpperHalfPlane.J_sq rw [Subgroup.dual, Γ₁] ext y simp only [Subgroup.mem_pointwise_smul_iff_inv_smul_mem, ConjAct.smul_def, @@ -238,101 +236,49 @@ instance CongruenceSubgroup.isSelfDual_Gamma1_map (N : ℕ) : constructor · rintro ⟨σ, hσ, hσy⟩ refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ - rw [mapGL_conjugateByJ, hσy] - rw [hJinv] + rw [mapGL_conjugateByJ, hσy, J_inv] calc - UpperHalfPlane.J * (UpperHalfPlane.J * y * UpperHalfPlane.J) * UpperHalfPlane.J = - (UpperHalfPlane.J * UpperHalfPlane.J) * y * - (UpperHalfPlane.J * UpperHalfPlane.J) := by group - _ = y := by simp [hJmul] + _ = (UpperHalfPlane.J * UpperHalfPlane.J) * y * (UpperHalfPlane.J * UpperHalfPlane.J) := by group + _ = y := by simp [J_mul_self] · rintro ⟨σ, hσ, rfl⟩ refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ rw [mapGL_conjugateByJ] - simp [hJinv] + simp [J_inv] /-- The complex conjugate of a `ℂˣ`-valued character. -/ def MonoidHom.conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : G →* ℂˣ := (Units.map (starRingEnd ℂ).toMonoidHom).comp χ +/-- Conjugating a character twice recovers the original. -/ @[simp] theorem MonoidHom.conjChar_conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : MonoidHom.conjChar (MonoidHom.conjChar χ) = χ := by ext g simp [MonoidHom.conjChar] -namespace ModularForm +namespace ModularFormClass -theorem dual_mem_range_modFormCharSpace_inclusion_conjChar {N : ℕ} [NeZero N] - (χ : (ZMod N)ˣ →* ℂˣ) (f : modFormCharSpace (N := N) k χ) : - ((Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ ModularForm.dual f : - ModularForm (Γ₁ N) k)) ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) := by - let F : ModularForm (Γ₁ N) k := - (Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ - ModularForm.dual (f : ModularForm (Γ₁ N) k)) +/-- The dual of a modular form with nebentypus `χ` has nebentypus the conjugate character. -/ +theorem dual_mem_range_modFormCharSpace_inclusion_conjChar {N : ℕ} [NeZero N] (χ : (ZMod N)ˣ →* ℂˣ) + (f : modFormCharSpace (N := N) k χ) : ((Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ ModularFormClass.dual + (f : ModularForm (Γ₁ N) k) : ModularForm (Γ₁ N) k)) ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) := by + let F : ModularForm (Γ₁ N) k := (Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ + ModularFormClass.dual (f : ModularForm (Γ₁ N) k)) change F ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) rw [modFormCharSpace_iff_nebentypus] intro γ - let γJ : ↥(Gamma0 N) := ⟨conjugateByJ (γ : SL(2, ℤ)), - conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ - have hf := - (modFormCharSpace_iff_nebentypus k χ (f : ModularForm (Γ₁ N) k)).mp f.property γJ - have hF : - ⇑F = ⇑(ModularForm.dual (f : ModularForm (Γ₁ N) k)) := + let γJ : ↥(Gamma0 N) := ⟨conjugateByJ (γ : SL(2, ℤ)), conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ + have hf := (modFormCharSpace_iff_nebentypus k χ (f : ModularForm (Γ₁ N) k)).mp f.property γJ + have hF : ⇑F = ⇑(ModularFormClass.dual (f : ModularForm (Γ₁ N) k)) := ModularForm.coe_cast_group _ _ rw [hF] change (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) ∣[k] - (mapGL ℝ (γ : SL(2, ℤ))) = - (↑(MonoidHom.conjChar χ (Gamma0MapUnits γ)) : ℂ) • + (mapGL ℝ (γ : SL(2, ℤ))) = (↑(MonoidHom.conjChar χ (Gamma0MapUnits γ)) : ℂ) • (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) rw [← SlashAction.slash_mul, J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J, SlashAction.slash_mul, hf, Gamma0MapUnits_conjugateByJ, ModularForm.smul_slash] simp [MonoidHom.conjChar] -end ModularForm +end ModularFormClass end Nebentypus - -variable {N : ℕ} [NeZero N] {k : ℤ} - -open HeckeRing.GL2 - -namespace HeckeRing.GL2 - -namespace Newform - -/-- The coefficient field `ℚ(a_n : n ≥ 1)` of a newform. -/ -noncomputable def coefficientField (f : Newform N k) : IntermediateField ℚ ℂ := - IntermediateField.adjoin ℚ - (Set.range fun n : ℕ+ => (qExpansion (1 : ℝ) f.toCuspForm).coeff n) - -/-- The coefficient field of a newform is finite-dimensional over `ℚ`. -/ -theorem coefficientField_finiteDimensional (f : Newform N k) : - FiniteDimensional ℚ f.coefficientField := by - sorry - -/-- The coefficient field of a newform is a number field. -/ -theorem coefficientField_numberField (f : Newform N k) : - NumberField f.coefficientField := by - sorry - -/-- The relative dimension attached to a newform. -/ -noncomputable def relativeDimension (f : Newform N k) : ℕ := - Module.finrank ℚ f.coefficientField - -theorem coefficientField_degree_eq_relativeDimension (f : Newform N k) : - Module.finrank ℚ f.coefficientField = f.relativeDimension := by - sorry - -/-- A newform's coefficient field is totally real if and only if the newform is self-dual. -/ -theorem coefficientField_isTotallyReal_iff_isSelfDual (f : Newform N k) : - NumberField.IsTotallyReal f.coefficientField ↔ IsSelfDual f.toCuspForm := by - sorry - -/-- A newform's coefficient field is CM if and only if the newform is not self-dual. -/ -theorem coefficientField_isCM_iff_not_isSelfDual (f : Newform N k) : - NumberField.IsCMField f.coefficientField ↔ ¬ IsSelfDual f.toCuspForm := by - sorry - -end Newform - -end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean deleted file mode 100644 index a482afef4..000000000 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual.lean +++ /dev/null @@ -1,35 +0,0 @@ -import Mathlib - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise - Subgroup -open UpperHalfPlane hiding I - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := - (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ - -/-- `Γ` is self-dual when it is fixed by conjugation by `J`. -/ -class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where - self_dual : Subgroup.dual Γ = Γ - -noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := - ModularForm.translate f UpperHalfPlane.J - -def ModularForm.isSelfDual (f : ModularForm Γ k) : Prop := - ⇑(ModularForm.dual f) = ⇑f - - - - - - - -theorem Subgroup.dual_width_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : - strictWidthInfty (Subgroup.dual Γ) = strictWidthInfty Γ := by - sorry - -theorem ModularForm.isSelfDual_iff (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ - ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := by - sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean deleted file mode 100644 index e3573a51b..000000000 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Basic.lean +++ /dev/null @@ -1,338 +0,0 @@ -import Mathlib -import LeanModularForms.HeckeRIngs.GL2.Gamma1Pair -import LeanModularForms.HeckeRIngs.GL2.Newforms - -open ModularForm UpperHalfPlane MatrixGroups ComplexConjugate -open CongruenceSubgroup Pointwise Subgroup - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -/-- The dual of a subgroup of `GL (Fin 2) ℝ` is its conjugate by `J⁻¹`. -/ -noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := - (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ - -namespace Subgroup - -open Matrix.GeneralLinearGroup - -/-- Conjugation by `J` sends `upperRightHom x` to `upperRightHom (-x)`. -/ -theorem dual_upperRightHom (x : ℝ) : - ConjAct.toConjAct UpperHalfPlane.J • upperRightHom x = upperRightHom (-x) := by - have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := - inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq - rw [ConjAct.toConjAct_smul, hJinv] - ext i j - fin_cases i <;> fin_cases j <;> - norm_num [UpperHalfPlane.J, Matrix.GeneralLinearGroup.upperRightHom, Matrix.mul_apply, - Fin.sum_univ_two] - -/-- Dualising a subgroup preserves its strict periods. -/ -theorem dual_strictPeriods_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : - (Subgroup.dual Γ).strictPeriods = Γ.strictPeriods := by - ext x - simp only [Subgroup.mem_strictPeriods_iff, Subgroup.dual, - Subgroup.mem_pointwise_smul_iff_inv_smul_mem, map_inv, inv_inv, dual_upperRightHom] - simpa using (Subgroup.inv_mem_iff (H := Γ) (x := upperRightHom x)) - -end Subgroup - -/-- A subgroup is self-dual when it equals its own dual. -/ -class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where - /-- A self-dual subgroup equals its own dual. -/ - isSelfDual : Subgroup.dual Γ = Γ - -instance : Subgroup.IsSelfDual (⊥ : Subgroup (GL (Fin 2) ℝ)) where - isSelfDual := by simp [Subgroup.dual] - -/-- The dual of a modular form is its translate by `J`. -/ -noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := - ModularForm.translate f UpperHalfPlane.J - -/-- A modular form is self-dual when it equals its own dual. -/ -noncomputable def ModularForm.isSelfDual (f : ModularForm Γ k) : Prop := - ⇑(ModularForm.dual f) = ⇑f - -/-- A cusp form is self-dual when its underlying modular form is self-dual. -/ -def IsSelfDual (f : CuspForm Γ k) : Prop := - ModularForm.isSelfDual f.toModularForm' - -theorem ModularForm.coe_cast_group {Γ Γ' : Subgroup (GL (Fin 2) ℝ)} - (h : Γ = Γ') (f : ModularForm Γ k) : ⇑(h ▸ f : ModularForm Γ' k) = ⇑f := by - cases h - rfl - -open Classical in -/-- Dualising a subgroup preserves the strict width of the cusp `∞`. -/ -theorem Subgroup.dual_width_eq (Γ : Subgroup (GL (Fin 2) ℝ)) : - strictWidthInfty (Subgroup.dual Γ) = strictWidthInfty Γ := - congrArg (fun H : AddSubgroup ℝ => - if h : DiscreteTopology H then - |Exists.choose <| H.isAddCyclic_iff_exists_zmultiples_eq_top.mp - <| AddSubgroup.discrete_iff_addCyclic.mpr h| - else 0) (Subgroup.dual_strictPeriods_eq Γ) - -private lemma strictWidthInfty_mem_dual_strictPeriods (Γ : Subgroup (GL (Fin 2) ℝ)) - [Γ.IsArithmetic] : strictWidthInfty Γ ∈ (Subgroup.dual Γ).strictPeriods := by - rw [← Subgroup.dual_width_eq Γ] - exact (Subgroup.dual Γ).strictWidthInfty_mem_strictPeriods - -private lemma qParam_J_smul (h : ℝ) (z : UpperHalfPlane) : - Function.Periodic.qParam h ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) = - conj (Function.Periodic.qParam h (z : ℂ)) := by - simp [Function.Periodic.qParam, UpperHalfPlane.coe_J_smul, ← Complex.exp_conj, map_ofNat] - -/-- `f.dual` at `z` equals the complex conjugate of `f` at `ofComplex (-conj z)`. -/ -theorem ModularForm.dual_explicit (f : ModularForm Γ k) (z : UpperHalfPlane) : - ModularForm.dual f z = conj (f (ofComplex (-(conj (z : ℂ))))) := by - change (⇑f ∣[(k : ℤ)] UpperHalfPlane.J) z = conj (f (ofComplex (-(conj (z : ℂ))))) - simp [ModularForm.slash_apply, UpperHalfPlane.J_smul] - -private lemma hasSum_qExpansion_dual [Γ.IsArithmetic] (f : ModularForm Γ k) (z : UpperHalfPlane) : - HasSum (fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m) • - Function.Periodic.qParam (strictWidthInfty Γ) (z : ℂ) ^ m) (ModularForm.dual f z) := by - have hf : HasSum (fun m : ℕ ↦ (qExpansion (strictWidthInfty Γ) f).coeff m • - Function.Periodic.qParam (strictWidthInfty Γ) - ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) ^ m) (f (UpperHalfPlane.J • z)) := - UpperHalfPlane.hasSum_qExpansion Γ.strictWidthInfty_pos - (SlashInvariantFormClass.periodic_comp_ofComplex f Γ.strictWidthInfty_mem_strictPeriods) - (ModularFormClass.holo f) (ModularFormClass.bdd_at_infty f) (UpperHalfPlane.J • z) - convert (Complex.hasSum_conj' (f := fun m : ℕ ↦ - (qExpansion (strictWidthInfty Γ) f).coeff m • Function.Periodic.qParam (strictWidthInfty Γ) - ((UpperHalfPlane.J • z : UpperHalfPlane) : ℂ) ^ m) - (x := f (UpperHalfPlane.J • z))).mpr hf using 1 - · ext m - simp [qParam_J_smul, smul_eq_mul] - · simp [ModularForm.dual_explicit, UpperHalfPlane.J_smul] - -/-- The `q`-expansion coefficients of the dual are the complex conjugates of the original's. -/ -theorem ModularForm.qExpansion_dual_coefficient [Γ.IsArithmetic] (f : ModularForm Γ k) (n : ℕ) : - (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = - conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := by - exact (ModularFormClass.qExpansion_coeff_unique (Γ := Subgroup.dual Γ) - (c := fun m : ℕ ↦ conj ((qExpansion (strictWidthInfty Γ) f).coeff m)) - Γ.strictWidthInfty_pos (strictWidthInfty_mem_dual_strictPeriods Γ) - (hasSum_qExpansion_dual f) n).symm - -private lemma im_coeff_eq_zero_of_isSelfDual [Γ.IsArithmetic] (f : ModularForm Γ k) - (hself : ModularForm.isSelfDual f) (n : ℕ) : - ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := by - have hcoeff : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = - conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := - ModularForm.qExpansion_dual_coefficient f n - have hsame : (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n = - (qExpansion (strictWidthInfty Γ) f).coeff n := by - simpa [ModularForm.isSelfDual] using - congrArg (fun g : UpperHalfPlane → ℂ ↦ (qExpansion (strictWidthInfty Γ) g).coeff n) hself - rw [hsame] at hcoeff - exact Complex.conj_eq_iff_im.mp hcoeff.symm - -private lemma isSelfDual_of_forall_im_coeff_eq_zero [Γ.IsArithmetic] (f : ModularForm Γ k) - (hreal : ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0) : - ModularForm.isSelfDual f := by - have hh : 0 < strictWidthInfty Γ := Γ.strictWidthInfty_pos - have hΓ : strictWidthInfty Γ ∈ Γ.strictPeriods := Γ.strictWidthInfty_mem_strictPeriods - have hdualΓ : strictWidthInfty Γ ∈ (Subgroup.dual Γ).strictPeriods := - strictWidthInfty_mem_dual_strictPeriods Γ - have hqeq : qExpansion (strictWidthInfty Γ) (ModularForm.dual f) = - qExpansion (strictWidthInfty Γ) f := by - ext n - calc - (qExpansion (strictWidthInfty Γ) (ModularForm.dual f)).coeff n - = conj ((qExpansion (strictWidthInfty Γ) f).coeff n) := - ModularForm.qExpansion_dual_coefficient f n - _ = (qExpansion (strictWidthInfty Γ) f).coeff n := - Complex.conj_eq_iff_im.mpr (hreal n) - have hqsub : - qExpansion (strictWidthInfty Γ) (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := by - rw [UpperHalfPlane.qExpansion_sub - (ModularFormClass.analyticAt_cuspFunction_zero (ModularForm.dual f) hh hdualΓ) - (ModularFormClass.analyticAt_cuspFunction_zero f hh hΓ), hqeq, sub_self] - have hper : Function.Periodic - ((⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) ∘ ofComplex) (strictWidthInfty Γ) := by - intro z - simpa only [Function.comp_apply, Pi.sub_apply] using - congrArg₂ (fun a b : ℂ ↦ a - b) - (SlashInvariantFormClass.periodic_comp_ofComplex (ModularForm.dual f) hdualΓ z) - (SlashInvariantFormClass.periodic_comp_ofComplex f hΓ z) - have hbdd : IsBoundedAtImInfty (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) := by - have : Fact (IsCusp OnePoint.infty (Subgroup.dual Γ)) := - ⟨(Subgroup.dual Γ).isCusp_of_mem_strictPeriods hh hdualΓ⟩ - change Filter.BoundedAtFilter UpperHalfPlane.atImInfty - (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) - simpa [sub_eq_add_neg] using - (ModularFormClass.bdd_at_infty (ModularForm.dual f)).add - (ModularFormClass.bdd_at_infty f).neg - have hzero : (⇑(ModularForm.dual f) - ⇑f : UpperHalfPlane → ℂ) = 0 := - (UpperHalfPlane.qExpansion_eq_zero_iff hh hper - ((ModularFormClass.holo (ModularForm.dual f)).sub (ModularFormClass.holo f)) hbdd).mp hqsub - exact funext fun z ↦ sub_eq_zero.mp (congrFun hzero z) - -/-- A modular form is self-dual iff all its `q`-expansion coefficients are real. -/ -theorem ModularForm.isSelfDual_iff [Γ.IsArithmetic] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ - ∀ n, ((qExpansion (strictWidthInfty Γ) f).coeff n).im = 0 := - ⟨im_coeff_eq_zero_of_isSelfDual f, isSelfDual_of_forall_im_coeff_eq_zero f⟩ - -section Nebentypus - -open Matrix.SpecialLinearGroup HeckeRing.GL2 - -abbrev Γ₁ (N : ℕ): Subgroup (GL (Fin 2) ℝ) := (Gamma1 N).map (mapGL ℝ) - -private def conjugateByJ (γ : SL(2, ℤ)) : SL(2, ℤ) where - val := !![γ 0 0, -γ 0 1; -γ 1 0, γ 1 1] - property := by - have hdet : γ.val.det = 1 := γ.property - rw [Matrix.det_fin_two] at hdet - simpa [Matrix.det_fin_two] using hdet - -private lemma conjugateByJ_mem_Gamma1_iff (γ : SL(2, ℤ)) : - conjugateByJ γ ∈ Gamma1 N ↔ γ ∈ Gamma1 N := by - rw [Gamma1_mem, Gamma1_mem] - simp [conjugateByJ] - -private lemma conjugateByJ_mem_Gamma0 {γ : SL(2, ℤ)} (hγ : γ ∈ Gamma0 N) : - conjugateByJ γ ∈ Gamma0 N := by - rw [Gamma0_mem] at hγ ⊢ - simpa [conjugateByJ] using hγ - -private lemma Gamma0MapUnits_conjugateByJ (γ : ↥(Gamma0 N)) : - Gamma0MapUnits (⟨conjugateByJ (γ : SL(2, ℤ)), - conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ : ↥(Gamma0 N)) = - Gamma0MapUnits γ := by - ext - simp [Gamma0MapUnits_val, Gamma0Map, conjugateByJ] - -private lemma mapGL_conjugateByJ (γ : SL(2, ℤ)) : - mapGL ℝ (conjugateByJ γ) = UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J := by - ext i j - fin_cases i <;> fin_cases j <;> - norm_num [conjugateByJ, UpperHalfPlane.J, Matrix.GeneralLinearGroup.coe_mul, - Matrix.mul_apply, Matrix.vecMul, dotProduct, Matrix.vecHead, Matrix.vecTail, - Fin.sum_univ_two] - -private lemma J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J (γ : SL(2, ℤ)) : - UpperHalfPlane.J * mapGL ℝ γ = mapGL ℝ (conjugateByJ γ) * UpperHalfPlane.J := by - have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by - simpa [sq] using UpperHalfPlane.J_sq - rw [mapGL_conjugateByJ] - calc - UpperHalfPlane.J * mapGL ℝ γ = UpperHalfPlane.J * mapGL ℝ γ * 1 := by rw [mul_one] - _ = UpperHalfPlane.J * mapGL ℝ γ * (UpperHalfPlane.J * UpperHalfPlane.J) := by - rw [hJmul] - _ = (UpperHalfPlane.J * mapGL ℝ γ * UpperHalfPlane.J) * UpperHalfPlane.J := by - group - -/-- `Γ₁(N)`, viewed inside `GL(2, ℝ)`, is self-dual. -/ -instance CongruenceSubgroup.isSelfDual_Gamma1_map (N : ℕ) : - Subgroup.IsSelfDual (Γ₁ N) where - isSelfDual := by - have hJinv : UpperHalfPlane.J⁻¹ = UpperHalfPlane.J := - inv_eq_of_mul_eq_one_right <| by simpa [sq] using UpperHalfPlane.J_sq - have hJmul : UpperHalfPlane.J * UpperHalfPlane.J = 1 := by - simpa [sq] using UpperHalfPlane.J_sq - rw [Subgroup.dual, Γ₁] - ext y - simp only [Subgroup.mem_pointwise_smul_iff_inv_smul_mem, ConjAct.smul_def, - ConjAct.ofConjAct_toConjAct, map_inv, inv_inv, Subgroup.mem_map] - constructor - · rintro ⟨σ, hσ, hσy⟩ - refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ - rw [mapGL_conjugateByJ, hσy] - rw [hJinv] - calc - UpperHalfPlane.J * (UpperHalfPlane.J * y * UpperHalfPlane.J) * UpperHalfPlane.J = - (UpperHalfPlane.J * UpperHalfPlane.J) * y * - (UpperHalfPlane.J * UpperHalfPlane.J) := by group - _ = y := by simp [hJmul] - · rintro ⟨σ, hσ, rfl⟩ - refine ⟨conjugateByJ σ, (conjugateByJ_mem_Gamma1_iff (N := N) σ).mpr hσ, ?_⟩ - rw [mapGL_conjugateByJ] - simp [hJinv] - -/-- The complex conjugate of a `ℂˣ`-valued character. -/ -def MonoidHom.conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : G →* ℂˣ := - (Units.map (starRingEnd ℂ).toMonoidHom).comp χ - -@[simp] -theorem MonoidHom.conjChar_conjChar {G : Type*} [Monoid G] (χ : G →* ℂˣ) : - MonoidHom.conjChar (MonoidHom.conjChar χ) = χ := by - ext g - simp [MonoidHom.conjChar] - -namespace ModularForm - -theorem dual_mem_range_modFormCharSpace_inclusion_conjChar {N : ℕ} [NeZero N] - (χ : (ZMod N)ˣ →* ℂˣ) (f : modFormCharSpace (N := N) k χ) : - ((Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ ModularForm.dual f : - ModularForm (Γ₁ N) k)) ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) := by - let F : ModularForm (Γ₁ N) k := - (Subgroup.IsSelfDual.isSelfDual (Γ := Γ₁ N) ▸ - ModularForm.dual (f : ModularForm (Γ₁ N) k)) - change F ∈ modFormCharSpace (N := N) k (MonoidHom.conjChar χ) - rw [modFormCharSpace_iff_nebentypus] - intro γ - let γJ : ↥(Gamma0 N) := ⟨conjugateByJ (γ : SL(2, ℤ)), - conjugateByJ_mem_Gamma0 (N := N) γ.property⟩ - have hf := - (modFormCharSpace_iff_nebentypus k χ (f : ModularForm (Γ₁ N) k)).mp f.property γJ - have hF : - ⇑F = ⇑(ModularForm.dual (f : ModularForm (Γ₁ N) k)) := - ModularForm.coe_cast_group _ _ - rw [hF] - change (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) ∣[k] - (mapGL ℝ (γ : SL(2, ℤ))) = - (↑(MonoidHom.conjChar χ (Gamma0MapUnits γ)) : ℂ) • - (⇑(f : ModularForm (Γ₁ N) k) ∣[k] UpperHalfPlane.J) - rw [← SlashAction.slash_mul, J_mul_mapGL_eq_mapGL_conjugateByJ_mul_J, - SlashAction.slash_mul, hf, Gamma0MapUnits_conjugateByJ, ModularForm.smul_slash] - simp [MonoidHom.conjChar] - -end ModularForm - -end Nebentypus - -variable {N : ℕ} [NeZero N] {k : ℤ} - -open HeckeRing.GL2 - -namespace HeckeRing.GL2 - -namespace Newform - -/-- The coefficient field `ℚ(a_n : n ≥ 1)` of a newform. -/ -noncomputable def coefficientField (f : Newform N k) : IntermediateField ℚ ℂ := - IntermediateField.adjoin ℚ - (Set.range fun n : ℕ+ => (qExpansion (1 : ℝ) f.toCuspForm).coeff n) - -/-- The coefficient field of a newform is finite-dimensional over `ℚ`. -/ -theorem coefficientField_finiteDimensional (f : Newform N k) : - FiniteDimensional ℚ f.coefficientField := by - sorry - -/-- The coefficient field of a newform is a number field. -/ -theorem coefficientField_numberField (f : Newform N k) : - NumberField f.coefficientField := by - sorry - -/-- The relative dimension attached to a newform. -/ -noncomputable def relativeDimension (f : Newform N k) : ℕ := - Module.finrank ℚ f.coefficientField - -theorem coefficientField_degree_eq_relativeDimension (f : Newform N k) : - Module.finrank ℚ f.coefficientField = f.relativeDimension := by - sorry - -/-- A newform's coefficient field is totally real if and only if the newform is self-dual. -/ -theorem coefficientField_isTotallyReal_iff_isSelfDual (f : Newform N k) : - NumberField.IsTotallyReal f.coefficientField ↔ IsSelfDual f.toCuspForm := by - sorry - -/-- A newform's coefficient field is CM if and only if the newform is not self-dual. -/ -theorem coefficientField_isCM_iff_not_isSelfDual (f : Newform N k) : - NumberField.IsCMField f.coefficientField ↔ ¬ IsSelfDual f.toCuspForm := by - sorry - -end Newform - -end HeckeRing.GL2 diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean deleted file mode 100644 index ef6810e10..000000000 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version1.lean +++ /dev/null @@ -1,50 +0,0 @@ -import LeanModularForms.Issues.SelfDual.Basic - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := - (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f - -theorem ModularForm.isSelfDual_iff_coe_dual_eq [Γ.IsSelfDual] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ ⇑(ModularForm.dual f) = ⇑f := by - sorry - -theorem ModularForm.isSelfDual_iff_apply [Γ.IsSelfDual] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ ∀ z, ModularForm.dual f z = f z := by - sorry - -@[simp] -theorem ModularForm.isSelfDual_zero [Γ.IsSelfDual] : - ModularForm.isSelfDual (0 : ModularForm Γ k) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual_add [Γ.IsSelfDual] {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : - ModularForm.isSelfDual (f + g) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual_neg [Γ.IsSelfDual] {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) : - ModularForm.isSelfDual (-f) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual_sub [Γ.IsSelfDual] {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) (hg : ModularForm.isSelfDual g) : - ModularForm.isSelfDual (f - g) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual_smul_real [Γ.IsSelfDual] (c : ℝ) {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual f) : - ModularForm.isSelfDual (c • f) := by - sorry - -theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ - ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean deleted file mode 100644 index f902f61c2..000000000 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual/Version2.lean +++ /dev/null @@ -1,46 +0,0 @@ -import LeanModularForms.Issues.SelfDual.Basic - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -def ModularForm.isSelfDual' (f : ModularForm Γ k) : Prop := - ⇑(ModularForm.dual f) = ⇑f - -theorem ModularForm.isSelfDual'_iff_apply (f : ModularForm Γ k) : - ModularForm.isSelfDual' f ↔ ∀ z, ModularForm.dual f z = f z := - ⟨fun h z => congrFun h z, fun h => funext h⟩ - -@[simp] -theorem ModularForm.isSelfDual'_zero : - ModularForm.isSelfDual' (0 : ModularForm Γ k) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual'_add {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : - ModularForm.isSelfDual' (f + g) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual'_neg {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) : - ModularForm.isSelfDual' (-f) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual'_sub {f g : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) (hg : ModularForm.isSelfDual' g) : - ModularForm.isSelfDual' (f - g) := by - sorry - -@[simp] -theorem ModularForm.isSelfDual'_smul_real (c : ℝ) {f : ModularForm Γ k} - (hf : ModularForm.isSelfDual' f) : - ModularForm.isSelfDual' (c • f) := by - sorry - -theorem ModularForm.isSelfDual_iff' [Γ.IsSelfDual] [Γ.IsArithmetic] (f : ModularForm Γ k) : - ModularForm.isSelfDual' f ↔ - ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - sorry diff --git a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual_old.lean b/projects/LeanModularForms/LeanModularForms/Issues/SelfDual_old.lean deleted file mode 100644 index c6ccbabd8..000000000 --- a/projects/LeanModularForms/LeanModularForms/Issues/SelfDual_old.lean +++ /dev/null @@ -1,41 +0,0 @@ -import Mathlib - -open CongruenceSubgroup Matrix.SpecialLinearGroup Complex MatrixGroups ModularForm Pointwise Subgroup - -variable {Γ : Subgroup (GL (Fin 2) ℝ)} {k : ℤ} - -noncomputable def Subgroup.dual (Γ : Subgroup (GL (Fin 2) ℝ)) : Subgroup (GL (Fin 2) ℝ) := - (ConjAct.toConjAct UpperHalfPlane.J⁻¹) • Γ - -/- -def Subgroup.isSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop := - Subgroup.dual Γ = Γ - -noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := - ModularForm.translate f UpperHalfPlane.J - -def ModularForm.isSelfDual [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : Prop := - ((Fact.out : Subgroup.isSelfDual Γ) ▸ ModularForm.dual f) = f - -theorem ModularForm.isSelfDual_iff [Fact (Subgroup.isSelfDual Γ)] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - sorry --/ - -/-- `Γ` is self-dual when it is fixed by conjugation by `J`. -/ -class Subgroup.IsSelfDual (Γ : Subgroup (GL (Fin 2) ℝ)) : Prop where - self_dual : Subgroup.dual Γ = Γ - -instance : Subgroup.IsSelfDual (⊥ : Subgroup (GL (Fin 2) ℝ)) where - self_dual := by simp [Subgroup.dual] - -noncomputable def ModularForm.dual (f : ModularForm Γ k) : ModularForm (Subgroup.dual Γ) k := - ModularForm.translate f UpperHalfPlane.J - -def ModularForm.isSelfDual [Γ.IsSelfDual] (f : ModularForm Γ k) : Prop := - (‹Γ.IsSelfDual›.self_dual ▸ ModularForm.dual f) = f - -theorem ModularForm.isSelfDual_iff [Γ.IsSelfDual] (f : ModularForm Γ k) : - ModularForm.isSelfDual f ↔ - ∀ n, ((UpperHalfPlane.qExpansion (Subgroup.strictWidthInfty Γ) f).coeff n).im = 0 := by - sorry