l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem coeff_map (n : ℕ) : coeff (p.map f) n = f (coeff p n) := by
  rw [map, eval₂_def, coeff_sum, sum]
  conv_rhs => rw [← sum_C_mul_X_pow_eq p, coeff_sum, sum, map_sum]
  refine' Finset.sum_congr rfl fun x _hx => _
  -- Porting note: Was `simp [Function.comp, coeff_C_mul_X_pow, f.map_mul]`.
  simp? [Function.comp, coeff_C_mul_X_pow, - map_mul, - coeff_C_mul] says
    simp only [RingHom.coe_comp, Function.comp_apply, coeff_C_mul_X_pow]
  split_ifs <;> 

Proof state:
case neg
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
n x : ℕ
_hx : x ∈ support p
h✝ : ¬n = x
⊢ 0 = f 0

Next tactic:
simp [f.map_zero]
/-- If `R` and `S` are isomorphic, then so are their polynomial rings. -/
@[simps!]
def mapEquiv (e : R ≃+* S) : R[X] ≃+* S[X] :=
  RingEquiv.ofHomInv (mapRingHom (e : R →+* S)) (mapRingHom (e.symm : S →+* R)) (by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
e : R ≃+* S
⊢ RingHom.comp ↑(mapRingHom ↑(RingEquiv.symm e)) ↑(mapRingHom ↑e) = RingHom.id R[X]

Next tactic:
ext
/-- If `R` and `S` are isomorphic, then so are their polynomial rings. -/
@[simps!]
def mapEquiv (e : R ≃+* S) : R[X] ≃+* S[X] :=
  RingEquiv.ofHomInv (mapRingHom (e : R →+* S)) (mapRingHom (e.symm : S →+* R)) (by ext <;> 

Proof state:
case h₁.a.a
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
e : R ≃+* S
x✝ : R
n✝ : ℕ
⊢ coeff ((RingHom.comp (RingHom.comp ↑(mapRingHom ↑(RingEquiv.symm e)) ↑(mapRingHom ↑e)) C) x✝) n✝ =
    coeff ((RingHom.comp (RingHom.id R[X]) C) x✝) n✝

Next tactic:
simp
/-- If `R` and `S` are isomorphic, then so are their polynomial rings. -/
@[simps!]
def mapEquiv (e : R ≃+* S) : R[X] ≃+* S[X] :=
  RingEquiv.ofHomInv (mapRingHom (e : R →+* S)) (mapRingHom (e.symm : S →+* R)) (by ext <;> 

Proof state:
case h₂.a
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
e : R ≃+* S
n✝ : ℕ
⊢ coeff ((RingHom.comp ↑(mapRingHom ↑(RingEquiv.symm e)) ↑(mapRingHom ↑e)) X) n✝ = coeff ((RingHom.id R[X]) X) n✝

Next tactic:
simp
/-- If `R` and `S` are isomorphic, then so are their polynomial rings. -/
@[simps!]
def mapEquiv (e : R ≃+* S) : R[X] ≃+* S[X] :=
  RingEquiv.ofHomInv (mapRingHom (e : R →+* S)) (mapRingHom (e.symm : S →+* R)) (by ext <;> simp)
    (by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
e : R ≃+* S
⊢ RingHom.comp ↑(mapRingHom ↑e) ↑(mapRingHom ↑(RingEquiv.symm e)) = RingHom.id S[X]

Next tactic:
ext
/-- If `R` and `S` are isomorphic, then so are their polynomial rings. -/
@[simps!]
def mapEquiv (e : R ≃+* S) : R[X] ≃+* S[X] :=
  RingEquiv.ofHomInv (mapRingHom (e : R →+* S)) (mapRingHom (e.symm : S →+* R)) (by ext <;> simp)
    (by ext <;> 

Proof state:
case h₁.a.a
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
e : R ≃+* S
x✝ : S
n✝ : ℕ
⊢ coeff ((RingHom.comp (RingHom.comp ↑(mapRingHom ↑e) ↑(mapRingHom ↑(RingEquiv.symm e))) C) x✝) n✝ =
    coeff ((RingHom.comp (RingHom.id S[X]) C) x✝) n✝

Next tactic:
simp
/-- If `R` and `S` are isomorphic, then so are their polynomial rings. -/
@[simps!]
def mapEquiv (e : R ≃+* S) : R[X] ≃+* S[X] :=
  RingEquiv.ofHomInv (mapRingHom (e : R →+* S)) (mapRingHom (e.symm : S →+* R)) (by ext <;> simp)
    (by ext <;> 

Proof state:
case h₂.a
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
e : R ≃+* S
n✝ : ℕ
⊢ coeff ((RingHom.comp ↑(mapRingHom ↑e) ↑(mapRingHom ↑(RingEquiv.symm e))) X) n✝ = coeff ((RingHom.id S[X]) X) n✝

Next tactic:
simp
theorem map_map [Semiring T] (g : S →+* T) (p : R[X]) : (p.map f).map g = p.map (g.comp f) :=
  ext (by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝² : Semiring R
p✝ q r : R[X]
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Semiring T
g : S →+* T
p : R[X]
⊢ ∀ (n : ℕ), coeff (map g (map f p)) n = coeff (map (RingHom.comp g f) p) n

Next tactic:
simp [coeff_map]
@[simp]
theorem map_id : p.map (RingHom.id _) = p := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
⊢ map (RingHom.id R) p = p

Next tactic:
simp [Polynomial.ext_iff, coeff_map]
theorem eval₂_eq_eval_map {x : S} : p.eval₂ f x = (p.map f).eval x := by
  -- Porting note: `apply` → `induction`
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
x : S
⊢ eval₂ f x p = eval x (map f p)

Next tactic:
induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp [hp, hq]
  | h_monomial n r =>
    simp
theorem eval₂_eq_eval_map {x : S} : p.eval₂ f x = (p.map f).eval x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q✝ r : R[X]
inst✝ : Semiring S
f : R →+* S
x : S
p q : R[X]
hp : eval₂ f x p = eval x (map f p)
hq : eval₂ f x q = eval x (map f q)
⊢ eval₂ f x (p + q) = eval x (map f (p + q))

Next tactic:
| h_add p q hp hq =>
    simp [hp, hq]
theorem eval₂_eq_eval_map {x : S} : p.eval₂ f x = (p.map f).eval x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q✝ r : R[X]
inst✝ : Semiring S
f : R →+* S
x : S
p q : R[X]
hp : eval₂ f x p = eval x (map f p)
hq : eval₂ f x q = eval x (map f q)
⊢ eval₂ f x (p + q) = eval x (map f (p + q))

Next tactic:
simp [hp, hq]
theorem eval₂_eq_eval_map {x : S} : p.eval₂ f x = (p.map f).eval x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp [hp, hq]
  

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p q r✝ : R[X]
inst✝ : Semiring S
f : R →+* S
x : S
n : ℕ
r : R
⊢ eval₂ f x ((monomial n) r) = eval x (map f ((monomial n) r))

Next tactic:
| h_monomial n r =>
    simp
theorem eval₂_eq_eval_map {x : S} : p.eval₂ f x = (p.map f).eval x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp [hp, hq]
  | h_monomial n r =>
    

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p q r✝ : R[X]
inst✝ : Semiring S
f : R →+* S
x : S
n : ℕ
r : R
⊢ eval₂ f x ((monomial n) r) = eval x (map f ((monomial n) r))

Next tactic:
simp
theorem map_injective (hf : Function.Injective f) : Function.Injective (map f) := fun p q h =>
  ext fun m => hf <| by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m✝ n : ℕ
inst✝¹ : Semiring R
p✝ q✝ r : R[X]
inst✝ : Semiring S
f : R →+* S
hf : Function.Injective ⇑f
p q : R[X]
h : map f p = map f q
m : ℕ
⊢ f (coeff p m) = f (coeff q m)

Next tactic:
rw [← coeff_map f, ← coeff_map f, h]
theorem map_surjective (hf : Function.Surjective f) : Function.Surjective (map f) := fun p =>
  Polynomial.induction_on' p
    (fun p q hp hq =>
      let ⟨p', hp'⟩ := hp
      let ⟨q', hq'⟩ := hq
      ⟨p' + q', by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝¹ q✝ r : R[X]
inst✝ : Semiring S
f : R →+* S
hf : Function.Surjective ⇑f
p✝ p q : S[X]
hp : ∃ a, map f a = p
hq : ∃ a, map f a = q
p' : R[X]
hp' : map f p' = p
q' : R[X]
hq' : map f q' = q
⊢ map f (p' + q') = p + q

Next tactic:
rw [Polynomial.map_add f, hp', hq']
theorem map_surjective (hf : Function.Surjective f) : Function.Surjective (map f) := fun p =>
  Polynomial.induction_on' p
    (fun p q hp hq =>
      let ⟨p', hp'⟩ := hp
      let ⟨q', hq'⟩ := hq
      ⟨p' + q', by rw [Polynomial.map_add f, hp', hq']⟩)
    fun n s =>
    let ⟨r, hr⟩ := hf s
    ⟨monomial n r, by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p✝ q r✝ : R[X]
inst✝ : Semiring S
f : R →+* S
hf : Function.Surjective ⇑f
p : S[X]
n : ℕ
s : S
r : R
hr : f r = s
⊢ map f ((monomial n) r) = (monomial n) s

Next tactic:
rw [map_monomial f, hr]
theorem degree_map_le (p : R[X]) : degree (p.map f) ≤ degree p := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
⊢ degree (map f p) ≤ degree p

Next tactic:
refine (degree_le_iff_coeff_zero _ _).2 fun m hm => ?_
theorem degree_map_le (p : R[X]) : degree (p.map f) ≤ degree p := by
  refine (degree_le_iff_coeff_zero _ _).2 fun m hm => ?_
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m✝ n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
m : ℕ
hm : degree p < ↑m
⊢ coeff (map f p) m = 0

Next tactic:
rw [degree_lt_iff_coeff_zero] at hm
theorem degree_map_le (p : R[X]) : degree (p.map f) ≤ degree p := by
  refine (degree_le_iff_coeff_zero _ _).2 fun m hm => ?_
  rw [degree_lt_iff_coeff_zero] at hm
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m✝ n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
m : ℕ
hm : ∀ (m_1 : ℕ), m ≤ m_1 → coeff p m_1 = 0
⊢ coeff (map f p) m = 0

Next tactic:
simp [hm m le_rfl]
theorem map_monic_eq_zero_iff (hp : p.Monic) : p.map f = 0 ↔ ∀ x, f x = 0 :=
  ⟨fun hfp x =>
    calc
      f x = f x * f p.leadingCoeff := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
hp : Monic p
hfp : map f p = 0
x : R
⊢ f x = f x * f (leadingCoeff p)

Next tactic:
simp only [mul_one, hp.leadingCoeff, f.map_one]
theorem map_monic_eq_zero_iff (hp : p.Monic) : p.map f = 0 ↔ ∀ x, f x = 0 :=
  ⟨fun hfp x =>
    calc
      f x = f x * f p.leadingCoeff := by simp only [mul_one, hp.leadingCoeff, f.map_one]
      _ = f x * (p.map f).coeff p.natDegree := (congr_arg _ (coeff_map _ _).symm)
      _ = 0 := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
hp : Monic p
hfp : map f p = 0
x : R
⊢ f x * coeff (map f p) (natDegree p) = 0

Next tactic:
simp only [hfp, mul_zero, coeff_zero]
theorem map_monic_eq_zero_iff (hp : p.Monic) : p.map f = 0 ↔ ∀ x, f x = 0 :=
  ⟨fun hfp x =>
    calc
      f x = f x * f p.leadingCoeff := by simp only [mul_one, hp.leadingCoeff, f.map_one]
      _ = f x * (p.map f).coeff p.natDegree := (congr_arg _ (coeff_map _ _).symm)
      _ = 0 := by simp only [hfp, mul_zero, coeff_zero]
      ,
    fun h => ext fun n => by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
hp : Monic p
h : ∀ (x : R), f x = 0
n : ℕ
⊢ coeff (map f p) n = coeff 0 n

Next tactic:
simp only [h, coeff_map, coeff_zero]
theorem degree_map_eq_of_leadingCoeff_ne_zero (f : R →+* S) (hf : f (leadingCoeff p) ≠ 0) :
    degree (p.map f) = degree p :=
  le_antisymm (degree_map_le f _) <| by
    

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
hf : f (leadingCoeff p) ≠ 0
⊢ degree p ≤ degree (map f p)

Next tactic:
have hp0 : p ≠ 0 :=
      leadingCoeff_ne_zero.mp fun hp0 => hf (_root_.trans (congr_arg _ hp0) f.map_zero)
theorem degree_map_eq_of_leadingCoeff_ne_zero (f : R →+* S) (hf : f (leadingCoeff p) ≠ 0) :
    degree (p.map f) = degree p :=
  le_antisymm (degree_map_le f _) <| by
    have hp0 : p ≠ 0 :=
      leadingCoeff_ne_zero.mp fun hp0 => hf (_root_.trans (congr_arg _ hp0) f.map_zero)
    

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
hf : f (leadingCoeff p) ≠ 0
hp0 : p ≠ 0
⊢ degree p ≤ degree (map f p)

Next tactic:
rw [degree_eq_natDegree hp0]
theorem degree_map_eq_of_leadingCoeff_ne_zero (f : R →+* S) (hf : f (leadingCoeff p) ≠ 0) :
    degree (p.map f) = degree p :=
  le_antisymm (degree_map_le f _) <| by
    have hp0 : p ≠ 0 :=
      leadingCoeff_ne_zero.mp fun hp0 => hf (_root_.trans (congr_arg _ hp0) f.map_zero)
    rw [degree_eq_natDegree hp0]
    

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
hf : f (leadingCoeff p) ≠ 0
hp0 : p ≠ 0
⊢ ↑(natDegree p) ≤ degree (map f p)

Next tactic:
refine' le_degree_of_ne_zero _
theorem degree_map_eq_of_leadingCoeff_ne_zero (f : R →+* S) (hf : f (leadingCoeff p) ≠ 0) :
    degree (p.map f) = degree p :=
  le_antisymm (degree_map_le f _) <| by
    have hp0 : p ≠ 0 :=
      leadingCoeff_ne_zero.mp fun hp0 => hf (_root_.trans (congr_arg _ hp0) f.map_zero)
    rw [degree_eq_natDegree hp0]
    refine' le_degree_of_ne_zero _
    

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
hf : f (leadingCoeff p) ≠ 0
hp0 : p ≠ 0
⊢ coeff (map f p) (natDegree p) ≠ 0

Next tactic:
rw [coeff_map]
theorem degree_map_eq_of_leadingCoeff_ne_zero (f : R →+* S) (hf : f (leadingCoeff p) ≠ 0) :
    degree (p.map f) = degree p :=
  le_antisymm (degree_map_le f _) <| by
    have hp0 : p ≠ 0 :=
      leadingCoeff_ne_zero.mp fun hp0 => hf (_root_.trans (congr_arg _ hp0) f.map_zero)
    rw [degree_eq_natDegree hp0]
    refine' le_degree_of_ne_zero _
    rw [coeff_map]
    

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
hf : f (leadingCoeff p) ≠ 0
hp0 : p ≠ 0
⊢ f (coeff p (natDegree p)) ≠ 0

Next tactic:
exact hf
theorem leadingCoeff_map_of_leadingCoeff_ne_zero (f : R →+* S) (hf : f (leadingCoeff p) ≠ 0) :
    leadingCoeff (p.map f) = f (leadingCoeff p) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
hf : f (leadingCoeff p) ≠ 0
⊢ leadingCoeff (map f p) = f (leadingCoeff p)

Next tactic:
unfold leadingCoeff
theorem leadingCoeff_map_of_leadingCoeff_ne_zero (f : R →+* S) (hf : f (leadingCoeff p) ≠ 0) :
    leadingCoeff (p.map f) = f (leadingCoeff p) := by
  unfold leadingCoeff
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
hf : f (leadingCoeff p) ≠ 0
⊢ coeff (map f p) (natDegree (map f p)) = f (coeff p (natDegree p))

Next tactic:
rw [coeff_map, natDegree_map_of_leadingCoeff_ne_zero f hf]
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
⊢ p ∈ RingHom.rangeS (mapRingHom f) ↔ ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f

Next tactic:
constructor
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · 

Proof state:
case mp
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
⊢ p ∈ RingHom.rangeS (mapRingHom f) → ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f

Next tactic:
rintro ⟨p, rfl⟩ n
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    

Proof state:
case mp.intro
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
n : ℕ
⊢ coeff ((mapRingHom f) p) n ∈ RingHom.rangeS f

Next tactic:
rw [coe_mapRingHom, coeff_map]
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    

Proof state:
case mp.intro
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
n : ℕ
⊢ f (coeff p n) ∈ RingHom.rangeS f

Next tactic:
exact Set.mem_range_self _
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    exact Set.mem_range_self _
  · 

Proof state:
case mpr
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
⊢ (∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f) → p ∈ RingHom.rangeS (mapRingHom f)

Next tactic:
intro h
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    exact Set.mem_range_self _
  · intro h
    

Proof state:
case mpr
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
h : ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f
⊢ p ∈ RingHom.rangeS (mapRingHom f)

Next tactic:
rw [p.as_sum_range_C_mul_X_pow]
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    exact Set.mem_range_self _
  · intro h
    rw [p.as_sum_range_C_mul_X_pow]
    

Proof state:
case mpr
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
h : ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f
⊢ ∑ i in range (natDegree p + 1), C (coeff p i) * X ^ i ∈ RingHom.rangeS (mapRingHom f)

Next tactic:
refine' (mapRingHom f).rangeS.sum_mem _
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    exact Set.mem_range_self _
  · intro h
    rw [p.as_sum_range_C_mul_X_pow]
    refine' (mapRingHom f).rangeS.sum_mem _
    

Proof state:
case mpr
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
h : ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f
⊢ ∀ c ∈ range (natDegree p + 1), C (coeff p c) * X ^ c ∈ RingHom.rangeS (mapRingHom f)

Next tactic:
intro i _hi
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    exact Set.mem_range_self _
  · intro h
    rw [p.as_sum_range_C_mul_X_pow]
    refine' (mapRingHom f).rangeS.sum_mem _
    intro i _hi
    

Proof state:
case mpr
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
h : ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f
i : ℕ
_hi : i ∈ range (natDegree p + 1)
⊢ C (coeff p i) * X ^ i ∈ RingHom.rangeS (mapRingHom f)

Next tactic:
rcases h i with ⟨c, hc⟩
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    exact Set.mem_range_self _
  · intro h
    rw [p.as_sum_range_C_mul_X_pow]
    refine' (mapRingHom f).rangeS.sum_mem _
    intro i _hi
    rcases h i with ⟨c, hc⟩
    

Proof state:
case mpr.intro
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
h : ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f
i : ℕ
_hi : i ∈ range (natDegree p + 1)
c : R
hc : f c = coeff p i
⊢ C (coeff p i) * X ^ i ∈ RingHom.rangeS (mapRingHom f)

Next tactic:
use C c * X ^ i
theorem mem_map_rangeS {p : S[X]} : p ∈ (mapRingHom f).rangeS ↔ ∀ n, p.coeff n ∈ f.rangeS := by
  constructor
  · rintro ⟨p, rfl⟩ n
    rw [coe_mapRingHom, coeff_map]
    exact Set.mem_range_self _
  · intro h
    rw [p.as_sum_range_C_mul_X_pow]
    refine' (mapRingHom f).rangeS.sum_mem _
    intro i _hi
    rcases h i with ⟨c, hc⟩
    use C c * X ^ i
    

Proof state:
case h
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : S[X]
h : ∀ (n : ℕ), coeff p n ∈ RingHom.rangeS f
i : ℕ
_hi : i ∈ range (natDegree p + 1)
c : R
hc : f c = coeff p i
⊢ (mapRingHom f) (C c * X ^ i) = C (coeff p i) * X ^ i

Next tactic:
rw [coe_mapRingHom, Polynomial.map_mul, map_C, hc, Polynomial.map_pow, map_X]
theorem eval₂_map [Semiring T] (g : S →+* T) (x : T) : (p.map f).eval₂ g x = p.eval₂ (g.comp f) x :=
  by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝² : Semiring R
p q r : R[X]
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Semiring T
g : S →+* T
x : T
⊢ eval₂ g x (map f p) = eval₂ (RingHom.comp g f) x p

Next tactic:
rw [eval₂_eq_eval_map, eval₂_eq_eval_map, map_map]
theorem map_comp (p q : R[X]) : map f (p.comp q) = (map f p).comp (map f q) :=
  Polynomial.induction_on p (by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q✝ r : R[X]
inst✝ : Semiring S
f : R →+* S
p q : R[X]
⊢ ∀ (a : R), map f (comp (C a) q) = comp (map f (C a)) (map f q)

Next tactic:
simp only [map_C, forall_const, C_comp, eq_self_iff_true]
theorem map_comp (p q : R[X]) : map f (p.comp q) = (map f p).comp (map f q) :=
  Polynomial.induction_on p (by simp only [map_C, forall_const, C_comp, eq_self_iff_true])
    (by
      

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q✝ r : R[X]
inst✝ : Semiring S
f : R →+* S
p q : R[X]
⊢ ∀ (p q_1 : R[X]),
    map f (comp p q) = comp (map f p) (map f q) →
      map f (comp q_1 q) = comp (map f q_1) (map f q) → map f (comp (p + q_1) q) = comp (map f (p + q_1)) (map f q)

Next tactic:
simp (config := { contextual := true }) only [Polynomial.map_add, add_comp, forall_const,
        imp_true_iff, eq_self_iff_true]
theorem map_comp (p q : R[X]) : map f (p.comp q) = (map f p).comp (map f q) :=
  Polynomial.induction_on p (by simp only [map_C, forall_const, C_comp, eq_self_iff_true])
    (by
      simp (config := { contextual := true }) only [Polynomial.map_add, add_comp, forall_const,
        imp_true_iff, eq_self_iff_true])
    (by
      

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q✝ r : R[X]
inst✝ : Semiring S
f : R →+* S
p q : R[X]
⊢ ∀ (n : ℕ) (a : R),
    map f (comp (C a * X ^ n) q) = comp (map f (C a * X ^ n)) (map f q) →
      map f (comp (C a * X ^ (n + 1)) q) = comp (map f (C a * X ^ (n + 1))) (map f q)

Next tactic:
simp (config := { contextual := true }) only [pow_succ', ← mul_assoc, comp, forall_const,
        eval₂_mul_X, imp_true_iff, eq_self_iff_true, map_X, Polynomial.map_mul]
@[simp]
theorem eval_zero_map (f : R →+* S) (p : R[X]) : (p.map f).eval 0 = f (p.eval 0) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
p : R[X]
⊢ eval 0 (map f p) = f (eval 0 p)

Next tactic:
simp [← coeff_zero_eq_eval_zero]
@[simp]
theorem eval_one_map (f : R →+* S) (p : R[X]) : (p.map f).eval 1 = f (p.eval 1) := by
  -- Porting note: `apply` → `induction`
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f✝ f : R →+* S
p : R[X]
⊢ eval 1 (map f p) = f (eval 1 p)

Next tactic:
induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp only [hp, hq, Polynomial.map_add, RingHom.map_add, eval_add]
  | h_monomial n r =>
    simp only [one_pow, mul_one, eval_monomial, map_monomial]