import Mathlib import Definitions.Def_LanglandsTunnell_NormClass import Definitions.Def_NumberField_RayCharacterData set_option autoImplicit false set_option linter.unusedSectionVars false noncomputable section namespace NumberField.NormResidueChar open NumberField NumberField.InfinitePlace IsDedekindDomain Deep.NTSupply open LanglandsTunnell.P2.Artin open scoped nonZeroDivisors Classical variable (K : Type) [Field K] [NumberField K] (m : β„•) [NeZero m] abbrev fm : Ideal (π“ž K) := Ideal.span {(m : π“ž K)} theorem fm_ne_bot : fm K m β‰  βŠ₯ := by rw [fm, Ne, Ideal.span_singleton_eq_bot] exact_mod_cast NeZero.ne m instance finite_G : Finite (NarrowRayClassGroup K (fm K m)) := Deep.NTSupply.finite K (fm_ne_bot K m) noncomputable instance fintype_G : Fintype (NarrowRayClassGroup K (fm K m)) := Fintype.ofFinite _ def nu : NarrowRayClassGroup K (fm K m) β†’* (ZMod m)Λ£ := normClassChar K m (dvd_refl _) def chi (ψ : DirichletCharacter β„‚ m) : NarrowRayClassGroup K (fm K m) β†’* β„‚ := (Units.coeHom β„‚).comp ((MulChar.toUnitHom ψ).comp (nu K m)) theorem chi_apply (ψ : DirichletCharacter β„‚ m) (g : NarrowRayClassGroup K (fm K m)) : chi K m ψ g = ψ ((nu K m g : (ZMod m)Λ£) : ZMod m) := by simp [chi] theorem chi_mul (ψ ΞΈ : DirichletCharacter β„‚ m) : chi K m (ψ * ΞΈ) = chi K m ψ * chi K m ΞΈ := by refine MonoidHom.ext fun g => ?_ rw [MonoidHom.mul_apply, chi_apply, chi_apply, chi_apply, MulChar.mul_apply] theorem chi_one : chi K m 1 = 1 := by refine MonoidHom.ext fun g => ?_ rw [chi_apply, MonoidHom.one_apply, MulChar.one_apply_coe] variable {K m} theorem dvd_fm_iff (v : HeightOneSpectrum (π“ž K)) : v.asIdeal ∣ fm K m ↔ (m : π“ž K) ∈ v.asIdeal := by rw [fm, Ideal.dvd_span_singleton] theorem absNorm_mem (v : HeightOneSpectrum (π“ž K)) : ((Ideal.absNorm v.asIdeal : β„•) : π“ž K) ∈ v.asIdeal := Ideal.absNorm_mem v.asIdeal theorem not_coprime_of_mem {v : HeightOneSpectrum (π“ž K)} (hv : (m : π“ž K) ∈ v.asIdeal) : Β¬ (Ideal.absNorm v.asIdeal).Coprime m := by intro hcop apply v.isPrime.ne_top rw [Ideal.eq_top_iff_one] have hg := Nat.gcd_eq_gcd_ab (Ideal.absNorm v.asIdeal) m rw [Nat.Coprime.gcd_eq_one hcop] at hg have h1' : (1 : π“ž K) = (Ideal.absNorm v.asIdeal : π“ž K) * (Nat.gcdA (Ideal.absNorm v.asIdeal) m : π“ž K) + (m : π“ž K) * (Nat.gcdB (Ideal.absNorm v.asIdeal) m : π“ž K) := by have := congrArg (fun z : β„€ => (z : π“ž K)) hg push_cast at this exact this rw [h1'] exact v.asIdeal.add_mem (v.asIdeal.mul_mem_right _ (absNorm_mem v)) (v.asIdeal.mul_mem_right _ hv) theorem coprime_of_not_mem {v : HeightOneSpectrum (π“ž K)} (hv : (m : π“ž K) βˆ‰ v.asIdeal) : (Ideal.absNorm v.asIdeal).Coprime m := absNorm_coprime_of_not_dvd K m v (by rwa [dvd_fm_iff] at *) theorem mk0_prime_mem_iff {𝔣 : Ideal (π“ž K)} (v : HeightOneSpectrum (π“ž K)) (h : (v.asIdeal : FractionalIdeal (π“ž K)⁰ K) β‰  0) : Units.mk0 (v.asIdeal : FractionalIdeal (π“ž K)⁰ K) h ∈ coprimeToModulus K 𝔣 ↔ Β¬ v.asIdeal ∣ 𝔣 := by rw [mem_coprimeToModulus_iff] constructor Β· intro hc hv have := hc v hv rw [Units.val_mk0, FractionalIdeal.count_self] at this exact one_ne_zero this Β· intro hv w hw rw [Units.val_mk0] exact FractionalIdeal.count_maximal_coprime K w (fun h => hv (h β–Έ hw)) theorem chiIdeal_prime {𝔣 : Ideal (π“ž K)} (Ο‡ : NarrowRayClassGroup K 𝔣 β†’* β„‚) (v : HeightOneSpectrum (π“ž K)) : M4aP2.chiIdeal K 𝔣 Ο‡ (v.asIdeal : FractionalIdeal (π“ž K)⁰ K) = if hv : v.asIdeal ∣ 𝔣 then 0 else Ο‡ (primeClass K 𝔣 v hv) := by have h0 : (v.asIdeal : FractionalIdeal (π“ž K)⁰ K) β‰  0 := by rw [Ne, FractionalIdeal.coeIdeal_eq_zero] exact v.ne_bot rw [M4aP2.chiIdeal, dif_pos h0] by_cases hv : v.asIdeal ∣ 𝔣 Β· rw [dif_pos hv, dif_neg (by rw [mk0_prime_mem_iff]; exact not_not.mpr hv)] Β· have hc : Units.mk0 (v.asIdeal : FractionalIdeal (π“ž K)⁰ K) h0 ∈ coprimeToModulus K 𝔣 := by rwa [mk0_prime_mem_iff] rw [dif_neg hv, dif_pos hc, primeClass] have heq : (⟨Units.mk0 _ h0, hc⟩ : β†₯(coprimeToModulus K 𝔣)) = ⟨primeUnit K v, primeUnit_mem_coprimeToModulus K hv⟩ := Subtype.ext (Units.ext (by rw [Units.val_mk0, primeUnit_val])) rw [heq] theorem chi_primeClass (ψ : DirichletCharacter β„‚ m) (v : HeightOneSpectrum (π“ž K)) (hv : Β¬ v.asIdeal ∣ fm K m) : chi K m ψ (primeClass K (fm K m) v hv) = ψ (Ideal.absNorm v.asIdeal : ZMod m) := by rw [chi_apply, nu, normClassChar_primeClass, normClass_coe] exact coprime_of_not_mem (by rwa [dvd_fm_iff] at hv) theorem chiIdeal_chi (ψ : DirichletCharacter β„‚ m) (v : HeightOneSpectrum (π“ž K)) : M4aP2.chiIdeal K (fm K m) (chi K m ψ) (v.asIdeal : FractionalIdeal (π“ž K)⁰ K) = ψ (Ideal.absNorm v.asIdeal : ZMod m) := by rw [chiIdeal_prime] by_cases hv : v.asIdeal ∣ fm K m Β· rw [dif_pos hv, eq_comm] apply MulChar.map_nonunit rw [ZMod.isUnit_iff_coprime] exact not_coprime_of_mem ((dvd_fm_iff v).mp hv) Β· rw [dif_neg hv, chi_primeClass] def paritySet (ψ : DirichletCharacter β„‚ m) : Finset {w : InfinitePlace K // w.IsReal} := if ψ (-1) = 1 then βˆ… else Finset.univ theorem psi_neg_one_sq (ψ : DirichletCharacter β„‚ m) : ψ (-1) * ψ (-1) = 1 := by rw [← map_mul, neg_mul_neg, one_mul, map_one] theorem psi_neg_one_eq (ψ : DirichletCharacter β„‚ m) : ψ (-1) = 1 ∨ ψ (-1) = -1 := by have h := psi_neg_one_sq ψ have : (ψ (-1) - 1) * (ψ (-1) + 1) = 0 := by ring_nf; rw [sq, h]; ring rcases mul_eq_zero.mp this with h1 | h1 Β· left; exact sub_eq_zero.mp h1 Β· right; exact eq_neg_of_add_eq_zero_left h1 theorem chiIdeal_chi_span (ψ : DirichletCharacter β„‚ m) {Ξ± : π“ž K} (hΞ± : Ξ± β‰  0) (h1 : Ξ± - 1 ∈ fm K m) : M4aP2.chiIdeal K (fm K m) (chi K m ψ) ((Ideal.span {Ξ±} : Ideal (π“ž K)) : FractionalIdeal (π“ž K)⁰ K) = ψ ((SignType.sign (Algebra.norm β„€ Ξ±) : β„€) : ZMod m) := by have hspan : (Ideal.span {Ξ±} : Ideal (π“ž K)) β‰  βŠ₯ := by rw [Ne, Ideal.span_singleton_eq_bot]; exact hΞ± have h0 : ((Ideal.span {Ξ±} : Ideal (π“ž K)) : FractionalIdeal (π“ž K)⁰ K) β‰  0 := by rw [Ne, FractionalIdeal.coeIdeal_eq_zero]; exact hspan have hcmem : Units.mk0 _ h0 ∈ coprimeToModulus K (fm K m) := by have h := principalUnit_mem_coprimeToModulus K hΞ± h1 rw [mem_coprimeToModulus_iff] at h ⊒ intro v hv have := h v hv rwa [principalUnit_val] at this rw [M4aP2.chiIdeal, dif_pos h0, dif_pos hcmem, chi_apply, nu, normClassChar, raySymbolDescend_mk, raySymbolHom_apply] have hcop : (Ideal.span {Ξ±} : Ideal (π“ž K)) βŠ” Ideal.span {(m : π“ž K)} = ⊀ := by rw [Ideal.eq_top_iff_one] have h1' : Ξ± - (Ξ± - 1) = 1 := by ring exact h1' β–Έ Submodule.sub_mem _ (Ideal.mem_sup_left (Ideal.subset_span rfl)) (Ideal.mem_sup_right h1) have hval : ((⟨Units.mk0 _ h0, hcmem⟩ : β†₯(coprimeToModulus K (fm K m))) : (FractionalIdeal (π“ž K)⁰ K)Λ£) = Units.mk0 _ h0 := rfl rw [hval, Units.val_mk0, raySymbol_normClass_coe K m hspan hcop, Ideal.absNorm_span_singleton] congr 1 have hN1 : ((Algebra.norm β„€ Ξ± : β„€) : ZMod m) = 1 := norm_int_cast_eq_one_of_sub_one_mem K m h1 have habs : ((Algebra.norm β„€ Ξ±).natAbs : β„€) = (SignType.sign (Algebra.norm β„€ Ξ±) : β„€) * Algebra.norm β„€ Ξ± := by rw [← Int.sign_eq_sign, Int.sign_mul_self_eq_natAbs] rw [← Int.cast_natCast (R := ZMod m) (Algebra.norm β„€ Ξ±).natAbs, habs, Int.cast_mul, hN1, mul_one] section Cyclo variable {L : Type} [Field L] [NumberField L] [Algebra K L] [IsCyclotomicExtension {m} K L] theorem absNorm_cast_eq_one {ΞΆ : L} (hΞΆ : IsPrimitiveRoot ΞΆ m) (w : HeightOneSpectrum (π“ž L)) (hw : (m : π“ž L) βˆ‰ w.asIdeal) : (Ideal.absNorm w.asIdeal : ZMod m) = 1 := by have hΞΆ' : IsPrimitiveRoot hΞΆ.toInteger m := hΞΆ.toInteger_isPrimitiveRoot have hcop : (Ideal.absNorm w.asIdeal).Coprime m := coprime_of_not_mem hw have hN1 : Ideal.absNorm w.asIdeal β‰  1 := by rw [Ne, Ideal.absNorm_eq_one_iff]; exact w.isPrime.ne_top haveI : w.asIdeal.IsMaximal := w.isPrime.isMaximal w.ne_bot letI : Field (π“ž L β§Έ w.asIdeal) := Ideal.Quotient.field w.asIdeal letI : Fintype (π“ž L β§Έ w.asIdeal) := Fintype.ofFinite _ have hinj := Ideal.rootsOfUnityMapQuot_injective (I := w.asIdeal) m hN1 hcop have hdvd := Subgroup.card_dvd_of_injective _ hinj rw [hΞΆ'.card_rootsOfUnity, Nat.card_units, ← Submodule.cardQuot_apply, ← Ideal.absNorm_apply] at hdvd have hpos : 1 ≀ Ideal.absNorm w.asIdeal := Nat.one_le_iff_ne_zero.mpr (by rw [Ne, Ideal.absNorm_eq_zero_iff]; exact w.ne_bot) have : ((Ideal.absNorm w.asIdeal : β„•) : ZMod m) = ((Ideal.absNorm w.asIdeal - 1 + 1 : β„•) : ZMod m) := by rw [Nat.sub_add_cancel hpos] rw [this, Nat.cast_add, Nat.cast_one, (ZMod.natCast_eq_zero_iff _ _).mpr hdvd, zero_add] theorem mem_primesOver_of_under_eq {w : HeightOneSpectrum (π“ž L)} {v : HeightOneSpectrum (π“ž K)} (h : w.under (π“ž K) = v) : w.asIdeal ∈ v.asIdeal.primesOver (π“ž L) := by refine ⟨w.isPrime, ⟨?_⟩⟩ rw [← h] rfl include m in theorem ncard_primesOver_le (v : HeightOneSpectrum (π“ž K)) : (v.asIdeal.primesOver (π“ž L)).ncard ≀ Module.finrank K L := by haveI : IsGalois K L := IsCyclotomicExtension.isGalois {m} K L haveI : IsGaloisGroup (L ≃ₐ[K] L) (π“ž K) (π“ž L) := IsGaloisGroup.of_isFractionRing (L ≃ₐ[K] L) (π“ž K) (π“ž L) K L haveI : v.asIdeal.IsMaximal := v.isPrime.isMaximal v.ne_bot have h := Ideal.ncard_primesOver_mul_ramificationIdxIn_mul_inertiaDegIn v.asIdeal (π“ž L) (L ≃ₐ[K] L) rw [IsGalois.card_aut_eq_finrank] at h have hpos : 0 < Module.finrank K L := Module.finrank_pos have hne : v.asIdeal.ramificationIdxIn (π“ž L) * v.asIdeal.inertiaDegIn (π“ž L) β‰  0 := by intro h0 rw [h0, mul_zero] at h omega calc (v.asIdeal.primesOver (π“ž L)).ncard ≀ (v.asIdeal.primesOver (π“ž L)).ncard * (v.asIdeal.ramificationIdxIn (π“ž L) * v.asIdeal.inertiaDegIn (π“ž L)) := Nat.le_mul_of_pos_right _ (Nat.pos_of_ne_zero hne) _ = Module.finrank K L := h theorem ncard_fibre_eq (v : HeightOneSpectrum (π“ž K)) : {w : HeightOneSpectrum (π“ž L) | w.under (π“ž K) = v}.ncard = (v.asIdeal.primesOver (π“ž L)).ncard := by have hinj : Set.InjOn (fun w : HeightOneSpectrum (π“ž L) => w.asIdeal) {w | w.under (π“ž K) = v} := fun _ _ _ _ h => HeightOneSpectrum.ext h rw [← hinj.ncard_image] congr 1 ext I constructor Β· rintro ⟨w, hw, rfl⟩ exact mem_primesOver_of_under_eq hw Β· rintro ⟨hI, hIo⟩ have hIbot : I β‰  βŠ₯ := Ideal.ne_bot_of_liesOver_of_ne_bot v.ne_bot I refine ⟨⟨I, hI, hIbot⟩, ?_, rfl⟩ apply HeightOneSpectrum.ext rw [HeightOneSpectrum.under_asIdeal] exact hIo.over.symm theorem finite_fibre (v : HeightOneSpectrum (π“ž K)) : {w : HeightOneSpectrum (π“ž L) | w.under (π“ž K) = v}.Finite := by have hinj : Set.InjOn (fun w : HeightOneSpectrum (π“ž L) => w.asIdeal) {w | w.under (π“ž K) = v} := fun _ _ _ _ h => HeightOneSpectrum.ext h haveI : v.asIdeal.IsMaximal := v.isPrime.isMaximal v.ne_bot refine Set.Finite.of_finite_image ?_ hinj refine (IsDedekindDomain.primesOver_finite v.asIdeal (π“ž L)).subset ?_ rintro _ ⟨w, hw, rfl⟩ exact mem_primesOver_of_under_eq hw include m in theorem ncard_fibre_le (v : HeightOneSpectrum (π“ž K)) : {w : HeightOneSpectrum (π“ž L) | w.under (π“ž K) = v}.ncard ≀ Module.finrank K L := by rw [ncard_fibre_eq] exact ncard_primesOver_le (m := m) v theorem absNorm_under_eq_of_prime (w : HeightOneSpectrum (π“ž L)) (hp : (Ideal.absNorm w.asIdeal).Prime) : Ideal.absNorm (w.under (π“ž K)).asIdeal = Ideal.absNorm w.asIdeal := by haveI : w.asIdeal.IsMaximal := w.isPrime.isMaximal w.ne_bot set v := w.under (π“ž K) haveI : v.asIdeal.IsMaximal := v.isPrime.isMaximal v.ne_bot haveI : w.asIdeal.LiesOver v.asIdeal := ⟨rfl⟩ letI : Field (π“ž K β§Έ v.asIdeal) := Ideal.Quotient.field _ letI : Field (π“ž L β§Έ w.asIdeal) := Ideal.Quotient.field _ have hpow : Nat.card (π“ž L β§Έ w.asIdeal) = Nat.card (π“ž K β§Έ v.asIdeal) ^ Module.finrank (π“ž K β§Έ v.asIdeal) (π“ž L β§Έ w.asIdeal) := Module.natCard_eq_pow_finrank rw [← Submodule.cardQuot_apply, ← Ideal.absNorm_apply, ← Submodule.cardQuot_apply, ← Ideal.absNorm_apply] at hpow rw [hpow] at hp have hf := Nat.Prime.eq_one_of_pow hp rw [hpow, hf, pow_one] variable (K m) def U0 {ΞΆ : L} (hΞΆ : IsPrimitiveRoot ΞΆ m) : Subgroup (ZMod m)Λ£ := (hΞΆ.autToPow K).range theorem card_U0 {ΞΆ : L} (hΞΆ : IsPrimitiveRoot ΞΆ m) : Nat.card (U0 K m hΞΆ) = Module.finrank K L := by haveI : IsGalois K L := IsCyclotomicExtension.isGalois {m} K L rw [U0, ← IsGalois.card_aut_eq_finrank K L, ← Nat.card_range_of_injective (hΞΆ.autToPow_injective K)] exact Nat.card_congr (Equiv.subtypeEquivRight (fun x => MonoidHom.mem_range)) theorem normClass_mem_U0 {ΞΆ : L} (hΞΆ : IsPrimitiveRoot ΞΆ m) (v : HeightOneSpectrum (π“ž K)) : normClass K m v ∈ U0 K m hΞΆ := by by_cases hv : (Ideal.absNorm v.asIdeal).Coprime m Β· haveI : IsGalois K L := IsCyclotomicExtension.isGalois {m} K L haveI : IsGaloisGroup (L ≃ₐ[K] L) (π“ž K) (π“ž L) := IsGaloisGroup.of_isFractionRing (L ≃ₐ[K] L) (π“ž K) (π“ž L) K L haveI : v.asIdeal.IsMaximal := v.isPrime.isMaximal v.ne_bot have hker : RingHom.ker (algebraMap (π“ž K) (π“ž L)) ≀ v.asIdeal := by have hinj : Function.Injective (algebraMap (π“ž K) (π“ž L)) := by intro x y hxy have h' : algebraMap (π“ž K) L x = algebraMap (π“ž K) L y := by rw [IsScalarTower.algebraMap_apply (π“ž K) (π“ž L) L, IsScalarTower.algebraMap_apply (π“ž K) (π“ž L) L, hxy] rw [IsScalarTower.algebraMap_apply (π“ž K) K L, IsScalarTower.algebraMap_apply (π“ž K) K L] at h' exact RingOfIntegers.coe_injective ((algebraMap K L).injective h') rw [(RingHom.injective_iff_ker_eq_bot _).mp hinj] exact bot_le obtain ⟨Q, hQmax, hQv⟩ := Ideal.exists_ideal_over_maximal_of_isIntegral v.asIdeal hker haveI : Q.IsMaximal := hQmax have hunder : Q.under (π“ž K) = v.asIdeal := hQv have hmQ : (m : π“ž L) βˆ‰ Q := by intro hmem apply not_coprime_of_mem (K := K) (m := m) (v := v) _ hv have : algebraMap (π“ž K) (π“ž L) (m : π“ž K) ∈ Q := by rwa [map_natCast] rw [← Ideal.mem_comap] at this rw [← hunder] exact this haveI : Q.LiesOver v.asIdeal := ⟨hunder.symm⟩ haveI : Finite (π“ž L β§Έ Q) := Q.finiteQuotientOfFreeOfNeBot (Ideal.ne_bot_of_liesOver_of_ne_bot v.ne_bot Q) set Ο† : L ≃ₐ[K] L := arithFrobAt (π“ž K) (L ≃ₐ[K] L) Q with hΟ†def have hΟ† : IsArithFrobAt (π“ž K) Ο† Q := IsArithFrobAt.arithFrobAt (π“ž K) (L ≃ₐ[K] L) Q have hΞΆ' : IsPrimitiveRoot hΞΆ.toInteger m := hΞΆ.toInteger_isPrimitiveRoot have hcardK : Nat.card (π“ž K β§Έ Q.under (π“ž K)) = Ideal.absNorm v.asIdeal := by rw [hunder, Ideal.absNorm_apply, Submodule.cardQuot_apply] have hφ΢' : Ο† β€’ hΞΆ.toInteger = hΞΆ.toInteger ^ Ideal.absNorm v.asIdeal := by have h := AlgHom.IsArithFrobAt.apply_of_pow_eq_one hΟ† hΞΆ'.pow_eq_one hmQ rw [hcardK] at h exact h have hφ΢ : Ο† ΞΆ = ΞΆ ^ Ideal.absNorm v.asIdeal := by have h := congrArg (fun x : π“ž L => (x : L)) hφ΢' have h2 : ((Ο† β€’ hΞΆ.toInteger : π“ž L) : L) = Ο† ΞΆ := rfl simpa [h2, hΞΆ.coe_toInteger] using h have hspec := hΞΆ.autToPow_spec K Ο† rw [hφ΢] at hspec have hmod : ((hΞΆ.autToPow K Ο† : ZMod m)).val ≑ Ideal.absNorm v.asIdeal [MOD m] := by have hm : 0 < m := NeZero.pos m rw [← pow_mod_orderOf ΞΆ ((hΞΆ.autToPow K Ο† : ZMod m)).val, ← pow_mod_orderOf ΞΆ (Ideal.absNorm v.asIdeal), ← hΞΆ.eq_orderOf] at hspec exact hΞΆ.pow_inj (Nat.mod_lt _ hm) (Nat.mod_lt _ hm) hspec have heq : hΞΆ.autToPow K Ο† = normClass K m v := by apply Units.ext rw [normClass_coe K m v hv, ← ZMod.natCast_zmod_val ((hΞΆ.autToPow K Ο† : ZMod m)), ZMod.natCast_eq_natCast_iff] exact hmod rw [← heq] exact βŸ¨Ο†, rfl⟩ Β· rw [normClass, dif_neg hv] exact one_mem _ theorem nu_mem_U0 {ΞΆ : L} (hΞΆ : IsPrimitiveRoot ΞΆ m) (g : NarrowRayClassGroup K (fm K m)) : nu K m g ∈ U0 K m hΞΆ := by obtain ⟨y, rfl⟩ := QuotientGroup.mk_surjective g have hmk : (QuotientGroup.mk y : NarrowRayClassGroup K (fm K m)) = NarrowRayClassGroup.mk K (fm K m) y := rfl rw [hmk, nu, normClassChar, raySymbolDescend_mk, raySymbolHom_apply, raySymbol] refine finprod_induction (Β· ∈ U0 K m hΞΆ) (one_mem _) (fun x y hx hy => mul_mem hx hy) ?_ intro v exact zpow_mem (normClass_mem_U0 K m hΞΆ v) _ theorem range_nu_le_U0 {ΞΆ : L} (hΞΆ : IsPrimitiveRoot ΞΆ m) : (nu K m).range ≀ U0 K m hΞΆ := by rintro _ ⟨g, rfl⟩ exact nu_mem_U0 K m hΞΆ g end Cyclo end NumberField.NormResidueChar end