import Mathlib set_option autoImplicit false open CategoryTheory Opposite TopologicalSpace universe u namespace AlgebraicGeometry def powCharRingHom (R : Type*) [CommRing R] (p n : ℕ) (hp : p.Prime) (h : (p : R) = 0) : R →+* R where toFun x := x ^ p ^ n map_one' := one_pow _ map_mul' x y := mul_pow x y _ map_zero' := zero_pow (pow_ne_zero n hp.ne_zero) map_add' x y := by obtain ⟨r, hr⟩ := (Commute.all x y).exists_add_pow_prime_pow_eq hp n rw [hr, h, zero_mul, zero_mul, zero_mul, add_zero] @[simp] theorem powCharRingHom_apply {R : Type*} [CommRing R] (p n : ℕ) (hp : p.Prime) (h : (p : R) = 0) (x : R) : powCharRingHom R p n hp h x = x ^ p ^ n := rfl theorem RingHom.map_powCharRingHom {R S : Type*} [CommRing R] [CommRing S] (f : R →+* S) (p n : ℕ) (hp : p.Prime) (hR : (p : R) = 0) (hS : (p : S) = 0) (x : R) : f (powCharRingHom R p n hp hR x) = powCharRingHom S p n hp hS (f x) := by simp [map_pow] theorem bijective_powCharRingHom_of_perfectRing {R : Type*} [CommRing R] (p n : ℕ) [hp : Fact p.Prime] [CharP R p] [PerfectRing R p] : Function.Bijective (powCharRingHom R p n hp.out (CharP.cast_eq_zero R p)) := by have : ⇑(powCharRingHom R p n hp.out (CharP.cast_eq_zero R p)) = ⇑(iterateFrobenius R p n) := by ext x; simp [iterateFrobenius_def] rw [this] exact bijective_iterateFrobenius R p n namespace Scheme variable (X : Scheme.{u}) (p n : ℕ) (hp : p.Prime) (hX : (p : Γ(X, ⊤)) = 0) theorem natCast_eq_zero_sections {X : Scheme.{u}} {p : ℕ} (hX : (p : Γ(X, ⊤)) = 0) (U : X.Opens) : (p : Γ(X, U)) = 0 := by have := congrArg (X.presheaf.map (homOfLE (le_top : U ≤ ⊤)).op) hX simpa using this theorem natCast_eq_zero_stalk {X : Scheme.{u}} {p : ℕ} (hX : (p : Γ(X, ⊤)) = 0) (x : X) : (p : X.presheaf.stalk x) = 0 := by have := congrArg (X.presheaf.germ ⊤ x trivial) hX simpa using this def frobeniusSheafHom : X.presheaf ⟶ X.presheaf where app U := CommRingCat.ofHom (powCharRingHom Γ(X, U.unop) p n hp (natCast_eq_zero_sections hX _)) naturality U V i := by ext s simp [map_pow] def frobenius : X ⟶ X where base := 𝟙 _ c := X.frobeniusSheafHom p n hp hX prop x := by constructor intro g hg obtain ⟨U, hxU, s, rfl⟩ := X.presheaf.exists_germ_eq g have key : (PresheafedSpace.Hom.stalkMap ⟨𝟙 _, X.frobeniusSheafHom p n hp hX⟩ x).hom (X.presheaf.germ U x hxU s) = X.presheaf.germ U x hxU s ^ p ^ n := by have h1 := PresheafedSpace.stalkMap_germ_apply (C := CommRingCat) (X := X.toPresheafedSpace) (Y := X.toPresheafedSpace) ⟨𝟙 _, X.frobeniusSheafHom p n hp hX⟩ U x hxU s refine h1.trans ?_ change (X.presheaf.germ U x hxU) (s ^ p ^ n) = _ rw [map_pow] erw [key] at hg exact (isUnit_pow_iff (pow_ne_zero n hp.ne_zero)).1 hg @[simp] theorem frobenius_base : (X.frobenius p n hp hX).base = 𝟙 _ := rfl theorem frobenius_apply (x : X) : (X.frobenius p n hp hX) x = x := rfl @[simp] theorem frobenius_preimage (U : X.Opens) : (X.frobenius p n hp hX) ⁻¹ᵁ U = U := rfl theorem frobenius_app_apply (U : X.Opens) (s : Γ(X, U)) : (X.frobenius p n hp hX).app U s = s ^ p ^ n := rfl theorem frobenius_appTop_apply (s : Γ(X, ⊤)) : (X.frobenius p n hp hX).appTop s = s ^ p ^ n := rfl theorem frobenius_stalkMap_apply (x : X) (g : X.presheaf.stalk x) : (X.frobenius p n hp hX).stalkMap x g = g ^ p ^ n := by obtain ⟨U, hxU, s, rfl⟩ := X.presheaf.exists_germ_eq g have h1 := Scheme.Hom.germ_stalkMap_apply (X.frobenius p n hp hX) U x hxU s refine h1.trans ?_ change (X.presheaf.germ U x hxU) (s ^ p ^ n) = _ rw [map_pow] theorem presheaf_map_eqToHom_op_apply {X : Scheme.{u}} {U V : X.Opens} (h : U = V) (t : Γ(X, V)) : X.presheaf.map (eqToHom h).op t = cast (by rw [h]) t := by subst h; simp @[reassoc] theorem frobenius_comp {X Y : Scheme.{u}} (f : X ⟶ Y) (p n : ℕ) (hp : p.Prime) (hX : (p : Γ(X, ⊤)) = 0) (hY : (p : Γ(Y, ⊤)) = 0) : X.frobenius p n hp hX ≫ f = f ≫ Y.frobenius p n hp hY := by refine Scheme.Hom.ext rfl (fun U => ?_) ext s simp only [Scheme.Hom.comp_app, CommRingCat.hom_comp, RingHom.coe_comp, Function.comp_apply] rw [presheaf_map_eqToHom_op_apply] refine (cast_eq _ _).trans ?_ change (X.frobenius p n hp hX).app _ (f.app U s) = f.app _ ((Y.frobenius p n hp hY).app U s) rw [frobenius_app_apply, frobenius_app_apply] change f.app U s ^ p ^ n = f.app U (s ^ p ^ n) rw [map_pow] theorem frobenius_zero : X.frobenius p 0 hp hX = 𝟙 X := by refine Scheme.Hom.ext rfl (fun U => ?_) ext s simp only [CommRingCat.hom_comp, RingHom.coe_comp, Function.comp_apply] rw [presheaf_map_eqToHom_op_apply] refine (cast_eq _ _).trans ?_ change (X.frobenius p 0 hp hX).app U s = (𝟙 X : X ⟶ X).app U s rw [frobenius_app_apply, pow_zero, pow_one] rfl @[reassoc] theorem frobenius_comp_frobenius (m : ℕ) : X.frobenius p m hp hX ≫ X.frobenius p n hp hX = X.frobenius p (m + n) hp hX := by refine Scheme.Hom.ext rfl (fun U => ?_) ext s simp only [Scheme.Hom.comp_app, CommRingCat.hom_comp, RingHom.coe_comp, Function.comp_apply] rw [presheaf_map_eqToHom_op_apply] refine (cast_eq _ _).trans ?_ change (X.frobenius p m hp hX).app _ ((X.frobenius p n hp hX).app U s) = (X.frobenius p (m + n) hp hX).app U s rw [frobenius_app_apply, frobenius_app_apply, frobenius_app_apply] change (s ^ p ^ n) ^ p ^ m = s ^ p ^ (m + n) rw [← pow_mul, ← pow_add, Nat.add_comm n m] theorem natCast_eq_zero_ΓSpec {R : Type u} [CommRing R] {p : ℕ} (hR : (p : R) = 0) : (p : Γ(Spec (.of R), ⊤)) = 0 := by have := congrArg (Scheme.ΓSpecIso (.of R)).inv hR simpa using this theorem frobenius_Spec {R : Type u} [CommRing R] (p n : ℕ) (hp : p.Prime) (hR : (p : R) = 0) : (Spec (.of R)).frobenius p n hp (natCast_eq_zero_ΓSpec hR) = Spec.map (CommRingCat.ofHom (powCharRingHom R p n hp hR)) := by refine ext_of_isAffine ?_ have hinj : Function.Injective (Scheme.ΓSpecIso (.of R)).hom := (ConcreteCategory.bijective_of_isIso (Scheme.ΓSpecIso (.of R)).hom).1 ext s apply hinj have h2 := congrArg (fun φ => φ.hom s) (Scheme.ΓSpecIso_naturality (CommRingCat.ofHom (powCharRingHom R p n hp hR))) simp only [CommRingCat.hom_comp, RingHom.coe_comp, Function.comp_apply, CommRingCat.hom_ofHom, powCharRingHom_apply] at h2 refine Eq.trans ?_ h2.symm change (Scheme.ΓSpecIso (.of R)).hom (((Spec (.of R)).frobenius p n hp (natCast_eq_zero_ΓSpec hR)).appTop s) = _ rw [frobenius_appTop_apply, map_pow] theorem isIso_frobenius_Spec_of_bijective {R : Type u} [CommRing R] (p n : ℕ) (hp : p.Prime) (hR : (p : R) = 0) (hbij : Function.Bijective (powCharRingHom R p n hp hR)) : IsIso ((Spec (.of R)).frobenius p n hp (natCast_eq_zero_ΓSpec hR)) := by rw [frobenius_Spec p n hp hR] have : IsIso (CommRingCat.ofHom (powCharRingHom R p n hp hR)) := (ConcreteCategory.isIso_iff_bijective (CommRingCat.ofHom (powCharRingHom R p n hp hR))).2 hbij infer_instance theorem isIso_frobenius_Spec_of_perfectRing {R : Type u} [CommRing R] (p n : ℕ) [hp : Fact p.Prime] [CharP R p] [PerfectRing R p] (h : (p : Γ(Spec (.of R), ⊤)) = 0) : IsIso ((Spec (.of R)).frobenius p n hp.out h) := isIso_frobenius_Spec_of_bijective p n hp.out (CharP.cast_eq_zero R p) (bijective_powCharRingHom_of_perfectRing p n) section Relative variable {X} {S : Scheme.{u}} (f : X ⟶ S) (hS : (p : Γ(S, ⊤)) = 0) noncomputable abbrev frobeniusTwist : Scheme.{u} := Limits.pullback f (S.frobenius p n hp hS) noncomputable def relFrobenius : X ⟶ frobeniusTwist p n hp f hS := Limits.pullback.lift (X.frobenius p n hp hX) f (frobenius_comp f p n hp hX hS) @[reassoc (attr := simp)] theorem relFrobenius_fst : relFrobenius p n hp hX f hS ≫ Limits.pullback.fst _ _ = X.frobenius p n hp hX := Limits.pullback.lift_fst _ _ _ @[reassoc (attr := simp)] theorem relFrobenius_snd : relFrobenius p n hp hX f hS ≫ Limits.pullback.snd _ _ = f := Limits.pullback.lift_snd _ _ _ theorem isIso_fst_frobeniusTwist [IsIso (S.frobenius p n hp hS)] : IsIso (Limits.pullback.fst f (S.frobenius p n hp hS)) := inferInstance theorem relFrobenius_eq_frobenius_comp_inv [IsIso (S.frobenius p n hp hS)] : relFrobenius p n hp hX f hS = X.frobenius p n hp hX ≫ inv (Limits.pullback.fst f (S.frobenius p n hp hS)) := by rw [← relFrobenius_fst p n hp hX f hS, Category.assoc, IsIso.hom_inv_id, Category.comp_id] end Relative end Scheme end AlgebraicGeometry