import Mathlib import Definitions.Def_AlgebraicCurve_IsCurveOver import Definitions.Def_AlgebraicCurve_DivisorPushPull import Definitions.Def_AlgebraicCurve_RatFuncPlaces import Definitions.Def_AlgebraicCurve_FrobeniusEndo import Definitions.Def_AlgebraicCurve_FrobeniusEndoPic0 import Definitions.Def_ModularCurve_JqCoeff import Definitions.Def_ModularCurve_FibrePoly import Definitions.Def_HeckeGalois_EichlerShimura import Theorems.Thm_ModularCurve_frobenius_identity_geom_unconditional set_option autoImplicit false noncomputable section open AlgebraicCurve Polynomial set_option synthInstance.maxHeartbeats 400000 set_option maxHeartbeats 800000 namespace ModularCurve section ConstantEmbedding variable {R : Type*} [CommRing R] theorem algebraMap_laurentSeries_apply_eq_single (c : R) : algebraMap R (LaurentSeries R) c = HahnSeries.single 0 c := by have h1 : algebraMap R (PowerSeries R) c = PowerSeries.C c := by simp rw [HahnSeries.algebraMap_apply', h1, HahnSeries.ofPowerSeries_C] rfl end ConstantEmbedding section QExpandAlg variable (K : Type*) [Field K] (N : ℕ) [NeZero N] def qExpandAlgC : LaurentSeries K →ₐ[K] LaurentSeries K where __ := qExpand K N commutes' r := by show qExpand K N (algebraMap K (LaurentSeries K) r) = algebraMap K (LaurentSeries K) r rw [algebraMap_laurentSeries_apply_eq_single, qExpand_single, mul_zero] @[simp] theorem qExpandAlgC_apply (f : LaurentSeries K) : qExpandAlgC K N f = qExpand K N f := rfl end QExpandAlg section FrobId variable (K : Type*) [Field K] {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] theorem ModularPolynomialData.frobenius_identity_geom (_data : ModularPolynomialData ℓ) (_hK : KroneckerCongruence ℓ _data) : jqNModC K ℓ = (jqModC K) ^ ℓ := frobenius_identity_geom_unconditional K end FrobId section DegOneBridge open AlgebraicCurve variable (K : Type*) [Field K] (N : ℕ) [NeZero N] [IsAlgClosed K] [IsCurveOver K (modularFunctionFieldC K N)] theorem deg_eq_one_modularFunctionFieldC : ∀ w : Place K (modularFunctionFieldC K N), w.deg = 1 := IsCurveOver.forall_deg_eq_one_of_isAlgClosed end DegOneBridge end ModularCurve noncomputable section open AlgebraicCurve Polynomial set_option synthInstance.maxHeartbeats 400000 set_option maxHeartbeats 800000 namespace ModularCurve section FrobeniusEndomorphism variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem qExpand_jqModC_eq_pow : qExpand K ℓ (jqModC K) = (jqModC K) ^ ℓ := data.frobenius_identity_geom K hKr include data hKr in theorem qExpand_jqNModC_eq_pow : qExpand K ℓ (jqNModC K N) = (jqNModC K N) ^ ℓ := by rw [jqNModC, qExpand_qExpand, qExpand_congr (mul_comm ℓ N), ← qExpand_qExpand, qExpand_jqModC_eq_pow K data hKr, map_pow] include data hKr in theorem frobeniusGeomLevel_map_le : (modularFunctionFieldC K N).map (qExpandAlgC K ℓ) ≤ modularFunctionFieldC K N := by show (IntermediateField.adjoin K {jqModC K, jqNModC K N}).map (qExpandAlgC K ℓ) ≤ _ rw [IntermediateField.adjoin_map, Set.image_pair, IntermediateField.adjoin_le_iff] rintro x (rfl | rfl) · show qExpandAlgC K ℓ (jqModC K) ∈ modularFunctionFieldC K N rw [qExpandAlgC_apply, qExpand_jqModC_eq_pow K data hKr] exact pow_mem (jqModC_mem K N) ℓ · show qExpandAlgC K ℓ (jqNModC K N) ∈ modularFunctionFieldC K N rw [qExpandAlgC_apply, qExpand_jqNModC_eq_pow K N data hKr] exact pow_mem (jqNModC_mem K N) ℓ def frobeniusGeomLevelImage : IntermediateField K (LaurentSeries K) := (modularFunctionFieldC K N).map (qExpandAlgC K ℓ) def frobeniusGeomLevelEquiv : (modularFunctionFieldC K N) ≃ₐ[K] (frobeniusGeomLevelImage K N (ℓ := ℓ)) := (modularFunctionFieldC K N).equivMap (qExpandAlgC K ℓ) omit [CharP K ℓ] in @[simp] theorem coe_frobeniusGeomLevelEquiv_apply (x : modularFunctionFieldC K N) : (frobeniusGeomLevelEquiv K N (ℓ := ℓ) x : LaurentSeries K) = qExpand K ℓ (x : LaurentSeries K) := IntermediateField.coe_equivMap_apply _ _ x include data hKr in def frobeniusGeomLevel : modularFunctionFieldC K N →ₐ[K] modularFunctionFieldC K N := (IntermediateField.inclusion (frobeniusGeomLevel_map_le K N data hKr)).comp (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).toAlgHom @[simp] theorem frobeniusGeomLevel_apply_coe (x : modularFunctionFieldC K N) : (frobeniusGeomLevel K N data hKr x : LaurentSeries K) = qExpand K ℓ (x : LaurentSeries K) := by refine (IntermediateField.coe_inclusion (frobeniusGeomLevel_map_le K N data hKr) _).trans ?_ exact coe_frobeniusGeomLevelEquiv_apply K N x theorem frobeniusGeomLevel_jq : frobeniusGeomLevel K N data hKr ⟨jqModC K, jqModC_mem K N⟩ = (⟨jqModC K, jqModC_mem K N⟩ : modularFunctionFieldC K N) ^ ℓ := by refine Subtype.ext ?_ rw [frobeniusGeomLevel_apply_coe] push_cast exact qExpand_jqModC_eq_pow K data hKr theorem frobeniusGeomLevel_jqN : frobeniusGeomLevel K N data hKr ⟨jqNModC K N, jqNModC_mem K N⟩ = (⟨jqNModC K N, jqNModC_mem K N⟩ : modularFunctionFieldC K N) ^ ℓ := by refine Subtype.ext ?_ rw [frobeniusGeomLevel_apply_coe] push_cast exact qExpand_jqNModC_eq_pow K N data hKr theorem frobeniusGeomLevel_injective : Function.Injective (frobeniusGeomLevel K N data hKr) := by intro x y h have h' := congrArg (fun z : modularFunctionFieldC K N => (z : LaurentSeries K)) h simp only [frobeniusGeomLevel_apply_coe] at h' exact Subtype.ext (qExpand_injective _ h') theorem exists_frobeniusGeomLevel_eq_iff (x : modularFunctionFieldC K N) : (∃ y, frobeniusGeomLevel K N data hKr y = x) ↔ (x : LaurentSeries K) ∈ frobeniusGeomLevelImage K N (ℓ := ℓ) := by constructor · rintro ⟨y, rfl⟩ rw [frobeniusGeomLevel_apply_coe] exact ⟨(y : LaurentSeries K), y.2, rfl⟩ · rintro ⟨y, hy, hyx⟩ refine ⟨⟨y, hy⟩, Subtype.ext ?_⟩ rw [frobeniusGeomLevel_apply_coe] exact hyx end FrobeniusEndomorphism section PurelyInseparable variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) omit [Fact ℓ.Prime] in theorem charP_laurentSeries : CharP (LaurentSeries K) ℓ := charP_of_injective_algebraMap (algebraMap K (LaurentSeries K)).injective ℓ include data hKr in theorem pow_mem_frobeniusGeomLevelImage {x : LaurentSeries K} (hx : x ∈ modularFunctionFieldC K N) : x ^ ℓ ∈ frobeniusGeomLevelImage K N (ℓ := ℓ) := by haveI : CharP (LaurentSeries K) ℓ := charP_laurentSeries K induction hx using IntermediateField.adjoin_induction with | mem y hy => rcases hy with rfl | rfl · rw [← qExpand_jqModC_eq_pow K data hKr] exact ⟨jqModC K, jqModC_mem K N, rfl⟩ · rw [← qExpand_jqNModC_eq_pow K N data hKr] exact ⟨jqNModC K N, jqNModC_mem K N, rfl⟩ | algebraMap c => rw [← map_pow] exact (frobeniusGeomLevelImage K N (ℓ := ℓ)).algebraMap_mem (c ^ ℓ) | add y z _ _ hy hz => rw [add_pow_char] exact add_mem hy hz | inv y _ hy => rw [inv_pow] exact inv_mem hy | mul y z _ _ hy hz => rw [mul_pow] exact mul_mem hy hz theorem exists_frobeniusGeomLevel_eq_pow (x : modularFunctionFieldC K N) : ∃ y, frobeniusGeomLevel K N data hKr y = x ^ ℓ := by rw [exists_frobeniusGeomLevel_eq_iff] show (x : LaurentSeries K) ^ ℓ ∈ frobeniusGeomLevelImage K N (ℓ := ℓ) exact pow_mem_frobeniusGeomLevelImage K N data hKr x.2 theorem _root_.ValuationSubring.mem_of_pow_mem' {F : Type*} [Field F] (A : ValuationSubring F) {x : F} {n : ℕ} (hn : n ≠ 0) (h : x ^ n ∈ A) : x ∈ A := by rcases A.mem_or_inv_mem x with hx | hx · exact hx rcases eq_or_ne x 0 with rfl | hx0 · exact A.zero_mem have hpow : x ^ n = x * x ^ (n - 1) := by rw [← pow_succ'] exact congrArg (x ^ ·) (by omega) have hkey : x ^ n * (x⁻¹) ^ (n - 1) = x := by rw [hpow, inv_pow, mul_assoc, mul_inv_cancel₀ (pow_ne_zero _ hx0), mul_one] rw [← hkey] exact A.mul_mem _ _ h (pow_mem hx _) theorem mem_valuationSubring_iff_pow_mem {F : Type*} [Field F] (A : ValuationSubring F) (x : F) : x ∈ A ↔ x ^ ℓ ∈ A := ⟨fun h => pow_mem h ℓ, fun h => ValuationSubring.mem_of_pow_mem' A (Fact.out : ℓ.Prime).pos.ne' h⟩ end PurelyInseparable section PlaceLevel variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in @[reducible] def frobImageAlgebra : Algebra (frobeniusGeomLevelImage K N (ℓ := ℓ)) (modularFunctionFieldC K N) := (IntermediateField.inclusion (frobeniusGeomLevel_map_le K N data hKr)).toRingHom.toAlgebra theorem frobImageTower : letI := frobImageAlgebra K N data hKr IsScalarTower K (frobeniusGeomLevelImage K N (ℓ := ℓ)) (modularFunctionFieldC K N) := letI := frobImageAlgebra K N data hKr IsScalarTower.of_algebraMap_eq fun _ => Subtype.ext rfl theorem frobImageIsIntegral : letI := frobImageAlgebra K N data hKr Algebra.IsIntegral (frobeniusGeomLevelImage K N (ℓ := ℓ)) (modularFunctionFieldC K N) := by letI := frobImageAlgebra K N data hKr refine ⟨fun x => ?_⟩ refine ⟨Polynomial.X ^ ℓ - Polynomial.C ⟨(x : LaurentSeries K) ^ ℓ, pow_mem_frobeniusGeomLevelImage K N data hKr x.2⟩, Polynomial.monic_X_pow_sub_C _ (Fact.out : ℓ.Prime).pos.ne', ?_⟩ rw [Polynomial.eval₂_sub, Polynomial.eval₂_X_pow, Polynomial.eval₂_C, sub_eq_zero] exact Subtype.ext rfl include data hKr in def frobOnPlacesGeomLevel (w : Place K (modularFunctionFieldC K N)) : Place K (modularFunctionFieldC K N) := letI := frobImageAlgebra K N data hKr letI := frobImageTower K N data hKr letI := frobImageIsIntegral K N data hKr (Place.congrEquiv (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).toRingEquiv (fun a => (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).commutes a)).symm (w.restrict (frobeniusGeomLevelImage K N (ℓ := ℓ))) theorem mem_frobOnPlacesGeomLevel_iff (w : Place K (modularFunctionFieldC K N)) (x : modularFunctionFieldC K N) : x ∈ (frobOnPlacesGeomLevel K N data hKr w).toValuationSubring ↔ frobeniusGeomLevel K N data hKr x ∈ w.toValuationSubring := by letI := frobImageAlgebra K N data hKr letI := frobImageTower K N data hKr letI := frobImageIsIntegral K N data hKr rw [show frobOnPlacesGeomLevel K N data hKr w = (Place.congrEquiv (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).toRingEquiv (fun a => (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).commutes a)).symm (w.restrict (frobeniusGeomLevelImage K N (ℓ := ℓ))) from rfl, Place.congrEquiv_symm_apply, Place.congrRingEquiv_toValuationSubring, ValuationSubring.mem_comap, RingEquiv.symm_symm] exact Iff.rfl theorem frobOnPlacesGeomLevel_injective : Function.Injective (frobOnPlacesGeomLevel K N data hKr) := by intro w w' h ext1 refine SetLike.ext fun x => ?_ obtain ⟨y, hy⟩ := exists_frobeniusGeomLevel_eq_pow K N data hKr x rw [mem_valuationSubring_iff_pow_mem (ℓ := ℓ) w.toValuationSubring x, ← hy, ← mem_frobOnPlacesGeomLevel_iff K N data hKr w y, h, mem_frobOnPlacesGeomLevel_iff K N data hKr w' y, hy, ← mem_valuationSubring_iff_pow_mem (ℓ := ℓ) w'.toValuationSubring x] include data hKr in open Classical in def verOnPlacesGeomLevel (u : Place K (modularFunctionFieldC K N)) : Place K (modularFunctionFieldC K N) := if h : ∃ w, frobOnPlacesGeomLevel K N data hKr w = u then h.choose else u theorem verOnPlacesGeomLevel_frobOnPlacesGeomLevel (w : Place K (modularFunctionFieldC K N)) : verOnPlacesGeomLevel K N data hKr (frobOnPlacesGeomLevel K N data hKr w) = w := by rw [verOnPlacesGeomLevel, dif_pos ⟨w, rfl⟩] exact frobOnPlacesGeomLevel_injective K N data hKr (Exists.choose_spec (⟨w, rfl⟩ : ∃ w', frobOnPlacesGeomLevel K N data hKr w' = frobOnPlacesGeomLevel K N data hKr w)) end PlaceLevel section DivisorLevel variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in def frobeniusPushforwardGeomLevel : Divisor K (modularFunctionFieldC K N) →+ Divisor K (modularFunctionFieldC K N) := Finsupp.mapDomain.addMonoidHom (frobOnPlacesGeomLevel K N data hKr) include data hKr in def frobeniusPullbackGeomLevel : Divisor K (modularFunctionFieldC K N) →+ Divisor K (modularFunctionFieldC K N) := Finsupp.liftAddHom fun v => (Finsupp.singleAddHom (verOnPlacesGeomLevel K N data hKr v)).comp (AddMonoidHom.mulRight (ℓ : ℤ)) include data hKr in def heckeFibreGeomLevel : Divisor K (modularFunctionFieldC K N) →+ Divisor K (modularFunctionFieldC K N) := frobeniusPushforwardGeomLevel K N data hKr + frobeniusPullbackGeomLevel K N data hKr @[simp] theorem frobeniusPushforwardGeomLevel_single (w : Place K (modularFunctionFieldC K N)) (n : ℤ) : frobeniusPushforwardGeomLevel K N data hKr (Finsupp.single w n) = Finsupp.single (frobOnPlacesGeomLevel K N data hKr w) n := by simp [frobeniusPushforwardGeomLevel, Finsupp.mapDomain.addMonoidHom_apply, Finsupp.mapDomain_single] @[simp] theorem frobeniusPullbackGeomLevel_single (w : Place K (modularFunctionFieldC K N)) (n : ℤ) : frobeniusPullbackGeomLevel K N data hKr (Finsupp.single w n) = Finsupp.single (verOnPlacesGeomLevel K N data hKr w) (n * ℓ) := by simp [frobeniusPullbackGeomLevel] theorem frobeniusPullbackGeomLevel_frobeniusPushforwardGeomLevel (D : Divisor K (modularFunctionFieldC K N)) : frobeniusPullbackGeomLevel K N data hKr (frobeniusPushforwardGeomLevel K N data hKr D) = (ℓ : ℤ) • D := by induction D using Finsupp.induction with | zero => simp | single_add v n D _ _ ih => rw [map_add, map_add, ih, frobeniusPushforwardGeomLevel_single, frobeniusPullbackGeomLevel_single, verOnPlacesGeomLevel_frobOnPlacesGeomLevel, smul_add, Finsupp.smul_single, smul_eq_mul, mul_comm] theorem eichlerShimura_special_fibre_geom_level (D : Divisor K (modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevel K N data hKr (frobeniusPushforwardGeomLevel K N data hKr D) - heckeFibreGeomLevel K N data hKr (frobeniusPushforwardGeomLevel K N data hKr D) + (ℓ : ℤ) • D = 0 := by rw [heckeFibreGeomLevel, AddMonoidHom.add_apply, frobeniusPullbackGeomLevel_frobeniusPushforwardGeomLevel] abel end DivisorLevel section Ramification variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) theorem exists_ramification_frobenius (w : Place K (modularFunctionFieldC K N)) : ∃ e : ℕ, 0 < e ∧ (e : ℤ) ∣ (ℓ : ℤ) ∧ ∀ g : modularFunctionFieldC K N, w.ord (frobeniusGeomLevel K N data hKr g) = e * (frobOnPlacesGeomLevel K N data hKr w).ord g := by letI := frobImageAlgebra K N data hKr letI := frobImageTower K N data hKr letI := frobImageIsIntegral K N data hKr refine ⟨Place.ramificationIndex (F := frobeniusGeomLevelImage K N (ℓ := ℓ)) w, Place.ramificationIndex_pos w, ?_, fun g => ?_⟩ · obtain ⟨π, hπ⟩ := IsDiscreteValuationRing.exists_irreducible w.toValuationSubring have hπ0 : (π : modularFunctionFieldC K N) ≠ 0 := by simpa [ne_eq, ZeroMemClass.coe_eq_zero] using hπ.ne_zero obtain ⟨y, hy⟩ := exists_frobeniusGeomLevel_eq_pow K N data hKr (π : modularFunctionFieldC K N) have hy0 : (frobeniusGeomLevelEquiv K N (ℓ := ℓ)) y ≠ 0 := by intro h0 have : y = 0 := by have := congrArg (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).symm h0 rwa [AlgEquiv.symm_apply_apply, map_zero] at this rw [this, map_zero] at hy exact pow_ne_zero ℓ hπ0 hy.symm have hdvd := Place.ramificationIndex_dvd_ord (F := frobeniusGeomLevelImage K N (ℓ := ℓ)) (w := w) hy0 rw [show (algebraMap (frobeniusGeomLevelImage K N (ℓ := ℓ)) (modularFunctionFieldC K N)) ((frobeniusGeomLevelEquiv K N (ℓ := ℓ)) y) = frobeniusGeomLevel K N data hKr y from rfl, hy, ← zpow_natCast, Place.ord_zpow, Place.ord_coe_irreducible w hπ, mul_one] at hdvd exact hdvd · rw [show frobeniusGeomLevel K N data hKr g = algebraMap (frobeniusGeomLevelImage K N (ℓ := ℓ)) (modularFunctionFieldC K N) ((frobeniusGeomLevelEquiv K N (ℓ := ℓ)).toRingEquiv g) from rfl, Place.ord_restrict] congr 1 have h2 := Place.ord_congrRingEquiv (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).toRingEquiv (fun a => (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).commutes a) (frobOnPlacesGeomLevel K N data hKr w) g rw [show Place.congrRingEquiv (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).toRingEquiv (fun a => (frobeniusGeomLevelEquiv K N (ℓ := ℓ)).commutes a) (frobOnPlacesGeomLevel K N data hKr w) = w.restrict (frobeniusGeomLevelImage K N (ℓ := ℓ)) from Equiv.apply_symm_apply (Place.congrEquiv _ _) _] at h2 exact h2 end Ramification end ModularCurve namespace AlgebraicCurve namespace Place section SinglePlace variable {K F : Type*} [Field K] [Field F] [Algebra K F] (v : Place K F) theorem ord_nonneg_of_mem {f : F} (hf : f ∈ v.toValuationSubring) : 0 ≤ v.ord f := by rcases eq_or_ne f 0 with rfl | hf0 · simp obtain ⟨π, hπ⟩ := IsDiscreteValuationRing.exists_irreducible v.toValuationSubring obtain ⟨n, u, hu⟩ := IsDiscreteValuationRing.eq_unit_mul_pow_irreducible (x := (⟨f, hf⟩ : v.toValuationSubring)) (by simpa [Subtype.ext_iff] using hf0) hπ have hcoe : f = ((u : v.toValuationSubring) : F) * ((π : F) ^ (n : ℤ)) := by have h := congrArg (Subtype.val) hu push_cast at h rw [zpow_natCast] exact h rw [hcoe, v.ord_unit_smul_zpow u hπ (n : ℤ)] exact Int.natCast_nonneg n theorem mem_of_ord_nonneg {f : F} (hf : f ≠ 0) (h : 0 ≤ v.ord f) : f ∈ v.toValuationSubring := by obtain ⟨π, hπ⟩ := IsDiscreteValuationRing.exists_irreducible v.toValuationSubring obtain ⟨u, hu⟩ := v.exists_unit_mul_zpow hf hπ rw [hu, show v.ord f = (((v.ord f).toNat : ℕ) : ℤ) from (Int.toNat_of_nonneg h).symm, zpow_natCast] exact mul_mem (u : v.toValuationSubring).2 (pow_mem (π : v.toValuationSubring).2 _) theorem mem_iff_ord_nonneg {f : F} (hf : f ≠ 0) : f ∈ v.toValuationSubring ↔ 0 ≤ v.ord f := ⟨v.ord_nonneg_of_mem, v.mem_of_ord_nonneg hf⟩ theorem exists_ord_pos : ∃ f : F, f ≠ 0 ∧ 0 < v.ord f := by obtain ⟨π, hπ⟩ := IsDiscreteValuationRing.exists_irreducible v.toValuationSubring refine ⟨(π : F), ?_, ?_⟩ · simpa [ne_eq, ZeroMemClass.coe_eq_zero] using hπ.ne_zero · rw [v.ord_coe_irreducible hπ] exact one_pos end SinglePlace section RestrictPriv variable {K F F' : Type*} [Field K] [Field F] [Field F'] [Algebra K F'] [Algebra F F'] theorem algebraMap_ne_zero {f : F} (hf : f ≠ 0) : algebraMap F F' f ≠ 0 := by simpa using hf variable (w : Place K F') theorem comap_algebraMap_ne_top [Algebra.IsIntegral F F'] : w.toValuationSubring.comap (algebraMap F F') ≠ ⊤ := by intro htop apply w.ne_top' have hF : ∀ f : F, algebraMap F F' f ∈ w.toValuationSubring := fun f => ValuationSubring.mem_comap.mp (htop ▸ ValuationSubring.mem_top f) refine SetLike.ext fun x => ⟨fun _ => ValuationSubring.mem_top x, fun _ => ?_⟩ letI : Algebra F w.toValuationSubring := ((algebraMap F F').codRestrict w.toValuationSubring.toSubring hF).toAlgebra letI : IsScalarTower F w.toValuationSubring F' := IsScalarTower.of_algebraMap_eq fun f => rfl have hx : IsIntegral w.toValuationSubring x := (Algebra.IsIntegral.isIntegral (R := F) x).tower_top obtain ⟨y, hy⟩ := IsIntegrallyClosed.isIntegral_iff.mp hx exact hy ▸ y.2 variable {w} in theorem mem_comap_iff_ord_nonneg {f : F} (hf : f ≠ 0) : f ∈ w.toValuationSubring.comap (algebraMap F F') ↔ 0 ≤ w.ord (algebraMap F F' f) := by rw [ValuationSubring.mem_comap] exact w.mem_iff_ord_nonneg (algebraMap_ne_zero hf) variable {w} in theorem isUnit_mk_comap_iff {f : F} (hf : f ≠ 0) (hmem : f ∈ w.toValuationSubring.comap (algebraMap F F')) : IsUnit (⟨f, hmem⟩ : w.toValuationSubring.comap (algebraMap F F')) ↔ w.ord (algebraMap F F' f) = 0 := by constructor · rintro h obtain ⟨b, hb⟩ := isUnit_iff_exists_inv.mp h have hb' : f * (b : F) = 1 := by simpa [Subtype.ext_iff] using hb have hbne : (b : F) ≠ 0 := by intro h0 rw [h0, mul_zero] at hb' exact zero_ne_one hb' have hsum : w.ord (algebraMap F F' f) + w.ord (algebraMap F F' (b : F)) = 0 := by rw [← w.ord_mul (algebraMap_ne_zero hf) (algebraMap_ne_zero hbne), ← map_mul, hb', map_one, w.ord_one] have h1 : 0 ≤ w.ord (algebraMap F F' f) := (mem_comap_iff_ord_nonneg hf).mp hmem have h2 : 0 ≤ w.ord (algebraMap F F' (b : F)) := (mem_comap_iff_ord_nonneg hbne).mp b.2 omega · intro h0 have hinv : f⁻¹ ∈ w.toValuationSubring.comap (algebraMap F F') := (mem_comap_iff_ord_nonneg (inv_ne_zero hf)).mpr (by rw [map_inv₀, w.ord_inv]; omega) exact ⟨⟨⟨f, hmem⟩, ⟨f⁻¹, hinv⟩, Subtype.ext (mul_inv_cancel₀ hf), Subtype.ext (inv_mul_cancel₀ hf)⟩, rfl⟩ theorem exists_ord_algebraMap_pos [Algebra.IsIntegral F F'] : ∃ f : F, f ≠ 0 ∧ 0 < w.ord (algebraMap F F' f) := by have h := w.comap_algebraMap_ne_top (F := F) rw [ne_eq, SetLike.ext_iff, not_forall] at h obtain ⟨g, hg⟩ := h simp only [ValuationSubring.mem_top, iff_true] at hg have hg0 : g ≠ 0 := by rintro rfl exact hg (zero_mem _) refine ⟨g⁻¹, inv_ne_zero hg0, ?_⟩ rw [map_inv₀, w.ord_inv] have := (mem_comap_iff_ord_nonneg hg0).not.mp hg omega variable [Algebra.IsIntegral F F'] theorem ramificationIndex_set_nonempty : {n : ℕ | 0 < n ∧ ∃ f : F, f ≠ 0 ∧ w.ord (algebraMap F F' f) = n}.Nonempty := by obtain ⟨f, hf0, hf⟩ := w.exists_ord_algebraMap_pos (F := F) exact ⟨(w.ord (algebraMap F F' f)).toNat, by omega, f, hf0, by omega⟩ theorem isPrincipalIdealRing_comap : IsPrincipalIdealRing (w.toValuationSubring.comap (algebraMap F F')) := by obtain ⟨g, hg0, hge⟩ := w.exists_ord_eq_ramificationIndex (F := F) have hepos : 0 < ramificationIndex (F := F) w := w.ramificationIndex_pos (F := F) have hgmem : g ∈ w.toValuationSubring.comap (algebraMap F F') := (mem_comap_iff_ord_nonneg hg0).mpr (by omega) refine (IsDiscreteValuationRing.ofHasUnitMulPowIrreducibleFactorization ⟨⟨g, hgmem⟩, irreducible_mk_comap w hg0 hgmem hge, ?_⟩).toIsPrincipalIdealRing rintro ⟨f, hmem⟩ hx have hf : f ≠ 0 := by simpa [Subtype.ext_iff] using hx obtain ⟨c, hc⟩ := w.ramificationIndex_dvd_ord (F := F) hf have hnonneg : 0 ≤ w.ord (algebraMap F F' f) := (mem_comap_iff_ord_nonneg hf).mp hmem have hcnonneg : 0 ≤ c := by by_contra hneg have hcle : c ≤ -1 := by omega have : (ramificationIndex (F := F) w : ℤ) * c ≤ (ramificationIndex (F := F) w : ℤ) * -1 := mul_le_mul_of_nonneg_left hcle (by omega) omega set n : ℕ := c.toNat with hn have hcn : (n : ℤ) = c := Int.toNat_of_nonneg hcnonneg refine ⟨n, ?_⟩ have hgn : g ^ n ≠ 0 := pow_ne_zero _ hg0 have hdiv0 : f / g ^ n ≠ 0 := div_ne_zero hf hgn have hu0 : w.ord (algebraMap F F' (f / g ^ n)) = 0 := by have hkey : algebraMap F F' (f / g ^ n) = algebraMap F F' f * (algebraMap F F' g) ^ (-(n : ℤ)) := by rw [div_eq_mul_inv, map_mul, map_inv₀, map_pow, ← zpow_natCast (algebraMap F F' g) n, ← zpow_neg] rw [hkey, w.ord_mul (algebraMap_ne_zero hf) (zpow_ne_zero _ (algebraMap_ne_zero hg0)), w.ord_zpow, hge, hc, ← hcn] ring have humem : f / g ^ n ∈ w.toValuationSubring.comap (algebraMap F F') := (mem_comap_iff_ord_nonneg hdiv0).mpr (le_of_eq hu0.symm) have hu : IsUnit (⟨f / g ^ n, humem⟩ : w.toValuationSubring.comap (algebraMap F F')) := (isUnit_mk_comap_iff hdiv0 humem).mpr hu0 refine ⟨hu.unit, ?_⟩ refine Subtype.ext ?_ have hcoe : ((hu.unit : w.toValuationSubring.comap (algebraMap F F')) : F) = f / g ^ n := by rw [IsUnit.unit_spec] push_cast rw [hcoe, mul_comm, div_mul_cancel₀] exact hgn end RestrictPriv end Place end AlgebraicCurve noncomputable section open AlgebraicCurve Polynomial set_option synthInstance.maxHeartbeats 400000 set_option maxHeartbeats 800000 namespace ModularCurve section Package variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem exists_pow_eq_frobeniusGeomLevel (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (y : modularFunctionFieldC K N) : ∃ x : modularFunctionFieldC K N, frobeniusGeomLevel K N data hKr y = x ^ ℓ := by haveI : CharP (LaurentSeries K) ℓ := charP_laurentSeries K have key : ∀ z : LaurentSeries K, z ∈ modularFunctionFieldC K N → ∃ w : LaurentSeries K, w ∈ modularFunctionFieldC K N ∧ qExpand K ℓ z = w ^ ℓ := by intro z hz induction hz using IntermediateField.adjoin_induction with | mem y hy => rcases hy with rfl | rfl · exact ⟨jqModC K, jqModC_mem K N, qExpand_jqModC_eq_pow K data hKr⟩ · exact ⟨jqNModC K N, jqNModC_mem K N, qExpand_jqNModC_eq_pow K N data hKr⟩ | algebraMap c => obtain ⟨d, hd⟩ := hperf c refine ⟨algebraMap K (LaurentSeries K) d, (modularFunctionFieldC K N).algebraMap_mem d, ?_⟩ rw [show qExpand K ℓ (algebraMap K (LaurentSeries K) c) = qExpandAlgC K ℓ (algebraMap K (LaurentSeries K) c) from rfl, (qExpandAlgC K ℓ).commutes c, ← map_pow, hd] | add y z _ _ hy hz => obtain ⟨w₁, hw₁, he₁⟩ := hy obtain ⟨w₂, hw₂, he₂⟩ := hz refine ⟨w₁ + w₂, add_mem hw₁ hw₂, ?_⟩ rw [show qExpand K ℓ (y + z) = qExpandAlgC K ℓ (y + z) from rfl, map_add, qExpandAlgC_apply, qExpandAlgC_apply, he₁, he₂, add_pow_char] | inv y _ hy => obtain ⟨w, hw, he⟩ := hy refine ⟨w⁻¹, inv_mem hw, ?_⟩ rw [show qExpand K ℓ y⁻¹ = qExpandAlgC K ℓ y⁻¹ from rfl, map_inv₀, qExpandAlgC_apply, he, inv_pow] | mul y z _ _ hy hz => obtain ⟨w₁, hw₁, he₁⟩ := hy obtain ⟨w₂, hw₂, he₂⟩ := hz refine ⟨w₁ * w₂, mul_mem hw₁ hw₂, ?_⟩ rw [show qExpand K ℓ (y * z) = qExpandAlgC K ℓ (y * z) from rfl, map_mul, qExpandAlgC_apply, qExpandAlgC_apply, he₁, he₂, mul_pow] obtain ⟨w, hw, he⟩ := key (y : LaurentSeries K) y.2 refine ⟨⟨w, hw⟩, Subtype.ext ?_⟩ rw [frobeniusGeomLevel_apply_coe] push_cast exact he include data hKr in theorem isFrobeniusEndo_frobeniusGeomLevel (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) : IsFrobeniusEndo ℓ (frobeniusGeomLevel K N data hKr) := ⟨exists_frobeniusGeomLevel_eq_pow K N data hKr, exists_pow_eq_frobeniusGeomLevel K N data hKr hperf⟩ include data hKr in theorem frobeniusGeomLevel_isIntegral (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) : (frobeniusGeomLevel K N data hKr).toRingHom.IsIntegral := (isFrobeniusEndo_frobeniusGeomLevel K N data hKr hperf).isIntegral (Fact.out : ℓ.Prime).pos.ne' theorem frobeniusGeomLevel_eq_pow_unique {g g' f : modularFunctionFieldC K N} (hg : frobeniusGeomLevel K N data hKr g = f ^ ℓ) (hg' : frobeniusGeomLevel K N data hKr g' = f ^ ℓ) : g = g' := frobeniusGeomLevel_injective K N data hKr (hg.trans hg'.symm) end Package section Identification variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) theorem mem_restrictAlong_iff {F : Type*} [Field F] [Algebra K F] (φ : F →ₐ[K] F) (hφ : φ.toRingHom.IsIntegral) (w : Place K F) (x : F) : x ∈ (w.restrictAlong φ hφ).toValuationSubring ↔ φ x ∈ w.toValuationSubring := by rw [show (w.restrictAlong φ hφ).toValuationSubring = w.toValuationSubring.comap φ.toRingHom from rfl, ValuationSubring.mem_comap] exact Iff.rfl include data hKr in theorem restrictAlong_frobeniusGeomLevel_eq (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (w : Place K (modularFunctionFieldC K N)) : w.restrictAlong (frobeniusGeomLevel K N data hKr) (frobeniusGeomLevel_isIntegral K N data hKr hperf) = frobOnPlacesGeomLevel K N data hKr w := by refine Place.ext (SetLike.ext fun x => ?_) rw [mem_restrictAlong_iff, mem_frobOnPlacesGeomLevel_iff] end Identification section Ramification variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem ramificationIndexAlong_frobeniusGeomLevel (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (w : Place K (modularFunctionFieldC K N)) : Place.ramificationIndexAlong (frobeniusGeomLevel K N data hKr) w = ℓ := (isFrobeniusEndo_frobeniusGeomLevel K N data hKr hperf).ramificationIndexAlong_eq (Fact.out : ℓ.Prime).pos.ne' w include data hKr in theorem ord_frobeniusGeomLevel_eq_mul (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (w : Place K (modularFunctionFieldC K N)) (g : modularFunctionFieldC K N) : w.ord (frobeniusGeomLevel K N data hKr g) = ℓ * (frobOnPlacesGeomLevel K N data hKr w).ord g := by have h := w.ord_restrictAlong (frobeniusGeomLevel K N data hKr) (frobeniusGeomLevel_isIntegral K N data hKr hperf) g rwa [ramificationIndexAlong_frobeniusGeomLevel K N data hKr hperf, restrictAlong_frobeniusGeomLevel_eq K N data hKr hperf] at h include data hKr in theorem ord_frobOnPlaces_of_pow_eq (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) {f g : modularFunctionFieldC K N} (hg : frobeniusGeomLevel K N data hKr g = f ^ ℓ) (w : Place K (modularFunctionFieldC K N)) : (frobOnPlacesGeomLevel K N data hKr w).ord g = w.ord f := by have hkey : (ℓ : ℤ) * (frobOnPlacesGeomLevel K N data hKr w).ord g = (ℓ : ℤ) * w.ord f := by rw [← ord_frobeniusGeomLevel_eq_mul K N data hKr hperf w g, hg, ← zpow_natCast, Place.ord_zpow] exact mul_left_cancel₀ (Int.natCast_ne_zero.mpr (Fact.out : ℓ.Prime).pos.ne') hkey end Ramification section NormFormula variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem frobeniusPushforwardGeomLevel_apply_frob (D : Divisor K (modularFunctionFieldC K N)) (w : Place K (modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevel K N data hKr D (frobOnPlacesGeomLevel K N data hKr w) = D w := by rw [show frobeniusPushforwardGeomLevel K N data hKr D = Finsupp.mapDomain (frobOnPlacesGeomLevel K N data hKr) D from rfl] exact Finsupp.mapDomain_apply (frobOnPlacesGeomLevel_injective K N data hKr) D w include data hKr in theorem frobeniusPushforwardGeomLevel_apply_of_notMem_range (D : Divisor K (modularFunctionFieldC K N)) {v : Place K (modularFunctionFieldC K N)} (hv : v ∉ Set.range (frobOnPlacesGeomLevel K N data hKr)) : frobeniusPushforwardGeomLevel K N data hKr D v = 0 := by rw [show frobeniusPushforwardGeomLevel K N data hKr D = Finsupp.mapDomain (frobOnPlacesGeomLevel K N data hKr) D from rfl] exact Finsupp.mapDomain_notin_range D v hv include data hKr in theorem frobeniusPushforwardGeomLevel_normFormula_apply_frob (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) {f g : modularFunctionFieldC K N} (hg : frobeniusGeomLevel K N data hKr g = f ^ ℓ) {D : Divisor K (modularFunctionFieldC K N)} (hD : ∀ w, D w = w.ord f) (w : Place K (modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevel K N data hKr D (frobOnPlacesGeomLevel K N data hKr w) = (frobOnPlacesGeomLevel K N data hKr w).ord g := by rw [frobeniusPushforwardGeomLevel_apply_frob K N data hKr D w, hD w, ord_frobOnPlaces_of_pow_eq K N data hKr hperf hg w] include data hKr in theorem frobeniusPushforwardGeomLevel_normFormula (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) {f g : modularFunctionFieldC K N} (hg : frobeniusGeomLevel K N data hKr g = f ^ ℓ) {D : Divisor K (modularFunctionFieldC K N)} (hD : ∀ w, D w = w.ord f) (v : Place K (modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevel K N data hKr D v = v.ord g := by obtain ⟨w, rfl⟩ := hsurj v exact frobeniusPushforwardGeomLevel_normFormula_apply_frob K N data hKr hperf hg hD w include data hKr in theorem isPrincipal_frobeniusPushforwardGeomLevel (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) {D : Divisor K (modularFunctionFieldC K N)} (hD : D.IsPrincipal) : (frobeniusPushforwardGeomLevel K N data hKr D).IsPrincipal := by obtain ⟨f, hf, hDf⟩ := hD obtain ⟨g, hg⟩ := exists_frobeniusGeomLevel_eq_pow K N data hKr f refine ⟨g, ?_, fun v => frobeniusPushforwardGeomLevel_normFormula K N data hKr hperf hsurj hg hDf v⟩ intro hg0 rw [hg0, map_zero] at hg exact pow_ne_zero ℓ hf hg.symm end NormFormula end ModularCurve noncomputable section namespace AlgebraicCurve section FrobNormHom variable {K F : Type*} [Field K] [Field F] [Algebra K F] variable {ℓ : ℕ} {φ : F →ₐ[K] F} namespace IsFrobeniusEndo theorem frobNorm_eq_of_map_eq_pow (h : IsFrobeniusEndo ℓ φ) {f g : F} (hg : φ g = f ^ ℓ) : h.frobNorm f = g := φ.toRingHom.injective ((h.map_frobNorm f).trans hg.symm) theorem frobNorm_map (h : IsFrobeniusEndo ℓ φ) (x : F) : h.frobNorm (φ x) = x ^ ℓ := h.frobNorm_eq_of_map_eq_pow (by rw [map_pow]) theorem frobNorm_one (h : IsFrobeniusEndo ℓ φ) : h.frobNorm 1 = 1 := h.frobNorm_eq_of_map_eq_pow (by rw [map_one, one_pow]) theorem frobNorm_mul (h : IsFrobeniusEndo ℓ φ) (a b : F) : h.frobNorm (a * b) = h.frobNorm a * h.frobNorm b := h.frobNorm_eq_of_map_eq_pow (by rw [map_mul, h.map_frobNorm, h.map_frobNorm, mul_pow]) theorem frobNorm_algebraMap (h : IsFrobeniusEndo ℓ φ) (c : K) : h.frobNorm (algebraMap K F c) = algebraMap K F c ^ ℓ := h.frobNorm_eq_of_map_eq_pow (by rw [map_pow, φ.commutes]) variable [Fact ℓ.Prime] [CharP F ℓ] omit [CharP F ℓ] in theorem frobNorm_zero (h : IsFrobeniusEndo ℓ φ) : h.frobNorm 0 = 0 := h.frobNorm_eq_of_map_eq_pow (by rw [map_zero, zero_pow (Fact.out : ℓ.Prime).pos.ne']) theorem frobNorm_add (h : IsFrobeniusEndo ℓ φ) (a b : F) : h.frobNorm (a + b) = h.frobNorm a + h.frobNorm b := h.frobNorm_eq_of_map_eq_pow (by rw [map_add, h.map_frobNorm, h.map_frobNorm, add_pow_char]) def frobNormRingHom (h : IsFrobeniusEndo ℓ φ) : F →+* F where toFun := h.frobNorm map_one' := h.frobNorm_one map_mul' := h.frobNorm_mul map_zero' := h.frobNorm_zero map_add' := h.frobNorm_add @[simp] theorem frobNormRingHom_apply (h : IsFrobeniusEndo ℓ φ) (f : F) : h.frobNormRingHom f = h.frobNorm f := rfl theorem frobNormRingHom_isIntegral (h : IsFrobeniusEndo ℓ φ) : h.frobNormRingHom.IsIntegral := by intro x refine ⟨Polynomial.X ^ ℓ - Polynomial.C (φ x), Polynomial.monic_X_pow_sub_C _ (Fact.out : ℓ.Prime).pos.ne', ?_⟩ simp [Polynomial.eval₂_sub, frobNormRingHom_apply, h.frobNorm_map x] end IsFrobeniusEndo end FrobNormHom section ExtendPlace variable {K F : Type*} [Field K] [Field F] [Algebra K F] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP F ℓ] {φ : F →ₐ[K] F} namespace IsFrobeniusEndo variable (h : IsFrobeniusEndo ℓ φ) def extendPlace (v : Place K F) : Place K F where toValuationSubring := v.toValuationSubring.comap h.frobNormRingHom algebraMap_mem' a := by rw [ValuationSubring.mem_comap, frobNormRingHom_apply, h.frobNorm_algebraMap] exact pow_mem (v.algebraMap_mem' a) ℓ ne_top' := by intro htop apply v.ne_top' refine SetLike.ext fun z => ⟨fun _ => ValuationSubring.mem_top z, fun _ => ?_⟩ have hz : φ z ∈ v.toValuationSubring.comap h.frobNormRingHom := htop ▸ ValuationSubring.mem_top (φ z) rw [ValuationSubring.mem_comap, frobNormRingHom_apply, h.frobNorm_map] at hz exact (v.toValuationSubring.pow_mem_iff (Fact.out : ℓ.Prime).pos.ne' z).mp hz isPrincipalIdealRing' := by letI : Algebra F F := h.frobNormRingHom.toAlgebra haveI : Algebra.IsIntegral F F := ⟨h.frobNormRingHom_isIntegral⟩ exact v.isPrincipalIdealRing_comap (F := F) theorem mem_extendPlace_iff (v : Place K F) (y : F) : y ∈ (h.extendPlace v).toValuationSubring ↔ h.frobNorm y ∈ v.toValuationSubring := ValuationSubring.mem_comap theorem restrictAlong_extendPlace (hφ : φ.toRingHom.IsIntegral) (v : Place K F) : (h.extendPlace v).restrictAlong φ hφ = v := by refine Place.ext (SetLike.ext fun x => ?_) rw [ModularCurve.mem_restrictAlong_iff (K := K) φ hφ (h.extendPlace v) x, h.mem_extendPlace_iff, h.frobNorm_map] exact v.toValuationSubring.pow_mem_iff (Fact.out : ℓ.Prime).pos.ne' x include h in theorem restrictAlong_surjective (hφ : φ.toRingHom.IsIntegral) : Function.Surjective (Place.restrictAlong φ hφ) := fun v => ⟨h.extendPlace v, h.restrictAlong_extendPlace hφ v⟩ theorem extendPlace_restrictAlong (hℓ : ℓ ≠ 0) (hφ : φ.toRingHom.IsIntegral) (w : Place K F) : h.extendPlace (w.restrictAlong φ hφ) = w := h.restrictAlong_injective hℓ hφ (h.restrictAlong_extendPlace hφ (w.restrictAlong φ hφ)) end IsFrobeniusEndo end ExtendPlace end AlgebraicCurve namespace ModularCurve open AlgebraicCurve section LevelN variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) omit [Fact ℓ.Prime] in theorem charP_modularFunctionFieldC : CharP (modularFunctionFieldC K N) ℓ := charP_of_injective_algebraMap (algebraMap K (modularFunctionFieldC K N)).injective ℓ include data hKr in def extendPlaceGeomLevel (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (v : Place K (modularFunctionFieldC K N)) : Place K (modularFunctionFieldC K N) := haveI : CharP (modularFunctionFieldC K N) ℓ := charP_modularFunctionFieldC K N (isFrobeniusEndo_frobeniusGeomLevel K N data hKr hperf).extendPlace v include data hKr in theorem frobOnPlacesGeomLevel_extendPlaceGeomLevel (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (v : Place K (modularFunctionFieldC K N)) : frobOnPlacesGeomLevel K N data hKr (extendPlaceGeomLevel K N data hKr hperf v) = v := by haveI : CharP (modularFunctionFieldC K N) ℓ := charP_modularFunctionFieldC K N rw [extendPlaceGeomLevel, ← restrictAlong_frobeniusGeomLevel_eq K N data hKr hperf] exact (isFrobeniusEndo_frobeniusGeomLevel K N data hKr hperf).restrictAlong_extendPlace (frobeniusGeomLevel_isIntegral K N data hKr hperf) v include data hKr in theorem frobOnPlacesGeomLevel_surjective (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) : Function.Surjective (frobOnPlacesGeomLevel K N data hKr) := fun v => ⟨extendPlaceGeomLevel K N data hKr hperf v, frobOnPlacesGeomLevel_extendPlaceGeomLevel K N data hKr hperf v⟩ include data hKr in theorem frobOnPlacesGeomLevel_bijective (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) : Function.Bijective (frobOnPlacesGeomLevel K N data hKr) := ⟨frobOnPlacesGeomLevel_injective K N data hKr, frobOnPlacesGeomLevel_surjective K N data hKr hperf⟩ include data hKr in theorem verOnPlacesGeomLevel_eq_extendPlaceGeomLevel (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (u : Place K (modularFunctionFieldC K N)) : verOnPlacesGeomLevel K N data hKr u = extendPlaceGeomLevel K N data hKr hperf u := by haveI : CharP (modularFunctionFieldC K N) ℓ := charP_modularFunctionFieldC K N obtain ⟨w, rfl⟩ := frobOnPlacesGeomLevel_surjective K N data hKr hperf u rw [verOnPlacesGeomLevel_frobOnPlacesGeomLevel K N data hKr w, extendPlaceGeomLevel, ← restrictAlong_frobeniusGeomLevel_eq K N data hKr hperf] exact ((isFrobeniusEndo_frobeniusGeomLevel K N data hKr hperf).extendPlace_restrictAlong (Fact.out : ℓ.Prime).pos.ne' (frobeniusGeomLevel_isIntegral K N data hKr hperf) w).symm end LevelN section Consumers variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem frobeniusPushforwardGeomLevel_normFormula' (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) {f g : modularFunctionFieldC K N} (hg : frobeniusGeomLevel K N data hKr g = f ^ ℓ) {D : Divisor K (modularFunctionFieldC K N)} (hD : ∀ w, D w = w.ord f) (v : Place K (modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevel K N data hKr D v = v.ord g := frobeniusPushforwardGeomLevel_normFormula K N data hKr hperf (frobOnPlacesGeomLevel_surjective K N data hKr hperf) hg hD v include data hKr in theorem isPrincipal_frobeniusPushforwardGeomLevel' (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) {D : Divisor K (modularFunctionFieldC K N)} (hD : D.IsPrincipal) : (frobeniusPushforwardGeomLevel K N data hKr D).IsPrincipal := isPrincipal_frobeniusPushforwardGeomLevel K N data hKr hperf (frobOnPlacesGeomLevel_surjective K N data hKr hperf) hD end Consumers end ModularCurve noncomputable section open AlgebraicCurve Polynomial set_option synthInstance.maxHeartbeats 400000 set_option maxHeartbeats 800000 namespace ModularCurve section PlaceLevel variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem frobOnPlacesGeomLevel_verOnPlacesGeomLevel (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) (v : Place K (modularFunctionFieldC K N)) : frobOnPlacesGeomLevel K N data hKr (verOnPlacesGeomLevel K N data hKr v) = v := by obtain ⟨u, rfl⟩ := hsurj v rw [verOnPlacesGeomLevel_frobOnPlacesGeomLevel K N data hKr u] include data hKr in theorem verOnPlacesGeomLevel_eq_iff (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) {v w : Place K (modularFunctionFieldC K N)} : verOnPlacesGeomLevel K N data hKr v = w ↔ v = frobOnPlacesGeomLevel K N data hKr w := by constructor · rintro rfl rw [frobOnPlacesGeomLevel_verOnPlacesGeomLevel K N data hKr hsurj v] · rintro rfl rw [verOnPlacesGeomLevel_frobOnPlacesGeomLevel K N data hKr w] end PlaceLevel section Evaluation variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem frobeniusPullbackGeomLevel_apply (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) (D : Divisor K (modularFunctionFieldC K N)) (w : Place K (modularFunctionFieldC K N)) : frobeniusPullbackGeomLevel K N data hKr D w = D (frobOnPlacesGeomLevel K N data hKr w) * ℓ := by induction D using Finsupp.induction with | zero => simp | single_add v n D _ _ ih => rw [map_add, Finsupp.add_apply, ih, frobeniusPullbackGeomLevel_single, Finsupp.add_apply, add_mul] congr 1 by_cases hvw : v = frobOnPlacesGeomLevel K N data hKr w · subst hvw rw [verOnPlacesGeomLevel_frobOnPlacesGeomLevel K N data hKr w, Finsupp.single_eq_same, Finsupp.single_eq_same] · have hne : verOnPlacesGeomLevel K N data hKr v ≠ w := fun h => hvw ((verOnPlacesGeomLevel_eq_iff K N data hKr hsurj).mp h) rw [Finsupp.single_eq_of_ne' hne, Finsupp.single_eq_of_ne' hvw, zero_mul] end Evaluation section Principal variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) include data hKr in theorem frobeniusPullbackGeomLevel_pullbackFormula (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) {f : modularFunctionFieldC K N} {D : Divisor K (modularFunctionFieldC K N)} (hD : ∀ w, D w = w.ord f) (w : Place K (modularFunctionFieldC K N)) : frobeniusPullbackGeomLevel K N data hKr D w = w.ord (frobeniusGeomLevel K N data hKr f) := by rw [frobeniusPullbackGeomLevel_apply K N data hKr hsurj D w, hD (frobOnPlacesGeomLevel K N data hKr w), ord_frobeniusGeomLevel_eq_mul K N data hKr hperf w f, mul_comm] include data hKr in theorem isPrincipal_frobeniusPullbackGeomLevel' (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) {D : Divisor K (modularFunctionFieldC K N)} (hD : D.IsPrincipal) : (frobeniusPullbackGeomLevel K N data hKr D).IsPrincipal := by obtain ⟨f, hf, hDf⟩ := hD refine ⟨frobeniusGeomLevel K N data hKr f, ?_, fun w => frobeniusPullbackGeomLevel_pullbackFormula K N data hKr hperf hsurj hDf w⟩ intro h0 exact hf (frobeniusGeomLevel_injective K N data hKr (h0.trans (map_zero _).symm)) include data hKr in theorem isPrincipal_heckeFibreGeomLevel' (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) (hsurj : Function.Surjective (frobOnPlacesGeomLevel K N data hKr)) {D : Divisor K (modularFunctionFieldC K N)} (hD : D.IsPrincipal) : (heckeFibreGeomLevel K N data hKr D).IsPrincipal := by have hpush := isPrincipal_frobeniusPushforwardGeomLevel' K N data hKr hperf hD have hpull := isPrincipal_frobeniusPullbackGeomLevel' K N data hKr hperf hsurj hD obtain ⟨g, hg, hDg⟩ := hpush obtain ⟨h, hh, hDh⟩ := hpull refine ⟨g * h, mul_ne_zero hg hh, fun v => ?_⟩ have key : heckeFibreGeomLevel K N data hKr D = frobeniusPushforwardGeomLevel K N data hKr D + frobeniusPullbackGeomLevel K N data hKr D := rfl rw [key, Finsupp.add_apply, hDg v, hDh v, v.ord_mul hg hh] end Principal end ModularCurve noncomputable section open AlgebraicCurve set_option synthInstance.maxHeartbeats 400000 set_option maxHeartbeats 800000 namespace ModularCurve section DegreePlace variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) variable (hdeg1 : ∀ w : Place K (modularFunctionFieldC K N), w.deg = 1) include data hKr hdeg1 in theorem deg_frobOnPlacesGeomLevel (w : Place K (modularFunctionFieldC K N)) : (frobOnPlacesGeomLevel K N data hKr w).deg = w.deg := by rw [hdeg1 (frobOnPlacesGeomLevel K N data hKr w), hdeg1 w] include data hKr hdeg1 in theorem deg_verOnPlacesGeomLevel (w : Place K (modularFunctionFieldC K N)) : (verOnPlacesGeomLevel K N data hKr w).deg = w.deg := by rw [hdeg1 (verOnPlacesGeomLevel K N data hKr w), hdeg1 w] end DegreePlace section DegreeDivisor variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) variable (hdeg1 : ∀ w : Place K (modularFunctionFieldC K N), w.deg = 1) include data hKr hdeg1 in theorem degree_frobeniusPushforwardGeomLevel (D : Divisor K (modularFunctionFieldC K N)) : Divisor.degree (frobeniusPushforwardGeomLevel K N data hKr D) = Divisor.degree D := by induction D using Finsupp.induction with | zero => simp | single_add v n D _ _ ih => rw [map_add, map_add, ih, frobeniusPushforwardGeomLevel_single, map_add, Divisor.degree_single, Divisor.degree_single, deg_frobOnPlacesGeomLevel K N data hKr hdeg1 v] include data hKr hdeg1 in theorem degree_frobeniusPullbackGeomLevel (D : Divisor K (modularFunctionFieldC K N)) : Divisor.degree (frobeniusPullbackGeomLevel K N data hKr D) = ℓ * Divisor.degree D := by induction D using Finsupp.induction with | zero => simp | single_add v n D _ _ ih => rw [map_add, map_add, ih, frobeniusPullbackGeomLevel_single, map_add, Divisor.degree_single, Divisor.degree_single, deg_verOnPlacesGeomLevel K N data hKr hdeg1 v, mul_add] ring include data hKr hdeg1 in theorem degree_heckeFibreGeomLevel (D : Divisor K (modularFunctionFieldC K N)) : Divisor.degree (heckeFibreGeomLevel K N data hKr D) = (ℓ + 1) * Divisor.degree D := by rw [show heckeFibreGeomLevel K N data hKr D = frobeniusPushforwardGeomLevel K N data hKr D + frobeniusPullbackGeomLevel K N data hKr D from rfl, map_add, degree_frobeniusPushforwardGeomLevel K N data hKr hdeg1 D, degree_frobeniusPullbackGeomLevel K N data hKr hdeg1 D] ring include data hKr hdeg1 in theorem frobeniusPushforwardGeomLevel_mem_degZero {D : Divisor K (modularFunctionFieldC K N)} (hD : D ∈ Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevel K N data hKr D ∈ Divisor.degZero (K := K) (F := modularFunctionFieldC K N) := by rw [Divisor.mem_degZero] at hD ⊢ rw [degree_frobeniusPushforwardGeomLevel K N data hKr hdeg1 D, hD] include data hKr hdeg1 in theorem frobeniusPullbackGeomLevel_mem_degZero {D : Divisor K (modularFunctionFieldC K N)} (hD : D ∈ Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : frobeniusPullbackGeomLevel K N data hKr D ∈ Divisor.degZero (K := K) (F := modularFunctionFieldC K N) := by rw [Divisor.mem_degZero] at hD ⊢ rw [degree_frobeniusPullbackGeomLevel K N data hKr hdeg1 D, hD, mul_zero] include data hKr hdeg1 in theorem heckeFibreGeomLevel_mem_degZero {D : Divisor K (modularFunctionFieldC K N)} (hD : D ∈ Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : heckeFibreGeomLevel K N data hKr D ∈ Divisor.degZero (K := K) (F := modularFunctionFieldC K N) := by rw [Divisor.mem_degZero] at hD ⊢ rw [degree_heckeFibreGeomLevel K N data hKr hdeg1 D, hD, mul_zero] include data hKr hdeg1 in def frobeniusPushforwardGeomLevelDegZero : Divisor.degZero (K := K) (F := modularFunctionFieldC K N) →+ Divisor.degZero (K := K) (F := modularFunctionFieldC K N) := ((frobeniusPushforwardGeomLevel K N data hKr).domRestrict (Divisor.degZero (K := K) (F := modularFunctionFieldC K N))).codRestrict _ (fun D => frobeniusPushforwardGeomLevel_mem_degZero K N data hKr hdeg1 D.2) @[simp] theorem coe_frobeniusPushforwardGeomLevelDegZero (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : (frobeniusPushforwardGeomLevelDegZero K N data hKr hdeg1 D : Divisor K (modularFunctionFieldC K N)) = frobeniusPushforwardGeomLevel K N data hKr (D : Divisor K (modularFunctionFieldC K N)) := rfl include data hKr hdeg1 in def frobeniusPullbackGeomLevelDegZero : Divisor.degZero (K := K) (F := modularFunctionFieldC K N) →+ Divisor.degZero (K := K) (F := modularFunctionFieldC K N) := ((frobeniusPullbackGeomLevel K N data hKr).domRestrict (Divisor.degZero (K := K) (F := modularFunctionFieldC K N))).codRestrict _ (fun D => frobeniusPullbackGeomLevel_mem_degZero K N data hKr hdeg1 D.2) @[simp] theorem coe_frobeniusPullbackGeomLevelDegZero (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : (frobeniusPullbackGeomLevelDegZero K N data hKr hdeg1 D : Divisor K (modularFunctionFieldC K N)) = frobeniusPullbackGeomLevel K N data hKr (D : Divisor K (modularFunctionFieldC K N)) := rfl include data hKr hdeg1 in def heckeFibreGeomLevelDegZero : Divisor.degZero (K := K) (F := modularFunctionFieldC K N) →+ Divisor.degZero (K := K) (F := modularFunctionFieldC K N) := ((heckeFibreGeomLevel K N data hKr).domRestrict (Divisor.degZero (K := K) (F := modularFunctionFieldC K N))).codRestrict _ (fun D => heckeFibreGeomLevel_mem_degZero K N data hKr hdeg1 D.2) @[simp] theorem coe_heckeFibreGeomLevelDegZero (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : (heckeFibreGeomLevelDegZero K N data hKr hdeg1 D : Divisor K (modularFunctionFieldC K N)) = heckeFibreGeomLevel K N data hKr (D : Divisor K (modularFunctionFieldC K N)) := rfl include data hKr hdeg1 in theorem heckeFibreGeomLevelDegZero_eq_add (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : heckeFibreGeomLevelDegZero K N data hKr hdeg1 D = frobeniusPushforwardGeomLevelDegZero K N data hKr hdeg1 D + frobeniusPullbackGeomLevelDegZero K N data hKr hdeg1 D := Subtype.ext rfl end DegreeDivisor section Pic0Ops variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) variable (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) variable (hdeg1 : ∀ w : Place K (modularFunctionFieldC K N), w.deg = 1) include data hKr hperf hdeg1 in def frobeniusPushforwardGeomLevelPic0 : Pic0 K (modularFunctionFieldC K N) →+ Pic0 K (modularFunctionFieldC K N) := QuotientAddGroup.map _ _ (frobeniusPushforwardGeomLevelDegZero K N data hKr hdeg1) (by rintro ⟨D, hD0⟩ hD simp only [AddSubgroup.mem_addSubgroupOf] at hD ⊢ exact isPrincipal_frobeniusPushforwardGeomLevel' K N data hKr hperf hD) @[simp] theorem frobeniusPushforwardGeomLevelPic0_mk (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevelPic0 K N data hKr hperf hdeg1 (Pic0.mk D) = Pic0.mk (frobeniusPushforwardGeomLevelDegZero K N data hKr hdeg1 D) := rfl include data hKr hperf hdeg1 in def frobeniusPullbackGeomLevelPic0 : Pic0 K (modularFunctionFieldC K N) →+ Pic0 K (modularFunctionFieldC K N) := QuotientAddGroup.map _ _ (frobeniusPullbackGeomLevelDegZero K N data hKr hdeg1) (by rintro ⟨D, hD0⟩ hD simp only [AddSubgroup.mem_addSubgroupOf] at hD ⊢ exact isPrincipal_frobeniusPullbackGeomLevel' K N data hKr hperf (frobOnPlacesGeomLevel_surjective K N data hKr hperf) hD) @[simp] theorem frobeniusPullbackGeomLevelPic0_mk (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : frobeniusPullbackGeomLevelPic0 K N data hKr hperf hdeg1 (Pic0.mk D) = Pic0.mk (frobeniusPullbackGeomLevelDegZero K N data hKr hdeg1 D) := rfl include data hKr hperf hdeg1 in def heckeFibreGeomLevelPic0 : Pic0 K (modularFunctionFieldC K N) →+ Pic0 K (modularFunctionFieldC K N) := QuotientAddGroup.map _ _ (heckeFibreGeomLevelDegZero K N data hKr hdeg1) (by rintro ⟨D, hD0⟩ hD simp only [AddSubgroup.mem_addSubgroupOf] at hD ⊢ exact isPrincipal_heckeFibreGeomLevel' K N data hKr hperf (frobOnPlacesGeomLevel_surjective K N data hKr hperf) hD) @[simp] theorem heckeFibreGeomLevelPic0_mk (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : heckeFibreGeomLevelPic0 K N data hKr hperf hdeg1 (Pic0.mk D) = Pic0.mk (heckeFibreGeomLevelDegZero K N data hKr hdeg1 D) := rfl include data hKr hperf hdeg1 in theorem heckeFibreGeomLevelPic0_eq_add (x : Pic0 K (modularFunctionFieldC K N)) : heckeFibreGeomLevelPic0 K N data hKr hperf hdeg1 x = frobeniusPushforwardGeomLevelPic0 K N data hKr hperf hdeg1 x + frobeniusPullbackGeomLevelPic0 K N data hKr hperf hdeg1 x := by obtain ⟨D, rfl⟩ := Pic0.mk_surjective x rw [heckeFibreGeomLevelPic0_mk, frobeniusPushforwardGeomLevelPic0_mk, frobeniusPullbackGeomLevelPic0_mk, ← Pic0.mk_add, heckeFibreGeomLevelDegZero_eq_add K N data hKr hdeg1 D] include data hKr hperf hdeg1 in theorem frobeniusPullbackGeomLevelPic0_frobeniusPushforwardGeomLevelPic0 (x : Pic0 K (modularFunctionFieldC K N)) : frobeniusPullbackGeomLevelPic0 K N data hKr hperf hdeg1 (frobeniusPushforwardGeomLevelPic0 K N data hKr hperf hdeg1 x) = (ℓ : ℤ) • x := by obtain ⟨D, rfl⟩ := Pic0.mk_surjective x rw [frobeniusPushforwardGeomLevelPic0_mk, frobeniusPullbackGeomLevelPic0_mk, show ((ℓ : ℤ) • Pic0.mk D : Pic0 K (modularFunctionFieldC K N)) = Pic0.mk ((ℓ : ℤ) • D) from rfl] refine congrArg Pic0.mk (Subtype.ext ?_) exact frobeniusPullbackGeomLevel_frobeniusPushforwardGeomLevel K N data hKr (D : Divisor K (modularFunctionFieldC K N)) end Pic0Ops section Relation variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) variable (hperf : ∀ c : K, ∃ d : K, d ^ ℓ = c) variable (hdeg1 : ∀ w : Place K (modularFunctionFieldC K N), w.deg = 1) include data hKr hperf hdeg1 in theorem eichlerShimura_special_fibre_pic0_level (x : Pic0 K (modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevelPic0 K N data hKr hperf hdeg1 (frobeniusPushforwardGeomLevelPic0 K N data hKr hperf hdeg1 x) - heckeFibreGeomLevelPic0 K N data hKr hperf hdeg1 (frobeniusPushforwardGeomLevelPic0 K N data hKr hperf hdeg1 x) + (ℓ : ℤ) • x = 0 := by obtain ⟨D, rfl⟩ := Pic0.mk_surjective x rw [frobeniusPushforwardGeomLevelPic0_mk, frobeniusPushforwardGeomLevelPic0_mk, heckeFibreGeomLevelPic0_mk, show ((ℓ : ℤ) • Pic0.mk D : Pic0 K (modularFunctionFieldC K N)) = Pic0.mk ((ℓ : ℤ) • D) from rfl, show (Pic0.mk _ - Pic0.mk _ + Pic0.mk ((ℓ : ℤ) • D) : Pic0 K (modularFunctionFieldC K N)) = Pic0.mk (frobeniusPushforwardGeomLevelDegZero K N data hKr hdeg1 (frobeniusPushforwardGeomLevelDegZero K N data hKr hdeg1 D) - heckeFibreGeomLevelDegZero K N data hKr hdeg1 (frobeniusPushforwardGeomLevelDegZero K N data hKr hdeg1 D) + (ℓ : ℤ) • D) from rfl] refine congrArg Pic0.mk (Subtype.ext ?_) push_cast exact eichlerShimura_special_fibre_geom_level K N data hKr (D : Divisor K (modularFunctionFieldC K N)) end Relation end ModularCurve noncomputable section open AlgebraicCurve set_option synthInstance.maxHeartbeats 400000 set_option maxHeartbeats 800000 namespace ModularCurve variable (K : Type*) [Field K] theorem perfect_of_isAlgClosed [IsAlgClosed K] {ℓ : ℕ} [hℓ : Fact ℓ.Prime] : ∀ c : K, ∃ d : K, d ^ ℓ = c := fun c => IsAlgClosed.exists_pow_nat_eq c hℓ.out.pos variable (N : ℕ) [NeZero N] variable [IsAlgClosed K] [IsCurveOver K (modularFunctionFieldC K N)] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) def frobeniusPushforwardGeomLevelPic0OfIsCurveOver : Pic0 K (modularFunctionFieldC K N) →+ Pic0 K (modularFunctionFieldC K N) := frobeniusPushforwardGeomLevelPic0 K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) def frobeniusPullbackGeomLevelPic0OfIsCurveOver : Pic0 K (modularFunctionFieldC K N) →+ Pic0 K (modularFunctionFieldC K N) := frobeniusPullbackGeomLevelPic0 K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) def heckeFibreGeomLevelPic0OfIsCurveOver : Pic0 K (modularFunctionFieldC K N) →+ Pic0 K (modularFunctionFieldC K N) := heckeFibreGeomLevelPic0 K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) theorem frobeniusPushforwardGeomLevelPic0OfIsCurveOver_eq : frobeniusPushforwardGeomLevelPic0OfIsCurveOver K N data hKr = frobeniusPushforwardGeomLevelPic0 K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) := rfl theorem heckeFibreGeomLevelPic0OfIsCurveOver_eq : heckeFibreGeomLevelPic0OfIsCurveOver K N data hKr = heckeFibreGeomLevelPic0 K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) := rfl @[simp] theorem frobeniusPushforwardGeomLevelPic0OfIsCurveOver_mk (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevelPic0OfIsCurveOver K N data hKr (Pic0.mk D) = Pic0.mk (frobeniusPushforwardGeomLevelDegZero K N data hKr (deg_eq_one_modularFunctionFieldC K N) D) := rfl @[simp] theorem frobeniusPullbackGeomLevelPic0OfIsCurveOver_mk (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : frobeniusPullbackGeomLevelPic0OfIsCurveOver K N data hKr (Pic0.mk D) = Pic0.mk (frobeniusPullbackGeomLevelDegZero K N data hKr (deg_eq_one_modularFunctionFieldC K N) D) := rfl @[simp] theorem heckeFibreGeomLevelPic0OfIsCurveOver_mk (D : Divisor.degZero (K := K) (F := modularFunctionFieldC K N)) : heckeFibreGeomLevelPic0OfIsCurveOver K N data hKr (Pic0.mk D) = Pic0.mk (heckeFibreGeomLevelDegZero K N data hKr (deg_eq_one_modularFunctionFieldC K N) D) := rfl theorem heckeFibreGeomLevelPic0OfIsCurveOver_eq_add (x : Pic0 K (modularFunctionFieldC K N)) : heckeFibreGeomLevelPic0OfIsCurveOver K N data hKr x = frobeniusPushforwardGeomLevelPic0OfIsCurveOver K N data hKr x + frobeniusPullbackGeomLevelPic0OfIsCurveOver K N data hKr x := heckeFibreGeomLevelPic0_eq_add K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) x theorem frobeniusPullbackPushforwardGeomLevelPic0OfIsCurveOver (x : Pic0 K (modularFunctionFieldC K N)) : frobeniusPullbackGeomLevelPic0OfIsCurveOver K N data hKr (frobeniusPushforwardGeomLevelPic0OfIsCurveOver K N data hKr x) = (ℓ : ℤ) • x := frobeniusPullbackGeomLevelPic0_frobeniusPushforwardGeomLevelPic0 K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) x theorem eichlerShimura_special_fibre_pic0_level_of_isCurveOver (x : Pic0 K (modularFunctionFieldC K N)) : frobeniusPushforwardGeomLevelPic0OfIsCurveOver K N data hKr (frobeniusPushforwardGeomLevelPic0OfIsCurveOver K N data hKr x) - heckeFibreGeomLevelPic0OfIsCurveOver K N data hKr (frobeniusPushforwardGeomLevelPic0OfIsCurveOver K N data hKr x) + (ℓ : ℤ) • x = 0 := eichlerShimura_special_fibre_pic0_level K N data hKr (perfect_of_isAlgClosed K) (deg_eq_one_modularFunctionFieldC K N) x end ModularCurve namespace ModularCurve open AlgebraicCurve section FamilyProps variable (K : Type*) [Field K] def IsCurveOverModularFunctionFieldCFamily : Prop := ∀ (N : ℕ), [NeZero N] → IsCurveOver K (modularFunctionFieldC K N) theorem isCurveOverModularFunctionFieldCFamily_iff : IsCurveOverModularFunctionFieldCFamily K ↔ ∀ (N : ℕ), [NeZero N] → IsCurveOver K (modularFunctionFieldC K N) := Iff.rfl theorem isCurveOver_modularFunctionFieldC_of_family (hfam : IsCurveOverModularFunctionFieldCFamily K) (N : ℕ) [NeZero N] : IsCurveOver K (modularFunctionFieldC K N) := hfam N variable (N : ℕ) [NeZero N] variable [IsAlgClosed K] [IsCurveOver K (modularFunctionFieldC K N)] variable {ℓ : ℕ} [hℓ : Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) def SpecialFibreHeckeModuleMatch (inst : Module HeckeAlg (Pic0 K (modularFunctionFieldC K N))) : Prop := ∀ x : Pic0 K (modularFunctionFieldC K N), letI := inst heckeGen ⟨ℓ, hℓ.out⟩ • x = heckeFibreGeomLevelPic0OfIsCurveOver K N data hKr x theorem specialFibreHeckeModuleMatch_iff (inst : Module HeckeAlg (Pic0 K (modularFunctionFieldC K N))) : SpecialFibreHeckeModuleMatch K N data hKr inst ↔ ∀ x, (letI := inst; heckeGen ⟨ℓ, hℓ.out⟩ • x) = heckeFibreGeomLevelPic0OfIsCurveOver K N data hKr x := Iff.rfl end FamilyProps end ModularCurve