Fermat's Last Theorem in Lean 4

← all definition modules

Definitions/Def_IsDedekindDomain_SelmerConnectingHom.lean

definition module

Connecting homomorphism from the Selmer group to the -class group

Throughout, R is a Dedekind domain with fraction field K, S a set of height-one primes of R and n a natural number (positive where required). The S-class group is built as follows: primeClass v is the class of the ideal v in ClassGroup R, sClasses S is the subgroup of ClassGroup R generated by \{[v] : v \in S\}, and ClassGroupModS S is the quotient \mathrm{Cl}(R)/\langle [v] : v\in S\rangle. Two normalisation lemmas record the translation between Mathlib's two ways of measuring a prime at a unit of K: \mathrm{toAdd}\,(v.\mathrm{valuationOfNeZero}\,x) equals -\,\mathrm{count}_v of the principal fractional ideal xR, whence n divides one exactly when it divides the other.

The predicate IsSel K S n x, for x \in K^\times, says that n \mid \mathrm{count}_v(xR) for every v \notin S; isSel_of_mk_mem and mk_mem_of_isSel identify this with membership of the class of x in Mathlib's selmerGroup (abbreviated Sel K S n inside Q_n = K^\times/(K^\times)^n). The "n-th root ideal" is defined by exponents radExp K S n x v, equal to 0 for v\in S and to the integer quotient \mathrm{count}_v(xR)/n otherwise; rad is the corresponding multipliable product \prod_v v^{\mathrm{radExp}}, a nonzero fractional ideal, radU its associated unit, and radClass its class in ClassGroupModS S. Under the hypothesis IsSel the exponents, hence rad and radClass, are multiplicative, radClass kills n-th powers, and radClass depends only on the class of x modulo (K^\times)^n. The named datum is connectingHom K S n : Sel K S n →* ClassGroupModS S, sending an element of the Selmer group to radClass of a chosen representative in K^\times (rep, via a quotient section); connectingHom_apply_mk evaluates it on the class of any x satisfying IsSel. Auxiliary lemmas supply the factorisation of a unit fractional ideal as a finite product of the primeUnit K v, the vanishing of the class of a principal fractional ideal, and the criterion that a unit fractional ideal supported in S has class in sClasses S.

Relation to Mathlib

Mathlib provides IsDedekindDomain.selmerGroup, HeightOneSpectrum.valuationOfNeZeroMod and FractionalIdeal.count but no comparison between count and valuationOfNeZero, and no map from the Selmer group to a class group; the S-class group ClassGroupModS and the homomorphism connectingHom are introduced here.

Where it is used

These definitions provide the ideal-theoretic side of the descent sequence 1 \to R_S^\times/(R_S^\times)^n \to K(S,n) \to \mathrm{Cl}_S(R)[n] \to 0, with connectingHom the middle map; statements about its range, kernel and naturality are proved elsewhere in the development.

References

  1. J. Neukirch, Algebraic Number Theory, Grundlehren der mathematischen Wissenschaften 322, Springer, 1999, Chapter I
  2. J. H. Silverman, The Arithmetic of Elliptic Curves, Graduate Texts in Mathematics 106, Springer, 1986, Chapter VIII

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

Declarations

Source

import Mathlib

set_option autoImplicit false

namespace IsDedekindDomain.selmerGroup

open IsDedekindDomain
open scoped nonZeroDivisors

variable {R : Type} [CommRing R] [IsDedekindDomain R] {K : Type} [Field K] [Algebra R K] [IsFractionRing R K]
  (v : HeightOneSpectrum R)

theorem toAdd_valuationOfNeZero_eq_neg_count (x : Kˣ) :
    Multiplicative.toAdd (v.valuationOfNeZero x) = -FractionalIdeal.count K v (FractionalIdeal.spanSingleton R⁰ (x : K)) := by
  classical
  set r : R := (IsLocalization.sec R⁰ (x : K)).1 with hrdef
  set s : R⁰ := (IsLocalization.sec R⁰ (x : K)).2 with hsdef
  have hx : IsLocalization.mk' K r s = (x : K) := IsLocalization.mk'_sec K (x : K)
  have hr : r ≠ 0 := by
    intro h
    rw [h, IsLocalization.mk'_zero] at hx
    exact x.ne_zero hx.symm
  have hs : (s : R) ≠ 0 := nonZeroDivisors.ne_zero s.2

  set a : ℤ := ((Associates.mk v.asIdeal).count (Associates.mk (Ideal.span {r} : Ideal R)).factors : ℤ) with ha
  set b : ℤ := ((Associates.mk v.asIdeal).count (Associates.mk (Ideal.span {(s : R)} : Ideal R)).factors : ℤ) with hb
  have h1 : (v.valuationOfNeZero x : WithZero (Multiplicative ℤ)) = WithZero.exp (-a - -b) := by
    rw [HeightOneSpectrum.valuationOfNeZero_eq, ← hx, HeightOneSpectrum.valuation_of_mk', HeightOneSpectrum.intValuation_if_neg _ hr,
      HeightOneSpectrum.intValuation_if_neg _ hs, WithZero.exp_sub]
  have h1' : v.valuationOfNeZero x = Multiplicative.ofAdd (-a - -b) := WithZero.coe_inj.1 h1

  have hspan : FractionalIdeal.spanSingleton R⁰ (x : K) * ((Ideal.span {(s : R)} : Ideal R) : FractionalIdeal R⁰ K) =
      ((Ideal.span {r} : Ideal R) : FractionalIdeal R⁰ K) := by
    rw [← hx]
    have := (FractionalIdeal.mk'_mul_coeIdeal_eq_coeIdeal K (I := Ideal.span {(s : R)}) (J := Ideal.span {r}) (x := r) s.2).2 (mul_comm _ _)
    simpa using this
  have hx0 : FractionalIdeal.spanSingleton R⁰ (x : K) ≠ 0 := FractionalIdeal.spanSingleton_ne_zero_iff.2 x.ne_zero
  have hs0 : ((Ideal.span {(s : R)} : Ideal R) : FractionalIdeal R⁰ K) ≠ 0 := by
    rw [Ne, FractionalIdeal.coeIdeal_eq_zero, Ideal.span_singleton_eq_bot]; exact hs
  have hcount := congrArg (FractionalIdeal.count K v) hspan
  rw [FractionalIdeal.count_mul K v hx0 hs0,
    FractionalIdeal.count_coe K v (by rw [Ideal.zero_eq_bot, Ne, Ideal.span_singleton_eq_bot]; exact hs),
    FractionalIdeal.count_coe K v (by rw [Ideal.zero_eq_bot, Ne, Ideal.span_singleton_eq_bot]; exact hr)] at hcount
  rw [h1', toAdd_ofAdd, ← ha, ← hb] at *
  omega

theorem dvd_toAdd_valuationOfNeZero_iff (n : ℕ) (x : Kˣ) :
    (n : ℤ) ∣ Multiplicative.toAdd (v.valuationOfNeZero x) ↔ (n : ℤ) ∣ FractionalIdeal.count K v (FractionalIdeal.spanSingleton R⁰ (x : K)) := by
  rw [toAdd_valuationOfNeZero_eq_neg_count, dvd_neg]

end IsDedekindDomain.selmerGroup

noncomputable section

namespace IsDedekindDomain.selmerGroup

open IsDedekindDomain FractionalIdeal
open scoped nonZeroDivisors Classical

variable {R : Type} [CommRing R] [IsDedekindDomain R] (K : Type) [Field K] [Algebra R K] [IsFractionRing R K]
  (S : Set (HeightOneSpectrum R)) (n : ℕ)

def primeClass (v : HeightOneSpectrum R) : ClassGroup R :=
  ClassGroup.mk0 ⟨v.asIdeal, mem_nonZeroDivisors_iff_ne_zero.2 (by simpa using v.ne_bot)⟩

abbrev sClasses : Subgroup (ClassGroup R) := Subgroup.closure (primeClass '' S)

abbrev ClassGroupModS : Type := ClassGroup R ⧸ sClasses S

theorem primeClass_eq_mk (v : HeightOneSpectrum R) :
    primeClass v = ClassGroup.mk K (Units.mk0 (v.asIdeal : FractionalIdeal R⁰ K) (coeIdeal_ne_zero.2 v.ne_bot)) := by
  rw [primeClass, ← ClassGroup.mk_mk0 K]
  congr 1

def radExp (x : Kˣ) (v : HeightOneSpectrum R) : ℤ :=
  if v ∈ S then 0 else count K v (spanSingleton R⁰ (x : K)) / n

theorem radExp_finite (x : Kˣ) : ∀ᶠ v : HeightOneSpectrum R in Filter.cofinite, radExp K S n x v = 0 :=
  (finite_factors (spanSingleton R⁰ (x : K))).mono fun v hv => by simp [radExp, hv]

def rad (x : Kˣ) : FractionalIdeal R⁰ K := ∏ᶠ v : HeightOneSpectrum R, (v.asIdeal : FractionalIdeal R⁰ K) ^ radExp K S n x v

theorem count_rad (x : Kˣ) (v : HeightOneSpectrum R) : count K v (rad K S n x) = radExp K S n x v :=
  count_finprod K v _ (radExp_finite K S n x)

theorem rad_ne_zero (x : Kˣ) : rad K S n x ≠ 0 := by
  rw [rad, finprod_def]
  split_ifs
  · exact Finset.prod_ne_zero_iff.2 fun v _ => zpow_ne_zero _ (coeIdeal_ne_zero.2 v.ne_bot)
  · exact one_ne_zero

theorem eq_of_count_eq {I J : FractionalIdeal R⁰ K} (hI : I ≠ 0) (hJ : J ≠ 0) (h : ∀ v, count K v I = count K v J) : I = J := by
  rw [← finprod_heightOneSpectrum_factorization' K hI, ← finprod_heightOneSpectrum_factorization' K hJ]
  exact finprod_congr fun v => by rw [h v]

def radClass (x : Kˣ) : ClassGroupModS S := QuotientGroup.mk (ClassGroup.mk K (Units.mk0 (rad K S n x) (rad_ne_zero K S n x)))

def IsSel (x : Kˣ) : Prop := ∀ v ∉ S, (n : ℤ) ∣ count K v (spanSingleton R⁰ (x : K))

variable {K S n}

theorem IsSel.mul {x y : Kˣ} (hx : IsSel K S n x) (hy : IsSel K S n y) : IsSel K S n (x * y) := fun v hv => by
  rw [Units.val_mul, ← spanSingleton_mul_spanSingleton, count_mul K v (spanSingleton_ne_zero_iff.2 x.ne_zero) (spanSingleton_ne_zero_iff.2 y.ne_zero)]
  exact dvd_add (hx v hv) (hy v hv)

theorem IsSel.pow (z : Kˣ) : IsSel K S n (z ^ n) := fun v _ => by
  rw [Units.val_pow_eq_pow_val, ← spanSingleton_pow, count_pow]
  exact dvd_mul_right _ _

variable (K S n)

theorem radExp_mul {x y : Kˣ} (hx : IsSel K S n x) (_hy : IsSel K S n y) (v : HeightOneSpectrum R) :
    radExp K S n (x * y) v = radExp K S n x v + radExp K S n y v := by
  unfold radExp
  split_ifs with hv
  · simp
  · rw [Units.val_mul, ← spanSingleton_mul_spanSingleton, count_mul K v (spanSingleton_ne_zero_iff.2 x.ne_zero) (spanSingleton_ne_zero_iff.2 y.ne_zero)]
    exact Int.add_ediv_of_dvd_left (hx v hv)

theorem rad_mul {x y : Kˣ} (hx : IsSel K S n x) (hy : IsSel K S n y) : rad K S n (x * y) = rad K S n x * rad K S n y := by
  apply eq_of_count_eq K (rad_ne_zero K S n _) (mul_ne_zero (rad_ne_zero K S n x) (rad_ne_zero K S n y))
  intro v
  rw [count_mul K v (rad_ne_zero K S n x) (rad_ne_zero K S n y), count_rad, count_rad, count_rad, radExp_mul K S n hx hy]

theorem radClass_mul {x y : Kˣ} (hx : IsSel K S n x) (hy : IsSel K S n y) : radClass K S n (x * y) = radClass K S n x * radClass K S n y := by
  unfold radClass
  rw [← QuotientGroup.mk_mul, ← map_mul]
  congr 2
  exact Units.ext (by simp [rad_mul K S n hx hy])

end IsDedekindDomain.selmerGroup

end

noncomputable section

namespace IsDedekindDomain.selmerGroup

open IsDedekindDomain FractionalIdeal
open scoped nonZeroDivisors Classical

variable {R : Type} [CommRing R] [IsDedekindDomain R] (K : Type) [Field K] [Algebra R K] [IsFractionRing R K]
  (S : Set (HeightOneSpectrum R)) (n : ℕ)

theorem mk_spanSingleton (z : Kˣ) :
    ClassGroup.mk K (Units.mk0 (spanSingleton R⁰ (z : K)) (spanSingleton_ne_zero_iff.2 z.ne_zero)) = 1 :=
  ClassGroup.mk_eq_one_iff.2 ⟨⟨(z : K), by simp [coe_spanSingleton]⟩⟩

def primeUnit (v : HeightOneSpectrum R) : (FractionalIdeal R⁰ K)ˣ := Units.mk0 (v.asIdeal : FractionalIdeal R⁰ K) (coeIdeal_ne_zero.2 v.ne_bot)

theorem mk_primeUnit (v : HeightOneSpectrum R) : ClassGroup.mk K (primeUnit K v) = primeClass v := (primeClass_eq_mk K v).symm

theorem hasFiniteMulSupport_primeUnit_zpow (e : HeightOneSpectrum R → ℤ) (he : ∀ᶠ v in Filter.cofinite, e v = 0) :
    Function.HasFiniteMulSupport fun v => primeUnit K v ^ e v := by
  apply he.subset
  intro v hv
  simp only [Function.mem_mulSupport] at hv
  intro h
  exact hv (by rw [h, zpow_zero])

theorem coe_finprod_primeUnit_zpow (e : HeightOneSpectrum R → ℤ) :
    ((∏ᶠ v, primeUnit K v ^ e v : (FractionalIdeal R⁰ K)ˣ) : FractionalIdeal R⁰ K) = ∏ᶠ v, (v.asIdeal : FractionalIdeal R⁰ K) ^ e v := by
  rw [← Units.coeHom_apply, MonoidHom.map_finprod_of_injective (Units.coeHom (FractionalIdeal R⁰ K)) Units.val_injective]
  exact finprod_congr fun v => by rw [map_zpow, Units.coeHom_apply]; rfl

theorem eq_finprod_primeUnit (I : (FractionalIdeal R⁰ K)ˣ) (e : HeightOneSpectrum R → ℤ) (he : ∀ v, e v = count K v (Units.val I)) :
    I = (∏ᶠ v : HeightOneSpectrum R, (primeUnit K v ^ e v : (FractionalIdeal R⁰ K)ˣ) : (FractionalIdeal R⁰ K)ˣ) := by
  apply Units.ext
  rw [coe_finprod_primeUnit_zpow]
  rw [show e = fun v => count K v (Units.val I) from funext he]
  exact (finprod_heightOneSpectrum_factorization' K I.ne_zero).symm

theorem mk_mem_sClasses (I : (FractionalIdeal R⁰ K)ˣ) (hI : ∀ v ∉ S, count K v (I : FractionalIdeal R⁰ K) = 0) :
    ClassGroup.mk K I ∈ sClasses S := by
  have hfin := hasFiniteMulSupport_primeUnit_zpow K (fun v => count K v (Units.val I)) (finite_factors _)
  rw [eq_finprod_primeUnit K I (fun v => count K v (Units.val I)) (fun v => rfl), MonoidHom.map_finprod _ hfin]
  refine finprod_induction (· ∈ sClasses S) (Subgroup.one_mem _) (fun _ _ => Subgroup.mul_mem _) fun v => ?_
  by_cases hv : v ∈ S
  · rw [map_zpow, mk_primeUnit]
    exact Subgroup.zpow_mem _ (Subgroup.subset_closure (Set.mem_image_of_mem primeClass hv)) _
  · change ClassGroup.mk K (primeUnit K v ^ count K v (Units.val I)) ∈ sClasses S
    rw [hI v hv, zpow_zero, map_one]
    exact Subgroup.one_mem _

def radU (x : Kˣ) : (FractionalIdeal R⁰ K)ˣ := Units.mk0 (rad K S n x) (rad_ne_zero K S n x)

theorem radClass_eq (x : Kˣ) : radClass K S n x = QuotientGroup.mk (ClassGroup.mk K (radU K S n x)) := rfl

variable [Fact (0 < n)]

theorem radClass_pow (z : Kˣ) : radClass K S n (z ^ n) = 1 := by
  have hn : (n : ℤ) ≠ 0 := by exact_mod_cast (Fact.out : 0 < n).ne'

  let J : (FractionalIdeal R⁰ K)ˣ := ∏ᶠ v, primeUnit K v ^ (if v ∈ S then count K v (spanSingleton R⁰ (z : K)) else 0)
  have hJsupp : ∀ᶠ v in Filter.cofinite, (if v ∈ S then count K v (spanSingleton R⁰ (z : K)) else 0) = 0 :=
    (finite_factors (spanSingleton R⁰ (z : K))).mono fun v hv => by simp [hv]
  have hJcount : ∀ v, count K v (J : FractionalIdeal R⁰ K) = if v ∈ S then count K v (spanSingleton R⁰ (z : K)) else 0 := fun v => by
    rw [coe_finprod_primeUnit_zpow, count_finprod K v _ hJsupp]
  have hprod : radU K S n (z ^ n) * J = Units.mk0 (spanSingleton R⁰ (z : K)) (spanSingleton_ne_zero_iff.2 z.ne_zero) := by
    apply Units.ext
    apply eq_of_count_eq K (mul_ne_zero (rad_ne_zero K S n _) J.ne_zero) (spanSingleton_ne_zero_iff.2 z.ne_zero)
    intro v
    change count K v (rad K S n (z ^ n) * (J : FractionalIdeal R⁰ K)) = _
    rw [count_mul K v (rad_ne_zero K S n _) J.ne_zero, count_rad, hJcount, radExp]
    split_ifs with hv
    · simp
    · rw [Units.val_pow_eq_pow_val, ← spanSingleton_pow, count_pow, add_zero, mul_comm, Int.mul_ediv_cancel _ hn]
  have hJmem : ClassGroup.mk K J ∈ sClasses S := mk_mem_sClasses K S J fun v hv => by rw [hJcount, if_neg hv]
  rw [radClass_eq, QuotientGroup.eq_one_iff]
  have : ClassGroup.mk K (radU K S n (z ^ n)) = (ClassGroup.mk K J)⁻¹ := by
    rw [eq_inv_iff_mul_eq_one, ← map_mul, hprod, mk_spanSingleton]
  rw [this]
  exact Subgroup.inv_mem _ hJmem

omit [Fact (0 < n)] in

theorem valuationOfNeZeroMod_mk (v : HeightOneSpectrum R) (x : Kˣ) :
    v.valuationOfNeZeroMod n (QuotientGroup.mk x : Kˣ ⧸ (powMonoidHom n : Kˣ →* Kˣ).range) =
      AddEquiv.toMultiplicative (Int.quotientZMultiplesNatEquivZMod n)
        (QuotientGroup.mk (s := AddSubgroup.toSubgroup (AddSubgroup.zmultiples (n : ℤ))) (v.valuationOfNeZero x)) := rfl

omit [Fact (0 < n)] in
theorem valuationOfNeZeroMod_mk_eq_one_iff (v : HeightOneSpectrum R) (x : Kˣ) :
    v.valuationOfNeZeroMod n (QuotientGroup.mk x : Kˣ ⧸ (powMonoidHom n : Kˣ →* Kˣ).range) = 1
      (n : ℤ) ∣ Multiplicative.toAdd (v.valuationOfNeZero x) := by
  rw [valuationOfNeZeroMod_mk, MulEquiv.map_eq_one_iff]
  change Multiplicative.ofAdd (QuotientAddGroup.mk (Multiplicative.toAdd (v.valuationOfNeZero x)) : ℤ ⧸ AddSubgroup.zmultiples (n : ℤ)) = 1 ↔ _
  rw [ofAdd_eq_one, QuotientAddGroup.eq_zero_iff, Int.mem_zmultiples_iff]

omit [Fact (0 < n)] in

theorem isSel_of_mk_mem {x : Kˣ} (hx : (QuotientGroup.mk x : Kˣ ⧸ (powMonoidHom n : Kˣ →* Kˣ).range) ∈ selmerGroup (R := R) (K := K) (S := S) (n := n)) :
    IsSel K S n x := fun v hv =>
  (dvd_toAdd_valuationOfNeZero_iff v n x).1 ((valuationOfNeZeroMod_mk_eq_one_iff K n v x).1 (hx v hv))

omit [Fact (0 < n)] in
theorem mk_mem_of_isSel {x : Kˣ} (hx : IsSel K S n x) :
    (QuotientGroup.mk x : Kˣ ⧸ (powMonoidHom n : Kˣ →* Kˣ).range) ∈ selmerGroup (R := R) (K := K) (S := S) (n := n) := fun v hv =>
  (valuationOfNeZeroMod_mk_eq_one_iff K n v x).2 ((dvd_toAdd_valuationOfNeZero_iff v n x).2 (hx v hv))

end IsDedekindDomain.selmerGroup

end

noncomputable section

namespace IsDedekindDomain.selmerGroup

open IsDedekindDomain FractionalIdeal
open scoped nonZeroDivisors Classical

variable {R : Type} [CommRing R] [IsDedekindDomain R] (K : Type) [Field K] [Algebra R K] [IsFractionRing R K]
  (S : Set (HeightOneSpectrum R)) (n : ℕ) [Fact (0 < n)]

abbrev Qn : Type := Kˣ ⧸ (powMonoidHom n : Kˣ →* Kˣ).range

abbrev Sel : Subgroup (Qn K n) := selmerGroup (R := R) (K := K) (S := S) (n := n)

omit [Fact (0 < n)] in
theorem IsSel.one : IsSel K S n 1 := by simpa using IsSel.pow (K := K) (S := S) (n := n) 1

omit [Fact (0 < n)] in
theorem IsSel.npow {x : Kˣ} (hx : IsSel K S n x) (k : ℕ) : IsSel K S n (x ^ k) := by
  induction k with
  | zero => simpa using IsSel.one K S n
  | succ k ih => rw [pow_succ]; exact ih.mul hx

theorem radClass_npow {x : Kˣ} (hx : IsSel K S n x) (k : ℕ) : radClass K S n (x ^ k) = radClass K S n x ^ k := by
  induction k with
  | zero =>
    rw [pow_zero, pow_zero]
    have := radClass_pow K S n (1 : Kˣ)
    rwa [one_pow] at this
  | succ k ih => rw [pow_succ, pow_succ, radClass_mul K S n (hx.npow K S n k) hx, ih]

theorem radClass_eq_of_mk_eq {x y : Kˣ} (hx : IsSel K S n x) (_hy : IsSel K S n y) (h : (QuotientGroup.mk x : Qn K n) = QuotientGroup.mk y) :
    radClass K S n x = radClass K S n y := by
  obtain ⟨z, hz⟩ := MonoidHom.mem_range.1 (QuotientGroup.eq.1 h)
  have : y = x * z ^ n := by rw [← powMonoidHom_apply, hz, mul_inv_cancel_left]
  rw [this, radClass_mul K S n hx (IsSel.pow z), radClass_pow, mul_one]

def rep (x : ↥(Sel K S n)) : Kˣ := Quotient.out (x.1 : Qn K n)

omit [Fact (0 < n)] in
theorem mk_rep (x : ↥(Sel K S n)) : (QuotientGroup.mk (rep K S n x) : Qn K n) = x.1 := Quotient.out_eq _

omit [Fact (0 < n)] in
theorem isSel_rep (x : ↥(Sel K S n)) : IsSel K S n (rep K S n x) :=
  isSel_of_mk_mem K S n (by rw [mk_rep]; exact x.2)

def connectingHom : ↥(Sel K S n) →* ClassGroupModS S where
  toFun x := radClass K S n (rep K S n x)
  map_one' := by
    have h1 : (QuotientGroup.mk (rep K S n 1) : Qn K n) = QuotientGroup.mk 1 := by rw [mk_rep]; rfl
    rw [radClass_eq_of_mk_eq K S n (isSel_rep K S n 1) (IsSel.one K S n) h1]
    have := radClass_pow K S n (1 : Kˣ)
    rwa [one_pow] at this
  map_mul' x y := by
    have h : (QuotientGroup.mk (rep K S n (x * y)) : Qn K n) = QuotientGroup.mk (rep K S n x * rep K S n y) := by
      rw [QuotientGroup.mk_mul, mk_rep, mk_rep, mk_rep]; rfl
    rw [radClass_eq_of_mk_eq K S n (isSel_rep K S n _) ((isSel_rep K S n x).mul (isSel_rep K S n y)) h,
      radClass_mul K S n (isSel_rep K S n x) (isSel_rep K S n y)]

theorem connectingHom_apply_mk {x : Kˣ} (hx : IsSel K S n x) (hmem : (QuotientGroup.mk x : Qn K n) ∈ Sel K S n) :
    connectingHom K S n ⟨QuotientGroup.mk x, hmem⟩ = radClass K S n x :=
  radClass_eq_of_mk_eq K S n (isSel_rep K S n _) hx (mk_rep K S n _)

theorem connectingHom_apply (x : ↥(Sel K S n)) : connectingHom K S n x = radClass K S n (rep K S n x) := rfl

end IsDedekindDomain.selmerGroup

end

Statements phrased using this module (0)

No statement module imports it directly (it is used through other definition modules or by proofs).