l3lab/ntp-mathlib huggingface dataset:
/-- Let `P →ₐ[R] A` be a surjection with kernel `J`, and `P` a formally smooth `R`-algebra,
then `A` is formally smooth over `R` iff the surjection `P ⧸ J ^ 2 →ₐ[R] A` has a section.

Geometric intuition: we require that a first-order thickening of `Spec A` inside `Spec P` admits
a retraction. -/
theorem FormallySmooth.iff_split_surjection [FormallySmooth R P] :
    FormallySmooth R A ↔ ∃ g, f.kerSquareLift.comp g = AlgHom.id R A := by
  constructor
  · intro
    have surj : Function.Surjective f.kerSquareLift := fun x =>
      ⟨Submodule.Quotient.mk (hf x).choose, (hf x).choose_spec⟩
    have sqz : RingHom.ker f.kerSquareLift.toRingHom ^ 2 = 0 := by
      rw [AlgHom.ker_kerSquareLift, Ideal.cotangentIdeal_square, Ideal.zero_eq_bot]
    refine'
      ⟨FormallySmooth.lift _ ⟨2, sqz⟩ (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom,
        _⟩
    ext x
    

Proof state:
case mp.H
R S : Type u
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
P A : Type u
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing P
inst✝¹ : Algebra R P
I : Ideal P
f : P →ₐ[R] A
hf : Function.Surjective ⇑f
inst✝ : FormallySmooth R P
a✝ : FormallySmooth R A
surj : Function.Surjective ⇑(AlgHom.kerSquareLift f)
sqz : RingHom.ker ↑(AlgHom.kerSquareLift f) ^ 2 = 0
x : A
⊢ (AlgHom.comp (AlgHom.kerSquareLift f)
        (lift (RingHom.ker ↑(AlgHom.kerSquareLift f)) (_ : ∃ n, RingHom.ker ↑(AlgHom.kerSquareLift f) ^ n = 0)
          ↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective surj))))
      x =
    (AlgHom.id R A) x

Next tactic:
have :=
      (Ideal.quotientKerAlgEquivOfSurjective surj).toAlgHom.congr_arg
        (FormallySmooth.mk_lift _ ⟨2, sqz⟩
          (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom x)
/-- Let `P →ₐ[R] A` be a surjection with kernel `J`, and `P` a formally smooth `R`-algebra,
then `A` is formally smooth over `R` iff the surjection `P ⧸ J ^ 2 →ₐ[R] A` has a section.

Geometric intuition: we require that a first-order thickening of `Spec A` inside `Spec P` admits
a retraction. -/
theorem FormallySmooth.iff_split_surjection [FormallySmooth R P] :
    FormallySmooth R A ↔ ∃ g, f.kerSquareLift.comp g = AlgHom.id R A := by
  constructor
  · intro
    have surj : Function.Surjective f.kerSquareLift := fun x =>
      ⟨Submodule.Quotient.mk (hf x).choose, (hf x).choose_spec⟩
    have sqz : RingHom.ker f.kerSquareLift.toRingHom ^ 2 = 0 := by
      rw [AlgHom.ker_kerSquareLift, Ideal.cotangentIdeal_square, Ideal.zero_eq_bot]
    refine'
      ⟨FormallySmooth.lift _ ⟨2, sqz⟩ (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom,
        _⟩
    ext x
    have :=
      (Ideal.quotientKerAlgEquivOfSurjective surj).toAlgHom.congr_arg
        (FormallySmooth.mk_lift _ ⟨2, sqz⟩
          (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom x)
    -- Porting note: was
    -- dsimp at this
    -- rw [AlgEquiv.apply_symm_apply] at this
    

Proof state:
case mp.H
R S : Type u
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
P A : Type u
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing P
inst✝¹ : Algebra R P
I : Ideal P
f : P →ₐ[R] A
hf : Function.Surjective ⇑f
inst✝ : FormallySmooth R P
a✝ : FormallySmooth R A
surj : Function.Surjective ⇑(AlgHom.kerSquareLift f)
sqz : RingHom.ker ↑(AlgHom.kerSquareLift f) ^ 2 = 0
x : A
this :
  ↑(Ideal.quotientKerAlgEquivOfSurjective surj)
      ((Ideal.Quotient.mk (RingHom.ker ↑(AlgHom.kerSquareLift f)))
        ((lift (RingHom.ker ↑(AlgHom.kerSquareLift f)) (_ : ∃ n, RingHom.ker ↑(AlgHom.kerSquareLift f) ^ n = 0)
            ↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective surj)))
          x)) =
    ↑(Ideal.quotientKerAlgEquivOfSurjective surj) (↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective surj)) x)
⊢ (AlgHom.comp (AlgHom.kerSquareLift f)
        (lift (RingHom.ker ↑(AlgHom.kerSquareLift f)) (_ : ∃ n, RingHom.ker ↑(AlgHom.kerSquareLift f) ^ n = 0)
          ↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective surj))))
      x =
    (AlgHom.id R A) x

Next tactic:
erw [AlgEquiv.apply_symm_apply] at this
/-- Let `P →ₐ[R] A` be a surjection with kernel `J`, and `P` a formally smooth `R`-algebra,
then `A` is formally smooth over `R` iff the surjection `P ⧸ J ^ 2 →ₐ[R] A` has a section.

Geometric intuition: we require that a first-order thickening of `Spec A` inside `Spec P` admits
a retraction. -/
theorem FormallySmooth.iff_split_surjection [FormallySmooth R P] :
    FormallySmooth R A ↔ ∃ g, f.kerSquareLift.comp g = AlgHom.id R A := by
  constructor
  · intro
    have surj : Function.Surjective f.kerSquareLift := fun x =>
      ⟨Submodule.Quotient.mk (hf x).choose, (hf x).choose_spec⟩
    have sqz : RingHom.ker f.kerSquareLift.toRingHom ^ 2 = 0 := by
      rw [AlgHom.ker_kerSquareLift, Ideal.cotangentIdeal_square, Ideal.zero_eq_bot]
    refine'
      ⟨FormallySmooth.lift _ ⟨2, sqz⟩ (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom,
        _⟩
    ext x
    have :=
      (Ideal.quotientKerAlgEquivOfSurjective surj).toAlgHom.congr_arg
        (FormallySmooth.mk_lift _ ⟨2, sqz⟩
          (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom x)
    -- Porting note: was
    -- dsimp at this
    -- rw [AlgEquiv.apply_symm_apply] at this
    erw [AlgEquiv.apply_symm_apply] at this
    

Proof state:
case mp.H
R S : Type u
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
P A : Type u
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing P
inst✝¹ : Algebra R P
I : Ideal P
f : P →ₐ[R] A
hf : Function.Surjective ⇑f
inst✝ : FormallySmooth R P
a✝ : FormallySmooth R A
surj : Function.Surjective ⇑(AlgHom.kerSquareLift f)
sqz : RingHom.ker ↑(AlgHom.kerSquareLift f) ^ 2 = 0
x : A
this :
  ↑(Ideal.quotientKerAlgEquivOfSurjective surj)
      ((Ideal.Quotient.mk (RingHom.ker ↑(AlgHom.kerSquareLift f)))
        ((lift (RingHom.ker ↑(AlgHom.kerSquareLift f)) (_ : ∃ n, RingHom.ker ↑(AlgHom.kerSquareLift f) ^ n = 0)
            ↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective surj)))
          x)) =
    x
⊢ (AlgHom.comp (AlgHom.kerSquareLift f)
        (lift (RingHom.ker ↑(AlgHom.kerSquareLift f)) (_ : ∃ n, RingHom.ker ↑(AlgHom.kerSquareLift f) ^ n = 0)
          ↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective surj))))
      x =
    (AlgHom.id R A) x

Next tactic:
conv_rhs => rw [← this, AlgHom.id_apply]
/-- Let `P →ₐ[R] A` be a surjection with kernel `J`, and `P` a formally smooth `R`-algebra,
then `A` is formally smooth over `R` iff the surjection `P ⧸ J ^ 2 →ₐ[R] A` has a section.

Geometric intuition: we require that a first-order thickening of `Spec A` inside `Spec P` admits
a retraction. -/
theorem FormallySmooth.iff_split_surjection [FormallySmooth R P] :
    FormallySmooth R A ↔ ∃ g, f.kerSquareLift.comp g = AlgHom.id R A := by
  constructor
  · intro
    have surj : Function.Surjective f.kerSquareLift := fun x =>
      ⟨Submodule.Quotient.mk (hf x).choose, (hf x).choose_spec⟩
    have sqz : RingHom.ker f.kerSquareLift.toRingHom ^ 2 = 0 := by
      rw [AlgHom.ker_kerSquareLift, Ideal.cotangentIdeal_square, Ideal.zero_eq_bot]
    refine'
      ⟨FormallySmooth.lift _ ⟨2, sqz⟩ (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom,
        _⟩
    ext x
    have :=
      (Ideal.quotientKerAlgEquivOfSurjective surj).toAlgHom.congr_arg
        (FormallySmooth.mk_lift _ ⟨2, sqz⟩
          (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom x)
    -- Porting note: was
    -- dsimp at this
    -- rw [AlgEquiv.apply_symm_apply] at this
    erw [AlgEquiv.apply_symm_apply] at this
    conv_rhs => 

Proof state:
R S : Type u
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
P A : Type u
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing P
inst✝¹ : Algebra R P
I : Ideal P
f : P →ₐ[R] A
hf : Function.Surjective ⇑f
inst✝ : FormallySmooth R P
a✝ : FormallySmooth R A
surj : Function.Surjective ⇑(AlgHom.kerSquareLift f)
sqz : RingHom.ker ↑(AlgHom.kerSquareLift f) ^ 2 = 0
x : A
this :
  ↑(Ideal.quotientKerAlgEquivOfSurjective surj)
      ((Ideal.Quotient.mk (RingHom.ker ↑(AlgHom.kerSquareLift f)))
        ((lift (RingHom.ker ↑(AlgHom.kerSquareLift f)) (_ : ∃ n, RingHom.ker ↑(AlgHom.kerSquareLift f) ^ n = 0)
            ↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective surj)))
          x)) =
    x
| (AlgHom.id R A) x

Next tactic:
rw [← this, AlgHom.id_apply]
/-- Let `P →ₐ[R] A` be a surjection with kernel `J`, and `P` a formally smooth `R`-algebra,
then `A` is formally smooth over `R` iff the surjection `P ⧸ J ^ 2 →ₐ[R] A` has a section.

Geometric intuition: we require that a first-order thickening of `Spec A` inside `Spec P` admits
a retraction. -/
theorem FormallySmooth.iff_split_surjection [FormallySmooth R P] :
    FormallySmooth R A ↔ ∃ g, f.kerSquareLift.comp g = AlgHom.id R A := by
  constructor
  · intro
    have surj : Function.Surjective f.kerSquareLift := fun x =>
      ⟨Submodule.Quotient.mk (hf x).choose, (hf x).choose_spec⟩
    have sqz : RingHom.ker f.kerSquareLift.toRingHom ^ 2 = 0 := by
      rw [AlgHom.ker_kerSquareLift, Ideal.cotangentIdeal_square, Ideal.zero_eq_bot]
    refine'
      ⟨FormallySmooth.lift _ ⟨2, sqz⟩ (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom,
        _⟩
    ext x
    have :=
      (Ideal.quotientKerAlgEquivOfSurjective surj).toAlgHom.congr_arg
        (FormallySmooth.mk_lift _ ⟨2, sqz⟩
          (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom x)
    -- Porting note: was
    -- dsimp at this
    -- rw [AlgEquiv.apply_symm_apply] at this
    erw [AlgEquiv.apply_symm_apply] at this
    conv_rhs => rw [← this, AlgHom.id_apply]
    -- Porting note: lean3 was not finished here:
    -- obtain ⟨y, e⟩ :=
    --   Ideal.Quotient.mk_surjective
    --     (FormallySmooth.lift _ ⟨2, sqz⟩
    --       (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom
    --       x)
    -- dsimp at e ⊢
    -- rw [← e]
    -- rfl
  · 

Proof state:
case mpr
R S : Type u
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
P A : Type u
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing P
inst✝¹ : Algebra R P
I : Ideal P
f : P →ₐ[R] A
hf : Function.Surjective ⇑f
inst✝ : FormallySmooth R P
⊢ (∃ g, AlgHom.comp (AlgHom.kerSquareLift f) g = AlgHom.id R A) → FormallySmooth R A

Next tactic:
rintro ⟨g, hg⟩
/-- Let `P →ₐ[R] A` be a surjection with kernel `J`, and `P` a formally smooth `R`-algebra,
then `A` is formally smooth over `R` iff the surjection `P ⧸ J ^ 2 →ₐ[R] A` has a section.

Geometric intuition: we require that a first-order thickening of `Spec A` inside `Spec P` admits
a retraction. -/
theorem FormallySmooth.iff_split_surjection [FormallySmooth R P] :
    FormallySmooth R A ↔ ∃ g, f.kerSquareLift.comp g = AlgHom.id R A := by
  constructor
  · intro
    have surj : Function.Surjective f.kerSquareLift := fun x =>
      ⟨Submodule.Quotient.mk (hf x).choose, (hf x).choose_spec⟩
    have sqz : RingHom.ker f.kerSquareLift.toRingHom ^ 2 = 0 := by
      rw [AlgHom.ker_kerSquareLift, Ideal.cotangentIdeal_square, Ideal.zero_eq_bot]
    refine'
      ⟨FormallySmooth.lift _ ⟨2, sqz⟩ (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom,
        _⟩
    ext x
    have :=
      (Ideal.quotientKerAlgEquivOfSurjective surj).toAlgHom.congr_arg
        (FormallySmooth.mk_lift _ ⟨2, sqz⟩
          (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom x)
    -- Porting note: was
    -- dsimp at this
    -- rw [AlgEquiv.apply_symm_apply] at this
    erw [AlgEquiv.apply_symm_apply] at this
    conv_rhs => rw [← this, AlgHom.id_apply]
    -- Porting note: lean3 was not finished here:
    -- obtain ⟨y, e⟩ :=
    --   Ideal.Quotient.mk_surjective
    --     (FormallySmooth.lift _ ⟨2, sqz⟩
    --       (Ideal.quotientKerAlgEquivOfSurjective surj).symm.toAlgHom
    --       x)
    -- dsimp at e ⊢
    -- rw [← e]
    -- rfl
  · rintro ⟨g, hg⟩; 

Proof state:
case mpr.intro
R S : Type u
inst✝⁶ : CommRing R
inst✝⁵ : CommSemiring S
P A : Type u
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing P
inst✝¹ : Algebra R P
I : Ideal P
f : P →ₐ[R] A
hf : Function.Surjective ⇑f
inst✝ : FormallySmooth R P
g : A →ₐ[R] P ⧸ RingHom.ker ↑f ^ 2
hg : AlgHom.comp (AlgHom.kerSquareLift f) g = AlgHom.id R A
⊢ FormallySmooth R A

Next tactic:
exact FormallySmooth.of_split f g hg
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  

Proof state:
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
⊢ Subsingleton (Ω[S⁄R])

Next tactic:
rw [← not_nontrivial_iff_subsingleton]
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  rw [← not_nontrivial_iff_subsingleton]
  

Proof state:
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
⊢ ¬Nontrivial (Ω[S⁄R])

Next tactic:
intro h
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  rw [← not_nontrivial_iff_subsingleton]
  intro h
  

Proof state:
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
h : Nontrivial (Ω[S⁄R])
⊢ False

Next tactic:
obtain ⟨f₁, f₂, e⟩ := (KaehlerDifferential.endEquiv R S).injective.nontrivial
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  rw [← not_nontrivial_iff_subsingleton]
  intro h
  obtain ⟨f₁, f₂, e⟩ := (KaehlerDifferential.endEquiv R S).injective.nontrivial
  

Proof state:
case mk.intro.intro
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
h : Nontrivial (Ω[S⁄R])
f₁ f₂ : { f // AlgHom.comp (AlgHom.kerSquareLift (TensorProduct.lmul' R)) f = AlgHom.id R S }
e : f₁ ≠ f₂
⊢ False

Next tactic:
apply e
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  rw [← not_nontrivial_iff_subsingleton]
  intro h
  obtain ⟨f₁, f₂, e⟩ := (KaehlerDifferential.endEquiv R S).injective.nontrivial
  apply e
  

Proof state:
case mk.intro.intro
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
h : Nontrivial (Ω[S⁄R])
f₁ f₂ : { f // AlgHom.comp (AlgHom.kerSquareLift (TensorProduct.lmul' R)) f = AlgHom.id R S }
e : f₁ ≠ f₂
⊢ f₁ = f₂

Next tactic:
ext1
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  rw [← not_nontrivial_iff_subsingleton]
  intro h
  obtain ⟨f₁, f₂, e⟩ := (KaehlerDifferential.endEquiv R S).injective.nontrivial
  apply e
  ext1
  

Proof state:
case mk.intro.intro.a
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
h : Nontrivial (Ω[S⁄R])
f₁ f₂ : { f // AlgHom.comp (AlgHom.kerSquareLift (TensorProduct.lmul' R)) f = AlgHom.id R S }
e : f₁ ≠ f₂
⊢ ↑f₁ = ↑f₂

Next tactic:
apply FormallyUnramified.lift_unique' _ _ _ _ (f₁.2.trans f₂.2.symm)
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  rw [← not_nontrivial_iff_subsingleton]
  intro h
  obtain ⟨f₁, f₂, e⟩ := (KaehlerDifferential.endEquiv R S).injective.nontrivial
  apply e
  ext1
  apply FormallyUnramified.lift_unique' _ _ _ _ (f₁.2.trans f₂.2.symm)
  

Proof state:
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
h : Nontrivial (Ω[S⁄R])
f₁ f₂ : { f // AlgHom.comp (AlgHom.kerSquareLift (TensorProduct.lmul' R)) f = AlgHom.id R S }
e : f₁ ≠ f₂
⊢ IsNilpotent (RingHom.ker ↑(AlgHom.kerSquareLift (TensorProduct.lmul' R)))

Next tactic:
rw [← AlgHom.toRingHom_eq_coe, AlgHom.ker_kerSquareLift]
instance FormallyUnramified.subsingleton_kaehlerDifferential [FormallyUnramified R S] :
    Subsingleton (Ω[S⁄R]) := by
  rw [← not_nontrivial_iff_subsingleton]
  intro h
  obtain ⟨f₁, f₂, e⟩ := (KaehlerDifferential.endEquiv R S).injective.nontrivial
  apply e
  ext1
  apply FormallyUnramified.lift_unique' _ _ _ _ (f₁.2.trans f₂.2.symm)
  rw [← AlgHom.toRingHom_eq_coe, AlgHom.ker_kerSquareLift]
  

Proof state:
R S : Type u
inst✝³ : CommRing R
inst✝² : CommRing S
inst✝¹ : Algebra R S
inst✝ : FormallyUnramified R S
h : Nontrivial (Ω[S⁄R])
f₁ f₂ : { f // AlgHom.comp (AlgHom.kerSquareLift (TensorProduct.lmul' R)) f = AlgHom.id R S }
e : f₁ ≠ f₂
⊢ IsNilpotent (Ideal.cotangentIdeal (RingHom.ker ↑(TensorProduct.lmul' R)))

Next tactic:
exact ⟨_, Ideal.cotangentIdeal_square _⟩
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  

Proof state:
R S : Type u
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : Algebra R S
⊢ FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R])

Next tactic:
constructor
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · 

Proof state:
case mp
R S : Type u
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : Algebra R S
⊢ FormallyUnramified R S → Subsingleton (Ω[S⁄R])

Next tactic:
intros
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; 

Proof state:
case mp
R S : Type u
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : Algebra R S
a✝ : FormallyUnramified R S
⊢ Subsingleton (Ω[S⁄R])

Next tactic:
infer_instance
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; infer_instance
  · 

Proof state:
case mpr
R S : Type u
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : Algebra R S
⊢ Subsingleton (Ω[S⁄R]) → FormallyUnramified R S

Next tactic:
intro H
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; infer_instance
  · intro H
    

Proof state:
case mpr
R S : Type u
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : Algebra R S
H : Subsingleton (Ω[S⁄R])
⊢ FormallyUnramified R S

Next tactic:
constructor
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; infer_instance
  · intro H
    constructor
    

Proof state:
case mpr.comp_injective
R S : Type u
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : Algebra R S
H : Subsingleton (Ω[S⁄R])
⊢ ∀ ⦃B : Type u⦄ [inst : CommRing B] [inst_1 : Algebra R B] (I : Ideal B),
    I ^ 2 = ⊥ → Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
intro B _ _ I hI f₁ f₂ e
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; infer_instance
  · intro H
    constructor
    intro B _ _ I hI f₁ f₂ e
    

Proof state:
case mpr.comp_injective
R S : Type u
inst✝⁴ : CommRing R
inst✝³ : CommRing S
inst✝² : Algebra R S
H : Subsingleton (Ω[S⁄R])
B : Type u
inst✝¹ : CommRing B
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : S →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
⊢ f₁ = f₂

Next tactic:
letI := f₁.toRingHom.toAlgebra
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; infer_instance
  · intro H
    constructor
    intro B _ _ I hI f₁ f₂ e
    letI := f₁.toRingHom.toAlgebra
    

Proof state:
case mpr.comp_injective
R S : Type u
inst✝⁴ : CommRing R
inst✝³ : CommRing S
inst✝² : Algebra R S
H : Subsingleton (Ω[S⁄R])
B : Type u
inst✝¹ : CommRing B
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : S →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
this : Algebra S B := RingHom.toAlgebra ↑f₁
⊢ f₁ = f₂

Next tactic:
haveI := IsScalarTower.of_algebraMap_eq' f₁.comp_algebraMap.symm
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; infer_instance
  · intro H
    constructor
    intro B _ _ I hI f₁ f₂ e
    letI := f₁.toRingHom.toAlgebra
    haveI := IsScalarTower.of_algebraMap_eq' f₁.comp_algebraMap.symm
    

Proof state:
case mpr.comp_injective
R S : Type u
inst✝⁴ : CommRing R
inst✝³ : CommRing S
inst✝² : Algebra R S
H : Subsingleton (Ω[S⁄R])
B : Type u
inst✝¹ : CommRing B
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : S →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
this✝ : Algebra S B := RingHom.toAlgebra ↑f₁
this : IsScalarTower R S B
⊢ f₁ = f₂

Next tactic:
have :=
      ((KaehlerDifferential.linearMapEquivDerivation R S).toEquiv.trans
            (derivationToSquareZeroEquivLift I hI)).surjective.subsingleton
theorem FormallyUnramified.iff_subsingleton_kaehlerDifferential :
    FormallyUnramified R S ↔ Subsingleton (Ω[S⁄R]) := by
  constructor
  · intros; infer_instance
  · intro H
    constructor
    intro B _ _ I hI f₁ f₂ e
    letI := f₁.toRingHom.toAlgebra
    haveI := IsScalarTower.of_algebraMap_eq' f₁.comp_algebraMap.symm
    have :=
      ((KaehlerDifferential.linearMapEquivDerivation R S).toEquiv.trans
            (derivationToSquareZeroEquivLift I hI)).surjective.subsingleton
    

Proof state:
case mpr.comp_injective
R S : Type u
inst✝⁴ : CommRing R
inst✝³ : CommRing S
inst✝² : Algebra R S
H : Subsingleton (Ω[S⁄R])
B : Type u
inst✝¹ : CommRing B
inst✝ : Algebra R B
I : Ideal B
hI : I ^ 2 = ⊥
f₁ f₂ : S →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) f₂
this✝¹ : Algebra S B := RingHom.toAlgebra ↑f₁
this✝ : IsScalarTower R S B
this : Subsingleton { f // AlgHom.comp (Ideal.Quotient.mkₐ R I) f = IsScalarTower.toAlgHom R S (B ⧸ I) }
⊢ f₁ = f₂

Next tactic:
exact Subtype.ext_iff.mp (@Subsingleton.elim _ this ⟨f₁, rfl⟩ ⟨f₂, e.symm⟩)
instance FormallyUnramified.base_change [FormallyUnramified R A] :
    FormallyUnramified B (B ⊗[R] A) := by
  

Proof state:
R : Type u
inst✝⁵ : CommSemiring R
A : Type u
inst✝⁴ : Semiring A
inst✝³ : Algebra R A
B : Type u
inst✝² : CommSemiring B
inst✝¹ : Algebra R B
inst✝ : FormallyUnramified R A
⊢ FormallyUnramified B (B ⊗[R] A)

Next tactic:
constructor
instance FormallyUnramified.base_change [FormallyUnramified R A] :
    FormallyUnramified B (B ⊗[R] A) := by
  constructor
  

Proof state:
case comp_injective
R : Type u
inst✝⁵ : CommSemiring R
A : Type u
inst✝⁴ : Semiring A
inst✝³ : Algebra R A
B : Type u
inst✝² : CommSemiring B
inst✝¹ : Algebra R B
inst✝ : FormallyUnramified R A
⊢ ∀ ⦃B_1 : Type u⦄ [inst : CommRing B_1] [inst_1 : Algebra B B_1] (I : Ideal B_1),
    I ^ 2 = ⊥ → Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ B I))

Next tactic:
intro C _ _ I hI f₁ f₂ e
instance FormallyUnramified.base_change [FormallyUnramified R A] :
    FormallyUnramified B (B ⊗[R] A) := by
  constructor
  intro C _ _ I hI f₁ f₂ e
  

Proof state:
case comp_injective
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B : Type u
inst✝⁴ : CommSemiring B
inst✝³ : Algebra R B
inst✝² : FormallyUnramified R A
C : Type u
inst✝¹ : CommRing C
inst✝ : Algebra B C
I : Ideal C
hI : I ^ 2 = ⊥
f₁ f₂ : B ⊗[R] A →ₐ[B] C
e : AlgHom.comp (Ideal.Quotient.mkₐ B I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ B I) f₂
⊢ f₁ = f₂

Next tactic:
letI := ((algebraMap B C).comp (algebraMap R B)).toAlgebra
instance FormallyUnramified.base_change [FormallyUnramified R A] :
    FormallyUnramified B (B ⊗[R] A) := by
  constructor
  intro C _ _ I hI f₁ f₂ e
  letI := ((algebraMap B C).comp (algebraMap R B)).toAlgebra
  

Proof state:
case comp_injective
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B : Type u
inst✝⁴ : CommSemiring B
inst✝³ : Algebra R B
inst✝² : FormallyUnramified R A
C : Type u
inst✝¹ : CommRing C
inst✝ : Algebra B C
I : Ideal C
hI : I ^ 2 = ⊥
f₁ f₂ : B ⊗[R] A →ₐ[B] C
e : AlgHom.comp (Ideal.Quotient.mkₐ B I) f₁ = AlgHom.comp (Ideal.Quotient.mkₐ B I) f₂
this : Algebra R C := RingHom.toAlgebra (RingHom.comp (algebraMap B C) (algebraMap R B))
⊢ f₁ = f₂

Next tactic:
haveI : IsScalarTower R B C := IsScalarTower.of_algebraMap_eq' rfl