Fermat's Last Theorem in Lean 4

← all definition modules

Definitions/Def_ModularCurve_ModularUnit.lean

definition module

Modular unit as a formal Laurent series

Everything here lives in \mathbb{Q}((q)), realised as LaurentSeries ℚ, and uses the substitution q \mapsto q^N given by the ring homomorphism qExpand ℚ N. The predicate IsMonicOfOrder f m says that the Hahn-series order of f is m and its leading coefficient is 1, i.e. the lowest-order term of f is 1\cdot q^{m}. Its namespace collects the elementary calculus of this notion: such an f is nonzero, its q^{m}-coefficient is 1 and all coefficients in degrees <m vanish; HahnSeries.single m 1 is monic of order m; a power series with constant coefficient 1, viewed as a Laurent series, is monic of order 0; orders add under multiplication, and conversely if f\cdot g is monic of order k and g is monic of order n then f is monic of order k-n; applying qExpand ℚ p multiplies the order by p.

On this basis, dedekindEtaUnitQ is the integral power series dedekindEtaUnit =\prod_{n\ge 1}(1-q^{n})^{24} pushed forward to \mathbb{Q}, with constant coefficient 1; deltaSeries is q\prod_{n\ge 1}(1-q^{n})^{24}, the q-expansion of the discriminant form, monic of order 1 and hence nonzero; and for N\neq 0, deltaSeriesN N is its image under qExpand ℚ N, monic of order N. The object of interest, modularUnitSeries N, is \Delta(q)\cdot\Delta(q^{N})^{-1} computed in the field \mathbb{Q}((q)); it satisfies the defining identity modularUnitSeries N * deltaSeriesN N = deltaSeries, is monic of order 1-N (so its order is 1-N, its q^{1-N}-coefficient is 1, and lower coefficients vanish), is nonzero, equals 1 for N=1, and is multiplicative in the sense that modularUnitSeries (a*b) is modularUnitSeries a times the q\mapsto q^{a} substitution of modularUnitSeries b.

Finally eisensteinNumerator p is the natural number (p-1)/\gcd(p-1,12); it divides p-1, and its values at p=5,7,13 (namely 1) and at p=11,17,19,23 (namely 5,4,3,11) are recorded.

Relation to Mathlib

The ambient ring LaurentSeries ℚ and the order/leadingCoeff API used throughout are Mathlib's; IsMonicOfOrder, the series deltaSeries, deltaSeriesN, modularUnitSeries and the arithmetic function eisensteinNumerator are the project's own, built on the project's qExpand and dedekindEtaUnit.

Where it is used

The series \Delta(q)/\Delta(q^{N}) is the standard modular unit on X_0(N), whose divisor is supported on the cusps; the order 1-N and the normalisation of its leading coefficient recorded here are what is needed for cuspidal divisor computations, and (p-1)/\gcd(p-1,12) is the invariant attached to the cuspidal divisor class on X_0(p).

References

  1. J.-P. Serre, A Course in Arithmetic, Graduate Texts in Mathematics 7, Springer, 1973, Ch. VII
  2. F. Diamond and J. Shurman, A First Course in Modular Forms, Graduate Texts in Mathematics 228, Springer, 2005
  3. A. Ogg, Rational points on certain elliptic modular curves, in: Analytic Number Theory, Proc. Sympos. Pure Math. 24, American Mathematical Society, 1973, 221–231

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_ModularUnit.lean

Imports

Imported by

Declarations

Source

import Definitions.Def_ModularCurve_X0

set_option autoImplicit false

noncomputable section

open HahnSeries

namespace ModularCurve

def IsMonicOfOrder (f : LaurentSeries ℚ) (m : ℤ) : Prop :=
  f.order = m ∧ f.leadingCoeff = 1

namespace IsMonicOfOrder

theorem ne_zero {f : LaurentSeries ℚ} {m : ℤ} (h : IsMonicOfOrder f m) : f ≠ 0 :=
  HahnSeries.leadingCoeff_ne_zero.mp (by rw [h.2]; exact one_ne_zero)

theorem coeff_self {f : LaurentSeries ℚ} {m : ℤ} (h : IsMonicOfOrder f m) :
    f.coeff m = 1 := by
  have h2 := h.2
  rwa [HahnSeries.leadingCoeff_eq, h.1] at h2

theorem coeff_of_lt {f : LaurentSeries ℚ} {m k : ℤ} (h : IsMonicOfOrder f m) (hk : k < m) :
    f.coeff k = 0 :=
  HahnSeries.coeff_eq_zero_of_lt_order (h.1 ▸ hk)

theorem single (m : ℤ) : IsMonicOfOrder (HahnSeries.single m (1 : ℚ)) m := by
  refine ⟨HahnSeries.order_single one_ne_zero, ?_⟩
  rw [HahnSeries.leadingCoeff_eq, HahnSeries.order_single one_ne_zero,
    HahnSeries.coeff_single_same]

theorem ofPowerSeries {U : PowerSeries ℚ} (hU : PowerSeries.constantCoeff U = 1) :
    IsMonicOfOrder (HahnSeries.ofPowerSeries ℤ ℚ U) 0 := by
  have hcoeff0 : (HahnSeries.ofPowerSeries ℤ ℚ U).coeff (0 : ℤ) = 1 := by
    rw [show (0 : ℤ) = ((0 : ℕ) : ℤ) from rfl, HahnSeries.ofPowerSeries_apply_coeff,
      PowerSeries.coeff_zero_eq_constantCoeff, hU]
  have hne0 : (HahnSeries.ofPowerSeries ℤ ℚ U).coeff (0 : ℤ) ≠ 0 := by
    rw [hcoeff0]; exact one_ne_zero
  have hne : HahnSeries.ofPowerSeries ℤ ℚ U ≠ 0 := HahnSeries.ne_zero_of_coeff_ne_zero hne0
  have horder : (HahnSeries.ofPowerSeries ℤ ℚ U).order = 0 := by
    refine le_antisymm (HahnSeries.order_le_of_coeff_ne_zero hne0) ?_
    by_contra hlt
    rw [not_le] at hlt
    exact hne (HahnSeries.coeff_order_eq_zero.mp
      (ModularCurve.ofPowerSeries_coeff_of_neg U hlt))
  exact ⟨horder, by rw [HahnSeries.leadingCoeff_eq, horder, hcoeff0]⟩

theorem mul {f g : LaurentSeries ℚ} {m n : ℤ} (hf : IsMonicOfOrder f m)
    (hg : IsMonicOfOrder g n) : IsMonicOfOrder (f * g) (m + n) := by
  have h1 : f.leadingCoeff * g.leadingCoeff ≠ 0 := by
    rw [hf.2, hg.2, one_mul]; exact one_ne_zero
  refine ⟨?_, ?_⟩
  · rw [HahnSeries.order_mul_of_ne_zero h1, hf.1, hg.1]
  · rw [HahnSeries.leadingCoeff_mul_of_ne_zero h1, hf.2, hg.2, one_mul]

theorem of_mul_right {f g : LaurentSeries ℚ} {k n : ℤ} (hfg : IsMonicOfOrder (f * g) k)
    (hg : IsMonicOfOrder g n) : IsMonicOfOrder f (k - n) := by

  have hlc : f.leadingCoeff = 1 := by
    have h := HahnSeries.leadingCoeff_mul f g
    rw [hfg.2, hg.2, mul_one] at h
    exact h.symm
  have h1 : f.leadingCoeff * g.leadingCoeff ≠ 0 := by
    rw [hlc, hg.2, one_mul]; exact one_ne_zero
  refine ⟨?_, hlc⟩
  have h := HahnSeries.order_mul_of_ne_zero h1
  rw [hfg.1, hg.1] at h
  omega

theorem qExpand {f : LaurentSeries ℚ} {m : ℤ} (p : ℕ) [NeZero p] (hf : IsMonicOfOrder f m) :
    IsMonicOfOrder (ModularCurve.qExpand ℚ p f) ((p : ℤ) * m) := by
  have hcoeff : (ModularCurve.qExpand ℚ p f).coeff ((p : ℤ) * m) = 1 := by
    rw [qExpand_coeff_mul]; exact hf.coeff_self
  have hcoeff' : (ModularCurve.qExpand ℚ p f).coeff ((p : ℤ) * m) ≠ 0 := by
    rw [hcoeff]; exact one_ne_zero
  have hne : ModularCurve.qExpand ℚ p f ≠ 0 := HahnSeries.ne_zero_of_coeff_ne_zero hcoeff'

  have hbelow : ∀ k : ℤ, k < (p : ℤ) * m → (ModularCurve.qExpand ℚ p f).coeff k = 0 := by
    intro k hk
    by_cases hdvd : (p : ℤ) ∣ k
    · obtain ⟨j, rfl⟩ := hdvd
      rw [qExpand_coeff_mul]
      refine hf.coeff_of_lt ?_
      have hp : (0 : ℤ) < (p : ℤ) := by exact_mod_cast Nat.pos_of_ne_zero (NeZero.ne p)
      exact lt_of_mul_lt_mul_left hk hp.le
    · exact qExpand_coeff_of_not_dvd p f hdvd
  have horder : (ModularCurve.qExpand ℚ p f).order = (p : ℤ) * m := by
    refine le_antisymm (HahnSeries.order_le_of_coeff_ne_zero hcoeff') ?_
    by_contra hlt
    rw [not_le] at hlt
    exact hne (HahnSeries.coeff_order_eq_zero.mp (hbelow _ hlt))
  exact ⟨horder, by rw [HahnSeries.leadingCoeff_eq, horder, hcoeff]⟩

end IsMonicOfOrder

section ModularUnit

def dedekindEtaUnitQ : PowerSeries ℚ := dedekindEtaUnit.map (Int.castRingHom ℚ)

@[simp]
theorem constantCoeff_dedekindEtaUnitQ : PowerSeries.constantCoeff dedekindEtaUnitQ = 1 := by
  rw [← PowerSeries.coeff_zero_eq_constantCoeff, dedekindEtaUnitQ, PowerSeries.coeff_map,
    PowerSeries.coeff_zero_eq_constantCoeff, constantCoeff_dedekindEtaUnit]
  simp

def deltaSeries : LaurentSeries ℚ :=
  HahnSeries.single (1 : ℤ) 1 * HahnSeries.ofPowerSeries ℤ ℚ dedekindEtaUnitQ

theorem isMonicOfOrder_deltaSeries : IsMonicOfOrder deltaSeries 1 := by
  have h := (IsMonicOfOrder.single (1 : ℤ)).mul
    (IsMonicOfOrder.ofPowerSeries constantCoeff_dedekindEtaUnitQ)
  rwa [add_zero] at h

theorem deltaSeries_ne_zero : deltaSeries0 := isMonicOfOrder_deltaSeries.ne_zero

variable (p : ℕ) [NeZero p]

def deltaSeriesN : LaurentSeries ℚ := qExpand ℚ p deltaSeries

theorem isMonicOfOrder_deltaSeriesN : IsMonicOfOrder (deltaSeriesN p) (p : ℤ) := by
  have h := isMonicOfOrder_deltaSeries.qExpand p
  rwa [mul_one] at h

theorem deltaSeriesN_ne_zero : deltaSeriesN p ≠ 0 := (isMonicOfOrder_deltaSeriesN p).ne_zero

def modularUnitSeries : LaurentSeries ℚ := deltaSeries * (deltaSeriesN p)⁻¹

theorem modularUnitSeries_mul_deltaSeriesN :
    modularUnitSeries p * deltaSeriesN p = deltaSeries := by
  rw [modularUnitSeries, mul_assoc, inv_mul_cancel₀ (deltaSeriesN_ne_zero p), mul_one]

theorem isMonicOfOrder_modularUnitSeries : IsMonicOfOrder (modularUnitSeries p) (1 - p) := by
  refine IsMonicOfOrder.of_mul_right ?_ (isMonicOfOrder_deltaSeriesN p)
  rw [modularUnitSeries_mul_deltaSeriesN]
  exact isMonicOfOrder_deltaSeries

theorem modularUnitSeries_ne_zero : modularUnitSeries p ≠ 0 :=
  (isMonicOfOrder_modularUnitSeries p).ne_zero

theorem order_modularUnitSeries : (modularUnitSeries p).order = 1 - (p : ℤ) :=
  (isMonicOfOrder_modularUnitSeries p).1

theorem coeff_modularUnitSeries_self : (modularUnitSeries p).coeff (1 - (p : ℤ)) = 1 :=
  (isMonicOfOrder_modularUnitSeries p).coeff_self

theorem coeff_modularUnitSeries_of_lt {k : ℤ} (hk : k < 1 - (p : ℤ)) :
    (modularUnitSeries p).coeff k = 0 :=
  (isMonicOfOrder_modularUnitSeries p).coeff_of_lt hk

theorem deltaSeriesN_one : deltaSeriesN 1 = deltaSeries :=
  qExpand_one_apply deltaSeries

theorem modularUnitSeries_one : modularUnitSeries 1 = 1 := by
  rw [modularUnitSeries, deltaSeriesN_one, mul_inv_cancel₀ deltaSeries_ne_zero]

theorem deltaSeriesN_mul (a b : ℕ) [NeZero a] [NeZero b] [NeZero (a * b)] :
    deltaSeriesN (a * b) = qExpand ℚ a (deltaSeriesN b) := by
  rw [deltaSeriesN, deltaSeriesN, qExpand_qExpand]

theorem modularUnitSeries_mul (a b : ℕ) [NeZero a] [NeZero b] [NeZero (a * b)] :
    modularUnitSeries (a * b) = modularUnitSeries a * qExpand ℚ a (modularUnitSeries b) := by
  rw [modularUnitSeries, modularUnitSeries, modularUnitSeries, map_mul, map_inv₀,
deltaSeriesN_mul, ← deltaSeriesN, mul_assoc, ← mul_assoc (deltaSeriesN a)⁻¹,
    inv_mul_cancel₀ (deltaSeriesN_ne_zero a), one_mul]

end ModularUnit

def eisensteinNumerator (p : ℕ) : ℕ := (p - 1) / Nat.gcd (p - 1) 12

theorem eisensteinNumerator_dvd (p : ℕ) : eisensteinNumerator p ∣ p - 1 :=
  Nat.div_dvd_of_dvd (Nat.gcd_dvd_left _ _)

@[simp] theorem eisensteinNumerator_five : eisensteinNumerator 5 = 1 := by decide
@[simp] theorem eisensteinNumerator_seven : eisensteinNumerator 7 = 1 := by decide
@[simp] theorem eisensteinNumerator_thirteen : eisensteinNumerator 13 = 1 := by decide

@[simp] theorem eisensteinNumerator_eleven : eisensteinNumerator 11 = 5 := by decide
@[simp] theorem eisensteinNumerator_seventeen : eisensteinNumerator 17 = 4 := by decide
@[simp] theorem eisensteinNumerator_nineteen : eisensteinNumerator 19 = 3 := by decide
@[simp] theorem eisensteinNumerator_twentythree : eisensteinNumerator 23 = 11 := by decide

end ModularCurve

end

Statements phrased using this module (203)

… and 53 more statements (search for the module name to find them).