import Mathlib set_option maxHeartbeats 800000 open Polynomial IntermediateField noncomputable section namespace AlgebraicCurve.KwPke theorem kw_pke_axiomAnchor : True := have _h₁ : True = True := propext Iff.rfl have _h₂ : ℕ := Classical.choice ⟨0⟩ have _h₃ : Quot.mk (fun (_ _ : ℕ) => True) 0 = Quot.mk (fun (_ _ : ℕ) => True) 1 := Quot.sound trivial trivial theorem kw_pke_mem_of_isSeparable_of_pow_mem {F : Type*} [Field F] {ℓ : ℕ} [hℓ : Fact ℓ.Prime] [CharP F ℓ] (B : Subfield F) {x : F} (hxp : x ^ ℓ ∈ B) (hsep : IsSeparable B x) : x ∈ B := by have _ := kw_pke_axiomAnchor have hcoe : (algebraMap B F) (⟨x ^ ℓ, hxp⟩ : B) = x ^ ℓ := rfl have hx_int : IsIntegral B x := by refine ⟨X ^ ℓ - C (⟨x ^ ℓ, hxp⟩ : B), ?_, ?_⟩ · exact monic_X_pow_sub_C _ hℓ.out.ne_zero · simp [Polynomial.eval₂_sub, hcoe] have hdvd : minpoly B x ∣ X ^ ℓ - C (⟨x ^ ℓ, hxp⟩ : B) := minpoly.dvd B x (by simp [Polynomial.aeval_def, Polynomial.eval₂_sub, hcoe]) have hmap_dvd : (minpoly B x).map (algebraMap B F) ∣ (X - C x) ^ ℓ := by have h1 : (X ^ ℓ - C (⟨x ^ ℓ, hxp⟩ : B) : Polynomial B).map (algebraMap B F) = X ^ ℓ - C (x ^ ℓ) := by simp [Polynomial.map_sub, Polynomial.map_pow, hcoe] have h2 : (X - C x : Polynomial F) ^ ℓ = X ^ ℓ - C (x ^ ℓ) := by have h := sub_pow_char (X : Polynomial F) (C x) rwa [← map_pow] at h rw [h2, ← h1] exact Polynomial.map_dvd _ hdvd have hsq : Squarefree ((minpoly B x).map (algebraMap B F)) := Polynomial.Separable.squarefree (Polynomial.Separable.map hsep) have hdvd1 : (minpoly B x).map (algebraMap B F) ∣ (X - C x) := by have hprime : Prime (X - C x : Polynomial F) := Polynomial.prime_X_sub_C x obtain ⟨k, hk, hassoc⟩ := (dvd_prime_pow hprime ℓ).mp hmap_dvd have hk1 : k ≤ 1 := by by_contra hk2 rw [not_le] at hk2 have hpp : (X - C x : Polynomial F) * (X - C x) ∣ (minpoly B x).map (algebraMap B F) := by calc (X - C x : Polynomial F) * (X - C x) = (X - C x) ^ 2 := by ring _ ∣ (X - C x) ^ k := pow_dvd_pow _ (by omega) _ ∣ _ := hassoc.symm.dvd exact hprime.not_unit (hsq _ hpp) calc (minpoly B x).map (algebraMap B F) ∣ (X - C x) ^ k := hassoc.dvd _ ∣ (X - C x) ^ 1 := pow_dvd_pow _ hk1 _ = X - C x := pow_one _ have hdeg_le : (minpoly B x).degree ≤ 1 := by have h := Polynomial.degree_le_of_dvd hdvd1 (X_sub_C_ne_zero x) rwa [degree_map, degree_X_sub_C] at h have hdeg_eq : (minpoly B x).degree = 1 := by have hnat : (minpoly B x).natDegree = 1 := le_antisymm (Polynomial.natDegree_le_iff_degree_le.mpr hdeg_le) (minpoly.natDegree_pos hx_int) exact (Polynomial.degree_eq_iff_natDegree_eq (minpoly.ne_zero hx_int)).mpr hnat rcases minpoly.mem_range_of_degree_eq_one B x hdeg_eq with ⟨b, rfl⟩ exact b.2 section PthPowers variable (F : Type*) [Field F] (ℓ : ℕ) [hℓ : Fact ℓ.Prime] [CharP F ℓ] def kw_pke_pthPowers : Subfield F := (frobenius F ℓ).fieldRange theorem kw_pke_mem_pthPowers_iff {y : F} : y ∈ kw_pke_pthPowers F ℓ ↔ ∃ g : F, g ^ ℓ = y := by simp [kw_pke_pthPowers, RingHom.mem_fieldRange, frobenius_def] theorem kw_pke_prime_field_pow (n : ℕ) : ((n : F)) ∈ kw_pke_pthPowers F ℓ := by have _ := kw_pke_axiomAnchor induction n with | zero => rw [Nat.cast_zero] exact zero_mem _ | succ k ih => have h : ((k + 1 : ℕ) : F) = ((k : ℕ) : F) + 1 := by push_cast; ring rw [h] exact add_mem ih (one_mem _) end PthPowers section Expansion variable {F : Type*} [Field F] {ℓ : ℕ} [hℓ : Fact ℓ.Prime] [CharP F ℓ] abbrev kw_pke_expansionField (t : F) : IntermediateField (kw_pke_pthPowers F ℓ) F := IntermediateField.adjoin (kw_pke_pthPowers F ℓ) {t} theorem kw_pke_mem_expansionField (t : F) (hsep : ∀ x : F, IsSeparable (kw_pke_expansionField (ℓ := ℓ) t).toSubfield x) (x : F) : x ∈ (kw_pke_expansionField (ℓ := ℓ) t).toSubfield := by have _ := kw_pke_axiomAnchor refine kw_pke_mem_of_isSeparable_of_pow_mem _ ?_ (hsep x) have hmem : x ^ ℓ ∈ kw_pke_pthPowers F ℓ := (kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨x, rfl⟩ exact (kw_pke_expansionField (ℓ := ℓ) t).algebraMap_mem ⟨_, hmem⟩ theorem kw_pke_isIntegral_gen (t : F) : IsIntegral (kw_pke_pthPowers F ℓ) t := by have _ := kw_pke_axiomAnchor have hcoe : (algebraMap (kw_pke_pthPowers F ℓ) F) (⟨t ^ ℓ, (kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨t, rfl⟩⟩ : kw_pke_pthPowers F ℓ) = t ^ ℓ := rfl refine ⟨X ^ ℓ - C (⟨t ^ ℓ, (kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨t, rfl⟩⟩ : kw_pke_pthPowers F ℓ), monic_X_pow_sub_C _ hℓ.out.ne_zero, ?_⟩ simp [Polynomial.eval₂_sub, hcoe] theorem kw_pke_minpoly_natDegree_le (t : F) : (minpoly (kw_pke_pthPowers F ℓ) t).natDegree ≤ ℓ := by have _ := kw_pke_axiomAnchor have hcoe : (algebraMap (kw_pke_pthPowers F ℓ) F) (⟨t ^ ℓ, (kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨t, rfl⟩⟩ : kw_pke_pthPowers F ℓ) = t ^ ℓ := rfl have hdvd : minpoly (kw_pke_pthPowers F ℓ) t ∣ X ^ ℓ - C (⟨t ^ ℓ, (kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨t, rfl⟩⟩ : kw_pke_pthPowers F ℓ) := minpoly.dvd _ t (by simp [Polynomial.aeval_def, Polynomial.eval₂_sub, hcoe]) have hne : (X ^ ℓ - C (⟨t ^ ℓ, (kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨t, rfl⟩⟩ : kw_pke_pthPowers F ℓ) : _) ≠ 0 := (monic_X_pow_sub_C _ hℓ.out.ne_zero).ne_zero have h := Polynomial.natDegree_le_of_dvd hdvd hne have hdeg : (X ^ ℓ - C (⟨t ^ ℓ, (kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨t, rfl⟩⟩ : kw_pke_pthPowers F ℓ) : _).natDegree = ℓ := Polynomial.natDegree_X_pow_sub_C rwa [hdeg] at h variable {K : Type*} [Field K] [Algebra K F] theorem kw_pke_ker_d_pthPower (t : F) (hsep : ∀ x : F, IsSeparable (kw_pke_expansionField (ℓ := ℓ) t).toSubfield x) (hdt : KaehlerDifferential.D K F t ≠ 0) {f : F} (hdf : KaehlerDifferential.D K F f = 0) : ∃ g : F, f = g ^ ℓ := by have _ := kw_pke_axiomAnchor classical set P := kw_pke_pthPowers F ℓ with hP set E := kw_pke_expansionField (ℓ := ℓ) t with hE have hint : IsIntegral P t := kw_pke_isIntegral_gen t set PB : PowerBasis P E := IntermediateField.adjoin.powerBasis hint with hPB have hfE : f ∈ E.toSubfield := kw_pke_mem_expansionField t hsep f set ξ : E := ⟨f, hfE⟩ with hξ set c : Fin PB.dim → P := fun i => PB.basis.repr ξ i with hc have hroots : ∀ i, ∃ g : F, g ^ ℓ = ((c i : P) : F) := fun i => (kw_pke_mem_pthPowers_iff F ℓ).mp (c i).2 choose a ha using hroots have hgen : E.val PB.gen = t := by rw [hPB, IntermediateField.adjoin.powerBasis_gen] exact IntermediateField.AdjoinSimple.algebraMap_gen P t have hval_basis : ∀ i : Fin PB.dim, E.val (PB.basis i) = t ^ (i : ℕ) := fun i => by rw [PB.coe_basis, map_pow, hgen] have hval_smul : ∀ (p : P) (v : E), E.val (p • v) = ((p : F)) * E.val v := fun p v => by rw [map_smul, Algebra.smul_def] rfl have hrepr : f = ∑ i : Fin PB.dim, (a i) ^ ℓ * t ^ (i : ℕ) := by have h0 : (∑ i, c i • PB.basis i) = ξ := PB.basis.sum_repr ξ have h1 : E.val ξ = f := rfl calc f = E.val ξ := rfl _ = E.val (∑ i, c i • PB.basis i) := by rw [h0] _ = ∑ i, ((c i : F)) * (t ^ (i : ℕ)) := by rw [map_sum] exact Finset.sum_congr rfl fun i _ => by rw [hval_smul, hval_basis] _ = ∑ i, (a i) ^ ℓ * t ^ (i : ℕ) := by exact Finset.sum_congr rfl fun i _ => by rw [ha i] set s : F := ∑ i : Fin PB.dim, ((i : ℕ) : F) * (a i) ^ ℓ * t ^ ((i : ℕ) - 1) with hs have hDpow_zero : ∀ g : F, KaehlerDifferential.D K F (g ^ ℓ) = 0 := fun g => by rw [Derivation.leibniz_pow, ← Nat.cast_smul_eq_nsmul F, CharP.cast_eq_zero F ℓ, zero_smul] have hDterm : ∀ i : Fin PB.dim, KaehlerDifferential.D K F ((a i) ^ ℓ * t ^ (i : ℕ)) = (((i : ℕ) : F) * (a i) ^ ℓ * t ^ ((i : ℕ) - 1)) • KaehlerDifferential.D K F t := fun i => by rw [Derivation.leibniz, hDpow_zero, smul_zero, add_zero, Derivation.leibniz_pow, ← Nat.cast_smul_eq_nsmul F, smul_smul, smul_smul] ring_nf have hsDt : s • KaehlerDifferential.D K F t = 0 := by have h0 : KaehlerDifferential.D K F f = ∑ i : Fin PB.dim, (((i : ℕ) : F) * (a i) ^ ℓ * t ^ ((i : ℕ) - 1)) • KaehlerDifferential.D K F t := by rw [hrepr, map_sum] exact Finset.sum_congr rfl fun i _ => hDterm i rw [hs, Finset.sum_smul, ← h0, hdf] have hs_zero : s = 0 := by rcases smul_eq_zero.mp hsDt with h | h · exact h · exact absurd h hdt have hts : (∑ i : Fin PB.dim, (((i : ℕ) : F) * (a i) ^ ℓ) * t ^ (i : ℕ)) = 0 := by have h0 : t * s = 0 := by rw [hs_zero, mul_zero] rw [hs, Finset.mul_sum] at h0 rw [← h0] refine Finset.sum_congr rfl fun i _ => ?_ rcases Nat.eq_zero_or_pos (i : ℕ) with hi | hi · rw [hi] simp · have hpow : t ^ (i : ℕ) = t ^ ((i : ℕ) - 1) * t := by conv_lhs => rw [← Nat.succ_pred_eq_of_pos hi] rw [pow_succ, Nat.pred_eq_sub_one] rw [hpow] ring have hm_mem : ∀ i : Fin PB.dim, (((i : ℕ) : F) * (a i) ^ ℓ) ∈ P := fun i => mul_mem (kw_pke_prime_field_pow F ℓ (i : ℕ)) ((kw_pke_mem_pthPowers_iff F ℓ).mpr ⟨a i, rfl⟩) have hm_zero : ∀ i : Fin PB.dim, (((i : ℕ) : F) * (a i) ^ ℓ) = 0 := by set m : Fin PB.dim → P := fun i => ⟨((i : ℕ) : F) * (a i) ^ ℓ, hm_mem i⟩ with hm have hη : E.val (∑ i : Fin PB.dim, m i • PB.basis i) = 0 := by rw [map_sum] calc (∑ i : Fin PB.dim, E.val (m i • PB.basis i)) = ∑ i : Fin PB.dim, (((i : ℕ) : F) * (a i) ^ ℓ) * t ^ (i : ℕ) := Finset.sum_congr rfl fun i _ => by rw [hval_smul, hval_basis] _ = 0 := hts have hη0 : (∑ i : Fin PB.dim, m i • PB.basis i) = 0 := by have hinj : Function.Injective E.val := E.val.injective exact hinj (by rw [hη, map_zero]) intro i have hli := linearIndependent_iff'.mp PB.basis.linearIndependent Finset.univ m (by simpa using hη0) i (Finset.mem_univ i) have hcoe0 : ((m i : P) : F) = 0 := by rw [hli]; rfl simpa [hm] using hcoe0 have ha_zero : ∀ i : Fin PB.dim, (i : ℕ) ≠ 0 → a i = 0 := by intro i hi have hilt : (i : ℕ) < ℓ := lt_of_lt_of_le i.2 (kw_pke_minpoly_natDegree_le t) have hcast : (((i : ℕ) : F)) ≠ 0 := by rw [Ne, CharP.cast_eq_zero_iff F ℓ] exact fun hdvd => absurd (Nat.le_of_dvd (Nat.pos_of_ne_zero hi) hdvd) (not_le.mpr hilt) have := hm_zero i rcases mul_eq_zero.mp this with h | h · exact absurd h hcast · exact pow_eq_zero_iff hℓ.out.ne_zero |>.mp h have hdim_pos : 0 < PB.dim := PB.dim_pos refine ⟨a ⟨0, hdim_pos⟩, ?_⟩ rw [hrepr] rw [Finset.sum_eq_single (⟨0, hdim_pos⟩ : Fin PB.dim)] · simp · intro i _ hne have hi : (i : ℕ) ≠ 0 := fun h => hne (Fin.ext h) rw [ha_zero i hi] rw [zero_pow hℓ.out.ne_zero, zero_mul] · intro h exact absurd (Finset.mem_univ _) h end Expansion end AlgebraicCurve.KwPke end section Audits /-- info: 'AlgebraicCurve.KwPke.kw_pke_axiomAnchor' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_axiomAnchor /-- info: 'AlgebraicCurve.KwPke.kw_pke_mem_of_isSeparable_of_pow_mem' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_mem_of_isSeparable_of_pow_mem /-- info: 'AlgebraicCurve.KwPke.kw_pke_mem_pthPowers_iff' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_mem_pthPowers_iff /-- info: 'AlgebraicCurve.KwPke.kw_pke_prime_field_pow' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_prime_field_pow /-- info: 'AlgebraicCurve.KwPke.kw_pke_mem_expansionField' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_mem_expansionField /-- info: 'AlgebraicCurve.KwPke.kw_pke_isIntegral_gen' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_isIntegral_gen /-- info: 'AlgebraicCurve.KwPke.kw_pke_minpoly_natDegree_le' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_minpoly_natDegree_le /-- info: 'AlgebraicCurve.KwPke.kw_pke_ker_d_pthPower' depends on axioms: [propext, Classical.choice, Quot.sound] -/ #guard_msgs (whitespace := lax) in #print axioms AlgebraicCurve.KwPke.kw_pke_ker_d_pthPower end Audits