Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LeanBridge.lean
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import LeanBridge.Example
import LeanBridge.ForMathlib.AbstractHeckeRing
32 changes: 32 additions & 0 deletions LeanBridge/ForMathlib/AbstractHeckeRing.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/-
Copyright (c) 2024 Chris Birkbeck. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Birkbeck
-/
import LeanBridge.ForMathlib.AbstractHeckeRing.Basic
import LeanBridge.ForMathlib.AbstractHeckeRing.Multiplication
import LeanBridge.ForMathlib.AbstractHeckeRing.Associativity
import LeanBridge.ForMathlib.AbstractHeckeRing.Ring
import LeanBridge.ForMathlib.AbstractHeckeRing.Module
import LeanBridge.ForMathlib.AbstractHeckeRing.Commutativity
import LeanBridge.ForMathlib.AbstractHeckeRing.Degree
import LeanBridge.ForMathlib.AbstractHeckeRing.StabConjugation

/-!
# Abstract Hecke ring

The full construction of the abstract Hecke ring, following Shimura, *Introduction to the
Arithmetic Theory of Automorphic Functions*, Ch. 3. For an arithmetic pair `(H, Ξ”)`
(`H ≀ Ξ” ≀ commensurator(H)`), this assembles:

* `HeckeRing.HeckePair`, the double-coset quotient `HeckeRing.HeckeCoset`, and the Hecke ring
type `HeckeRing.𝕋` (`Basic`);
* the convolution product (`Multiplication`, `Associativity`) and the resulting `Ring`
structure (`Ring`);
* the Hecke module over the left cosets (`Module`);
* commutativity from an anti-involution (`Commutativity`), the degree map (`Degree`), and
stabilizer/conjugation lemmas (`StabConjugation`).

Ported from the AINTLIB project
(`projects/LeanModularForms/LeanModularForms/HeckeRIngs/AbstractHeckeRing`).
-/
749 changes: 749 additions & 0 deletions LeanBridge/ForMathlib/AbstractHeckeRing/Associativity.lean

Large diffs are not rendered by default.

345 changes: 345 additions & 0 deletions LeanBridge/ForMathlib/AbstractHeckeRing/Basic.lean

Large diffs are not rendered by default.

478 changes: 478 additions & 0 deletions LeanBridge/ForMathlib/AbstractHeckeRing/Commutativity.lean

Large diffs are not rendered by default.

284 changes: 284 additions & 0 deletions LeanBridge/ForMathlib/AbstractHeckeRing/Degree.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/-
Copyright (c) 2024 Chris Birkbeck. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Birkbeck
-/
import LeanBridge.ForMathlib.AbstractHeckeRing.Ring

/-!
# Hecke Rings: Degree Map

The degree ring homomorphism `deg : 𝕋 P β„€ β†’+* β„€`, which sends each
double coset `HgH` to the number of left cosets it contains:
`deg(HgH) = [H : H ∩ gHg⁻¹]`.

This is Shimura Β§3.1, Proposition 3.3.

## Main definitions

* `HeckeCoset_deg P D` : the degree of a single double coset
* `deg P` : the degree ring homomorphism `𝕋 P β„€ β†’+* β„€`

## Main results

* `deg_T_single` : `deg(T_single D a) = a * HeckeCoset_deg D`
* `HeckeCoset_deg_pos` : `0 < HeckeCoset_deg D`
* `deg_mul` : `deg(f * g) = deg f * deg g` (the degree map is multiplicative)

## Proof strategy

Multiplicativity `deg(f * g) = deg(f) * deg(g)` is proved using the module action
on `HeckeModule P β„€`.
We show `deg(f) = coeffSum(f β€’ 1)` where `coeffSum` sums all coefficients, and then use
`IsScalarTower` (Shimura Prop 3.4) to get `(f * g) β€’ 1 = g β€’ (f β€’ 1)`. The key intermediate
result is `coeffSum(f β€’ m) = deg(f) * coeffSum(m)`, which follows from the orbit cardinality
lemma `smulOrbit_card`.
-/

open Classical MulOpposite Set DoubleCoset Subgroup

open scoped Pointwise

namespace HeckeRing

variable {G : Type*} [Group G]
variable (P : HeckePair G)

open Finsupp

/-- The degree of a double coset: `deg(HgH) = [H : H ∩ gHg⁻¹]`, the number of left cosets
in the decomposition of `HgH`. -/
noncomputable def HeckeCoset_deg (D : HeckeCoset P) : β„€ :=
Fintype.card (decompQuot P (HeckeCoset.rep D))

/-- The degree of the identity double coset is 1. -/
@[simp] lemma HeckeCoset_deg_T_one : HeckeCoset_deg P (HeckeCoset.one P) = 1 := by
haveI := subsingleton_decompQuot_T_one P
haveI : Unique (decompQuot P (HeckeCoset.one P).rep) :=
uniqueOfSubsingleton (one_in_decompQuot_T_one P).some
simp [HeckeCoset_deg, Fintype.card_unique]

/-- Every double coset has positive degree. -/
lemma HeckeCoset_deg_pos (D : HeckeCoset P) : 0 < HeckeCoset_deg P D := by
unfold HeckeCoset_deg; exact_mod_cast Fintype.card_pos

section SmulOrbitCard

private lemma smulOrbit_map_inj (g : P.Ξ”) (Ξ² : P.Ξ”) :
Function.Injective (fun i : decompQuot P g ↦
(⟦⟨(β : G) * (i.out : G) * (g : G),
delta_mul_mem P.H P.Ξ” i.out Ξ² g P.hβ‚€βŸ©βŸ§ : HeckeLeftCoset P)) := by
intro i₁ iβ‚‚ heq
by_contra hne
have hset : ({(Ξ² : G) * (i₁.out : G) * (g : G)} : Set G) * (P.H : Set G) =
{(Ξ² : G) * (iβ‚‚.out : G) * (g : G)} * P.H := Quotient.exact heq
have hmem : (Ξ² : G) * (i₁.out : G) * (g : G) ∈
({(Ξ² : G) * (iβ‚‚.out : G) * (g : G)} : Set G) * (P.H : Set G) :=
hset β–Έ ⟨_, rfl, 1, P.H.one_mem, mul_one _⟩
obtain ⟨_, ha, k, hk, hkk⟩ := hmem
rw [Set.mem_singleton_iff] at ha; subst ha
have cancel : (iβ‚‚.out : G) * (g : G) * k = (i₁.out : G) * (g : G) := by
refine mul_left_cancel (a := (Ξ² : G)) ?_
have := hkk; group at this ⊒; exact this
refine decompQuot_coset_diff P g i₁ iβ‚‚ hne
(leftCoset_eq_of_not_disjoint (H := P.H) _ _ ?_)
rw [Set.not_disjoint_iff]
exact ⟨(i₁.out : G) * (g : G), ⟨1, P.H.one_mem, mul_one _⟩, ⟨k, hk, cancel⟩⟩

/-- The cardinality of a smul orbit equals the degree of the acting double coset. -/
lemma smulOrbit_card (g : P.Ξ”) (Ξ² : P.Ξ”) :
(smulOrbit P g Ξ²).card = Fintype.card (decompQuot P g) := by
show (Finset.image _ ⊀).card = _
rw [Finset.top_eq_univ]
convert (Finset.card_image_of_injective Finset.univ
(smulOrbit_map_inj P g Ξ²)).trans Finset.card_univ
rfl

/-- The cardinality of a smul orbit cast to `β„€` equals `HeckeCoset_deg`. -/
lemma smulOrbit_card_intCast (D : HeckeCoset P) (Ξ² : P.Ξ”) :
((smulOrbit P (HeckeCoset.rep D) Ξ²).card : β„€) = HeckeCoset_deg P D := by
simp [smulOrbit_card, HeckeCoset_deg]

end SmulOrbitCard

section CoeffSum

/-- The coefficient sum homomorphism: sums all coefficients of a formal linear combination
of left cosets. -/
noncomputable def coeffSum : HeckeModule P β„€ β†’+ β„€ :=
Finsupp.liftAddHom (fun _ : HeckeLeftCoset P ↦ AddMonoidHom.id β„€)

/-- The coefficient sum of a single basis element is its coefficient. -/
@[simp] lemma coeffSum_single (mβ‚€ : HeckeLeftCoset P) (b : β„€) :
coeffSum P (HeckeLeftCoset_single P β„€ mβ‚€ b) = b := Finsupp.liftAddHom_apply_single _ _ _

/-- The coefficient sum is additive. -/
lemma coeffSum_add (m₁ mβ‚‚ : HeckeModule P β„€) :
coeffSum P (m₁ + mβ‚‚) = coeffSum P m₁ + coeffSum P mβ‚‚ := map_add _ _ _

/-- The coefficient sum distributes over finite sums. -/
lemma coeffSum_finset_sum {ΞΉ : Type*} (s : Finset ΞΉ) (f : ΞΉ β†’ HeckeModule P β„€) :
coeffSum P (βˆ‘ i ∈ s, f i) = βˆ‘ i ∈ s, coeffSum P (f i) := map_sum _ _ _

/-- The coefficient sum of a single-single smul product equals `a * deg(D) * b`. -/
lemma coeffSum_single_smul_single (D : HeckeCoset P) (mβ‚€ : HeckeLeftCoset P) (a b : β„€) :
coeffSum P (T_single P β„€ D a β€’ HeckeLeftCoset_single P β„€ mβ‚€ b) =
a * HeckeCoset_deg P D * b := by
rw [T_single_smul_HeckeLeftCoset_single, coeffSum_finset_sum]
simp only [coeffSum_single, Finset.sum_const, Int.nsmul_eq_mul,
smulOrbit_card_intCast P D (HeckeLeftCoset.rep mβ‚€)]
ring

end CoeffSum

section DegreeMap

/-- The underlying function of the degree map: `Ξ£_D a_D * deg(D)`. -/
noncomputable def deg_fun (f : 𝕋 P β„€) : β„€ := f.sum fun D a ↦ a * HeckeCoset_deg P D

/-- The degree function of zero is zero. -/
@[simp] lemma deg_fun_zero : deg_fun P (0 : 𝕋 P β„€) = 0 := Finsupp.sum_zero_index

/-- The degree function of a basis element is `a * deg(D)`. -/
@[simp] lemma deg_fun_T_single (D : HeckeCoset P) (a : β„€) :
deg_fun P (T_single P β„€ D a) = a * HeckeCoset_deg P D :=
Finsupp.sum_single_index (by simp)

/-- The degree function is additive. -/
lemma deg_fun_add (f g : 𝕋 P β„€) :
deg_fun P (f + g) = deg_fun P f + deg_fun P g :=
Finsupp.sum_add_index' (fun _ ↦ by simp) (fun _ _ _ ↦ by ring)

/-- The degree function of the identity is 1. -/
@[simp] lemma deg_fun_one : deg_fun P (1 : 𝕋 P β„€) = 1 := by
simp [one_def]

/-- The degree equals the coefficient sum of the action on the identity module element. -/
lemma deg_fun_eq_coeffSum_smul_one (f : 𝕋 P β„€) :
deg_fun P f = coeffSum P (f β€’ (1 : HeckeModule P β„€)) := by
let toT : (HeckeCoset P β†’β‚€ β„€) β†’ 𝕋 P β„€ := fun a ↦ a
let mot : (HeckeCoset P β†’β‚€ β„€) β†’ Prop :=
fun f' ↦ deg_fun P (toT f') = coeffSum P ((toT f') β€’ (1 : HeckeModule P β„€))
change mot f
apply Finsupp.induction_linear
Β· show deg_fun P (toT 0) = coeffSum P ((toT 0) β€’ (1 : HeckeModule P β„€))
change deg_fun P (0 : 𝕋 P β„€) = coeffSum P (((0 : 𝕋 P β„€)) β€’ (1 : HeckeModule P β„€))
simp [zero_smul_HeckeModule]
Β· intro f g ihf ihg
show deg_fun P (toT (f + g)) =
coeffSum P ((toT (f + g)) β€’ (1 : HeckeModule P β„€))
change deg_fun P ((toT f + toT g) : 𝕋 P β„€) =
coeffSum P (((toT f + toT g) : 𝕋 P β„€) β€’ (1 : HeckeModule P β„€))
rw [deg_fun_add, ihf, ihg, smul_add_left, coeffSum_add]
Β· intro D a
show deg_fun P (toT (Finsupp.single D a)) =
coeffSum P ((toT (Finsupp.single D a)) β€’ (1 : HeckeModule P β„€))
rw [deg_fun_T_single, one_eq_HeckeLeftCoset_single,
coeffSum_single_smul_single, mul_one]

/-- The coefficient sum of a smul product factors as `deg(f) * coeffSum(m)`. -/
lemma coeffSum_smul_eq (f : 𝕋 P β„€) (m : HeckeModule P β„€) :
coeffSum P (f β€’ m) = deg_fun P f * coeffSum P m := by
let toT : (HeckeCoset P β†’β‚€ β„€) β†’ 𝕋 P β„€ := fun a ↦ a
let toM : (HeckeLeftCoset P β†’β‚€ β„€) β†’ HeckeModule P β„€ := fun a ↦ a
let motf : (HeckeCoset P β†’β‚€ β„€) β†’ Prop :=
fun f' ↦ coeffSum P ((toT f') β€’ m) = deg_fun P (toT f') * coeffSum P m
change motf f
apply Finsupp.induction_linear
Β· show coeffSum P ((toT 0) β€’ m) = deg_fun P (toT 0) * coeffSum P m
change coeffSum P (((0 : 𝕋 P β„€)) β€’ m) = deg_fun P (0 : 𝕋 P β„€) * coeffSum P m
simp [zero_smul_HeckeModule]
Β· intro f₁ fβ‚‚ ih₁ ihβ‚‚
show coeffSum P ((toT (f₁ + fβ‚‚)) β€’ m) =
deg_fun P (toT (f₁ + fβ‚‚)) * coeffSum P m
change coeffSum P (((toT f₁ + toT fβ‚‚) : 𝕋 P β„€) β€’ m) =
deg_fun P ((toT f₁ + toT fβ‚‚) : 𝕋 P β„€) * coeffSum P m
rw [smul_add_left, coeffSum_add, ih₁, ihβ‚‚, deg_fun_add]; ring
Β· intro D a
show coeffSum P ((toT (Finsupp.single D a)) β€’ m) =
deg_fun P (toT (Finsupp.single D a)) * coeffSum P m
let motm : (HeckeLeftCoset P β†’β‚€ β„€) β†’ Prop :=
fun m' ↦ coeffSum P ((toT (Finsupp.single D a)) β€’ (toM m')) =
deg_fun P (toT (Finsupp.single D a)) * coeffSum P (toM m')
change motm m
apply Finsupp.induction_linear
Β· show coeffSum P ((toT (Finsupp.single D a)) β€’ (toM 0)) =
deg_fun P (toT (Finsupp.single D a)) * coeffSum P (toM 0)
change coeffSum P ((toT (Finsupp.single D a)) β€’ (0 : HeckeModule P β„€)) =
deg_fun P (toT (Finsupp.single D a)) * coeffSum P (0 : HeckeModule P β„€)
simp [smul_zero_HeckeModule]
Β· intro m₁ mβ‚‚ ih₁ ihβ‚‚
show coeffSum P ((toT (Finsupp.single D a)) β€’ (toM (m₁ + mβ‚‚))) =
deg_fun P (toT (Finsupp.single D a)) * coeffSum P (toM (m₁ + mβ‚‚))
change coeffSum P
((toT (Finsupp.single D a)) β€’ ((toM m₁ + toM mβ‚‚) : HeckeModule P β„€)) =
deg_fun P (toT (Finsupp.single D a)) *
coeffSum P ((toM m₁ + toM mβ‚‚) : HeckeModule P β„€)
rw [smul_add_right, coeffSum_add, ih₁, ihβ‚‚, coeffSum_add, deg_fun_T_single]; ring
Β· intro mβ‚€ b
show coeffSum P ((toT (Finsupp.single D a)) β€’ (toM (Finsupp.single mβ‚€ b))) =
deg_fun P (toT (Finsupp.single D a)) * coeffSum P (toM (Finsupp.single mβ‚€ b))
rw [coeffSum_single_smul_single, coeffSum_single, deg_fun_T_single]

/-- The degree function is multiplicative. -/
lemma deg_fun_mul (f g : 𝕋 P β„€) :
deg_fun P (f * g) = deg_fun P f * deg_fun P g := by
have h := (instIsScalarTower P).smul_assoc g f (1 : HeckeModule P β„€)
simp only [smul_def] at h
rw [deg_fun_eq_coeffSum_smul_one P (f * g), h, coeffSum_smul_eq,
← deg_fun_eq_coeffSum_smul_one P f]; ring

/-- The degree ring homomorphism `deg : 𝕋 P β„€ β†’+* β„€`, sending each double coset to the
number of left cosets it contains (Shimura Proposition 3.3). -/
noncomputable def deg : 𝕋 P β„€ β†’+* β„€ where
toFun := deg_fun P
map_zero' := deg_fun_zero P
map_one' := deg_fun_one P
map_add' := deg_fun_add P
map_mul' := deg_fun_mul P

end DegreeMap

section API

/-- The degree of a basis element is the coefficient times the degree of the double coset. -/
@[simp] lemma deg_T_single (D : HeckeCoset P) (a : β„€) :
deg P (T_single P β„€ D a) = a * HeckeCoset_deg P D := deg_fun_T_single P D a

/-- The degree map is multiplicative: `deg(f * g) = deg(f) * deg(g)`. -/
lemma deg_mul (f g : 𝕋 P β„€) : deg P (f * g) = deg P f * deg P g := (deg P).map_mul f g

/-- **Generic multiplicity-degree-sum identity**: when the support of the
multiplication finsupp `m P D₁ Dβ‚‚` is contained in `{D_out1, D_out2}`, the
weighted sum of multiplicities by degrees equals the product of degrees. -/
lemma heckeMultiplicity_deg_sum_eq (D1 D2 D_out1 D_out2 : HeckeCoset P)
(h_ne : D_out1 β‰  D_out2) (h_zero : βˆ€ A, A β‰  D_out1 β†’ A β‰  D_out2 β†’
heckeMultiplicity P (HeckeCoset.rep D1) (HeckeCoset.rep D2)
(HeckeCoset.rep A) = 0) :
heckeMultiplicity P (HeckeCoset.rep D1) (HeckeCoset.rep D2)
(HeckeCoset.rep D_out1) * HeckeCoset_deg P D_out1 +
heckeMultiplicity P (HeckeCoset.rep D1) (HeckeCoset.rep D2)
(HeckeCoset.rep D_out2) * HeckeCoset_deg P D_out2 =
HeckeCoset_deg P D1 * HeckeCoset_deg P D2 := by
have h1 : deg P (m P (HeckeCoset.rep D1) (HeckeCoset.rep D2)) =
HeckeCoset_deg P D1 * HeckeCoset_deg P D2 := by
rw [← T_single_one_mul_T_single_one, deg_mul, deg_T_single, deg_T_single]; ring
have h2 : deg P (m P (HeckeCoset.rep D1) (HeckeCoset.rep D2)) =
heckeMultiplicity P (HeckeCoset.rep D1) (HeckeCoset.rep D2)
(HeckeCoset.rep D_out1) * HeckeCoset_deg P D_out1 +
heckeMultiplicity P (HeckeCoset.rep D1) (HeckeCoset.rep D2)
(HeckeCoset.rep D_out2) * HeckeCoset_deg P D_out2 := by
simp only [deg, RingHom.coe_mk, MonoidHom.coe_mk, OneHom.coe_mk, deg_fun]
have hsub : (m P (HeckeCoset.rep D1) (HeckeCoset.rep D2)).support βŠ†
({D_out1, D_out2} : Finset _) := fun A hA ↦ by
simp only [Finset.mem_insert, Finset.mem_singleton]
rw [Finsupp.mem_support_iff] at hA
exact or_iff_not_imp_left.mpr fun h1 ↦
(Classical.em (A = D_out2)).elim id fun h2 ↦ absurd (h_zero A h1 h2) hA
exact (Finset.sum_subset hsub fun A _ hA ↦ by
rw [Finsupp.notMem_support_iff.mp hA]; simp).trans (Finset.sum_pair h_ne)
linarith

end API

end HeckeRing
Loading