l3lab/ntp-mathlib huggingface dataset:
lemma zero_le_four [Preorder α] [ZeroLEOneClass α] [CovariantClass α α (·+·) (·≤·)] :
    (0 : α) ≤ 4 := by
  rw [← three_add_one_eq_four]
  

Proof state:
α : Type u_1
inst✝³ : AddMonoidWithOne α
inst✝² : Preorder α
inst✝¹ : ZeroLEOneClass α
inst✝ : CovariantClass α α (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
⊢ 0 ≤ 3 + 1

Next tactic:
exact add_nonneg zero_le_three zero_le_one
/-- See `zero_lt_three'` for a version with the type explicit. -/
@[simp] lemma zero_lt_three : (0 : α) < 3 := by
  

Proof state:
α : Type u_1
inst✝⁴ : AddMonoidWithOne α
inst✝³ : PartialOrder α
inst✝² : ZeroLEOneClass α
inst✝¹ : NeZero 1
inst✝ : CovariantClass α α (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
⊢ 0 < 3

Next tactic:
rw [← two_add_one_eq_three]
/-- See `zero_lt_three'` for a version with the type explicit. -/
@[simp] lemma zero_lt_three : (0 : α) < 3 := by
  rw [← two_add_one_eq_three]
  

Proof state:
α : Type u_1
inst✝⁴ : AddMonoidWithOne α
inst✝³ : PartialOrder α
inst✝² : ZeroLEOneClass α
inst✝¹ : NeZero 1
inst✝ : CovariantClass α α (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
⊢ 0 < 2 + 1

Next tactic:
exact lt_add_of_lt_of_nonneg zero_lt_two zero_le_one
/-- See `zero_lt_four'` for a version with the type explicit. -/
@[simp] lemma zero_lt_four : (0 : α) < 4 := by
  

Proof state:
α : Type u_1
inst✝⁴ : AddMonoidWithOne α
inst✝³ : PartialOrder α
inst✝² : ZeroLEOneClass α
inst✝¹ : NeZero 1
inst✝ : CovariantClass α α (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
⊢ 0 < 4

Next tactic:
rw [← three_add_one_eq_four]
/-- See `zero_lt_four'` for a version with the type explicit. -/
@[simp] lemma zero_lt_four : (0 : α) < 4 := by
  rw [← three_add_one_eq_four]
  

Proof state:
α : Type u_1
inst✝⁴ : AddMonoidWithOne α
inst✝³ : PartialOrder α
inst✝² : ZeroLEOneClass α
inst✝¹ : NeZero 1
inst✝ : CovariantClass α α (fun x x_1 => x + x_1) fun x x_1 => x ≤ x_1
⊢ 0 < 3 + 1

Next tactic:
exact lt_add_of_lt_of_nonneg zero_lt_three zero_le_one
lemma one_lt_two [CovariantClass α α (·+·) (·<·)] : (1 : α) < 2 := by
  

Proof state:
α : Type u_1
inst✝⁴ : AddMonoidWithOne α
inst✝³ : PartialOrder α
inst✝² : ZeroLEOneClass α
inst✝¹ : NeZero 1
inst✝ : CovariantClass α α (fun x x_1 => x + x_1) fun x x_1 => x < x_1
⊢ 1 < 2

Next tactic:
rw [← one_add_one_eq_two]
lemma one_lt_two [CovariantClass α α (·+·) (·<·)] : (1 : α) < 2 := by
  rw [← one_add_one_eq_two]
  

Proof state:
α : Type u_1
inst✝⁴ : AddMonoidWithOne α
inst✝³ : PartialOrder α
inst✝² : ZeroLEOneClass α
inst✝¹ : NeZero 1
inst✝ : CovariantClass α α (fun x x_1 => x + x_1) fun x x_1 => x < x_1
⊢ 1 < 1 + 1

Next tactic:
exact lt_add_one _
theorem FormallyEtale.iff_unramified_and_smooth :
    FormallyEtale R A ↔ FormallyUnramified R A ∧ FormallySmooth 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✝¹ : CommRing B
inst✝ : Algebra R B
I : Ideal B
⊢ FormallyEtale R A ↔ FormallyUnramified R A ∧ FormallySmooth R A

Next tactic:
rw [FormallyUnramified_iff, FormallySmooth_iff, FormallyEtale_iff]
theorem FormallyEtale.iff_unramified_and_smooth :
    FormallyEtale R A ↔ FormallyUnramified R A ∧ FormallySmooth R A := by
  rw [FormallyUnramified_iff, FormallySmooth_iff, FormallyEtale_iff]
  

Proof state:
R : Type u
inst✝⁴ : CommSemiring R
A : Type u
inst✝³ : Semiring A
inst✝² : Algebra R A
B : Type u
inst✝¹ : CommRing B
inst✝ : Algebra R B
I : Ideal B
⊢ (∀ ⦃B : Type u⦄ [inst : CommRing B] [inst_1 : Algebra R B] (I : Ideal B),
      I ^ 2 = ⊥ → Function.Bijective (AlgHom.comp (Ideal.Quotient.mkₐ R I))) ↔
    (∀ ⦃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))) ∧
      ∀ ⦃B : Type u⦄ [inst : CommRing B] [inst_1 : Algebra R B] (I : Ideal B),
        I ^ 2 = ⊥ → Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
simp_rw [← forall_and]
theorem FormallyEtale.iff_unramified_and_smooth :
    FormallyEtale R A ↔ FormallyUnramified R A ∧ FormallySmooth R A := by
  rw [FormallyUnramified_iff, FormallySmooth_iff, FormallyEtale_iff]
  simp_rw [← forall_and]
  

Proof state:
R : Type u
inst✝⁴ : CommSemiring R
A : Type u
inst✝³ : Semiring A
inst✝² : Algebra R A
B : Type u
inst✝¹ : CommRing B
inst✝ : Algebra R B
I : Ideal B
⊢ (∀ ⦃B : Type u⦄ [inst : CommRing B] [inst_1 : Algebra R B] (I : Ideal B),
      I ^ 2 = ⊥ → Function.Bijective (AlgHom.comp (Ideal.Quotient.mkₐ R I))) ↔
    ∀ (x : Type u) (x_1 : CommRing x) (x_2 : Algebra R x) (x_3 : Ideal x),
      x_3 ^ 2 = ⊥ →
        Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R x_3)) ∧
          Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R x_3))

Next tactic:
rfl
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
_RB : Algebra R B
inst✝ : FormallyUnramified R A
I : Ideal B
hI : IsNilpotent I
g₁ g₂ : A →ₐ[R] B
h : AlgHom.comp (Ideal.Quotient.mkₐ R I) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) g₂
⊢ g₁ = g₂

Next tactic:
revert g₁ g₂
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
_RB : Algebra R B
inst✝ : FormallyUnramified R A
I : Ideal B
hI : IsNilpotent I
⊢ ∀ (g₁ g₂ : A →ₐ[R] B), AlgHom.comp (Ideal.Quotient.mkₐ R I) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) g₂ → g₁ = g₂

Next tactic:
change Function.Injective (Ideal.Quotient.mkₐ R I).comp
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
_RB : Algebra R B
inst✝ : FormallyUnramified R A
I : Ideal B
hI : IsNilpotent I
⊢ Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
revert _RB
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
inst✝ : FormallyUnramified R A
I : Ideal B
hI : IsNilpotent I
⊢ ∀ [_RB : Algebra R B], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
apply Ideal.IsNilpotent.induction_on (R := B) I hI
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · 

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

Next tactic:
intro B _ I hI _
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; 

Proof state:
case h₁
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B✝¹ : Type u
inst✝⁴ : CommRing B✝¹
inst✝³ : Algebra R B✝¹
I✝¹ : Ideal B✝¹
B✝ : Type u
inst✝² : CommRing B✝
inst✝¹ : FormallyUnramified R A
I✝ : Ideal B✝
hI✝ : IsNilpotent I✝
B : Type u
inst✝ : CommRing B
I : Ideal B
hI : I ^ 2 = ⊥
_RB✝ : Algebra R B
⊢ Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
exact FormallyUnramified.comp_injective I hI
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallyUnramified.comp_injective I hI
  · 

Proof state:
case h₂
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
inst✝ : FormallyUnramified R A
I : Ideal B
hI : IsNilpotent I
⊢ ∀ ⦃S : Type u⦄ [inst : CommRing S] (I J : Ideal S),
    I ≤ J →
      (∀ [_RB : Algebra R S], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))) →
        (∀ [_RB : Algebra R (S ⧸ I)],
            Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))) →
          ∀ [_RB : Algebra R S], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R J))

Next tactic:
intro B _ I J hIJ h₁ h₂ _ g₁ g₂ e
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallyUnramified.comp_injective I hI
  · intro B _ I J hIJ h₁ h₂ _ g₁ g₂ e
    

Proof state:
case h₂
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B✝¹ : Type u
inst✝⁴ : CommRing B✝¹
inst✝³ : Algebra R B✝¹
I✝¹ : Ideal B✝¹
B✝ : Type u
inst✝² : CommRing B✝
inst✝¹ : FormallyUnramified R A
I✝ : Ideal B✝
hI : IsNilpotent I✝
B : Type u
inst✝ : CommRing B
I J : Ideal B
hIJ : I ≤ J
h₁ : ∀ [_RB : Algebra R B], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g₁ g₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R J) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R J) g₂
⊢ g₁ = g₂

Next tactic:
apply h₁
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallyUnramified.comp_injective I hI
  · intro B _ I J hIJ h₁ h₂ _ g₁ g₂ e
    apply h₁
    

Proof state:
case h₂.a
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B✝¹ : Type u
inst✝⁴ : CommRing B✝¹
inst✝³ : Algebra R B✝¹
I✝¹ : Ideal B✝¹
B✝ : Type u
inst✝² : CommRing B✝
inst✝¹ : FormallyUnramified R A
I✝ : Ideal B✝
hI : IsNilpotent I✝
B : Type u
inst✝ : CommRing B
I J : Ideal B
hIJ : I ≤ J
h₁ : ∀ [_RB : Algebra R B], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g₁ g₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R J) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R J) g₂
⊢ AlgHom.comp (Ideal.Quotient.mkₐ R I) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R I) g₂

Next tactic:
apply h₂
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallyUnramified.comp_injective I hI
  · intro B _ I J hIJ h₁ h₂ _ g₁ g₂ e
    apply h₁
    apply h₂
    

Proof state:
case h₂.a.a
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B✝¹ : Type u
inst✝⁴ : CommRing B✝¹
inst✝³ : Algebra R B✝¹
I✝¹ : Ideal B✝¹
B✝ : Type u
inst✝² : CommRing B✝
inst✝¹ : FormallyUnramified R A
I✝ : Ideal B✝
hI : IsNilpotent I✝
B : Type u
inst✝ : CommRing B
I J : Ideal B
hIJ : I ≤ J
h₁ : ∀ [_RB : Algebra R B], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g₁ g₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R J) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R J) g₂
⊢ AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) (AlgHom.comp (Ideal.Quotient.mkₐ R I) g₁) =
    AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) (AlgHom.comp (Ideal.Quotient.mkₐ R I) g₂)

Next tactic:
ext x
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallyUnramified.comp_injective I hI
  · intro B _ I J hIJ h₁ h₂ _ g₁ g₂ e
    apply h₁
    apply h₂
    ext x
    

Proof state:
case h₂.a.a.H
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B✝¹ : Type u
inst✝⁴ : CommRing B✝¹
inst✝³ : Algebra R B✝¹
I✝¹ : Ideal B✝¹
B✝ : Type u
inst✝² : CommRing B✝
inst✝¹ : FormallyUnramified R A
I✝ : Ideal B✝
hI : IsNilpotent I✝
B : Type u
inst✝ : CommRing B
I J : Ideal B
hIJ : I ≤ J
h₁ : ∀ [_RB : Algebra R B], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g₁ g₂ : A →ₐ[R] B
e : AlgHom.comp (Ideal.Quotient.mkₐ R J) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R J) g₂
x : A
⊢ (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) (AlgHom.comp (Ideal.Quotient.mkₐ R I) g₁)) x =
    (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) (AlgHom.comp (Ideal.Quotient.mkₐ R I) g₂)) x

Next tactic:
replace e := AlgHom.congr_fun e x
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallyUnramified.comp_injective I hI
  · intro B _ I J hIJ h₁ h₂ _ g₁ g₂ e
    apply h₁
    apply h₂
    ext x
    replace e := AlgHom.congr_fun e x
    

Proof state:
case h₂.a.a.H
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B✝¹ : Type u
inst✝⁴ : CommRing B✝¹
inst✝³ : Algebra R B✝¹
I✝¹ : Ideal B✝¹
B✝ : Type u
inst✝² : CommRing B✝
inst✝¹ : FormallyUnramified R A
I✝ : Ideal B✝
hI : IsNilpotent I✝
B : Type u
inst✝ : CommRing B
I J : Ideal B
hIJ : I ≤ J
h₁ : ∀ [_RB : Algebra R B], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g₁ g₂ : A →ₐ[R] B
x : A
e : (AlgHom.comp (Ideal.Quotient.mkₐ R J) g₁) x = (AlgHom.comp (Ideal.Quotient.mkₐ R J) g₂) x
⊢ (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) (AlgHom.comp (Ideal.Quotient.mkₐ R I) g₁)) x =
    (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) (AlgHom.comp (Ideal.Quotient.mkₐ R I) g₂)) x

Next tactic:
dsimp only [AlgHom.comp_apply, Ideal.Quotient.mkₐ_eq_mk] at e ⊢
theorem FormallyUnramified.lift_unique {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallyUnramified R A] (I : Ideal B) (hI : IsNilpotent I) (g₁ g₂ : A →ₐ[R] B)
    (h : (Ideal.Quotient.mkₐ R I).comp g₁ = (Ideal.Quotient.mkₐ R I).comp g₂) : g₁ = g₂ := by
  revert g₁ g₂
  change Function.Injective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallyUnramified.comp_injective I hI
  · intro B _ I J hIJ h₁ h₂ _ g₁ g₂ e
    apply h₁
    apply h₂
    ext x
    replace e := AlgHom.congr_fun e x
    dsimp only [AlgHom.comp_apply, Ideal.Quotient.mkₐ_eq_mk] at e ⊢
    

Proof state:
case h₂.a.a.H
R : Type u
inst✝⁷ : CommSemiring R
A : Type u
inst✝⁶ : Semiring A
inst✝⁵ : Algebra R A
B✝¹ : Type u
inst✝⁴ : CommRing B✝¹
inst✝³ : Algebra R B✝¹
I✝¹ : Ideal B✝¹
B✝ : Type u
inst✝² : CommRing B✝
inst✝¹ : FormallyUnramified R A
I✝ : Ideal B✝
hI : IsNilpotent I✝
B : Type u
inst✝ : CommRing B
I J : Ideal B
hIJ : I ≤ J
h₁ : ∀ [_RB : Algebra R B], Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Injective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g₁ g₂ : A →ₐ[R] B
x : A
e : (Ideal.Quotient.mk J) (g₁ x) = (Ideal.Quotient.mk J) (g₂ x)
⊢ (Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) ((Ideal.Quotient.mk I) (g₁ x)) =
    (Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk I) J)) ((Ideal.Quotient.mk I) (g₂ x))

Next tactic:
rwa [Ideal.Quotient.eq, ← map_sub, Ideal.mem_quotient_iff_mem hIJ, ← Ideal.Quotient.eq]
theorem FormallyUnramified.lift_unique_of_ringHom [FormallyUnramified R A] {C : Type u} [CommRing C]
    (f : B →+* C) (hf : IsNilpotent <| RingHom.ker f) (g₁ g₂ : A →ₐ[R] B)
    (h : f.comp ↑g₁ = f.comp (g₂ : A →+* B)) : g₁ = g₂ :=
  FormallyUnramified.lift_unique _ hf _ _
    (by
      

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B : Type u
inst✝³ : CommRing B
inst✝² : Algebra R B
I : Ideal B
inst✝¹ : FormallyUnramified R A
C : Type u
inst✝ : CommRing C
f : B →+* C
hf : IsNilpotent (RingHom.ker f)
g₁ g₂ : A →ₐ[R] B
h : RingHom.comp f ↑g₁ = RingHom.comp f ↑g₂
⊢ AlgHom.comp (Ideal.Quotient.mkₐ R (RingHom.ker f)) g₁ = AlgHom.comp (Ideal.Quotient.mkₐ R (RingHom.ker f)) g₂

Next tactic:
ext x
theorem FormallyUnramified.lift_unique_of_ringHom [FormallyUnramified R A] {C : Type u} [CommRing C]
    (f : B →+* C) (hf : IsNilpotent <| RingHom.ker f) (g₁ g₂ : A →ₐ[R] B)
    (h : f.comp ↑g₁ = f.comp (g₂ : A →+* B)) : g₁ = g₂ :=
  FormallyUnramified.lift_unique _ hf _ _
    (by
      ext x
      

Proof state:
case H
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B : Type u
inst✝³ : CommRing B
inst✝² : Algebra R B
I : Ideal B
inst✝¹ : FormallyUnramified R A
C : Type u
inst✝ : CommRing C
f : B →+* C
hf : IsNilpotent (RingHom.ker f)
g₁ g₂ : A →ₐ[R] B
h : RingHom.comp f ↑g₁ = RingHom.comp f ↑g₂
x : A
⊢ (AlgHom.comp (Ideal.Quotient.mkₐ R (RingHom.ker f)) g₁) x = (AlgHom.comp (Ideal.Quotient.mkₐ R (RingHom.ker f)) g₂) x

Next tactic:
have := RingHom.congr_fun h x
theorem FormallyUnramified.lift_unique_of_ringHom [FormallyUnramified R A] {C : Type u} [CommRing C]
    (f : B →+* C) (hf : IsNilpotent <| RingHom.ker f) (g₁ g₂ : A →ₐ[R] B)
    (h : f.comp ↑g₁ = f.comp (g₂ : A →+* B)) : g₁ = g₂ :=
  FormallyUnramified.lift_unique _ hf _ _
    (by
      ext x
      have := RingHom.congr_fun h x
      

Proof state:
case H
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B : Type u
inst✝³ : CommRing B
inst✝² : Algebra R B
I : Ideal B
inst✝¹ : FormallyUnramified R A
C : Type u
inst✝ : CommRing C
f : B →+* C
hf : IsNilpotent (RingHom.ker f)
g₁ g₂ : A →ₐ[R] B
h : RingHom.comp f ↑g₁ = RingHom.comp f ↑g₂
x : A
this : (RingHom.comp f ↑g₁) x = (RingHom.comp f ↑g₂) x
⊢ (AlgHom.comp (Ideal.Quotient.mkₐ R (RingHom.ker f)) g₁) x = (AlgHom.comp (Ideal.Quotient.mkₐ R (RingHom.ker f)) g₂) x

Next tactic:
simpa only [Ideal.Quotient.eq, Function.comp_apply, AlgHom.coe_comp, Ideal.Quotient.mkₐ_eq_mk,
        RingHom.mem_ker, map_sub, sub_eq_zero]
theorem FormallySmooth.exists_lift {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallySmooth R A] (I : Ideal B) (hI : IsNilpotent I) (g : A →ₐ[R] B ⧸ I) :
    ∃ f : A →ₐ[R] B, (Ideal.Quotient.mkₐ R I).comp f = g := by
  

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
_RB : Algebra R B
inst✝ : FormallySmooth R A
I : Ideal B
hI : IsNilpotent I
g : A →ₐ[R] B ⧸ I
⊢ ∃ f, AlgHom.comp (Ideal.Quotient.mkₐ R I) f = g

Next tactic:
revert g
theorem FormallySmooth.exists_lift {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallySmooth R A] (I : Ideal B) (hI : IsNilpotent I) (g : A →ₐ[R] B ⧸ I) :
    ∃ f : A →ₐ[R] B, (Ideal.Quotient.mkₐ R I).comp f = g := by
  revert g
  

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
_RB : Algebra R B
inst✝ : FormallySmooth R A
I : Ideal B
hI : IsNilpotent I
⊢ ∀ (g : A →ₐ[R] B ⧸ I), ∃ f, AlgHom.comp (Ideal.Quotient.mkₐ R I) f = g

Next tactic:
change Function.Surjective (Ideal.Quotient.mkₐ R I).comp
theorem FormallySmooth.exists_lift {B : Type u} [CommRing B] [_RB : Algebra R B]
    [FormallySmooth R A] (I : Ideal B) (hI : IsNilpotent I) (g : A →ₐ[R] B ⧸ I) :
    ∃ f : A →ₐ[R] B, (Ideal.Quotient.mkₐ R I).comp f = g := by
  revert g
  change Function.Surjective (Ideal.Quotient.mkₐ R I).comp
  

Proof state:
R : Type u
inst✝⁶ : CommSemiring R
A : Type u
inst✝⁵ : Semiring A
inst✝⁴ : Algebra R A
B✝ : Type u
inst✝³ : CommRing B✝
inst✝² : Algebra R B✝
I✝ : Ideal B✝
B : Type u
inst✝¹ : CommRing B
_RB : Algebra R B
inst✝ : FormallySmooth R A
I : Ideal B
hI : IsNilpotent I
⊢ Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
revert _RB