-- Mathlib/RingTheory/Smooth/Pi.lean
theorem pi_iff [Finite I] :
    FormallySmooth R (Π i, A i) ↔ ∀ i, FormallySmooth R (A i)

Proof state:
case intro.mpr.comp_surjective.intro.intro
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝⁵ : CommRing R
inst✝⁴ : (i : I) → CommRing (A i)
inst✝³ : (i : I) → Algebra R (A i)
inst✝² : Finite I
val✝ : Fintype I
H : ∀ (i : I), FormallySmooth R (A i)
B : Type (max u v)
inst✝¹ : CommRing B
inst✝ : Algebra R B
J : Ideal B
hJ : J ^ 2 = ⊥
g : ((i : I) → A i) →ₐ[R] B ⧸ J
hJ' : ∀ x ∈ RingHom.ker (Ideal.Quotient.mk J), IsNilpotent x
e : I → B
he : CompleteOrthogonalIdempotents e
he' : ∀ (i : I), (Ideal.Quotient.mk J) (e i) = g (Pi.single i 1)
iso : B ≃ₐ[R] (i : I) → B ⧸ Ideal.span {1 - e i} :=
  let __spread.0 :=
    Pi.algHom R (fun i => B ⧸ Ideal.span {1 - e i}) fun i => Ideal.Quotient.mkₐ R (Ideal.span {1 - e i});
  let __spread.1 := Equiv.ofBijective ⇑(Pi.ringHom fun i => Ideal.Quotient.mk (Ideal.span {1 - e i})) ⋯;
  { toFun := (↑↑__spread.0.toRingHom).toFun, invFun := __spread.1.invFun, left_inv := ⋯, right_inv := ⋯, map_mul' := ⋯,
    map_add' := ⋯, commutes' := ⋯ }
⊢ ∃ a, (Ideal.Quotient.mkₐ R J).comp a = g

Tactic:
let J' := fun i ↦ J.map (Ideal.Quotient.mk (Ideal.span {1 - e i}))

Result:
case intro.mpr.comp_surjective.intro.intro
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝⁵ : CommRing R
inst✝⁴ : (i : I) → CommRing (A i)
inst✝³ : (i : I) → Algebra R (A i)
inst✝² : Finite I
val✝ : Fintype I
H : ∀ (i : I), FormallySmooth R (A i)
B : Type (max u v)
inst✝¹ : CommRing B
inst✝ : Algebra R B
J : Ideal B
hJ : J ^ 2 = ⊥
g : ((i : I) → A i) →ₐ[R] B ⧸ J
hJ' : ∀ x ∈ RingHom.ker (Ideal.Quotient.mk J), IsNilpotent x
e : I → B
he : CompleteOrthogonalIdempotents e
he' : ∀ (i : I), (Ideal.Quotient.mk J) (e i) = g (Pi.single i 1)
iso : B ≃ₐ[R] (i : I) → B ⧸ Ideal.span {1 - e i} :=
  let __spread.0 :=
    Pi.algHom R (fun i => B ⧸ Ideal.span {1 - e i}) fun i => Ideal.Quotient.mkₐ R (Ideal.span {1 - e i});
  let __spread.1 := Equiv.ofBijective ⇑(Pi.ringHom fun i => Ideal.Quotient.mk (Ideal.span {1 - e i})) ⋯;
  { toFun := (↑↑__spread.0.toRingHom).toFun, invFun := __spread.1.invFun, left_inv := ⋯, right_inv := ⋯, map_mul' := ⋯,
    map_add' := ⋯, commutes' := ⋯ }
J' : (i : I) → Ideal (B ⧸ Ideal.span {1 - e i}) := fun i => Ideal.map (Ideal.Quotient.mk (Ideal.span {1 - e i})) J
⊢ ∃ a, (Ideal.Quotient.mkₐ R J).comp a = g

Proof state:
case intro
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝³ : CommRing R
inst✝² : (i : I) → CommRing (A i)
inst✝¹ : (i : I) → Algebra R (A i)
inst✝ : Finite I
val✝ : Fintype I
⊢ FormallySmooth R ((i : I) → A i) ↔ ∀ (i : I), FormallySmooth R (A i)

Tactic:
constructor

Result:
case intro.mp
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝³ : CommRing R
inst✝² : (i : I) → CommRing (A i)
inst✝¹ : (i : I) → Algebra R (A i)
inst✝ : Finite I
val✝ : Fintype I
⊢ FormallySmooth R ((i : I) → A i) → ∀ (i : I), FormallySmooth R (A i)

case intro.mpr
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝³ : CommRing R
inst✝² : (i : I) → CommRing (A i)
inst✝¹ : (i : I) → Algebra R (A i)
inst✝ : Finite I
val✝ : Fintype I
⊢ (∀ (i : I), FormallySmooth R (A i)) → FormallySmooth R ((i : I) → A i)

Proof state:
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝⁵ : CommRing R
inst✝⁴ : (i : I) → CommRing (A i)
inst✝³ : (i : I) → Algebra R (A i)
inst✝² : Finite I
val✝ : Fintype I
H : ∀ (i : I), FormallySmooth R (A i)
B : Type (max u v)
inst✝¹ : CommRing B
inst✝ : Algebra R B
J : Ideal B
hJ : J ^ 2 = ⊥
g : ((i : I) → A i) →ₐ[R] B ⧸ J
x : B
hx : x ∈ RingHom.ker (Ideal.Quotient.mk J)
⊢ x ^ 2 ∈ ⊥

Tactic:
rw [← hJ]

Result:
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝⁵ : CommRing R
inst✝⁴ : (i : I) → CommRing (A i)
inst✝³ : (i : I) → Algebra R (A i)
inst✝² : Finite I
val✝ : Fintype I
H : ∀ (i : I), FormallySmooth R (A i)
B : Type (max u v)
inst✝¹ : CommRing B
inst✝ : Algebra R B
J : Ideal B
hJ : J ^ 2 = ⊥
g : ((i : I) → A i) →ₐ[R] B ⧸ J
x : B
hx : x ∈ RingHom.ker (Ideal.Quotient.mk J)
⊢ x ^ 2 ∈ J ^ 2

Proof state:
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝⁵ : CommRing R
inst✝⁴ : (i : I) → CommRing (A i)
inst✝³ : (i : I) → Algebra R (A i)
inst✝² : Finite I
val✝ : Fintype I
H : ∀ (i : I), FormallySmooth R (A i)
B : Type (max u v)
inst✝¹ : CommRing B
inst✝ : Algebra R B
J : Ideal B
hJ : J ^ 2 = ⊥
g : ((i : I) → A i) →ₐ[R] B ⧸ J
hJ' : ∀ x ∈ RingHom.ker (Ideal.Quotient.mk J), IsNilpotent x
e : I → B
he : CompleteOrthogonalIdempotents e
he' : ∀ (i : I), (Ideal.Quotient.mk J) (e i) = g (Pi.single i 1)
iso : B ≃ₐ[R] (i : I) → B ⧸ Ideal.span {1 - e i} :=
  let __spread.0 :=
    Pi.algHom R (fun i => B ⧸ Ideal.span {1 - e i}) fun i => Ideal.Quotient.mkₐ R (Ideal.span {1 - e i});
  let __spread.1 := Equiv.ofBijective ⇑(Pi.ringHom fun i => Ideal.Quotient.mk (Ideal.span {1 - e i})) ⋯;
  { toFun := (↑↑__spread.0.toRingHom).toFun, invFun := __spread.1.invFun, left_inv := ⋯, right_inv := ⋯, map_mul' := ⋯,
    map_add' := ⋯, commutes' := ⋯ }
J' : (i : I) → Ideal (B ⧸ Ideal.span {1 - e i}) := fun i => Ideal.map (Ideal.Quotient.mk (Ideal.span {1 - e i})) J
ι : (i : I) → B ⧸ J →ₐ[R] (B ⧸ Ideal.span {1 - e i}) ⧸ J' i :=
  fun i => Ideal.quotientMapₐ (J' i) (IsScalarTower.toAlgHom R B (B ⧸ Ideal.span {1 - e i})) ⋯
hι : ∀ (i : I) (x : B ⧸ J), (ι i) x = 0 → (Ideal.Quotient.mk J) (e i) * x = 0
a : (i : I) → A i →ₐ[R] B ⧸ Ideal.span {1 - e i}
ha : ∀ (i : I) (x : A i), (Ideal.Quotient.mk (J' i)) ((a i) x) = (ι i) (g (Pi.single i x))
x✝ : (i : I) → A i
i : I
x : A i
y : B
hy : (Ideal.Quotient.mk (Ideal.span {1 - e i})) y = (a i) x
hy' : (Ideal.Quotient.mk (Ideal.span {1 - e i})) (y * e i) = (a i) x
⊢ (Ideal.Quotient.mk J) (y * e i) = g (Pi.single i x)

Tactic:
have : ι i (Ideal.Quotient.mk J (y * e i)) = ι i (g (Pi.single i x)) := by
  rw [← ha, ← hy']
  simp only [Ideal.quotient_map_mkₐ, IsScalarTower.coe_toAlgHom',
    Ideal.Quotient.algebraMap_eq, Ideal.Quotient.mkₐ_eq_mk, ι]

Result:
R : Type (max u v)
I : Type u
A : I → Type (max u v)
inst✝⁵ : CommRing R
inst✝⁴ : (i : I) → CommRing (A i)
inst✝³ : (i : I) → Algebra R (A i)
inst✝² : Finite I
val✝ : Fintype I
H : ∀ (i : I), FormallySmooth R (A i)
B : Type (max u v)
inst✝¹ : CommRing B
inst✝ : Algebra R B
J : Ideal B
hJ : J ^ 2 = ⊥
g : ((i : I) → A i) →ₐ[R] B ⧸ J
hJ' : ∀ x ∈ RingHom.ker (Ideal.Quotient.mk J), IsNilpotent x
e : I → B
he : CompleteOrthogonalIdempotents e
he' : ∀ (i : I), (Ideal.Quotient.mk J) (e i) = g (Pi.single i 1)
iso : B ≃ₐ[R] (i : I) → B ⧸ Ideal.span {1 - e i} :=
  let __spread.0 :=
    Pi.algHom R (fun i => B ⧸ Ideal.span {1 - e i}) fun i => Ideal.Quotient.mkₐ R (Ideal.span {1 - e i});
  let __spread.1 := Equiv.ofBijective ⇑(Pi.ringHom fun i => Ideal.Quotient.mk (Ideal.span {1 - e i})) ⋯;
  { toFun := (↑↑__spread.0.toRingHom).toFun, invFun := __spread.1.invFun, left_inv := ⋯, right_inv := ⋯, map_mul' := ⋯,
    map_add' := ⋯, commutes' := ⋯ }
J' : (i : I) → Ideal (B ⧸ Ideal.span {1 - e i}) := fun i => Ideal.map (Ideal.Quotient.mk (Ideal.span {1 - e i})) J
ι : (i : I) → B ⧸ J →ₐ[R] (B ⧸ Ideal.span {1 - e i}) ⧸ J' i :=
  fun i => Ideal.quotientMapₐ (J' i) (IsScalarTower.toAlgHom R B (B ⧸ Ideal.span {1 - e i})) ⋯
hι : ∀ (i : I) (x : B ⧸ J), (ι i) x = 0 → (Ideal.Quotient.mk J) (e i) * x = 0
a : (i : I) → A i →ₐ[R] B ⧸ Ideal.span {1 - e i}
ha : ∀ (i : I) (x : A i), (Ideal.Quotient.mk (J' i)) ((a i) x) = (ι i) (g (Pi.single i x))
x✝ : (i : I) → A i
i : I
x : A i
y : B
hy : (Ideal.Quotient.mk (Ideal.span {1 - e i})) y = (a i) x
hy' : (Ideal.Quotient.mk (Ideal.span {1 - e i})) (y * e i) = (a i) x
this : (ι i) ((Ideal.Quotient.mk J) (y * e i)) = (ι i) (g (Pi.single i x))
⊢ (Ideal.Quotient.mk J) (y * e i) = g (Pi.single i x)