l3lab/ntp-mathlib huggingface dataset:
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
  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✝ : FormallySmooth R A
I : Ideal B
hI : IsNilpotent I
⊢ ∀ [_RB : Algebra R B], Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
apply Ideal.IsNilpotent.induction_on (R := B) I hI
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
  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✝ : FormallySmooth R A
I : Ideal B
hI : IsNilpotent I
⊢ ∀ ⦃S : Type u⦄ [inst : CommRing S] (I : Ideal S),
    I ^ 2 = ⊥ → ∀ [_RB : Algebra R S], Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
intro B _ I hI _
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
  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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))

Next tactic:
exact FormallySmooth.comp_surjective I hI
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
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective 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✝ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))) →
        (∀ [_RB : Algebra R (S ⧸ I)],
            Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))) →
          ∀ [_RB : Algebra R S], Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R J))

Next tactic:
intro B _ I J hIJ h₁ h₂ _ 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
  change Function.Surjective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective I hI
  · intro B _ I J hIJ h₁ h₂ _ g
    

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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g : A →ₐ[R] B ⧸ J
⊢ ∃ a, AlgHom.comp (Ideal.Quotient.mkₐ R J) a = g

Next tactic:
let this : ((B ⧸ I) ⧸ J.map (Ideal.Quotient.mk I)) ≃ₐ[R] B ⧸ J :=
      {
        (DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr hIJ)) with
        commutes' := fun x => rfl }
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
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective I hI
  · intro B _ I J hIJ h₁ h₂ _ g
    let this : ((B ⧸ I) ⧸ J.map (Ideal.Quotient.mk I)) ≃ₐ[R] B ⧸ J :=
      {
        (DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr hIJ)) with
        commutes' := fun x => rfl }
    

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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g : A →ₐ[R] B ⧸ J
this : ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J) ≃ₐ[R] B ⧸ J :=
  let src := RingEquiv.trans (DoubleQuot.quotQuotEquivQuotSup I J) (Ideal.quotEquivOfEq (_ : I ⊔ J = J));
  { toEquiv := src.toEquiv,
    map_mul' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x * y) = Equiv.toFun src.toEquiv x * Equiv.toFun src.toEquiv y),
    map_add' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x + y) = Equiv.toFun src.toEquiv x + Equiv.toFun src.toEquiv y),
    commutes' :=
      (_ :
        ∀ (x : R),
          Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x) =
            Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x)) }
⊢ ∃ a, AlgHom.comp (Ideal.Quotient.mkₐ R J) a = g

Next tactic:
obtain ⟨g', e⟩ := h₂ (this.symm.toAlgHom.comp 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
  change Function.Surjective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective I hI
  · intro B _ I J hIJ h₁ h₂ _ g
    let this : ((B ⧸ I) ⧸ J.map (Ideal.Quotient.mk I)) ≃ₐ[R] B ⧸ J :=
      {
        (DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr hIJ)) with
        commutes' := fun x => rfl }
    obtain ⟨g', e⟩ := h₂ (this.symm.toAlgHom.comp g)
    

Proof state:
case h₂.intro
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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g : A →ₐ[R] B ⧸ J
this : ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J) ≃ₐ[R] B ⧸ J :=
  let src := RingEquiv.trans (DoubleQuot.quotQuotEquivQuotSup I J) (Ideal.quotEquivOfEq (_ : I ⊔ J = J));
  { toEquiv := src.toEquiv,
    map_mul' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x * y) = Equiv.toFun src.toEquiv x * Equiv.toFun src.toEquiv y),
    map_add' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x + y) = Equiv.toFun src.toEquiv x + Equiv.toFun src.toEquiv y),
    commutes' :=
      (_ :
        ∀ (x : R),
          Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x) =
            Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x)) }
g' : A →ₐ[R] B ⧸ I
e : AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) g' = AlgHom.comp (↑(AlgEquiv.symm this)) g
⊢ ∃ a, AlgHom.comp (Ideal.Quotient.mkₐ R J) a = g

Next tactic:
obtain ⟨g', rfl⟩ := h₁ 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
  change Function.Surjective (Ideal.Quotient.mkₐ R I).comp
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective I hI
  · intro B _ I J hIJ h₁ h₂ _ g
    let this : ((B ⧸ I) ⧸ J.map (Ideal.Quotient.mk I)) ≃ₐ[R] B ⧸ J :=
      {
        (DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr hIJ)) with
        commutes' := fun x => rfl }
    obtain ⟨g', e⟩ := h₂ (this.symm.toAlgHom.comp g)
    obtain ⟨g', rfl⟩ := h₁ g'
    

Proof state:
case h₂.intro.intro
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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g : A →ₐ[R] B ⧸ J
this : ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J) ≃ₐ[R] B ⧸ J :=
  let src := RingEquiv.trans (DoubleQuot.quotQuotEquivQuotSup I J) (Ideal.quotEquivOfEq (_ : I ⊔ J = J));
  { toEquiv := src.toEquiv,
    map_mul' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x * y) = Equiv.toFun src.toEquiv x * Equiv.toFun src.toEquiv y),
    map_add' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x + y) = Equiv.toFun src.toEquiv x + Equiv.toFun src.toEquiv y),
    commutes' :=
      (_ :
        ∀ (x : R),
          Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x) =
            Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x)) }
g' : A →ₐ[R] B
e :
  AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)) (AlgHom.comp (Ideal.Quotient.mkₐ R I) g') =
    AlgHom.comp (↑(AlgEquiv.symm this)) g
⊢ ∃ a, AlgHom.comp (Ideal.Quotient.mkₐ R J) a = g

Next tactic:
replace e := congr_arg this.toAlgHom.comp e
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
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective I hI
  · intro B _ I J hIJ h₁ h₂ _ g
    let this : ((B ⧸ I) ⧸ J.map (Ideal.Quotient.mk I)) ≃ₐ[R] B ⧸ J :=
      {
        (DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr hIJ)) with
        commutes' := fun x => rfl }
    obtain ⟨g', e⟩ := h₂ (this.symm.toAlgHom.comp g)
    obtain ⟨g', rfl⟩ := h₁ g'
    replace e := congr_arg this.toAlgHom.comp e
    

Proof state:
case h₂.intro.intro
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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g : A →ₐ[R] B ⧸ J
this : ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J) ≃ₐ[R] B ⧸ J :=
  let src := RingEquiv.trans (DoubleQuot.quotQuotEquivQuotSup I J) (Ideal.quotEquivOfEq (_ : I ⊔ J = J));
  { toEquiv := src.toEquiv,
    map_mul' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x * y) = Equiv.toFun src.toEquiv x * Equiv.toFun src.toEquiv y),
    map_add' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x + y) = Equiv.toFun src.toEquiv x + Equiv.toFun src.toEquiv y),
    commutes' :=
      (_ :
        ∀ (x : R),
          Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x) =
            Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x)) }
g' : A →ₐ[R] B
e :
  AlgHom.comp (↑this)
      (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J))
        (AlgHom.comp (Ideal.Quotient.mkₐ R I) g')) =
    AlgHom.comp (↑this) (AlgHom.comp (↑(AlgEquiv.symm this)) g)
⊢ ∃ a, AlgHom.comp (Ideal.Quotient.mkₐ R J) a = g

Next tactic:
conv_rhs at e =>
      rw [← AlgHom.comp_assoc, AlgEquiv.toAlgHom_eq_coe, AlgEquiv.toAlgHom_eq_coe,
        AlgEquiv.comp_symm, AlgHom.id_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
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective I hI
  · intro B _ I J hIJ h₁ h₂ _ g
    let this : ((B ⧸ I) ⧸ J.map (Ideal.Quotient.mk I)) ≃ₐ[R] B ⧸ J :=
      {
        (DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr hIJ)) with
        commutes' := fun x => rfl }
    obtain ⟨g', e⟩ := h₂ (this.symm.toAlgHom.comp g)
    obtain ⟨g', rfl⟩ := h₁ g'
    replace e := congr_arg this.toAlgHom.comp e
    conv_rhs at e =>
      

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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g : A →ₐ[R] B ⧸ J
this : ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J) ≃ₐ[R] B ⧸ J :=
  let src := RingEquiv.trans (DoubleQuot.quotQuotEquivQuotSup I J) (Ideal.quotEquivOfEq (_ : I ⊔ J = J));
  { toEquiv := src.toEquiv,
    map_mul' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x * y) = Equiv.toFun src.toEquiv x * Equiv.toFun src.toEquiv y),
    map_add' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x + y) = Equiv.toFun src.toEquiv x + Equiv.toFun src.toEquiv y),
    commutes' :=
      (_ :
        ∀ (x : R),
          Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x) =
            Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x)) }
g' : A →ₐ[R] B
e :
  AlgHom.comp (↑this)
      (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J))
        (AlgHom.comp (Ideal.Quotient.mkₐ R I) g')) =
    AlgHom.comp (↑this) (AlgHom.comp (↑(AlgEquiv.symm this)) g)
| AlgHom.comp (↑this) (AlgHom.comp (↑(AlgEquiv.symm this)) g)

Next tactic:
rw [← AlgHom.comp_assoc, AlgEquiv.toAlgHom_eq_coe, AlgEquiv.toAlgHom_eq_coe,
        AlgEquiv.comp_symm, AlgHom.id_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
  revert _RB
  apply Ideal.IsNilpotent.induction_on (R := B) I hI
  · intro B _ I hI _; exact FormallySmooth.comp_surjective I hI
  · intro B _ I J hIJ h₁ h₂ _ g
    let this : ((B ⧸ I) ⧸ J.map (Ideal.Quotient.mk I)) ≃ₐ[R] B ⧸ J :=
      {
        (DoubleQuot.quotQuotEquivQuotSup I J).trans
          (Ideal.quotEquivOfEq (sup_eq_right.mpr hIJ)) with
        commutes' := fun x => rfl }
    obtain ⟨g', e⟩ := h₂ (this.symm.toAlgHom.comp g)
    obtain ⟨g', rfl⟩ := h₁ g'
    replace e := congr_arg this.toAlgHom.comp e
    conv_rhs at e =>
      rw [← AlgHom.comp_assoc, AlgEquiv.toAlgHom_eq_coe, AlgEquiv.toAlgHom_eq_coe,
        AlgEquiv.comp_symm, AlgHom.id_comp]
    

Proof state:
case h₂.intro.intro
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✝¹ : FormallySmooth 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.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R I))
h₂ :
  ∀ [_RB : Algebra R (B ⧸ I)],
    Function.Surjective (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J)))
_RB✝ : Algebra R B
g : A →ₐ[R] B ⧸ J
this : ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J) ≃ₐ[R] B ⧸ J :=
  let src := RingEquiv.trans (DoubleQuot.quotQuotEquivQuotSup I J) (Ideal.quotEquivOfEq (_ : I ⊔ J = J));
  { toEquiv := src.toEquiv,
    map_mul' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x * y) = Equiv.toFun src.toEquiv x * Equiv.toFun src.toEquiv y),
    map_add' :=
      (_ :
        ∀ (x y : (B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J),
          Equiv.toFun src.toEquiv (x + y) = Equiv.toFun src.toEquiv x + Equiv.toFun src.toEquiv y),
    commutes' :=
      (_ :
        ∀ (x : R),
          Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x) =
            Equiv.toFun src.toEquiv ((algebraMap R ((B ⧸ I) ⧸ Ideal.map (Ideal.Quotient.mk I) J)) x)) }
g' : A →ₐ[R] B
e :
  AlgHom.comp (↑this)
      (AlgHom.comp (Ideal.Quotient.mkₐ R (Ideal.map (Ideal.Quotient.mk I) J))
        (AlgHom.comp (Ideal.Quotient.mkₐ R I) g')) =
    g
⊢ ∃ a, AlgHom.comp (Ideal.Quotient.mkₐ R J) a = g

Next tactic:
exact ⟨g', e⟩
@[simp]
theorem FormallySmooth.liftOfSurjective_apply [FormallySmooth R A] (f : A →ₐ[R] C) (g : B →ₐ[R] C)
    (hg : Function.Surjective g) (hg' : IsNilpotent <| RingHom.ker (g : B →+* C)) (x : A) :
    g (FormallySmooth.liftOfSurjective f g hg hg' x) = f x := 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
C : Type u
inst✝² : CommRing C
inst✝¹ : Algebra R C
inst✝ : FormallySmooth R A
f : A →ₐ[R] C
g : B →ₐ[R] C
hg : Function.Surjective ⇑g
hg' : IsNilpotent (RingHom.ker ↑g)
x : A
⊢ g ((liftOfSurjective f g hg hg') x) = f x

Next tactic:
apply (Ideal.quotientKerAlgEquivOfSurjective hg).symm.injective
@[simp]
theorem FormallySmooth.liftOfSurjective_apply [FormallySmooth R A] (f : A →ₐ[R] C) (g : B →ₐ[R] C)
    (hg : Function.Surjective g) (hg' : IsNilpotent <| RingHom.ker (g : B →+* C)) (x : A) :
    g (FormallySmooth.liftOfSurjective f g hg hg' x) = f x := by
  apply (Ideal.quotientKerAlgEquivOfSurjective hg).symm.injective
  

Proof state:
case 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
C : Type u
inst✝² : CommRing C
inst✝¹ : Algebra R C
inst✝ : FormallySmooth R A
f : A →ₐ[R] C
g : B →ₐ[R] C
hg : Function.Surjective ⇑g
hg' : IsNilpotent (RingHom.ker ↑g)
x : A
⊢ (AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective hg)) (g ((liftOfSurjective f g hg hg') x)) =
    (AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective hg)) (f x)

Next tactic:
change _ = ((Ideal.quotientKerAlgEquivOfSurjective hg).symm.toAlgHom.comp f) x
@[simp]
theorem FormallySmooth.liftOfSurjective_apply [FormallySmooth R A] (f : A →ₐ[R] C) (g : B →ₐ[R] C)
    (hg : Function.Surjective g) (hg' : IsNilpotent <| RingHom.ker (g : B →+* C)) (x : A) :
    g (FormallySmooth.liftOfSurjective f g hg hg' x) = f x := by
  apply (Ideal.quotientKerAlgEquivOfSurjective hg).symm.injective
  change _ = ((Ideal.quotientKerAlgEquivOfSurjective hg).symm.toAlgHom.comp f) x
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  

Proof state:
case 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
C : Type u
inst✝² : CommRing C
inst✝¹ : Algebra R C
inst✝ : FormallySmooth R A
f : A →ₐ[R] C
g : B →ₐ[R] C
hg : Function.Surjective ⇑g
hg' : IsNilpotent (RingHom.ker ↑g)
x : A
⊢ (AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective hg)) (g ((liftOfSurjective f g hg hg') x)) =
    (AlgHom.comp (↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective hg))) f) x

Next tactic:
erw [← FormallySmooth.mk_lift _ hg'
    ((Ideal.quotientKerAlgEquivOfSurjective hg).symm.toAlgHom.comp f)]
@[simp]
theorem FormallySmooth.liftOfSurjective_apply [FormallySmooth R A] (f : A →ₐ[R] C) (g : B →ₐ[R] C)
    (hg : Function.Surjective g) (hg' : IsNilpotent <| RingHom.ker (g : B →+* C)) (x : A) :
    g (FormallySmooth.liftOfSurjective f g hg hg' x) = f x := by
  apply (Ideal.quotientKerAlgEquivOfSurjective hg).symm.injective
  change _ = ((Ideal.quotientKerAlgEquivOfSurjective hg).symm.toAlgHom.comp f) x
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  erw [← FormallySmooth.mk_lift _ hg'
    ((Ideal.quotientKerAlgEquivOfSurjective hg).symm.toAlgHom.comp f)]
  

Proof state:
case 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
C : Type u
inst✝² : CommRing C
inst✝¹ : Algebra R C
inst✝ : FormallySmooth R A
f : A →ₐ[R] C
g : B →ₐ[R] C
hg : Function.Surjective ⇑g
hg' : IsNilpotent (RingHom.ker ↑g)
x : A
⊢ (AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective hg)) (g ((liftOfSurjective f g hg hg') x)) =
    (Ideal.Quotient.mk (RingHom.ker ↑g))
      ((lift (RingHom.ker ↑g) hg' (AlgHom.comp (↑(AlgEquiv.symm (Ideal.quotientKerAlgEquivOfSurjective hg))) f)) x)

Next tactic:
apply (Ideal.quotientKerAlgEquivOfSurjective hg).injective