import Definitions.Def_AlgebraicCurve_DivisorClassGroup import Mathlib.RingTheory.Valuation.LocalSubring import Mathlib.RingTheory.IntegralClosure.IntegrallyClosed import Mathlib.RingTheory.IntegralClosure.Algebra.Basic import Mathlib.RingTheory.Norm.Basic import Mathlib.LinearAlgebra.Dimension.Free set_option autoImplicit false noncomputable section open IsDedekindDomain WithZero IsLocalRing namespace AlgebraicCurve namespace Place section SinglePlace variable {K F : Type*} [Field K] [Field F] [Algebra K F] (v : Place K F) private theorem ord_nonneg_of_mem {f : F} (hf : f ∈ v.toValuationSubring) : 0 ≤ v.ord f := by rcases eq_or_ne f 0 with rfl | hf0 · simp obtain ⟨π, hπ⟩ := IsDiscreteValuationRing.exists_irreducible v.toValuationSubring obtain ⟨n, u, hu⟩ := IsDiscreteValuationRing.eq_unit_mul_pow_irreducible (x := (⟨f, hf⟩ : v.toValuationSubring)) (by simpa [Subtype.ext_iff] using hf0) hπ have hcoe : f = ((u : v.toValuationSubring) : F) * ((π : F) ^ (n : ℤ)) := by have h := congrArg (Subtype.val) hu push_cast at h rw [zpow_natCast] exact h rw [hcoe, v.ord_unit_smul_zpow u hπ (n : ℤ)] exact Int.natCast_nonneg n private theorem mem_of_ord_nonneg {f : F} (hf : f ≠ 0) (h : 0 ≤ v.ord f) : f ∈ v.toValuationSubring := by obtain ⟨π, hπ⟩ := IsDiscreteValuationRing.exists_irreducible v.toValuationSubring obtain ⟨u, hu⟩ := v.exists_unit_mul_zpow hf hπ rw [hu, show v.ord f = (((v.ord f).toNat : ℕ) : ℤ) from (Int.toNat_of_nonneg h).symm, zpow_natCast] exact mul_mem (u : v.toValuationSubring).2 (pow_mem (π : v.toValuationSubring).2 _) private theorem mem_iff_ord_nonneg {f : F} (hf : f ≠ 0) : f ∈ v.toValuationSubring ↔ 0 ≤ v.ord f := ⟨v.ord_nonneg_of_mem, v.mem_of_ord_nonneg hf⟩ private theorem exists_ord_pos : ∃ f : F, f ≠ 0 ∧ 0 < v.ord f := by obtain ⟨π, hπ⟩ := IsDiscreteValuationRing.exists_irreducible v.toValuationSubring refine ⟨(π : F), ?_, ?_⟩ · simpa [ne_eq, ZeroMemClass.coe_eq_zero] using hπ.ne_zero · rw [v.ord_coe_irreducible hπ] exact one_pos end SinglePlace section Restrict variable {K F F' : Type*} [Field K] [Field F] [Field F'] [Algebra K F'] [Algebra F F'] private theorem algebraMap_ne_zero {f : F} (hf : f ≠ 0) : algebraMap F F' f ≠ 0 := by simpa using hf variable (w : Place K F') private theorem comap_algebraMap_ne_top [Algebra.IsIntegral F F'] : w.toValuationSubring.comap (algebraMap F F') ≠ ⊤ := by intro htop apply w.ne_top' have hF : ∀ f : F, algebraMap F F' f ∈ w.toValuationSubring := fun f => ValuationSubring.mem_comap.mp (htop ▸ ValuationSubring.mem_top f) refine SetLike.ext fun x => ⟨fun _ => ValuationSubring.mem_top x, fun _ => ?_⟩ letI : Algebra F w.toValuationSubring := ((algebraMap F F').codRestrict w.toValuationSubring.toSubring hF).toAlgebra letI : IsScalarTower F w.toValuationSubring F' := IsScalarTower.of_algebraMap_eq fun f => rfl have hx : IsIntegral w.toValuationSubring x := (Algebra.IsIntegral.isIntegral (R := F) x).tower_top obtain ⟨y, hy⟩ := IsIntegrallyClosed.isIntegral_iff.mp hx exact hy ▸ y.2 variable {w} in private theorem mem_comap_iff_ord_nonneg {f : F} (hf : f ≠ 0) : f ∈ w.toValuationSubring.comap (algebraMap F F') ↔ 0 ≤ w.ord (algebraMap F F' f) := by rw [ValuationSubring.mem_comap] exact w.mem_iff_ord_nonneg (algebraMap_ne_zero hf) variable {w} in private theorem isUnit_mk_comap_iff {f : F} (hf : f ≠ 0) (hmem : f ∈ w.toValuationSubring.comap (algebraMap F F')) : IsUnit (⟨f, hmem⟩ : w.toValuationSubring.comap (algebraMap F F')) ↔ w.ord (algebraMap F F' f) = 0 := by constructor · rintro h obtain ⟨b, hb⟩ := isUnit_iff_exists_inv.mp h have hb' : f * (b : F) = 1 := by simpa [Subtype.ext_iff] using hb have hbne : (b : F) ≠ 0 := by intro h0 rw [h0, mul_zero] at hb' exact zero_ne_one hb' have hsum : w.ord (algebraMap F F' f) + w.ord (algebraMap F F' (b : F)) = 0 := by rw [← w.ord_mul (algebraMap_ne_zero hf) (algebraMap_ne_zero hbne), ← map_mul, hb', map_one, w.ord_one] have h1 : 0 ≤ w.ord (algebraMap F F' f) := (mem_comap_iff_ord_nonneg hf).mp hmem have h2 : 0 ≤ w.ord (algebraMap F F' (b : F)) := (mem_comap_iff_ord_nonneg hbne).mp b.2 omega · intro h0 have hinv : f⁻¹ ∈ w.toValuationSubring.comap (algebraMap F F') := (mem_comap_iff_ord_nonneg (inv_ne_zero hf)).mpr (by rw [map_inv₀, w.ord_inv]; omega) exact ⟨⟨⟨f, hmem⟩, ⟨f⁻¹, hinv⟩, Subtype.ext (mul_inv_cancel₀ hf), Subtype.ext (inv_mul_cancel₀ hf)⟩, rfl⟩ private theorem exists_ord_algebraMap_pos [Algebra.IsIntegral F F'] : ∃ f : F, f ≠ 0 ∧ 0 < w.ord (algebraMap F F' f) := by have h := w.comap_algebraMap_ne_top (F := F) rw [ne_eq, SetLike.ext_iff, not_forall] at h obtain ⟨g, hg⟩ := h simp only [ValuationSubring.mem_top, iff_true] at hg have hg0 : g ≠ 0 := by rintro rfl exact hg (zero_mem _) refine ⟨g⁻¹, inv_ne_zero hg0, ?_⟩ rw [map_inv₀, w.ord_inv] have := (mem_comap_iff_ord_nonneg hg0).not.mp hg omega def ramificationIndex (F : Type*) [Field F] [Algebra F F'] : ℕ := sInf {n : ℕ | 0 < n ∧ ∃ f : F, f ≠ 0 ∧ w.ord (algebraMap F F' f) = n} theorem ramificationIndex_le_ord {f : F} (hf : f ≠ 0) (hpos : 0 < w.ord (algebraMap F F' f)) : (ramificationIndex (F := F) w : ℤ) ≤ w.ord (algebraMap F F' f) := by have h := Nat.sInf_le (s := {n : ℕ | 0 < n ∧ ∃ f : F, f ≠ 0 ∧ w.ord (algebraMap F F' f) = n}) (m := (w.ord (algebraMap F F' f)).toNat) ⟨by omega, f, hf, by omega⟩ rw [ramificationIndex] omega variable [Algebra.IsIntegral F F'] private theorem ramificationIndex_set_nonempty : {n : ℕ | 0 < n ∧ ∃ f : F, f ≠ 0 ∧ w.ord (algebraMap F F' f) = n}.Nonempty := by obtain ⟨f, hf0, hf⟩ := w.exists_ord_algebraMap_pos (F := F) exact ⟨(w.ord (algebraMap F F' f)).toNat, by omega, f, hf0, by omega⟩ theorem ramificationIndex_pos : 0 < ramificationIndex (F := F) w := (Nat.sInf_mem (w.ramificationIndex_set_nonempty (F := F))).1 theorem exists_ord_eq_ramificationIndex : ∃ f : F, f ≠ 0 ∧ w.ord (algebraMap F F' f) = ramificationIndex (F := F) w := (Nat.sInf_mem (w.ramificationIndex_set_nonempty (F := F))).2 theorem ramificationIndex_dvd_ord {f : F} (hf : f ≠ 0) : (ramificationIndex (F := F) w : ℤ) ∣ w.ord (algebraMap F F' f) := by obtain ⟨g, hg0, hge⟩ := w.exists_ord_eq_ramificationIndex (F := F) set e : ℤ := (ramificationIndex (F := F) w : ℤ) with he have hepos : 0 < e := by have := w.ramificationIndex_pos (F := F) omega set m : ℤ := w.ord (algebraMap F F' f) with hm set q : ℤ := m / e with hq have hgq : algebraMap F F' (g ^ (-q)) = (algebraMap F F' g) ^ (-q) := map_zpow₀ _ _ _ have hr : w.ord (algebraMap F F' (f * g ^ (-q))) = m - e * q := by rw [map_mul, w.ord_mul (algebraMap_ne_zero hf) (by rw [hgq]; exact zpow_ne_zero _ (algebraMap_ne_zero hg0)), hgq, w.ord_zpow, hge, ← hm] ring have hmod := Int.emod_nonneg m (by omega : e ≠ 0) have hmod' := Int.emod_lt_of_pos m hepos have hbridge : m % e = m - e * q := by rw [hq] exact Int.emod_def m e rcases eq_or_lt_of_le (show (0 : ℤ) ≤ m - e * q by omega) with heq | hlt · exact ⟨q, by omega⟩ · exfalso have hfg : f * g ^ (-q) ≠ 0 := mul_ne_zero hf (zpow_ne_zero _ hg0) have hle := w.ramificationIndex_le_ord (F := F) hfg (by omega) rw [hr, ← he] at hle omega theorem irreducible_mk_comap {g : F} (hg0 : g ≠ 0) (hmem : g ∈ w.toValuationSubring.comap (algebraMap F F')) (hge : w.ord (algebraMap F F' g) = ramificationIndex (F := F) w) : Irreducible (⟨g, hmem⟩ : w.toValuationSubring.comap (algebraMap F F')) := by have hepos : 0 < ramificationIndex (F := F) w := w.ramificationIndex_pos (F := F) constructor · rw [isUnit_mk_comap_iff hg0 hmem, hge] omega · rintro ⟨a, ha⟩ ⟨b, hb⟩ hab have hab' : g = a * b := by simpa [Subtype.ext_iff] using hab have ha0 : a ≠ 0 := by rintro rfl exact hg0 (by simpa using hab') have hb0 : b ≠ 0 := by rintro rfl exact hg0 (by simpa using hab') have hsum : w.ord (algebraMap F F' a) + w.ord (algebraMap F F' b) = ramificationIndex (F := F) w := by rw [← w.ord_mul (algebraMap_ne_zero ha0) (algebraMap_ne_zero hb0), ← map_mul, ← hab', hge] have ha' : 0 ≤ w.ord (algebraMap F F' a) := (mem_comap_iff_ord_nonneg ha0).mp ha have hb' : 0 ≤ w.ord (algebraMap F F' b) := (mem_comap_iff_ord_nonneg hb0).mp hb rcases eq_or_lt_of_le ha' with ha0' | hapos · exact Or.inl ((isUnit_mk_comap_iff ha0 ha).mpr ha0'.symm) rcases eq_or_lt_of_le hb' with hb0' | hbpos · exact Or.inr ((isUnit_mk_comap_iff hb0 hb).mpr hb0'.symm) exfalso have h1 := w.ramificationIndex_le_ord (F := F) ha0 hapos have h2 := w.ramificationIndex_le_ord (F := F) hb0 hbpos omega private theorem isPrincipalIdealRing_comap : IsPrincipalIdealRing (w.toValuationSubring.comap (algebraMap F F')) := by obtain ⟨g, hg0, hge⟩ := w.exists_ord_eq_ramificationIndex (F := F) have hepos : 0 < ramificationIndex (F := F) w := w.ramificationIndex_pos (F := F) have hgmem : g ∈ w.toValuationSubring.comap (algebraMap F F') := (mem_comap_iff_ord_nonneg hg0).mpr (by omega) refine (IsDiscreteValuationRing.ofHasUnitMulPowIrreducibleFactorization ⟨⟨g, hgmem⟩, irreducible_mk_comap w hg0 hgmem hge, ?_⟩).toIsPrincipalIdealRing rintro ⟨f, hmem⟩ hx have hf : f ≠ 0 := by simpa [Subtype.ext_iff] using hx obtain ⟨c, hc⟩ := w.ramificationIndex_dvd_ord (F := F) hf have hnonneg : 0 ≤ w.ord (algebraMap F F' f) := (mem_comap_iff_ord_nonneg hf).mp hmem have hcnonneg : 0 ≤ c := by by_contra hneg have hcle : c ≤ -1 := by omega have : (ramificationIndex (F := F) w : ℤ) * c ≤ (ramificationIndex (F := F) w : ℤ) * -1 := mul_le_mul_of_nonneg_left hcle (by omega) omega set n : ℕ := c.toNat with hn have hcn : (n : ℤ) = c := Int.toNat_of_nonneg hcnonneg refine ⟨n, ?_⟩ have hgn : g ^ n ≠ 0 := pow_ne_zero _ hg0 have hdiv0 : f / g ^ n ≠ 0 := div_ne_zero hf hgn have hu0 : w.ord (algebraMap F F' (f / g ^ n)) = 0 := by have hkey : algebraMap F F' (f / g ^ n) = algebraMap F F' f * (algebraMap F F' g) ^ (-(n : ℤ)) := by rw [div_eq_mul_inv, map_mul, map_inv₀, map_pow, ← zpow_natCast (algebraMap F F' g) n, ← zpow_neg] rw [hkey, w.ord_mul (algebraMap_ne_zero hf) (zpow_ne_zero _ (algebraMap_ne_zero hg0)), w.ord_zpow, hge, hc, ← hcn] ring have humem : f / g ^ n ∈ w.toValuationSubring.comap (algebraMap F F') := (mem_comap_iff_ord_nonneg hdiv0).mpr (le_of_eq hu0.symm) have hu : IsUnit (⟨f / g ^ n, humem⟩ : w.toValuationSubring.comap (algebraMap F F')) := (isUnit_mk_comap_iff hdiv0 humem).mpr hu0 refine ⟨hu.unit, ?_⟩ refine Subtype.ext ?_ have hcoe : ((hu.unit : w.toValuationSubring.comap (algebraMap F F')) : F) = f / g ^ n := by rw [IsUnit.unit_spec] push_cast rw [hcoe, mul_comm, div_mul_cancel₀] exact hgn section RestrictDef variable [Algebra K F] [IsScalarTower K F F'] variable (F) in def restrict : Place K F where toValuationSubring := w.toValuationSubring.comap (algebraMap F F') algebraMap_mem' a := by rw [ValuationSubring.mem_comap, ← IsScalarTower.algebraMap_apply] exact w.algebraMap_mem' a ne_top' := w.comap_algebraMap_ne_top isPrincipalIdealRing' := w.isPrincipalIdealRing_comap @[simp] theorem restrict_toValuationSubring : (w.restrict F).toValuationSubring = w.toValuationSubring.comap (algebraMap F F') := rfl theorem mem_restrict_iff {f : F} : f ∈ (w.restrict F).toValuationSubring ↔ algebraMap F F' f ∈ w.toValuationSubring := Iff.rfl theorem ord_restrict (f : F) : w.ord (algebraMap F F' f) = ramificationIndex (F := F) w * (w.restrict F).ord f := by rcases eq_or_ne f 0 with rfl | hf · simp obtain ⟨g, hg0, hge⟩ := w.exists_ord_eq_ramificationIndex (F := F) have hepos : 0 < ramificationIndex (F := F) w := w.ramificationIndex_pos (F := F) have hgmem : g ∈ w.toValuationSubring.comap (algebraMap F F') := (mem_comap_iff_ord_nonneg hg0).mpr (by omega) obtain ⟨u, hu⟩ := (w.restrict F).exists_unit_mul_zpow hf (π := ⟨g, hgmem⟩) (irreducible_mk_comap w hg0 hgmem hge) set n : ℤ := (w.restrict F).ord f with hn have hune : ((u : (w.restrict F).toValuationSubring) : F) ≠ 0 := by intro h0 have := u.mul_inv rw [Subtype.ext_iff] at this push_cast at this rw [h0, zero_mul] at this exact zero_ne_one this have huord : w.ord (algebraMap F F' ((u : (w.restrict F).toValuationSubring) : F)) = 0 := (isUnit_mk_comap_iff hune (u : (w.restrict F).toValuationSubring).2).mp u.isUnit have hgz : (algebraMap F F' g) ^ n ≠ 0 := zpow_ne_zero _ (algebraMap_ne_zero hg0) calc w.ord (algebraMap F F' f) = w.ord (algebraMap F F' (((u : (w.restrict F).toValuationSubring) : F) * g ^ n)) := by rw [← hu] _ = w.ord (algebraMap F F' ((u : (w.restrict F).toValuationSubring) : F)) + w.ord ((algebraMap F F' g) ^ n) := by rw [map_mul, map_zpow₀] exact w.ord_mul (algebraMap_ne_zero hune) hgz _ = ramificationIndex (F := F) w * n := by rw [huord, w.ord_zpow, hge, zero_add, mul_comm] theorem ord_algebraMap_ne_zero_of_restrict_eq {v : Place K F} {f : F} (hford : v.ord f ≠ 0) (hw : w.restrict F = v) : w.ord (algebraMap F F' f) ≠ 0 := by rw [w.ord_restrict f, hw] have hepos : 0 < ramificationIndex (F := F) w := w.ramificationIndex_pos (F := F) exact mul_ne_zero (by omega) hford theorem restrict_fiber_finite [HasPrincipalDivisors K F'] (v : Place K F) : {w : Place K F' | w.restrict F = v}.Finite := by obtain ⟨f, hf0, hford⟩ := v.exists_ord_pos obtain ⟨D, hD, -⟩ := HasPrincipalDivisors.exists_divisor (K := K) (algebraMap F F' f) (algebraMap_ne_zero hf0) apply Set.Finite.subset D.support.finite_toSet intro w hw simp only [Finset.mem_coe, Finsupp.mem_support_iff, hD w] exact w.ord_algebraMap_ne_zero_of_restrict_eq (by omega) hw end RestrictDef end Restrict end Place end AlgebraicCurve set_option autoImplicit false noncomputable section open IsDedekindDomain WithZero IsLocalRing namespace AlgebraicCurve variable {K F F' : Type*} [Field K] [Field F] [Field F'] [Algebra K F] [Algebra K F'] [Algebra F F'] [IsScalarTower K F F'] [Algebra.IsIntegral F F'] namespace Place variable (w : Place K F') variable (F) in def restrictInclusion : (w.restrict F).toValuationSubring →+* w.toValuationSubring where toFun a := ⟨algebraMap F F' (a : F), ValuationSubring.mem_comap.mp a.2⟩ map_one' := Subtype.ext (map_one (algebraMap F F')) map_mul' a b := Subtype.ext (map_mul (algebraMap F F') (a : F) (b : F)) map_zero' := Subtype.ext (map_zero (algebraMap F F')) map_add' a b := Subtype.ext (map_add (algebraMap F F') (a : F) (b : F)) @[simp] theorem coe_restrictInclusion (a : (w.restrict F).toValuationSubring) : ((restrictInclusion F w a : w.toValuationSubring) : F') = algebraMap F F' (a : F) := rfl instance instIsLocalHomRestrictInclusion : IsLocalHom (restrictInclusion F w) where map_nonunit a ha := by have hord : w.ord (algebraMap F F' (a : F)) = 0 := by have h := w.ord_coe_unit ha.unit rwa [IsUnit.unit_spec, coe_restrictInclusion] at h have ha0 : (a : F) ≠ 0 := by rintro h0 obtain ⟨b, hb⟩ := isUnit_iff_exists_inv.mp ha have hb' : algebraMap F F' (a : F) * (b : F') = 1 := congrArg Subtype.val hb rw [h0, map_zero, zero_mul] at hb' exact zero_ne_one hb' exact (isUnit_mk_comap_iff ha0 a.2).mpr hord variable (F) in def restrictResidueMap : (w.restrict F).ResidueField →+* w.ResidueField := IsLocalRing.ResidueField.map (restrictInclusion F w) @[simp] theorem restrictResidueMap_residue (a : (w.restrict F).toValuationSubring) : restrictResidueMap F w (IsLocalRing.residue _ a) = IsLocalRing.residue _ (restrictInclusion F w a) := IsLocalRing.ResidueField.map_residue _ _ instance instAlgebraResidueFieldRestrictPushforward : Algebra (w.restrict F).ResidueField w.ResidueField := (restrictResidueMap F w).toAlgebra theorem algebraMap_residueField_eq : algebraMap (w.restrict F).ResidueField w.ResidueField = restrictResidueMap F w := rfl instance instIsScalarTowerResidueFieldRestrictPushforward : IsScalarTower K (w.restrict F).ResidueField w.ResidueField := by refine IsScalarTower.of_algebraMap_eq fun a => ?_ show IsLocalRing.residue _ (algebraMap K w.toValuationSubring a) = restrictResidueMap F w (IsLocalRing.residue _ (algebraMap K (w.restrict F).toValuationSubring a)) rw [restrictResidueMap_residue] refine congrArg _ (Subtype.ext ?_) show algebraMap K F' a = algebraMap F F' (algebraMap K F a) rw [← IsScalarTower.algebraMap_apply] variable (F) in def inertiaDeg : ℕ := Module.finrank (w.restrict F).ResidueField w.ResidueField theorem deg_restrict_mul_inertiaDeg : (w.restrict F).deg * w.inertiaDeg F = w.deg := Module.finrank_mul_finrank K (w.restrict F).ResidueField w.ResidueField end Place namespace Divisor variable (F) in def mapRestrict : Divisor K F' →+ Divisor K F := Finsupp.liftAddHom fun w => Finsupp.singleAddHom (w.restrict F) @[simp] theorem mapRestrict_single (w : Place K F') (n : ℤ) : mapRestrict F (Finsupp.single w n) = Finsupp.single (w.restrict F) n := by simp [mapRestrict] variable (F) in def pushforward : Divisor K F' →+ Divisor K F := Finsupp.liftAddHom fun w => (Finsupp.singleAddHom (w.restrict F)).comp (AddMonoidHom.mulRight (w.inertiaDeg F : ℤ)) @[simp] theorem pushforward_single (w : Place K F') (n : ℤ) : pushforward F (Finsupp.single w n) = Finsupp.single (w.restrict F) (n * w.inertiaDeg F) := by simp [pushforward] @[simp] theorem degree_pushforward (D : Divisor K F') : degree (pushforward F D) = degree D := by induction D using Finsupp.induction with | zero => simp | single_add w n D hw hn ih => simp only [map_add, pushforward_single, degree_single, ih] have h := w.deg_restrict_mul_inertiaDeg (F := F) push_cast [← h] ring theorem pushforward_mem_degZero {D : Divisor K F'} (hD : D ∈ degZero (K := K) (F := F')) : pushforward F D ∈ degZero (K := K) (F := F) := by rwa [mem_degZero, degree_pushforward] theorem pushforward_apply [DecidableEq (Place K F)] (D : Divisor K F') (v : Place K F) : pushforward F D v = ∑ w ∈ D.support, if w.restrict F = v then D w * (w.inertiaDeg F : ℤ) else 0 := by classical rw [pushforward, Finsupp.liftAddHom_apply, Finsupp.sum_apply, Finsupp.sum] refine Finset.sum_congr rfl fun w _ => ?_ simp [Finsupp.single_apply] variable (K F F') in def PushforwardNormFormula [Module.Finite F F'] : Prop := ∀ (f : F'), f ≠ 0 → ∀ D : Divisor K F', (∀ w, D w = w.ord f) → ∀ v : Place K F, pushforward F D v = v.ord (Algebra.norm F f) theorem pushforward_eq_of_normFormula [Module.Finite F F'] (H : PushforwardNormFormula K F F') {f : F'} (hf : f ≠ 0) {D : Divisor K F'} (hD : ∀ w, D w = w.ord f) {E : Divisor K F} (hE : ∀ v, E v = v.ord (Algebra.norm F f)) : pushforward F D = E := Finsupp.ext fun v => (H f hf D hD v).trans (hE v).symm theorem isPrincipal_pushforward_of_normFormula [Module.Finite F F'] (H : PushforwardNormFormula K F F') {D : Divisor K F'} (hD : IsPrincipal D) : IsPrincipal (pushforward F D) := by obtain ⟨f, hf, hDf⟩ := hD exact ⟨Algebra.norm F f, Algebra.norm_ne_zero_iff.mpr hf, fun v => H f hf D hDf v⟩ end Divisor end AlgebraicCurve set_option autoImplicit false noncomputable section namespace AlgebraicCurve variable {K F F' : Type*} [Field K] [Field F] [Field F'] [Algebra K F] [Algebra K F'] [Algebra F F'] [IsScalarTower K F F'] [Algebra.IsIntegral F F'] [HasPrincipalDivisors K F'] namespace Place variable (F') in def fiber (v : Place K F) : Finset (Place K F') := (restrict_fiber_finite v).toFinset @[simp] theorem mem_fiber {v : Place K F} {w : Place K F'} : w ∈ v.fiber F' ↔ w.restrict F = v := by simp only [fiber, Set.Finite.mem_toFinset, Set.mem_setOf_eq] theorem restrict_mem_fiber (w : Place K F') : w ∈ (w.restrict F).fiber F' := mem_fiber.mpr rfl end Place namespace Divisor variable (F') in def pullbackSingleHom (v : Place K F) : ℤ →+ Divisor K F' where toFun n := ∑ w ∈ v.fiber F', Finsupp.single w (n * w.ramificationIndex F) map_zero' := by simp map_add' m n := by rw [← Finset.sum_add_distrib] exact Finset.sum_congr rfl fun w _ => by rw [add_mul, Finsupp.single_add] theorem pullbackSingleHom_apply (v : Place K F) (n : ℤ) : pullbackSingleHom F' v n = ∑ w ∈ v.fiber F', Finsupp.single w (n * w.ramificationIndex F) := rfl variable (F') in def pullback : Divisor K F →+ Divisor K F' := Finsupp.liftAddHom (pullbackSingleHom F') theorem pullback_single (v : Place K F) (n : ℤ) : pullback F' (Finsupp.single v n) = ∑ w ∈ v.fiber F', Finsupp.single w (n * w.ramificationIndex F) := Finsupp.liftAddHom_apply_single _ _ _ theorem pullback_single_apply_of_restrict_eq {v : Place K F} {w : Place K F'} (hw : w.restrict F = v) (n : ℤ) : pullback F' (Finsupp.single v n) w = n * w.ramificationIndex F := by rw [pullback_single, Finset.sum_apply'] trans (Finsupp.single w (n * (w.ramificationIndex F : ℤ))) w · refine Finset.sum_eq_single_of_mem w (Place.mem_fiber.mpr hw) ?_ intro b _ hb exact Finsupp.single_eq_of_ne' hb · exact Finsupp.single_eq_same theorem pullback_single_apply_of_restrict_ne {v : Place K F} {w : Place K F'} (hw : w.restrict F ≠ v) (n : ℤ) : pullback F' (Finsupp.single v n) w = 0 := by rw [pullback_single, Finset.sum_apply'] exact Finset.sum_eq_zero fun b hb => Finsupp.single_eq_of_ne fun h => hw (h ▸ Place.mem_fiber.mp hb) theorem pullback_apply (D : Divisor K F) (w : Place K F') : pullback F' D w = w.ramificationIndex F * D (w.restrict F) := by induction D using Finsupp.induction with | zero => simp | single_add v n D _ _ ih => rw [map_add, Finsupp.add_apply, ih, Finsupp.add_apply, mul_add] congr 1 by_cases hw : w.restrict F = v · subst hw rw [pullback_single_apply_of_restrict_eq rfl, Finsupp.single_eq_same, mul_comm] · rw [pullback_single_apply_of_restrict_ne hw, Finsupp.single_eq_of_ne hw, mul_zero] theorem restrict_mem_support_of_mem_support_pullback {D : Divisor K F} {w : Place K F'} (hw : w ∈ (pullback F' D).support) : w.restrict F ∈ D.support := by rw [Finsupp.mem_support_iff] at hw ⊢ intro h exact hw (by rw [pullback_apply, h, mul_zero]) theorem pullback_apply_eq_ord {f : F} {D : Divisor K F} (hD : ∀ v : Place K F, D v = v.ord f) (w : Place K F') : pullback F' D w = w.ord (algebraMap F F' f) := by rw [pullback_apply, hD, ← Place.ord_restrict] theorem isPrincipal_pullback {D : Divisor K F} (hD : D.IsPrincipal) : (pullback F' D).IsPrincipal := by obtain ⟨f, hf, hDf⟩ := hD exact ⟨algebraMap F F' f, by simpa using hf, fun w => pullback_apply_eq_ord hDf w⟩ theorem pullback_mem_principal {D : Divisor K F} (hD : D ∈ principal (K := K) (F := F)) : pullback F' D ∈ principal (K := K) (F := F') := isPrincipal_pullback hD end Divisor variable (K F F') in class FundamentalIdentity : Prop where sum_ramificationIndex_mul_deg : ∀ v : Place K F, ∑ w ∈ v.fiber F', (w.ramificationIndex F : ℤ) * (w.deg : ℤ) = (Module.finrank F F' : ℤ) * (v.deg : ℤ) namespace Divisor theorem degree_pullback_single [FundamentalIdentity K F F'] (v : Place K F) (n : ℤ) : degree (pullback F' (Finsupp.single v n)) = (Module.finrank F F' : ℤ) * degree (Finsupp.single v n) := by rw [pullback_single, map_sum, degree_single] simp_rw [degree_single, mul_assoc] rw [← Finset.mul_sum, FundamentalIdentity.sum_ramificationIndex_mul_deg (K := K) (F := F) (F' := F') v] ring theorem degree_pullback [FundamentalIdentity K F F'] (D : Divisor K F) : degree (pullback F' D) = (Module.finrank F F' : ℤ) * degree D := by induction D using Finsupp.induction with | zero => simp | single_add v n D _ _ ih => rw [map_add, map_add, map_add, mul_add, ih, degree_pullback_single] theorem pullback_mem_degZero [FundamentalIdentity K F F'] {D : Divisor K F} (hD : D ∈ degZero (K := K) (F := F)) : pullback F' D ∈ degZero (K := K) (F := F') := by rw [mem_degZero] at hD ⊢ rw [degree_pullback, hD, mul_zero] end Divisor end AlgebraicCurve set_option autoImplicit false noncomputable section namespace AlgebraicCurve variable {K F F' : Type*} [Field K] [Field F] [Field F'] [Algebra K F] [Algebra K F'] [Algebra F F'] [IsScalarTower K F F'] [Algebra.IsIntegral F F'] [HasPrincipalDivisors K F'] variable (K F F') in class SumRamificationInertia : Prop where sum_ramificationIndex_mul_inertiaDeg : ∀ v : Place K F, ∑ w ∈ v.fiber F', (w.ramificationIndex F : ℤ) * (w.inertiaDeg F : ℤ) = (Module.finrank F F' : ℤ) instance (priority := 100) instFundamentalIdentityOfSumRamificationInertia [SumRamificationInertia K F F'] : FundamentalIdentity K F F' where sum_ramificationIndex_mul_deg v := by have key := SumRamificationInertia.sum_ramificationIndex_mul_inertiaDeg (K := K) (F := F) (F' := F') v calc ∑ w ∈ v.fiber F', (w.ramificationIndex F : ℤ) * (w.deg : ℤ) = ∑ w ∈ v.fiber F', (v.deg : ℤ) * ((w.ramificationIndex F : ℤ) * (w.inertiaDeg F : ℤ)) := by refine Finset.sum_congr rfl fun w hw => ?_ have htower : ((w.restrict F).deg : ℤ) * (w.inertiaDeg F : ℤ) = (w.deg : ℤ) := by exact_mod_cast congrArg (Nat.cast (R := ℤ)) (w.deg_restrict_mul_inertiaDeg (F := F)) rw [Place.mem_fiber.mp hw] at htower rw [← htower]; ring _ = (v.deg : ℤ) * ∑ w ∈ v.fiber F', (w.ramificationIndex F : ℤ) * (w.inertiaDeg F : ℤ) := by rw [Finset.mul_sum] _ = (Module.finrank F F' : ℤ) * (v.deg : ℤ) := by rw [key]; ring namespace Pic0 variable (F') in def pullbackDegZeroHom [FundamentalIdentity K F F'] : Divisor.degZero (K := K) (F := F) →+ Divisor.degZero (K := K) (F := F') := ((Divisor.pullback F').domRestrict (Divisor.degZero (K := K) (F := F))).codRestrict _ fun D => Divisor.pullback_mem_degZero D.2 @[simp] theorem coe_pullbackDegZeroHom [FundamentalIdentity K F F'] (D : Divisor.degZero (K := K) (F := F)) : (pullbackDegZeroHom F' D : Divisor K F') = Divisor.pullback F' (D : Divisor K F) := rfl variable (F') in def pullbackHom [FundamentalIdentity K F F'] : Pic0 K F →+ Pic0 K F' := QuotientAddGroup.map _ _ (pullbackDegZeroHom F') (by rintro ⟨D, hD0⟩ hD simp only [AddSubgroup.mem_addSubgroupOf] at hD ⊢ exact Divisor.pullback_mem_principal hD) theorem pullbackHom_mk [FundamentalIdentity K F F'] (D : Divisor.degZero (K := K) (F := F)) : pullbackHom F' (mk D) = mk (pullbackDegZeroHom F' D) := rfl variable (F) in def pushforwardDegZeroHom : Divisor.degZero (K := K) (F := F') →+ Divisor.degZero (K := K) (F := F) := ((Divisor.pushforward F).domRestrict (Divisor.degZero (K := K) (F := F'))).codRestrict _ fun D => Divisor.pushforward_mem_degZero D.2 omit [HasPrincipalDivisors K F'] in @[simp] theorem coe_pushforwardDegZeroHom (D : Divisor.degZero (K := K) (F := F')) : (pushforwardDegZeroHom F D : Divisor K F) = Divisor.pushforward F (D : Divisor K F') := rfl variable (K F F') in def pushforwardHom [Module.Finite F F'] (H : Divisor.PushforwardNormFormula K F F') : Pic0 K F' →+ Pic0 K F := QuotientAddGroup.map _ _ (pushforwardDegZeroHom F) (by rintro ⟨D, hD0⟩ hD simp only [AddSubgroup.mem_addSubgroupOf] at hD ⊢ exact Divisor.isPrincipal_pushforward_of_normFormula H hD) omit [HasPrincipalDivisors K F'] in theorem pushforwardHom_mk [Module.Finite F F'] (H : Divisor.PushforwardNormFormula K F F') (D : Divisor.degZero (K := K) (F := F')) : pushforwardHom K F F' H (mk D) = mk (pushforwardDegZeroHom F D) := rfl end Pic0 end AlgebraicCurve