import Mathlib import Definitions.Def_AbstractHeckeOperator set_option autoImplicit false open scoped Pointwise open Function MulAction namespace HeckePair noncomputable section variable {G : Type*} [Group G] (U : Subgroup G) variable (R₀ : Type*) [CommRing R₀] variable {U R₀} in structure IsHeckeFun (f : G → R₀) : Prop where left_inv : ∀ u ∈ U, ∀ x, f (u * x) = f x right_inv : ∀ u ∈ U, ∀ x, f (x * u) = f x finite_cosets : ((QuotientGroup.mk '' (Function.support f)) : Set (G ⧸ U)).Finite variable {U R₀} in theorem IsHeckeFun.zero : IsHeckeFun (U := U) (0 : G → R₀) := ⟨fun _ _ _ => rfl, fun _ _ _ => rfl, by simp⟩ variable {U R₀} in theorem IsHeckeFun.add {f g : G → R₀} (hf : IsHeckeFun (U := U) f) (hg : IsHeckeFun (U := U) g) : IsHeckeFun (U := U) (f + g) := by refine ⟨fun u hu x => ?_, fun u hu x => ?_, ?_⟩ · simp only [Pi.add_apply, hf.left_inv u hu, hg.left_inv u hu] · simp only [Pi.add_apply, hf.right_inv u hu, hg.right_inv u hu] · refine ((hf.finite_cosets.union hg.finite_cosets).subset ?_) rw [← Set.image_union] refine Set.image_mono fun x hx => ?_ by_contra hcon simp only [Set.mem_union, Function.mem_support, not_or, not_not] at hcon exact hx (by simp [Pi.add_apply, hcon.1, hcon.2]) variable {U R₀} in theorem IsHeckeFun.smul {f : G → R₀} (r : R₀) (hf : IsHeckeFun (U := U) f) : IsHeckeFun (U := U) (r • f) := by refine ⟨fun u hu x => ?_, fun u hu x => ?_, ?_⟩ · simp only [Pi.smul_apply, hf.left_inv u hu] · simp only [Pi.smul_apply, hf.right_inv u hu] · refine hf.finite_cosets.subset (Set.image_mono ?_) intro x hx simp only [Function.mem_support, Pi.smul_apply, smul_eq_mul] at hx exact Function.mem_support.mpr (right_ne_zero_of_mul hx) def heckeSubmodule : Submodule R₀ (G → R₀) where carrier := {f | IsHeckeFun (U := U) f} add_mem' hf hg := hf.add hg zero_mem' := IsHeckeFun.zero smul_mem' r _ hf := hf.smul r abbrev HeckeAlgebra := heckeSubmodule U R₀ variable {U R₀} theorem mem_heckeSubmodule_iff {f : G → R₀} : f ∈ heckeSubmodule U R₀ ↔ IsHeckeFun (U := U) f := Iff.rfl theorem isHeckeFun (f : HeckeAlgebra U R₀) : IsHeckeFun (U := U) (f : G → R₀) := f.2 theorem apply_left_mul (f : HeckeAlgebra U R₀) {u : G} (hu : u ∈ U) (x : G) : (f : G → R₀) (u * x) = (f : G → R₀) x := f.2.left_inv u hu x theorem apply_mul_right (f : HeckeAlgebra U R₀) {u : G} (hu : u ∈ U) (x : G) : (f : G → R₀) (x * u) = (f : G → R₀) x := f.2.right_inv u hu x theorem finite_cosets (f : HeckeAlgebra U R₀) : ((QuotientGroup.mk '' (Function.support (f : G → R₀))) : Set (G ⧸ U)).Finite := f.2.finite_cosets @[ext] theorem ext {f g : HeckeAlgebra U R₀} (h : ∀ x, (f : G → R₀) x = (g : G → R₀) x) : f = g := Subtype.ext (funext h) @[simp] theorem coe_apply_add (f g : HeckeAlgebra U R₀) (x : G) : ((f + g : HeckeAlgebra U R₀) : G → R₀) x = (f : G → R₀) x + (g : G → R₀) x := rfl @[simp] theorem coe_apply_smul (r : R₀) (f : HeckeAlgebra U R₀) (x : G) : ((r • f : HeckeAlgebra U R₀) : G → R₀) x = r * (f : G → R₀) x := rfl def convTerm (f₁ f₂ : HeckeAlgebra U R₀) (x : G) : G ⧸ U → R₀ := Quotient.lift (fun y => (f₁ : G → R₀) y * (f₂ : G → R₀) (y⁻¹ * x)) <| by intro a b hab obtain ⟨u, hu, rfl⟩ : ∃ u ∈ U, a * u = b := ⟨a⁻¹ * b, QuotientGroup.leftRel_apply.mp hab, by group⟩ rw [apply_mul_right f₁ hu, mul_inv_rev, mul_assoc, apply_left_mul f₂ (inv_mem hu)] @[simp] theorem convTerm_mk (f₁ f₂ : HeckeAlgebra U R₀) (x y : G) : convTerm f₁ f₂ x (QuotientGroup.mk y) = (f₁ : G → R₀) y * (f₂ : G → R₀) (y⁻¹ * x) := rfl theorem support_convTerm_subset (f₁ f₂ : HeckeAlgebra U R₀) (x : G) : Function.support (convTerm f₁ f₂ x) ⊆ QuotientGroup.mk '' (Function.support (f₁ : G → R₀)) := by intro c hc obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [Function.mem_support, convTerm_mk] at hc exact ⟨y, left_ne_zero_of_mul hc, rfl⟩ theorem finite_support_convTerm (f₁ f₂ : HeckeAlgebra U R₀) (x : G) : (Function.support (convTerm f₁ f₂ x)).Finite := (finite_cosets f₁).subset (support_convTerm_subset f₁ f₂ x) def conv (f₁ f₂ : HeckeAlgebra U R₀) (x : G) : R₀ := ∑ᶠ c : G ⧸ U, convTerm f₁ f₂ x c theorem conv_eq_sum (f₁ f₂ : HeckeAlgebra U R₀) (x : G) {T : Finset (G ⧸ U)} (hT : QuotientGroup.mk '' (Function.support (f₁ : G → R₀)) ⊆ (T : Set (G ⧸ U))) : conv f₁ f₂ x = ∑ c ∈ T, convTerm f₁ f₂ x c := finsum_eq_sum_of_support_subset _ <| (support_convTerm_subset f₁ f₂ x).trans hT theorem support_conv_subset (f₁ f₂ : HeckeAlgebra U R₀) : Function.support (conv f₁ f₂) ⊆ Function.support (f₁ : G → R₀) * Function.support (f₂ : G → R₀) := by intro x hx have h : ∃ c, convTerm f₁ f₂ x c ≠ 0 := by by_contra h push Not at h exact hx (by simp only [conv, finsum_congr h, finsum_zero]) obtain ⟨c, hc⟩ := h obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [convTerm_mk] at hc exact ⟨y, left_ne_zero_of_mul hc, y⁻¹ * x, right_ne_zero_of_mul hc, by group⟩ theorem finite_image_mk_mul_support (f₁ f₂ : HeckeAlgebra U R₀) : ((QuotientGroup.mk '' (Function.support (f₁ : G → R₀) * Function.support (f₂ : G → R₀))) : Set (G ⧸ U)).Finite := by refine Set.Finite.subset (Set.Finite.image2 (fun c d => Quotient.out c • d) (finite_cosets f₁) (finite_cosets f₂)) ?_ rintro _ ⟨_, ⟨y, hy, z, hz, rfl⟩, rfl⟩ obtain ⟨u, hu⟩ := QuotientGroup.mk_out_eq_mul U y refine Set.mem_image2.mpr ⟨QuotientGroup.mk y, ⟨y, hy, rfl⟩, QuotientGroup.mk ((u : G)⁻¹ * z), ⟨(u : G)⁻¹ * z, ?_, rfl⟩, ?_⟩ · simpa only [Function.mem_support, apply_left_mul f₂ (inv_mem u.2)] using hz · rw [hu, MulAction.Quotient.smul_mk, smul_eq_mul] congr 1 group theorem finite_image_mk_support_conv (f₁ f₂ : HeckeAlgebra U R₀) : ((QuotientGroup.mk '' (Function.support (conv f₁ f₂))) : Set (G ⧸ U)).Finite := (finite_image_mk_mul_support f₁ f₂).subset <| Set.image_mono <| support_conv_subset f₁ f₂ theorem convTerm_smul_left (f₁ f₂ : HeckeAlgebra U R₀) {u : G} (hu : u ∈ U) (x : G) (y : G) : convTerm f₁ f₂ (u * x) (QuotientGroup.mk (u * y)) = convTerm f₁ f₂ x (QuotientGroup.mk y) := by rw [convTerm_mk, convTerm_mk, apply_left_mul f₁ hu] congr 2 group theorem isHeckeFun_conv (f₁ f₂ : HeckeAlgebra U R₀) : IsHeckeFun (U := U) (conv f₁ f₂) := by refine ⟨fun u hu x => ?_, fun u hu x => ?_, finite_image_mk_support_conv f₁ f₂⟩ · calc conv f₁ f₂ (u * x) = ∑ᶠ c : G ⧸ U, convTerm f₁ f₂ (u * x) ((MulAction.toPerm u) c) := (finsum_comp_equiv (MulAction.toPerm u)).symm _ = ∑ᶠ c : G ⧸ U, convTerm f₁ f₂ x c := by refine finsum_congr fun c => ?_ obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [MulAction.toPerm_apply, MulAction.Quotient.smul_mk, smul_eq_mul] exact convTerm_smul_left f₁ f₂ hu x y _ = conv f₁ f₂ x := rfl · refine finsum_congr fun c => ?_ obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [convTerm_mk, convTerm_mk, ← mul_assoc, apply_mul_right f₂ hu] instance : Mul (HeckeAlgebra U R₀) := ⟨fun f₁ f₂ => ⟨conv f₁ f₂, isHeckeFun_conv f₁ f₂⟩⟩ theorem coe_mul (f₁ f₂ : HeckeAlgebra U R₀) : ((f₁ * f₂ : HeckeAlgebra U R₀) : G → R₀) = conv f₁ f₂ := rfl theorem mul_apply (f₁ f₂ : HeckeAlgebra U R₀) (x : G) : ((f₁ * f₂ : HeckeAlgebra U R₀) : G → R₀) x = ∑ᶠ c : G ⧸ U, convTerm f₁ f₂ x c := rfl variable (U R₀) in def heckeOne : HeckeAlgebra U R₀ := ⟨Set.indicator (U : Set G) 1, by refine ⟨fun u hu x => ?_, fun u hu x => ?_, ?_⟩ · by_cases hx : x ∈ U · simp only [Set.indicator_of_mem (mul_mem hu hx : u * x ∈ U), Set.indicator_of_mem hx, Pi.one_apply] · rw [Set.indicator_of_notMem (fun h => hx (by simpa using mul_mem (inv_mem hu) h)), Set.indicator_of_notMem hx] · by_cases hx : x ∈ U · simp only [Set.indicator_of_mem (mul_mem hx hu : x * u ∈ U), Set.indicator_of_mem hx, Pi.one_apply] · rw [Set.indicator_of_notMem (fun h => hx (by simpa using mul_mem h (inv_mem hu))), Set.indicator_of_notMem hx] · refine (Set.finite_singleton (QuotientGroup.mk (1 : G))).subset ?_ rintro _ ⟨y, hy, rfl⟩ have hyU : y ∈ U := by by_contra hyU exact hy (Set.indicator_of_notMem hyU 1) exact Set.mem_singleton_iff.mpr (QuotientGroup.eq.mpr (by simpa using inv_mem hyU))⟩ instance : One (HeckeAlgebra U R₀) := ⟨heckeOne U R₀⟩ theorem coe_one : ((1 : HeckeAlgebra U R₀) : G → R₀) = Set.indicator (U : Set G) 1 := rfl theorem one_apply_of_mem {x : G} (hx : x ∈ U) : ((1 : HeckeAlgebra U R₀) : G → R₀) x = 1 := Set.indicator_of_mem hx 1 theorem one_apply_of_notMem {x : G} (hx : x ∉ U) : ((1 : HeckeAlgebra U R₀) : G → R₀) x = 0 := Set.indicator_of_notMem hx 1 protected theorem one_mul (f : HeckeAlgebra U R₀) : 1 * f = f := by ext x rw [mul_apply] refine (finsum_eq_single _ (QuotientGroup.mk (1 : G)) fun c hc => ?_).trans ?_ · obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [convTerm_mk, one_apply_of_notMem, zero_mul] intro hyU exact hc (QuotientGroup.eq.mpr (by simpa using inv_mem hyU)) · rw [convTerm_mk, one_apply_of_mem (one_mem U), one_mul, inv_one, one_mul] protected theorem mul_one (f : HeckeAlgebra U R₀) : f * 1 = f := by ext x rw [mul_apply] refine (finsum_eq_single _ (QuotientGroup.mk x) fun c hc => ?_).trans ?_ · obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [convTerm_mk, one_apply_of_notMem, mul_zero] intro hyx exact hc (QuotientGroup.eq.mpr hyx) · rw [convTerm_mk, inv_mul_cancel, one_apply_of_mem (one_mem U), mul_one] protected theorem zero_mul (f : HeckeAlgebra U R₀) : 0 * f = 0 := by ext x rw [mul_apply] refine finsum_eq_zero_of_forall_eq_zero fun c => ?_ obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [convTerm_mk] exact zero_mul _ protected theorem mul_zero (f : HeckeAlgebra U R₀) : f * 0 = 0 := by ext x rw [mul_apply] refine finsum_eq_zero_of_forall_eq_zero fun c => ?_ obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c rw [convTerm_mk] exact mul_zero _ protected theorem add_mul (f₁ f₂ g : HeckeAlgebra U R₀) : (f₁ + f₂) * g = f₁ * g + f₂ * g := by ext x rw [mul_apply] have h : ∀ c : G ⧸ U, convTerm (f₁ + f₂) g x c = convTerm f₁ g x c + convTerm f₂ g x c := by intro c obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c simp only [convTerm_mk, coe_apply_add, add_mul] rw [finsum_congr h, finsum_add_distrib (finite_support_convTerm f₁ g x) (finite_support_convTerm f₂ g x)] rfl protected theorem mul_add (f g₁ g₂ : HeckeAlgebra U R₀) : f * (g₁ + g₂) = f * g₁ + f * g₂ := by ext x rw [mul_apply] have h : ∀ c : G ⧸ U, convTerm f (g₁ + g₂) x c = convTerm f g₁ x c + convTerm f g₂ x c := by intro c obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c simp only [convTerm_mk, coe_apply_add, mul_add] rw [finsum_congr h, finsum_add_distrib (finite_support_convTerm f g₁ x) (finite_support_convTerm f g₂ x)] rfl protected theorem smul_mul (r : R₀) (f g : HeckeAlgebra U R₀) : (r • f) * g = r • (f * g) := by ext x rw [mul_apply] have h : ∀ c : G ⧸ U, convTerm (r • f) g x c = r * convTerm f g x c := by intro c obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c simp only [convTerm_mk, coe_apply_smul, mul_assoc] rw [finsum_congr h, ← mul_finsum' _ _ (finite_support_convTerm f g x)] rfl protected theorem mul_smul_comm (r : R₀) (f g : HeckeAlgebra U R₀) : f * (r • g) = r • (f * g) := by ext x rw [mul_apply] have h : ∀ c : G ⧸ U, convTerm f (r • g) x c = r * convTerm f g x c := by intro c obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective c simp only [convTerm_mk, coe_apply_smul] ring rw [finsum_congr h, ← mul_finsum' _ _ (finite_support_convTerm f g x)] rfl protected theorem mul_assoc (f₁ f₂ f₃ : HeckeAlgebra U R₀) : f₁ * f₂ * f₃ = f₁ * (f₂ * f₃) := by ext x set A : G ⧸ U → G ⧸ U → R₀ := fun c d => convTerm f₁ f₂ (Quotient.out c) d * (f₃ : G → R₀) ((Quotient.out c)⁻¹ * x) with hA set T₁ : Finset (G ⧸ U) := (finite_image_mk_mul_support f₁ f₂).toFinset with hT₁def set T₂ : Finset (G ⧸ U) := (finite_cosets f₁).toFinset with hT₂def have hT₁ : (QuotientGroup.mk '' (Function.support (f₁ : G → R₀) * Function.support (f₂ : G → R₀)) : Set (G ⧸ U)) ⊆ ↑T₁ := by rw [hT₁def]; simp have hT₂ : (QuotientGroup.mk '' (Function.support (f₁ : G → R₀)) : Set (G ⧸ U)) ⊆ ↑T₂ := by rw [hT₂def]; simp have hAsupp₂ : ∀ c, Function.support (A c) ⊆ ↑T₂ := by intro c d hd refine hT₂ (support_convTerm_subset f₁ f₂ (Quotient.out c) (Function.mem_support.mpr ?_)) intro h0 apply hd simp only [hA, h0, zero_mul] have hAsupp₁ : ∀ d, Function.support (A · d) ⊆ ↑T₁ := by intro d c hc refine hT₁ ?_ obtain ⟨z, rfl⟩ := QuotientGroup.mk_surjective d simp only [hA, convTerm_mk, Function.mem_support] at hc have h₁ : (f₁ : G → R₀) z ≠ 0 := left_ne_zero_of_mul (left_ne_zero_of_mul hc) have h₂ : (f₂ : G → R₀) (z⁻¹ * Quotient.out c) ≠ 0 := right_ne_zero_of_mul (left_ne_zero_of_mul hc) exact ⟨Quotient.out c, ⟨z, h₁, z⁻¹ * Quotient.out c, h₂, by group⟩, QuotientGroup.out_eq' c⟩ have lhs_eq : ((f₁ * f₂ * f₃ : HeckeAlgebra U R₀) : G → R₀) x = ∑ᶠ c, ∑ᶠ d, A c d := by rw [mul_apply] refine finsum_congr fun c => ?_ conv_lhs => rw [← QuotientGroup.out_eq' c] rw [convTerm_mk, mul_apply, finsum_mul' _ _ (finite_support_convTerm f₁ f₂ _)] have swap_eq : (∑ᶠ c, ∑ᶠ d, A c d) = ∑ᶠ d, ∑ᶠ c, A c d := by have e₁ : (∑ᶠ c, ∑ᶠ d, A c d) = ∑ᶠ c, ∑ d ∈ T₂, A c d := finsum_congr fun c => finsum_eq_sum_of_support_subset _ (hAsupp₂ c) have e₂ : (∑ᶠ d, ∑ᶠ c, A c d) = ∑ᶠ d, ∑ c ∈ T₁, A c d := finsum_congr fun d => finsum_eq_sum_of_support_subset _ (hAsupp₁ d) rw [e₁, e₂, finsum_eq_sum_of_support_subset (fun c => ∑ d ∈ T₂, A c d) (fun c hc => by obtain ⟨d, _, hd⟩ := Finset.exists_ne_zero_of_sum_ne_zero hc exact hAsupp₁ d hd), finsum_eq_sum_of_support_subset (fun d => ∑ c ∈ T₁, A c d) (fun d hd => by obtain ⟨c, _, hc⟩ := Finset.exists_ne_zero_of_sum_ne_zero hd exact hAsupp₂ c hc)] exact Finset.sum_comm have inner_eq : ∀ d, (∑ᶠ c, A c d) = convTerm f₁ (f₂ * f₃) x d := by intro d obtain ⟨z, rfl⟩ := QuotientGroup.mk_surjective d rw [convTerm_mk, mul_apply, mul_finsum' _ _ (finite_support_convTerm f₂ f₃ (z⁻¹ * x)), ← finsum_comp_equiv (MulAction.toPerm z)] refine finsum_congr fun e => ?_ obtain ⟨w, rfl⟩ := QuotientGroup.mk_surjective e simp only [MulAction.toPerm_apply, MulAction.Quotient.smul_mk, smul_eq_mul, hA] obtain ⟨u, hu⟩ := QuotientGroup.mk_out_eq_mul U (z * w) rw [hu, convTerm_mk, show z⁻¹ * (z * w * (u : G)) = w * (u : G) by group, apply_mul_right f₂ u.2, show (z * w * (u : G))⁻¹ * x = (u : G)⁻¹ * (w⁻¹ * (z⁻¹ * x)) by group, apply_left_mul f₃ (inv_mem u.2), convTerm_mk, mul_assoc] show ((f₁ * f₂ * f₃ : HeckeAlgebra U R₀) : G → R₀) x = ((f₁ * (f₂ * f₃) : HeckeAlgebra U R₀) : G → R₀) x rw [lhs_eq, swap_eq, finsum_congr inner_eq] rfl instance : Ring (HeckeAlgebra U R₀) where __ : AddCommGroup (HeckeAlgebra U R₀) := inferInstance mul := (· * ·) one := 1 mul_assoc := HeckePair.mul_assoc one_mul := HeckePair.one_mul mul_one := HeckePair.mul_one left_distrib := HeckePair.mul_add right_distrib := fun f₁ f₂ g => HeckePair.add_mul f₁ f₂ g zero_mul := HeckePair.zero_mul mul_zero := HeckePair.mul_zero instance : SMulCommClass R₀ (HeckeAlgebra U R₀) (HeckeAlgebra U R₀) := ⟨fun r f g => (HeckePair.mul_smul_comm r f g).symm⟩ instance : IsScalarTower R₀ (HeckeAlgebra U R₀) (HeckeAlgebra U R₀) := ⟨fun r f g => by rw [smul_eq_mul, smul_eq_mul, HeckePair.smul_mul]⟩ instance : Algebra R₀ (HeckeAlgebra U R₀) := Algebra.ofModule HeckePair.smul_mul HeckePair.mul_smul_comm variable (U) in def doubleCoset (g : G) : Set G := (U : Set G) * {g} * (U : Set G) theorem mem_doubleCoset_iff {g x : G} : x ∈ doubleCoset U g ↔ ∃ u ∈ U, ∃ v ∈ U, u * g * v = x := by constructor · rintro ⟨_, ⟨u, hu, _, rfl, rfl⟩, v, hv, rfl⟩ exact ⟨u, hu, v, hv, rfl⟩ · rintro ⟨u, hu, v, hv, rfl⟩ exact ⟨u * g, ⟨u, hu, g, rfl, rfl⟩, v, hv, rfl⟩ theorem self_mem_doubleCoset (g : G) : g ∈ doubleCoset U g := mem_doubleCoset_iff.mpr ⟨1, one_mem U, 1, one_mem U, by group⟩ theorem mul_mem_doubleCoset {g x : G} (hx : x ∈ doubleCoset U g) {u : G} (hu : u ∈ U) : u * x ∈ doubleCoset U g := by obtain ⟨a, ha, b, hb, rfl⟩ := mem_doubleCoset_iff.mp hx exact mem_doubleCoset_iff.mpr ⟨u * a, mul_mem hu ha, b, hb, by group⟩ theorem doubleCoset_mul_mem {g x : G} (hx : x ∈ doubleCoset U g) {u : G} (hu : u ∈ U) : x * u ∈ doubleCoset U g := by obtain ⟨a, ha, b, hb, rfl⟩ := mem_doubleCoset_iff.mp hx exact mem_doubleCoset_iff.mpr ⟨a, ha, b * u, mul_mem hb hu, by group⟩ theorem image_mk_doubleCoset (g : G) : (QuotientGroup.mk '' (doubleCoset U g) : Set (G ⧸ U)) = QuotientGroup.mk '' ((U : Set G) * {g}) := by apply Set.Subset.antisymm · rintro _ ⟨x, hx, rfl⟩ obtain ⟨a, ha, b, hb, rfl⟩ := mem_doubleCoset_iff.mp hx refine ⟨a * g, ⟨a, ha, g, rfl, rfl⟩, QuotientGroup.eq.mpr ?_⟩ rw [show (a * g)⁻¹ * (a * g * b) = b by group] exact hb · rintro _ ⟨w, ⟨a, ha, v, hv, rfl⟩, rfl⟩ obtain rfl : v = g := hv exact ⟨a * v, mem_doubleCoset_iff.mpr ⟨a, ha, 1, one_mem U, by group⟩, rfl⟩ variable (R₀) in def heckeIndicator (g : G) (hfin : (QuotientGroup.mk '' ((U : Set G) * {g}) : Set (G ⧸ U)).Finite) : HeckeAlgebra U R₀ := ⟨Set.indicator (doubleCoset U g) 1, by refine ⟨fun u hu x => ?_, fun u hu x => ?_, ?_⟩ · by_cases hx : x ∈ doubleCoset U g · simp only [Set.indicator_of_mem (mul_mem_doubleCoset hx hu), Set.indicator_of_mem hx, Pi.one_apply] · rw [Set.indicator_of_notMem (fun h => hx ?_), Set.indicator_of_notMem hx] simpa using mul_mem_doubleCoset h (inv_mem hu) · by_cases hx : x ∈ doubleCoset U g · simp only [Set.indicator_of_mem (doubleCoset_mul_mem hx hu), Set.indicator_of_mem hx, Pi.one_apply] · rw [Set.indicator_of_notMem (fun h => hx ?_), Set.indicator_of_notMem hx] simpa using doubleCoset_mul_mem h (inv_mem hu) · rw [← image_mk_doubleCoset] at hfin refine hfin.subset (Set.image_mono ?_) intro y hy by_contra hyD exact hy (Set.indicator_of_notMem hyD 1)⟩ theorem heckeIndicator_apply_of_mem {g x : G} (hfin) (hx : x ∈ doubleCoset U g) : ((heckeIndicator R₀ g hfin : HeckeAlgebra U R₀) : G → R₀) x = 1 := Set.indicator_of_mem hx 1 theorem heckeIndicator_apply_of_notMem {g x : G} (hfin) (hx : x ∉ doubleCoset U g) : ((heckeIndicator R₀ g hfin : HeckeAlgebra U R₀) : G → R₀) x = 0 := Set.indicator_of_notMem hx 1 theorem heckeIndicator_of_mem {u : G} (hu : u ∈ U) (hfin) : heckeIndicator R₀ u hfin = (1 : HeckeAlgebra U R₀) := by ext x rw [coe_one] by_cases hx : x ∈ U · rw [heckeIndicator_apply_of_mem _ (mem_doubleCoset_iff.mpr ⟨x * u⁻¹, mul_mem hx (inv_mem hu), 1, one_mem U, by group⟩), Set.indicator_of_mem hx] rfl · rw [heckeIndicator_apply_of_notMem, Set.indicator_of_notMem hx] intro h obtain ⟨a, ha, b, hb, rfl⟩ := mem_doubleCoset_iff.mp h exact hx (mul_mem (mul_mem ha hu) hb) end end HeckePair