l3lab/ntp-mathlib huggingface dataset:
/-- 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
    rintro ⟨f⟩
    

Proof state:
case mk
R : Type u_1
inst✝ : CommRing R
I : Ideal R
x✝ : R[X] ⧸ map C I
f : R[X]
⊢ (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))
      ((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))
        (Quot.mk Setoid.r f)) =
    Quot.mk Setoid.r 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 ?_ ?_
    · 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
    rintro ⟨f⟩
    refine Polynomial.induction_on' f ?_ ?_
    · -- Porting note: was `simp_intro p q hp hq`
      

Proof state:
case mk.refine_1
R : Type u_1
inst✝ : CommRing R
I : Ideal R
x✝ : R[X] ⧸ map C I
f : R[X]
⊢ ∀ (p q : R[X]),
    (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))
          ((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))
            (Quot.mk Setoid.r p)) =
        Quot.mk Setoid.r p →
      (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))
            ((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))
              (Quot.mk Setoid.r q)) =
          Quot.mk Setoid.r q →
        (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))
            ((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))
              (Quot.mk Setoid.r (p + q))) =
          Quot.mk Setoid.r (p + q)

Next tactic:
intros 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
      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
    rintro ⟨f⟩
    refine Polynomial.induction_on' f ?_ ?_
    · -- Porting note: was `simp_intro p q hp hq`
      intros p q hp hq
      

Proof state:
case mk.refine_1
R : Type u_1
inst✝ : CommRing R
I : Ideal R
x✝ : R[X] ⧸ map C I
f p q : R[X]
hp :
  (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))
      ((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))
        (Quot.mk Setoid.r p)) =
    Quot.mk Setoid.r p
hq :
  (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))
      ((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))
        (Quot.mk Setoid.r q)) =
    Quot.mk Setoid.r q
⊢ (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))
      ((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))
        (Quot.mk Setoid.r (p + q))) =
    Quot.mk Setoid.r (p + q)

Next tactic:
simp only [Submodule.Quotient.quot_mk_eq_mk, Quotient.mk_eq_mk, map_add, Quotient.lift_mk,
        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
      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
    rintro ⟨f⟩
    refine Polynomial.induction_on' f ?_ ?_
    · -- Porting note: was `simp_intro p q hp hq`
      intros p q hp hq
      simp only [Submodule.Quotient.quot_mk_eq_mk, Quotient.mk_eq_mk, map_add, Quotient.lift_mk,
        coe_eval₂RingHom] at hp hq ⊢
      

Proof state:
case mk.refine_1
R : Type u_1
inst✝ : CommRing R
I : Ideal R
x✝ : R[X] ⧸ map C I
f p q : R[X]
hp :
  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) (eval₂ (RingHom.comp C (Quotient.mk I)) X p) =
    (Quotient.mk (map C I)) p
hq :
  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) (eval₂ (RingHom.comp C (Quotient.mk I)) X q) =
    (Quotient.mk (map C I)) q
⊢ 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) (eval₂ (RingHom.comp C (Quotient.mk I)) X p) +
      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) (eval₂ (RingHom.comp C (Quotient.mk I)) X q) =
    (Quotient.mk (map C I)) p + (Quotient.mk (map C I)) q

Next tactic:
rw [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
      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
    rintro ⟨f⟩
    refine Polynomial.induction_on' f ?_ ?_
    · -- Porting note: was `simp_intro p q hp hq`
      intros p q hp hq
      simp only [Submodule.Quotient.quot_mk_eq_mk, Quotient.mk_eq_mk, map_add, Quotient.lift_mk,
        coe_eval₂RingHom] at hp hq ⊢
      rw [hp, hq]
    · 

Proof state:
case mk.refine_2
R : Type u_1
inst✝ : CommRing R
I : Ideal R
x✝ : R[X] ⧸ map C I
f : R[X]
⊢ ∀ (n : ℕ) (a : R),
    (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))
        ((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))
          (Quot.mk Setoid.r ((monomial n) a))) =
      Quot.mk Setoid.r ((monomial n) a)

Next tactic:
intro n a
/-- 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
    rintro ⟨f⟩
    refine Polynomial.induction_on' f ?_ ?_
    · -- Porting note: was `simp_intro p q hp hq`
      intros p q hp hq
      simp only [Submodule.Quotient.quot_mk_eq_mk, Quotient.mk_eq_mk, map_add, Quotient.lift_mk,
        coe_eval₂RingHom] at hp hq ⊢
      rw [hp, hq]
    · intro n a
      

Proof state:
case mk.refine_2
R : Type u_1
inst✝ : CommRing R
I : Ideal R
x✝ : R[X] ⧸ map C I
f : R[X]
n : ℕ
a : R
⊢ (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))
      ((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))
        (Quot.mk Setoid.r ((monomial n) a))) =
    Quot.mk Setoid.r ((monomial n) a)

Next tactic:
simp only [← smul_X_eq_monomial, ← C_mul' a (X ^ n), 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]
@[simp]
theorem polynomialQuotientEquivQuotientPolynomial_symm_mk (I : Ideal R) (f : R[X]) :
    I.polynomialQuotientEquivQuotientPolynomial.symm (Quotient.mk _ f) = f.map (Quotient.mk I) := by
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f : R[X]
⊢ (RingEquiv.symm (polynomialQuotientEquivQuotientPolynomial I)) ((Quotient.mk (map C I)) f) =
    Polynomial.map (Quotient.mk I) f

Next tactic:
rw [polynomialQuotientEquivQuotientPolynomial, RingEquiv.symm_mk, RingEquiv.coe_mk,
    Equiv.coe_fn_mk, Quotient.lift_mk, coe_eval₂RingHom, eval₂_eq_eval_map, ← Polynomial.map_map,
    ← eval₂_eq_eval_map, Polynomial.eval₂_C_X]
@[simp]
theorem polynomialQuotientEquivQuotientPolynomial_map_mk (I : Ideal R) (f : R[X]) :
    I.polynomialQuotientEquivQuotientPolynomial (f.map <| Quotient.mk I) =
    Quotient.mk (map C I : Ideal R[X]) f := by
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f : R[X]
⊢ (polynomialQuotientEquivQuotientPolynomial I) (Polynomial.map (Quotient.mk I) f) = (Quotient.mk (map C I)) f

Next tactic:
apply (polynomialQuotientEquivQuotientPolynomial I).symm.injective
@[simp]
theorem polynomialQuotientEquivQuotientPolynomial_map_mk (I : Ideal R) (f : R[X]) :
    I.polynomialQuotientEquivQuotientPolynomial (f.map <| Quotient.mk I) =
    Quotient.mk (map C I : Ideal R[X]) f := by
  apply (polynomialQuotientEquivQuotientPolynomial I).symm.injective
  

Proof state:
case a
R : Type u_1
inst✝ : CommRing R
I : Ideal R
f : R[X]
⊢ (RingEquiv.symm (polynomialQuotientEquivQuotientPolynomial I))
      ((polynomialQuotientEquivQuotientPolynomial I) (Polynomial.map (Quotient.mk I) f)) =
    (RingEquiv.symm (polynomialQuotientEquivQuotientPolynomial I)) ((Quotient.mk (map C I)) f)

Next tactic:
rw [RingEquiv.symm_apply_apply, polynomialQuotientEquivQuotientPolynomial_symm_mk]
/-- Given any ring `R` and an ideal `I` of `R[X]`, we get a map `R → R[x] → R[x]/I`.
  If we let `R` be the image of `R` in `R[x]/I` then we also have a map `R[x] → R'[x]`.
  In particular we can map `I` across this map, to get `I'` and a new map `R' → R'[x] → R'[x]/I`.
  This theorem shows `I'` will not contain any non-zero constant polynomials. -/
theorem eq_zero_of_polynomial_mem_map_range (I : Ideal R[X]) (x : ((Quotient.mk I).comp C).range)
    (hx : C x ∈ I.map (Polynomial.mapRingHom ((Quotient.mk I).comp C).rangeRestrict)) : x = 0 := by
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R[X]
x : ↥(RingHom.range (RingHom.comp (Quotient.mk I) C))
hx : C x ∈ map (mapRingHom (RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C))) I
⊢ x = 0

Next tactic:
let i := ((Quotient.mk I).comp C).rangeRestrict
/-- Given any ring `R` and an ideal `I` of `R[X]`, we get a map `R → R[x] → R[x]/I`.
  If we let `R` be the image of `R` in `R[x]/I` then we also have a map `R[x] → R'[x]`.
  In particular we can map `I` across this map, to get `I'` and a new map `R' → R'[x] → R'[x]/I`.
  This theorem shows `I'` will not contain any non-zero constant polynomials. -/
theorem eq_zero_of_polynomial_mem_map_range (I : Ideal R[X]) (x : ((Quotient.mk I).comp C).range)
    (hx : C x ∈ I.map (Polynomial.mapRingHom ((Quotient.mk I).comp C).rangeRestrict)) : x = 0 := by
  let i := ((Quotient.mk I).comp C).rangeRestrict
  

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R[X]
x : ↥(RingHom.range (RingHom.comp (Quotient.mk I) C))
hx : C x ∈ map (mapRingHom (RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C))) I
i : R →+* ↥(RingHom.range (RingHom.comp (Quotient.mk I) C)) := RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C)
⊢ x = 0

Next tactic:
have hi' : RingHom.ker (Polynomial.mapRingHom i) ≤ I := by
    refine' fun f hf => polynomial_mem_ideal_of_coeff_mem_ideal I f fun n => _
    rw [mem_comap, ← Quotient.eq_zero_iff_mem, ← RingHom.comp_apply]
    rw [RingHom.mem_ker, coe_mapRingHom] at hf
    replace hf := congr_arg (fun f : Polynomial _ => f.coeff n) hf
    simp only [coeff_map, coeff_zero] at hf
    rwa [Subtype.ext_iff, RingHom.coe_rangeRestrict] at hf
/-- Given any ring `R` and an ideal `I` of `R[X]`, we get a map `R → R[x] → R[x]/I`.
  If we let `R` be the image of `R` in `R[x]/I` then we also have a map `R[x] → R'[x]`.
  In particular we can map `I` across this map, to get `I'` and a new map `R' → R'[x] → R'[x]/I`.
  This theorem shows `I'` will not contain any non-zero constant polynomials. -/
theorem eq_zero_of_polynomial_mem_map_range (I : Ideal R[X]) (x : ((Quotient.mk I).comp C).range)
    (hx : C x ∈ I.map (Polynomial.mapRingHom ((Quotient.mk I).comp C).rangeRestrict)) : x = 0 := by
  let i := ((Quotient.mk I).comp C).rangeRestrict
  have hi' : RingHom.ker (Polynomial.mapRingHom i) ≤ I := by
    

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R[X]
x : ↥(RingHom.range (RingHom.comp (Quotient.mk I) C))
hx : C x ∈ map (mapRingHom (RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C))) I
i : R →+* ↥(RingHom.range (RingHom.comp (Quotient.mk I) C)) := RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C)
⊢ RingHom.ker (mapRingHom i) ≤ I

Next tactic:
refine' fun f hf => polynomial_mem_ideal_of_coeff_mem_ideal I f fun n => _
/-- Given any ring `R` and an ideal `I` of `R[X]`, we get a map `R → R[x] → R[x]/I`.
  If we let `R` be the image of `R` in `R[x]/I` then we also have a map `R[x] → R'[x]`.
  In particular we can map `I` across this map, to get `I'` and a new map `R' → R'[x] → R'[x]/I`.
  This theorem shows `I'` will not contain any non-zero constant polynomials. -/
theorem eq_zero_of_polynomial_mem_map_range (I : Ideal R[X]) (x : ((Quotient.mk I).comp C).range)
    (hx : C x ∈ I.map (Polynomial.mapRingHom ((Quotient.mk I).comp C).rangeRestrict)) : x = 0 := by
  let i := ((Quotient.mk I).comp C).rangeRestrict
  have hi' : RingHom.ker (Polynomial.mapRingHom i) ≤ I := by
    refine' fun f hf => polynomial_mem_ideal_of_coeff_mem_ideal I f fun n => _
    

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R[X]
x : ↥(RingHom.range (RingHom.comp (Quotient.mk I) C))
hx : C x ∈ map (mapRingHom (RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C))) I
i : R →+* ↥(RingHom.range (RingHom.comp (Quotient.mk I) C)) := RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C)
f : R[X]
hf : f ∈ RingHom.ker (mapRingHom i)
n : ℕ
⊢ coeff f n ∈ comap C I

Next tactic:
rw [mem_comap, ← Quotient.eq_zero_iff_mem, ← RingHom.comp_apply]
/-- Given any ring `R` and an ideal `I` of `R[X]`, we get a map `R → R[x] → R[x]/I`.
  If we let `R` be the image of `R` in `R[x]/I` then we also have a map `R[x] → R'[x]`.
  In particular we can map `I` across this map, to get `I'` and a new map `R' → R'[x] → R'[x]/I`.
  This theorem shows `I'` will not contain any non-zero constant polynomials. -/
theorem eq_zero_of_polynomial_mem_map_range (I : Ideal R[X]) (x : ((Quotient.mk I).comp C).range)
    (hx : C x ∈ I.map (Polynomial.mapRingHom ((Quotient.mk I).comp C).rangeRestrict)) : x = 0 := by
  let i := ((Quotient.mk I).comp C).rangeRestrict
  have hi' : RingHom.ker (Polynomial.mapRingHom i) ≤ I := by
    refine' fun f hf => polynomial_mem_ideal_of_coeff_mem_ideal I f fun n => _
    rw [mem_comap, ← Quotient.eq_zero_iff_mem, ← RingHom.comp_apply]
    

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R[X]
x : ↥(RingHom.range (RingHom.comp (Quotient.mk I) C))
hx : C x ∈ map (mapRingHom (RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C))) I
i : R →+* ↥(RingHom.range (RingHom.comp (Quotient.mk I) C)) := RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C)
f : R[X]
hf : f ∈ RingHom.ker (mapRingHom i)
n : ℕ
⊢ (RingHom.comp (Quotient.mk I) C) (coeff f n) = 0

Next tactic:
rw [RingHom.mem_ker, coe_mapRingHom] at hf
/-- Given any ring `R` and an ideal `I` of `R[X]`, we get a map `R → R[x] → R[x]/I`.
  If we let `R` be the image of `R` in `R[x]/I` then we also have a map `R[x] → R'[x]`.
  In particular we can map `I` across this map, to get `I'` and a new map `R' → R'[x] → R'[x]/I`.
  This theorem shows `I'` will not contain any non-zero constant polynomials. -/
theorem eq_zero_of_polynomial_mem_map_range (I : Ideal R[X]) (x : ((Quotient.mk I).comp C).range)
    (hx : C x ∈ I.map (Polynomial.mapRingHom ((Quotient.mk I).comp C).rangeRestrict)) : x = 0 := by
  let i := ((Quotient.mk I).comp C).rangeRestrict
  have hi' : RingHom.ker (Polynomial.mapRingHom i) ≤ I := by
    refine' fun f hf => polynomial_mem_ideal_of_coeff_mem_ideal I f fun n => _
    rw [mem_comap, ← Quotient.eq_zero_iff_mem, ← RingHom.comp_apply]
    rw [RingHom.mem_ker, coe_mapRingHom] at hf
    

Proof state:
R : Type u_1
inst✝ : CommRing R
I : Ideal R[X]
x : ↥(RingHom.range (RingHom.comp (Quotient.mk I) C))
hx : C x ∈ map (mapRingHom (RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C))) I
i : R →+* ↥(RingHom.range (RingHom.comp (Quotient.mk I) C)) := RingHom.rangeRestrict (RingHom.comp (Quotient.mk I) C)
f : R[X]
hf : Polynomial.map i f = 0
n : ℕ
⊢ (RingHom.comp (Quotient.mk I) C) (coeff f n) = 0

Next tactic:
replace hf := congr_arg (fun f : Polynomial _ => f.coeff n) hf