import Mathlib import Definitions.Def_ModularCurve_QAdicPlaceMod import Definitions.Def_ModularCurve_CharLFrobeniusGeomLevel import Definitions.Def_ModularCurve_SpecializeModuli import Definitions.Def_AlgebraicCurve_PlaceEvaluation import Theorems.Thm_AlgebraicCurve_Place_evalAt_congr import Theorems.Thm_AlgebraicCurve_Place_evalAt_ne_zero import Theorems.Thm_AlgebraicCurve_Place_evalAt_algebraMap set_option autoImplicit false set_option synthInstance.maxHeartbeats 400000 set_option maxHeartbeats 800000 namespace AlgebraicCurve.Place open IsDedekindDomain WithZero IsLocalRing variable {K F : Type*} [Field K] [Field F] [Algebra K F] (v : Place K F) theorem mk_mem_maximalIdeal_of_ord_pos {f : F} (hf : f ∈ v.toValuationSubring) (h : 0 < v.ord f) : (⟨f, hf⟩ : v.toValuationSubring) ∈ IsLocalRing.maximalIdeal v.toValuationSubring := by rcases eq_or_ne f 0 with rfl | hf0 · exact Submodule.zero_mem _ rw [v.mem_maximalIdeal_iff_adicValuation_lt_one] have hne : v.adicValuation f ≠ 0 := v.adicValuation_ne_zero hf0 rw [← exp_log hne, show (1 : ℤᵐ⁰) = exp 0 from rfl, exp_lt_exp] have : v.ord f = -log (v.adicValuation f) := rfl omega end AlgebraicCurve.Place noncomputable section open AlgebraicCurve Polynomial namespace ModularCurve variable (K : Type*) [Field K] in def evalAtJGeom : Polynomial ℤ →+* LaurentSeries K := Polynomial.eval₂RingHom (Int.castRingHom (LaurentSeries K)) (jqModC K) variable (K : Type*) [Field K] in theorem evalAtJGeom_X : evalAtJGeom K Polynomial.X = jqModC K := Polynomial.eval₂_X _ _ variable (K : Type*) [Field K] in theorem laurentMap_comp_evalAtJInt_geom : (laurentMap (Int.castRingHom K)).comp evalAtJInt = evalAtJGeom K := by refine Polynomial.ringHom_ext' (Subsingleton.elim _ _) ?_ rw [RingHom.comp_apply, evalAtJInt_X, evalAtJGeom_X, jqModC, jqInt, map_mul, laurentMap_single, laurentMap_ofPowerSeries, map_one] variable (K : Type*) [Field K] in theorem laurentMap_jqIntN_geom (N : ℕ) [NeZero N] : laurentMap (Int.castRingHom K) (jqIntN N) = jqNModC K N := by rw [jqIntN, laurentMap_qExpand, jqNModC, jqModC, jqInt, map_mul, laurentMap_single, laurentMap_ofPowerSeries, map_one] variable {N : ℕ} [NeZero N] in theorem ModularPolynomialData.eval_int_eq_zero (data : ModularPolynomialData N) : data.Φ.eval₂ evalAtJInt (jqIntN N) = 0 := by refine laurentMap_injective (f := Int.castRingHom ℚ) Int.cast_injective ?_ rw [map_zero, Polynomial.hom_eval₂, laurentMap_comp_evalAtJInt, laurentMap_jqIntN] exact data.eval_eq_zero variable (K : Type*) [Field K] {N : ℕ} [NeZero N] in theorem eval_int_eq_zero_geom (data : ModularPolynomialData N) : data.Φ.eval₂ (evalAtJGeom K) (jqNModC K N) = 0 := by have h := congrArg (laurentMap (Int.castRingHom K)) data.eval_int_eq_zero rwa [map_zero, Polynomial.hom_eval₂, laurentMap_comp_evalAtJInt_geom, laurentMap_jqIntN_geom] at h section Generators variable (K : Type*) [Field K] (N : ℕ) [NeZero N] def jGeomGen : modularFunctionFieldC K N := ⟨jqModC K, jqModC_mem K N⟩ def jNGeomGen : modularFunctionFieldC K N := ⟨jqNModC K N, jqNModC_mem K N⟩ @[simp] theorem coe_jGeomGen : ((jGeomGen K N : modularFunctionFieldC K N) : LaurentSeries K) = jqModC K := rfl @[simp] theorem coe_jNGeomGen : ((jNGeomGen K N : modularFunctionFieldC K N) : LaurentSeries K) = jqNModC K N := rfl theorem jNGeomGen_one : jNGeomGen K 1 = jGeomGen K 1 := Subtype.ext (jqNModC_one K) theorem transcendental_jqNModC : Transcendental K (jqNModC K N) := by refine transcendental_iff.mpr fun p hp => ?_ refine transcendental_iff.mp (transcendental_jqModC K) p ?_ refine qExpand_injective N ?_ rw [map_zero] calc qExpand K N (Polynomial.aeval (jqModC K) p) = qExpandAlgC K N (Polynomial.aeval (jqModC K) p) := rfl _ = Polynomial.aeval (qExpandAlgC K N (jqModC K)) p := (Polynomial.aeval_algHom_apply _ _ _).symm _ = Polynomial.aeval (jqNModC K N) p := rfl _ = 0 := hp theorem jGeomGen_sub_algebraMap_ne_zero (a : K) : jGeomGen K N - algebraMap K (modularFunctionFieldC K N) a ≠ 0 := by rw [sub_ne_zero] intro h have hcoe : jqModC K = algebraMap K (LaurentSeries K) a := by have := congrArg (fun z : modularFunctionFieldC K N => (z : LaurentSeries K)) h simpa using this exact transcendental_jqModC K (hcoe ▸ isAlgebraic_algebraMap a) theorem jNGeomGen_sub_algebraMap_ne_zero (a : K) : jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) a ≠ 0 := by rw [sub_ne_zero] intro h have hcoe : jqNModC K N = algebraMap K (LaurentSeries K) a := by have := congrArg (fun z : modularFunctionFieldC K N => (z : LaurentSeries K)) h simpa using this exact transcendental_jqNModC K N (hcoe ▸ isAlgebraic_algebraMap a) end Generators section Evaluation variable {R S : Type*} [CommRing R] [CommRing S] def evalModularPair (x y : R) (Φ : Polynomial (Polynomial ℤ)) : R := Φ.eval₂ (Polynomial.eval₂RingHom (Int.castRingHom R) x) y theorem map_evalModularPair (φ : R →+* S) (x y : R) (Φ : Polynomial (Polynomial ℤ)) : φ (evalModularPair x y Φ) = evalModularPair (φ x) (φ y) Φ := by unfold evalModularPair rw [Polynomial.hom_eval₂] congr 1 refine Polynomial.ringHom_ext' (Subsingleton.elim _ _) ?_ simp only [RingHom.comp_apply, coe_eval₂RingHom, eval₂_X] theorem evalModularPair_jq_eq_zero (K : Type*) [Field K] {N : ℕ} [NeZero N] (data : ModularPolynomialData N) : evalModularPair (jqModC K) (jqNModC K N) data.Φ = 0 := eval_int_eq_zero_geom K data theorem evalModularPair_jGeomGen_eq_zero (K : Type*) [Field K] (N : ℕ) [NeZero N] (data : ModularPolynomialData N) : evalModularPair (jGeomGen K N) (jNGeomGen K N) data.Φ = 0 := by have hval := map_evalModularPair (modularFunctionFieldC K N).val.toRingHom (jGeomGen K N) (jNGeomGen K N) data.Φ have hgen : (modularFunctionFieldC K N).val.toRingHom (jGeomGen K N) = jqModC K := rfl have hgenN : (modularFunctionFieldC K N).val.toRingHom (jNGeomGen K N) = jqNModC K N := rfl rw [hgen, hgenN, evalModularPair_jq_eq_zero K data] at hval exact (map_eq_zero_iff _ (modularFunctionFieldC K N).val.toRingHom.injective).mp hval end Evaluation section Centre variable (K : Type*) [Field K] (N : ℕ) [NeZero N] def IsCentreOf (c : K × K) (w : Place K (modularFunctionFieldC K N)) : Prop := 0 < w.ord (jGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.1) ∧ 0 < w.ord (jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.2) variable {K N} variable {c : K × K} {w : Place K (modularFunctionFieldC K N)} theorem IsCentreOf.jGeomGen_mem (h : IsCentreOf K N c w) : jGeomGen K N ∈ w.toValuationSubring := by have hmem : jGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.1 ∈ w.toValuationSubring := w.mem_of_ord_nonneg (jGeomGen_sub_algebraMap_ne_zero K N c.1) h.1.le have := add_mem hmem (w.algebraMap_mem' c.1) rwa [sub_add_cancel] at this theorem IsCentreOf.jNGeomGen_mem (h : IsCentreOf K N c w) : jNGeomGen K N ∈ w.toValuationSubring := by have hmem : jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.2 ∈ w.toValuationSubring := w.mem_of_ord_nonneg (jNGeomGen_sub_algebraMap_ne_zero K N c.2) h.2.le have := add_mem hmem (w.algebraMap_mem' c.2) rwa [sub_add_cancel] at this theorem IsCentreOf.evalAt_jGeomGen (h : IsCentreOf K N c w) : w.evalAt (jGeomGen K N) = c.1 := by have hcongr := w.evalAt_congr h.jGeomGen_mem (w.algebraMap_mem' c.1) (Or.inr h.1) rw [hcongr, w.evalAt_algebraMap] theorem IsCentreOf.evalAt_jNGeomGen (h : IsCentreOf K N c w) : w.evalAt (jNGeomGen K N) = c.2 := by have hcongr := w.evalAt_congr h.jNGeomGen_mem (w.algebraMap_mem' c.2) (Or.inr h.2) rw [hcongr, w.evalAt_algebraMap] theorem IsCentreOf.eq {c' : K × K} (h : IsCentreOf K N c w) (h' : IsCentreOf K N c' w) : c = c' := by have h1 : c.1 = c'.1 := by rw [← h.evalAt_jGeomGen, h'.evalAt_jGeomGen] have h2 : c.2 = c'.2 := by rw [← h.evalAt_jNGeomGen, h'.evalAt_jNGeomGen] exact Prod.ext h1 h2 theorem IsCentreOf.ne_of_ne {c' : K × K} {w' : Place K (modularFunctionFieldC K N)} (h : IsCentreOf K N c w) (h' : IsCentreOf K N c' w') (hcc : c ≠ c') : w ≠ w' := by rintro rfl exact hcc (h.eq h') theorem IsCentreOf.mk_sub_mem_maximalIdeal_fst (h : IsCentreOf K N c w) : (⟨jGeomGen K N, h.jGeomGen_mem⟩ : w.toValuationSubring) - algebraMap K w.toValuationSubring c.1 ∈ IsLocalRing.maximalIdeal w.toValuationSubring := by have hsub : ((⟨jGeomGen K N, h.jGeomGen_mem⟩ : w.toValuationSubring) - algebraMap K w.toValuationSubring c.1 : w.toValuationSubring) = ⟨jGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.1, sub_mem h.jGeomGen_mem (w.algebraMap_mem' c.1)⟩ := by refine Subtype.ext ?_ show jGeomGen K N - (algebraMap K w.toValuationSubring c.1 : modularFunctionFieldC K N) = jGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.1 rw [Place.coe_algebraMap] rw [hsub] exact w.mk_mem_maximalIdeal_of_ord_pos _ h.1 theorem IsCentreOf.mk_sub_mem_maximalIdeal_snd (h : IsCentreOf K N c w) : (⟨jNGeomGen K N, h.jNGeomGen_mem⟩ : w.toValuationSubring) - algebraMap K w.toValuationSubring c.2 ∈ IsLocalRing.maximalIdeal w.toValuationSubring := by have hsub : ((⟨jNGeomGen K N, h.jNGeomGen_mem⟩ : w.toValuationSubring) - algebraMap K w.toValuationSubring c.2 : w.toValuationSubring) = ⟨jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.2, sub_mem h.jNGeomGen_mem (w.algebraMap_mem' c.2)⟩ := by refine Subtype.ext ?_ show jNGeomGen K N - (algebraMap K w.toValuationSubring c.2 : modularFunctionFieldC K N) = jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) c.2 rw [Place.coe_algebraMap] rw [hsub] exact w.mk_mem_maximalIdeal_of_ord_pos _ h.2 theorem IsCentreOf.residue_jGeomGen (h : IsCentreOf K N c w) : IsLocalRing.residue w.toValuationSubring ⟨jGeomGen K N, h.jGeomGen_mem⟩ = algebraMap K w.ResidueField c.1 := by rw [← sub_eq_zero, IsScalarTower.algebraMap_apply K w.toValuationSubring w.ResidueField, IsLocalRing.ResidueField.algebraMap_eq, ← map_sub] exact (IsLocalRing.residue_eq_zero_iff _).mpr h.mk_sub_mem_maximalIdeal_fst theorem IsCentreOf.residue_jNGeomGen (h : IsCentreOf K N c w) : IsLocalRing.residue w.toValuationSubring ⟨jNGeomGen K N, h.jNGeomGen_mem⟩ = algebraMap K w.ResidueField c.2 := by rw [← sub_eq_zero, IsScalarTower.algebraMap_apply K w.toValuationSubring w.ResidueField, IsLocalRing.ResidueField.algebraMap_eq, ← map_sub] exact (IsLocalRing.residue_eq_zero_iff _).mpr h.mk_sub_mem_maximalIdeal_snd end Centre section ModularEquation variable {K : Type*} [Field K] {N : ℕ} [NeZero N] variable {c : K × K} {w : Place K (modularFunctionFieldC K N)} theorem evalModularPair_mk_eq_zero (data : ModularPolynomialData N) (hJ : jGeomGen K N ∈ w.toValuationSubring) (hJN : jNGeomGen K N ∈ w.toValuationSubring) : evalModularPair (⟨jGeomGen K N, hJ⟩ : w.toValuationSubring) ⟨jNGeomGen K N, hJN⟩ data.Φ = 0 := by have hval := map_evalModularPair (SubringClass.subtype w.toValuationSubring) (⟨jGeomGen K N, hJ⟩ : w.toValuationSubring) ⟨jNGeomGen K N, hJN⟩ data.Φ have hgen : SubringClass.subtype w.toValuationSubring (⟨jGeomGen K N, hJ⟩ : w.toValuationSubring) = jGeomGen K N := rfl have hgenN : SubringClass.subtype w.toValuationSubring (⟨jNGeomGen K N, hJN⟩ : w.toValuationSubring) = jNGeomGen K N := rfl rw [hgen, hgenN, evalModularPair_jGeomGen_eq_zero K N data] at hval exact (map_eq_zero_iff (SubringClass.subtype w.toValuationSubring) Subtype.val_injective).mp hval theorem IsCentreOf.modularEquation (data : ModularPolynomialData N) (h : IsCentreOf K N c w) : evalModularPair c.1 c.2 data.Φ = 0 := by have hres := congrArg (IsLocalRing.residue w.toValuationSubring) (evalModularPair_mk_eq_zero data h.jGeomGen_mem h.jNGeomGen_mem) rw [map_zero, map_evalModularPair, h.residue_jGeomGen, h.residue_jNGeomGen, ← map_evalModularPair] at hres exact (map_eq_zero_iff _ (algebraMap K w.ResidueField).injective).mp hres end ModularEquation section Frobenius variable (K : Type*) [Field K] (N : ℕ) [NeZero N] variable {ℓ : ℕ} [Fact ℓ.Prime] [CharP K ℓ] variable (data : ModularPolynomialData ℓ) (hKr : KroneckerCongruence ℓ data) theorem frobeniusGeomLevel_jGeomGen_sub_pow (a : K) : frobeniusGeomLevel K N data hKr (jGeomGen K N - algebraMap K (modularFunctionFieldC K N) (a ^ ℓ)) = (jGeomGen K N - algebraMap K (modularFunctionFieldC K N) a) ^ ℓ := by haveI : CharP (LaurentSeries K) ℓ := charP_laurentSeries K have hj : frobeniusGeomLevel K N data hKr (jGeomGen K N) = jGeomGen K N ^ ℓ := frobeniusGeomLevel_jq K N data hKr rw [map_sub, AlgHom.commutes, hj, map_pow] refine Subtype.ext ?_ push_cast rw [sub_pow_char] theorem frobeniusGeomLevel_jNGeomGen_sub_pow (b : K) : frobeniusGeomLevel K N data hKr (jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) (b ^ ℓ)) = (jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) b) ^ ℓ := by haveI : CharP (LaurentSeries K) ℓ := charP_laurentSeries K have hj : frobeniusGeomLevel K N data hKr (jNGeomGen K N) = jNGeomGen K N ^ ℓ := frobeniusGeomLevel_jqN K N data hKr rw [map_sub, AlgHom.commutes, hj, map_pow] refine Subtype.ext ?_ push_cast rw [sub_pow_char] variable {K N} omit [Fact ℓ.Prime] [CharP K ℓ] in private theorem ord_pow_prime (w : Place K (modularFunctionFieldC K N)) (g : modularFunctionFieldC K N) : w.ord (g ^ ℓ) = (ℓ : ℤ) * w.ord g := by rw [show g ^ ℓ = g ^ ((ℓ : ℕ) : ℤ) from (zpow_natCast g ℓ).symm, w.ord_zpow] private theorem pos_of_mul_pos_left' {e x : ℤ} (h : 0 < e * x) (he : 0 < e) : 0 < x := by rcases lt_trichotomy x 0 with hx | hx | hx · exact absurd h (not_lt.mpr (mul_nonpos_iff.mpr (Or.inl ⟨he.le, hx.le⟩))) · subst hx; simp at h · exact hx theorem IsCentreOf.frobOnPlacesGeomLevel {c : K × K} {w : Place K (modularFunctionFieldC K N)} (h : IsCentreOf K N c w) : IsCentreOf K N (c.1 ^ ℓ, c.2 ^ ℓ) (frobOnPlacesGeomLevel K N data hKr w) := by obtain ⟨e, he, -, hord⟩ := exists_ramification_frobenius K N data hKr w have hℓ : 0 < (ℓ : ℤ) := by exact_mod_cast (Fact.out : ℓ.Prime).pos constructor · have hkey := hord (jGeomGen K N - algebraMap K (modularFunctionFieldC K N) (c.1 ^ ℓ)) rw [frobeniusGeomLevel_jGeomGen_sub_pow K N data hKr c.1, ord_pow_prime] at hkey refine pos_of_mul_pos_left' (e := (e : ℤ)) ?_ (by exact_mod_cast he) rw [← hkey] exact mul_pos hℓ h.1 · have hkey := hord (jNGeomGen K N - algebraMap K (modularFunctionFieldC K N) (c.2 ^ ℓ)) rw [frobeniusGeomLevel_jNGeomGen_sub_pow K N data hKr c.2, ord_pow_prime] at hkey refine pos_of_mul_pos_left' (e := (e : ℤ)) ?_ (by exact_mod_cast he) rw [← hkey] exact mul_pos hℓ h.2 end Frobenius section Existence variable {K : Type*} [Field K] {N : ℕ} [NeZero N] def IsAffineGeomPlace (K : Type*) [Field K] (N : ℕ) [NeZero N] (w : Place K (modularFunctionFieldC K N)) : Prop := jGeomGen K N ∈ w.toValuationSubring ∧ jNGeomGen K N ∈ w.toValuationSubring theorem IsCentreOf.isAffineGeomPlace {c : K × K} {w : Place K (modularFunctionFieldC K N)} (h : IsCentreOf K N c w) : IsAffineGeomPlace K N w := ⟨h.jGeomGen_mem, h.jNGeomGen_mem⟩ theorem ord_sub_evalAt_pos_of_isRational {w : Place K (modularFunctionFieldC K N)} (hrat : w.IsRational) {f : modularFunctionFieldC K N} (hf : f ∈ w.toValuationSubring) (hne : f - algebraMap K (modularFunctionFieldC K N) (w.evalAt f) ≠ 0) : 0 < w.ord (f - algebraMap K (modularFunctionFieldC K N) (w.evalAt f)) := by have hmem : f - algebraMap K (modularFunctionFieldC K N) (w.evalAt f) ∈ w.toValuationSubring := sub_mem hf (w.algebraMap_mem' _) rcases eq_or_ne (w.ord (f - algebraMap K (modularFunctionFieldC K N) (w.evalAt f))) 0 with h0 | h0 · exfalso refine w.evalAt_ne_zero hrat hne h0 ?_ have hres : algebraMap K w.ResidueField (w.evalAt (f - algebraMap K (modularFunctionFieldC K N) (w.evalAt f))) = 0 := by rw [w.algebraMap_evalAt hrat hmem] have hcoe : (⟨f - algebraMap K (modularFunctionFieldC K N) (w.evalAt f), hmem⟩ : w.toValuationSubring) = ⟨f, hf⟩ - algebraMap K w.toValuationSubring (w.evalAt f) := by refine Subtype.ext ?_ show f - algebraMap K (modularFunctionFieldC K N) (w.evalAt f) = f - (algebraMap K w.toValuationSubring (w.evalAt f) : modularFunctionFieldC K N) rw [Place.coe_algebraMap] rw [hcoe, map_sub, sub_eq_zero, ← w.algebraMap_evalAt hrat hf, IsScalarTower.algebraMap_apply K w.toValuationSubring w.ResidueField, IsLocalRing.ResidueField.algebraMap_eq] exact (map_eq_zero_iff _ (algebraMap K w.ResidueField).injective).mp hres · have hnonneg := w.ord_nonneg_of_mem hmem omega theorem exists_isCentreOf_of_isRational {w : Place K (modularFunctionFieldC K N)} (hrat : w.IsRational) (haff : IsAffineGeomPlace K N w) : IsCentreOf K N (w.evalAt (jGeomGen K N), w.evalAt (jNGeomGen K N)) w := ⟨ord_sub_evalAt_pos_of_isRational hrat haff.1 (jGeomGen_sub_algebraMap_ne_zero K N _), ord_sub_evalAt_pos_of_isRational hrat haff.2 (jNGeomGen_sub_algebraMap_ne_zero K N _)⟩ end Existence end ModularCurve