Fermat's Last Theorem in Lean 4

← all definition modules

Definitions/Def_ModularCurve_CharLSpecialFibreLevelNDictionary.lean

definition module

Centres of places on the level- geometric modular curve

Throughout, K is a field, N\ge 1, and the ambient field is the intermediate field \mathrm{modularFunctionFieldC}\,K\,N = K(\bar j,\bar j_N) of the Laurent series field K((q)), generated by the q-expansion \bar j = q^{-1}+\dots of the j-invariant with coefficients reduced into K and by its N-fold substitution \bar j_N = \bar j(q^N). The two generators are packaged as elements jGeomGen K N and jNGeomGen K N of that field, and transcendental_jqNModC records that \bar j_N is transcendental over K, whence neither generator differs from a constant by zero. A ring homomorphism evalAtJGeom K evaluates integral one-variable polynomials at \bar j, and evalModularPair x y Φ evaluates a two-variable integral polynomial Φ (an element of \mathbb{Z}[X][Y]) at a pair (x,y) of elements of any commutative ring, compatibly with ring homomorphisms. For a modular-polynomial packet data : ModularPolynomialData N, whose polynomial data.Φ comes with the vanishing of its value at the pair of rational q-expansions, the module derives the same vanishing over \mathbb{Z}, over K, and in K(\bar j,\bar j_N).

The central definition is IsCentreOf K N (a,b) w for a place w of K(\bar j,\bar j_N) over K (a proper valuation subring containing K whose ring is principal, hence a discrete valuation ring) and a pair (a,b)\in K\times K: it asserts \operatorname{ord}_w(\bar j-a)>0 and \operatorname{ord}_w(\bar j_N-b)>0, where \operatorname{ord} is the normalised valuation. The weaker predicate IsAffineGeomPlace K N w asks only that both generators lie in the valuation subring. From a centre one obtains: both generators are w-integral; a and b are the residue-field evaluations w.\mathrm{evalAt} of the generators, so a centre is unique and distinct centres force distinct places; the residues of the generators are the images of a and b; and (a,b) satisfies the modular equation, \mathrm{evalModularPair}\,a\,b\,data.Φ=0 for every packet. For K of characteristic \ell prime, given data : ModularPolynomialData ℓ and a Kronecker-congruence hypothesis KroneckerCongruence ℓ data, the endomorphism frobeniusGeomLevel sends \bar j-a^\ell to (\bar j-a)^\ell and likewise for \bar j_N, and consequently IsCentreOf.frobOnPlacesGeomLevel: if (a,b) is a centre of w then (a^\ell,b^\ell) is a centre of the place frobOnPlacesGeomLevel K N data hKr w. Finally, exists_isCentreOf_of_isRational shows that a place with residue field K at which both generators are integral has the centre (w.\mathrm{evalAt}\,\bar j,\;w.\mathrm{evalAt}\,\bar j_N); the converse construction, producing a place from a prescribed solution of the modular equation, is not asserted.

Relation to Mathlib

Mathlib has no notion of the centre of a place on a modular curve; IsCentreOf, IsAffineGeomPlace and evalModularPair are the project's own, formulated for the project's AlgebraicCurve.Place structure and its ord and evalAt. The underlying Laurent series, valuation subrings, discrete valuation rings and residue fields are Mathlib's.

Where it is used

These notions provide the dictionary between places of the characteristic-\ell function field K(\bar j,\bar j_N) and points of the reduced modular equation \Phi_N=0, together with the compatibility of that dictionary with the \ell-power Frobenius. They are the geometric input on the special fibre used in the Eichler–Shimura style analysis of Hecke and Frobenius actions that underlies level lowering.

References

  1. S. Lang, Elliptic Functions, 2nd edition, Graduate Texts in Mathematics 112, Springer, 1987
  2. G. Shimura, Introduction to the Arithmetic Theory of Automorphic Functions, Princeton University Press, 1971

References are suggested automatically and have not been individually verified.

English text generated automatically from the Lean source; the Lean statement is authoritative.

Source file: Definitions/Def_ModularCurve_CharLSpecialFibreLevelNDictionary.lean

Imports

Theorems imported by this definition module

Imported by

Declarations

Source

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.toValuationSubringjGeomGen 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.toValuationSubringjNGeomGen 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.toValuationSubringjNGeomGen 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

Statements phrased using this module (49)