l3lab/ntp-mathlib huggingface dataset:
/-- For a commutative ring $R$, evaluating a polynomial at an element $y \in R$ induces an
isomorphism of $R$-algebras $R[X] / \langle x, X - y \rangle \cong R / \langle x \rangle$. -/
noncomputable def quotientSpanCXSubCAlgEquiv (x y : R) :
    (R[X] ⧸ (Ideal.span {C x, X - C y} : Ideal R[X])) ≃ₐ[R] R ⧸ (Ideal.span {x} : Ideal R) :=
  (Ideal.quotientEquivAlgOfEq R <| by rw [Ideal.span_insert, sup_comm]).trans <|
    (DoubleQuot.quotQuotEquivQuotSupₐ R _ _).symm.trans <|
      (Ideal.quotientEquivAlg _ _ (quotientSpanXSubCAlgEquiv y) rfl).trans <|
        Ideal.quotientEquivAlgOfEq R <| by
          simp only [Ideal.map_span, Set.image_singleton]; 

Proof state:
R : Type u_1
inst✝ : CommRing R
x y : R
⊢ Ideal.span {↑(quotientSpanXSubCAlgEquiv y) ((Ideal.Quotient.mkₐ R (Ideal.span {X - C y})) (C x))} = Ideal.span {x}

Next tactic:
congr 2
/-- For a commutative ring $R$, evaluating a polynomial at an element $y \in R$ induces an
isomorphism of $R$-algebras $R[X] / \langle x, X - y \rangle \cong R / \langle x \rangle$. -/
noncomputable def quotientSpanCXSubCAlgEquiv (x y : R) :
    (R[X] ⧸ (Ideal.span {C x, X - C y} : Ideal R[X])) ≃ₐ[R] R ⧸ (Ideal.span {x} : Ideal R) :=
  (Ideal.quotientEquivAlgOfEq R <| by rw [Ideal.span_insert, sup_comm]).trans <|
    (DoubleQuot.quotQuotEquivQuotSupₐ R _ _).symm.trans <|
      (Ideal.quotientEquivAlg _ _ (quotientSpanXSubCAlgEquiv y) rfl).trans <|
        Ideal.quotientEquivAlgOfEq R <| by
          simp only [Ideal.map_span, Set.image_singleton]; congr 2; 

Proof state:
case e_s.e_a
R : Type u_1
inst✝ : CommRing R
x y : R
⊢ ↑(quotientSpanXSubCAlgEquiv y) ((Ideal.Quotient.mkₐ R (Ideal.span {X - C y})) (C x)) = x

Next tactic:
exact eval_C
theorem quotient_map_C_eq_zero {I : Ideal R} :
    ∀ a ∈ I, ((Quotient.mk (map (C : R →+* R[X]) I : Ideal R[X])).comp C) a = 0 := by
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
⊢ ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0

Next tactic:
intro a ha
theorem quotient_map_C_eq_zero {I : Ideal R} :
    ∀ a ∈ I, ((Quotient.mk (map (C : R →+* R[X]) I : Ideal R[X])).comp C) a = 0 := by
  intro a ha
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R
ha : a ∈ I
⊢ (RingHom.comp (Quotient.mk (map C I)) C) a = 0

Next tactic:
rw [RingHom.comp_apply, Quotient.eq_zero_iff_mem]
theorem quotient_map_C_eq_zero {I : Ideal R} :
    ∀ a ∈ I, ((Quotient.mk (map (C : R →+* R[X]) I : Ideal R[X])).comp C) a = 0 := by
  intro a ha
  rw [RingHom.comp_apply, Quotient.eq_zero_iff_mem]
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R
ha : a ∈ I
⊢ C a ∈ map C I

Next tactic:
exact mem_map_of_mem _ ha
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
⊢ ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0

Next tactic:
intro a ha
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
⊢ (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) a = 0

Next tactic:
rw [← sum_monomial_eq a]
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
⊢ (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) (sum a fun n a => (monomial n) a) = 0

Next tactic:
dsimp
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
⊢ eval₂ (RingHom.comp C (Quotient.mk I)) X (sum a fun n a => (monomial n) a) = 0

Next tactic:
rw [eval₂_sum]
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
⊢ (sum a fun n a => eval₂ (RingHom.comp C (Quotient.mk I)) X ((monomial n) a)) = 0

Next tactic:
refine' Finset.sum_eq_zero fun n _ => _
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  refine' Finset.sum_eq_zero fun n _ => _
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
n : ℕ
x✝ : n ∈ support a
⊢ (fun n a => eval₂ (RingHom.comp C (Quotient.mk I)) X ((monomial n) a)) n (coeff a n) = 0

Next tactic:
dsimp
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  refine' Finset.sum_eq_zero fun n _ => _
  dsimp
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
n : ℕ
x✝ : n ∈ support a
⊢ eval₂ (RingHom.comp C (Quotient.mk I)) X ((monomial n) (coeff a n)) = 0

Next tactic:
rw [eval₂_monomial (C.comp (Quotient.mk I)) X]
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  refine' Finset.sum_eq_zero fun n _ => _
  dsimp
  rw [eval₂_monomial (C.comp (Quotient.mk I)) X]
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
n : ℕ
x✝ : n ∈ support a
⊢ (RingHom.comp C (Quotient.mk I)) (coeff a n) * X ^ n = 0

Next tactic:
refine' mul_eq_zero_of_left (Polynomial.ext fun m => _) (X ^ n)
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  refine' Finset.sum_eq_zero fun n _ => _
  dsimp
  rw [eval₂_monomial (C.comp (Quotient.mk I)) X]
  refine' mul_eq_zero_of_left (Polynomial.ext fun m => _) (X ^ n)
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
n : ℕ
x✝ : n ∈ support a
m : ℕ
⊢ coeff ((RingHom.comp C (Quotient.mk I)) (coeff a n)) m = coeff 0 m

Next tactic:
erw [coeff_C]
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  refine' Finset.sum_eq_zero fun n _ => _
  dsimp
  rw [eval₂_monomial (C.comp (Quotient.mk I)) X]
  refine' mul_eq_zero_of_left (Polynomial.ext fun m => _) (X ^ n)
  erw [coeff_C]
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
n : ℕ
x✝ : n ∈ support a
m : ℕ
⊢ (if m = 0 then (Quotient.mk I) (coeff a n) else 0) = coeff 0 m

Next tactic:
by_cases h : m = 0
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  refine' Finset.sum_eq_zero fun n _ => _
  dsimp
  rw [eval₂_monomial (C.comp (Quotient.mk I)) X]
  refine' mul_eq_zero_of_left (Polynomial.ext fun m => _) (X ^ n)
  erw [coeff_C]
  by_cases h : m = 0
  · 

Proof state:
case pos
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
n : ℕ
x✝ : n ∈ support a
m : ℕ
h : m = 0
⊢ (if m = 0 then (Quotient.mk I) (coeff a n) else 0) = coeff 0 m

Next tactic:
simpa [h] using Quotient.eq_zero_iff_mem.2 ((mem_map_C_iff.1 ha) n)
theorem eval₂_C_mk_eq_zero {I : Ideal R} :
    ∀ f ∈ (map (C : R →+* R[X]) I : Ideal R[X]), eval₂RingHom (C.comp (Quotient.mk I)) X f = 0 := by
  intro a ha
  rw [← sum_monomial_eq a]
  dsimp
  rw [eval₂_sum]
  refine' Finset.sum_eq_zero fun n _ => _
  dsimp
  rw [eval₂_monomial (C.comp (Quotient.mk I)) X]
  refine' mul_eq_zero_of_left (Polynomial.ext fun m => _) (X ^ n)
  erw [coeff_C]
  by_cases h : m = 0
  · simpa [h] using Quotient.eq_zero_iff_mem.2 ((mem_map_C_iff.1 ha) n)
  · 

Proof state:
case neg
R : Type u_1
inst✝ : CommRing R
I : Ideal R
a : R[X]
ha : a ∈ map C I
n : ℕ
x✝ : n ∈ support a
m : ℕ
h : ¬m = 0
⊢ (if m = 0 then (Quotient.mk I) (coeff a n) else 0) = coeff 0 m

Next tactic:
simp [h]
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
⊢ Function.LeftInverse
    ⇑(Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
    ⇑(eval₂RingHom
        (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
          (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
        ((Quotient.mk (map C I)) X))

Next tactic:
intro f
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    intro f
    

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f : (R ⧸ I)[X]
⊢ (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      ((eval₂RingHom
          (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
            (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
          ((Quotient.mk (map C I)) X))
        f) =
    f

Next tactic:
refine Polynomial.induction_on' f ?_ ?_
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    intro f
    refine Polynomial.induction_on' f ?_ ?_
    · 

Proof state:
case refine_1
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f : (R ⧸ I)[X]
⊢ ∀ (p q : (R ⧸ I)[X]),
    (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
            (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
          ((eval₂RingHom
              (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
                (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
              ((Quotient.mk (map C I)) X))
            p) =
        p →
      (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
              (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
            ((eval₂RingHom
                (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
                  (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
                ((Quotient.mk (map C I)) X))
              q) =
          q →
        (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
              (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
            ((eval₂RingHom
                (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
                  (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
                ((Quotient.mk (map C I)) X))
              (p + q)) =
          p + q

Next tactic:
intro p q hp hq
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    intro f
    refine Polynomial.induction_on' f ?_ ?_
    · intro p q hp hq
      

Proof state:
case refine_1
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f p q : (R ⧸ I)[X]
hp :
  (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      ((eval₂RingHom
          (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
            (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
          ((Quotient.mk (map C I)) X))
        p) =
    p
hq :
  (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      ((eval₂RingHom
          (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
            (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
          ((Quotient.mk (map C I)) X))
        q) =
    q
⊢ (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      ((eval₂RingHom
          (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
            (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
          ((Quotient.mk (map C I)) X))
        (p + q)) =
    p + q

Next tactic:
simp only [coe_eval₂RingHom] at hp hq
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    intro f
    refine Polynomial.induction_on' f ?_ ?_
    · intro p q hp hq
      simp only [coe_eval₂RingHom] at hp hq
      

Proof state:
case refine_1
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f p q : (R ⧸ I)[X]
hp :
  (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      (eval₂
        (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
          (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
        ((Quotient.mk (map C I)) X) p) =
    p
hq :
  (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      (eval₂
        (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
          (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
        ((Quotient.mk (map C I)) X) q) =
    q
⊢ (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      ((eval₂RingHom
          (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
            (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
          ((Quotient.mk (map C I)) X))
        (p + q)) =
    p + q

Next tactic:
simp only [coe_eval₂RingHom, hp, hq, RingHom.map_add]
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    intro f
    refine Polynomial.induction_on' f ?_ ?_
    · intro p q hp hq
      simp only [coe_eval₂RingHom] at hp hq
      simp only [coe_eval₂RingHom, hp, hq, RingHom.map_add]
    · 

Proof state:
case refine_2
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f : (R ⧸ I)[X]
⊢ ∀ (n : ℕ) (a : R ⧸ I),
    (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
          (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
        ((eval₂RingHom
            (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
              (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
            ((Quotient.mk (map C I)) X))
          ((monomial n) a)) =
      (monomial n) a

Next tactic:
rintro n ⟨x⟩
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    intro f
    refine Polynomial.induction_on' f ?_ ?_
    · intro p q hp hq
      simp only [coe_eval₂RingHom] at hp hq
      simp only [coe_eval₂RingHom, hp, hq, RingHom.map_add]
    · rintro n ⟨x⟩
      

Proof state:
case refine_2.mk
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f : (R ⧸ I)[X]
n : ℕ
a✝ : R ⧸ I
x : R
⊢ (Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
      ((eval₂RingHom
          (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
            (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
          ((Quotient.mk (map C I)) X))
        ((monomial n) (Quot.mk Setoid.r x))) =
    (monomial n) (Quot.mk Setoid.r x)

Next tactic:
simp only [← smul_X_eq_monomial, C_mul', Quotient.lift_mk, Submodule.Quotient.quot_mk_eq_mk,
        Quotient.mk_eq_mk, eval₂_X_pow, eval₂_smul, coe_eval₂RingHom, RingHom.map_pow, eval₂_C,
        RingHom.coe_comp, RingHom.map_mul, eval₂_X, Function.comp_apply]
/-- If `I` is an ideal of `R`, then the ring polynomials over the quotient ring `I.quotient` is
isomorphic to the quotient of `R[X]` by the ideal `map C I`,
where `map C I` contains exactly the polynomials whose coefficients all lie in `I`. -/
def polynomialQuotientEquivQuotientPolynomial (I : Ideal R) :
    (R ⧸ I)[X] ≃+* R[X] ⧸ (map C I : Ideal R[X]) where
  toFun :=
    eval₂RingHom
      (Quotient.lift I ((Quotient.mk (map C I : Ideal R[X])).comp C) quotient_map_C_eq_zero)
      (Quotient.mk (map C I : Ideal R[X]) X)
  invFun :=
    Quotient.lift (map C I : Ideal R[X]) (eval₂RingHom (C.comp (Quotient.mk I)) X)
      eval₂_C_mk_eq_zero
  map_mul' f g := by simp only [coe_eval₂RingHom, eval₂_mul]
  map_add' f g := by simp only [eval₂_add, coe_eval₂RingHom]
  left_inv := by
    intro f
    refine Polynomial.induction_on' f ?_ ?_
    · intro p q hp hq
      simp only [coe_eval₂RingHom] at hp hq
      simp only [coe_eval₂RingHom, hp, hq, RingHom.map_add]
    · rintro n ⟨x⟩
      simp only [← smul_X_eq_monomial, C_mul', Quotient.lift_mk, Submodule.Quotient.quot_mk_eq_mk,
        Quotient.mk_eq_mk, eval₂_X_pow, eval₂_smul, coe_eval₂RingHom, RingHom.map_pow, eval₂_C,
        RingHom.coe_comp, RingHom.map_mul, eval₂_X, Function.comp_apply]
  right_inv := by
    

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
⊢ Function.RightInverse
    ⇑(Quotient.lift (map C I) (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X)
        (_ : ∀ f ∈ map C I, (eval₂RingHom (RingHom.comp C (Quotient.mk I)) X) f = 0))
    ⇑(eval₂RingHom
        (Quotient.lift I (RingHom.comp (Quotient.mk (map C I)) C)
          (_ : ∀ a ∈ I, (RingHom.comp (Quotient.mk (map C I)) C) a = 0))
        ((Quotient.mk (map C I)) X))

Next tactic:
rintro ⟨f⟩