Module docstring
{"# Theory of univariate polynomials
We show that A[X] is an R-algebra when A is an R-algebra.
We promote eval₂ to an algebra hom in aeval.
"}
{"# Theory of univariate polynomials
We show that A[X] is an R-algebra when A is an R-algebra.
We promote eval₂ to an algebra hom in aeval.
"}
Polynomial.algebraOfAlgebra
instance
: Algebra R A[X]
/-- Note that this instance also provides `Algebra R R[X]`. -/
instance algebraOfAlgebra : Algebra R A[X] where
smul_def' r p :=
toFinsupp_injective <| by
dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply]
rw [toFinsupp_smul, toFinsupp_mul, toFinsupp_C]
exact Algebra.smul_def' _ _
commutes' r p :=
toFinsupp_injective <| by
dsimp only [RingHom.toFun_eq_coe, RingHom.comp_apply]
simp_rw [toFinsupp_mul, toFinsupp_C]
convert Algebra.commutes' r p.toFinsupp
algebraMap := C.comp (algebraMap R A)
Polynomial.algebraMap_apply
theorem
(r : R) : algebraMap R A[X] r = C (algebraMap R A r)
@[simp]
theorem algebraMap_apply (r : R) : algebraMap R A[X] r = C (algebraMap R A r) :=
rfl
Polynomial.toFinsupp_algebraMap
theorem
(r : R) : (algebraMap R A[X] r).toFinsupp = algebraMap R _ r
@[simp]
theorem toFinsupp_algebraMap (r : R) : (algebraMap R A[X] r).toFinsupp = algebraMap R _ r :=
show toFinsupp (C (algebraMap _ _ r)) = _ by
rw [toFinsupp_C]
rfl
Polynomial.ofFinsupp_algebraMap
theorem
(r : R) : (⟨algebraMap R _ r⟩ : A[X]) = algebraMap R A[X] r
theorem ofFinsupp_algebraMap (r : R) : (⟨algebraMap R _ r⟩ : A[X]) = algebraMap R A[X] r :=
toFinsupp_injective (toFinsupp_algebraMap _).symm
Polynomial.C_eq_algebraMap
theorem
(r : R) : C r = algebraMap R R[X] r
/-- When we have `[CommSemiring R]`, the function `C` is the same as `algebraMap R R[X]`.
(But note that `C` is defined when `R` is not necessarily commutative, in which case
`algebraMap` is not available.)
-/
theorem C_eq_algebraMap (r : R) : C r = algebraMap R R[X] r :=
rfl
Polynomial.algebraMap_eq
theorem
: algebraMap R R[X] = C
@[simp]
theorem algebraMap_eq : algebraMap R R[X] = C :=
rfl
Polynomial.CAlgHom
definition
: A →ₐ[R] A[X]
/-- `Polynomial.C` as an `AlgHom`. -/
@[simps! apply]
def CAlgHom : A →ₐ[R] A[X] where
toRingHom := C
commutes' _ := rfl
Polynomial.algHom_ext'
theorem
{f g : A[X] →ₐ[R] B} (hC : f.comp CAlgHom = g.comp CAlgHom) (hX : f X = g X) : f = g
/-- Extensionality lemma for algebra maps out of `A'[X]` over a smaller base ring than `A'`
-/
@[ext 1100]
theorem algHom_ext' {f g : A[X]A[X] →ₐ[R] B}
(hC : f.comp CAlgHom = g.comp CAlgHom)
(hX : f X = g X) : f = g :=
AlgHom.coe_ringHom_injective (ringHom_ext' (congr_arg AlgHom.toRingHom hC) hX)
Polynomial.toFinsuppIsoAlg
definition
: R[X] ≃ₐ[R] R[ℕ]
/-- Algebra isomorphism between `R[X]` and `R[ℕ]`. This is just an
implementation detail, but it can be useful to transfer results from `Finsupp` to polynomials. -/
@[simps!]
def toFinsuppIsoAlg : R[X]R[X] ≃ₐ[R] R[ℕ] :=
{ toFinsuppIso R with
commutes' := fun r => by
dsimp }
Polynomial.subalgebraNontrivial
instance
[Nontrivial A] : Nontrivial (Subalgebra R A[X])
instance subalgebraNontrivial [Nontrivial A] : Nontrivial (Subalgebra R A[X]) :=
⟨⟨⊥, ⊤, by
rw [Ne, SetLike.ext_iff, not_forall]
refine ⟨X, ?_⟩
simp only [Algebra.mem_bot, not_exists, Set.mem_range, iff_true, Algebra.mem_top,
algebraMap_apply, not_forall]
intro x
rw [ext_iff, not_forall]
refine ⟨1, ?_⟩
simp [coeff_C]⟩⟩
Polynomial.algHom_eval₂_algebraMap
theorem
{R A B : Type*} [CommSemiring R] [Semiring A] [Semiring B] [Algebra R A] [Algebra R B] (p : R[X]) (f : A →ₐ[R] B)
(a : A) : f (eval₂ (algebraMap R A) a p) = eval₂ (algebraMap R B) (f a) p
@[simp]
theorem algHom_eval₂_algebraMap {R A B : Type*} [CommSemiring R] [Semiring A] [Semiring B]
[Algebra R A] [Algebra R B] (p : R[X]) (f : A →ₐ[R] B) (a : A) :
f (eval₂ (algebraMap R A) a p) = eval₂ (algebraMap R B) (f a) p := by
simp only [eval₂_eq_sum, sum_def]
simp only [map_sum, map_mul, map_pow, eq_intCast, map_intCast, AlgHom.commutes]
Polynomial.eval₂_algebraMap_X
theorem
{R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (p : R[X]) (f : R[X] →ₐ[R] A) :
eval₂ (algebraMap R A) (f X) p = f p
@[simp]
theorem eval₂_algebraMap_X {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (p : R[X])
(f : R[X]R[X] →ₐ[R] A) : eval₂ (algebraMap R A) (f X) p = f p := by
conv_rhs => rw [← Polynomial.sum_C_mul_X_pow_eq p]
simp only [eval₂_eq_sum, sum_def]
simp only [map_sum, map_mul, map_pow, eq_intCast, map_intCast]
simp [Polynomial.C_eq_algebraMap]
Polynomial.ringHom_eval₂_intCastRingHom
theorem
{R S : Type*} [Ring R] [Ring S] (p : ℤ[X]) (f : R →+* S) (r : R) :
f (eval₂ (Int.castRingHom R) r p) = eval₂ (Int.castRingHom S) (f r) p
@[simp]
theorem ringHom_eval₂_intCastRingHom {R S : Type*} [Ring R] [Ring S] (p : ℤℤ[X]) (f : R →+* S)
(r : R) : f (eval₂ (Int.castRingHom R) r p) = eval₂ (Int.castRingHom S) (f r) p :=
algHom_eval₂_algebraMap p f.toIntAlgHom r
Polynomial.eval₂_intCastRingHom_X
theorem
{R : Type*} [Ring R] (p : ℤ[X]) (f : ℤ[X] →+* R) : eval₂ (Int.castRingHom R) (f X) p = f p
@[simp]
theorem eval₂_intCastRingHom_X {R : Type*} [Ring R] (p : ℤℤ[X]) (f : ℤℤ[X]ℤ[X] →+* R) :
eval₂ (Int.castRingHom R) (f X) p = f p :=
eval₂_algebraMap_X p f.toIntAlgHom
Polynomial.eval₂AlgHom'
definition
(f : A →ₐ[R] B) (b : B) (hf : ∀ a, Commute (f a) b) : A[X] →ₐ[R] B
/-- `Polynomial.eval₂` as an `AlgHom` for noncommutative algebras.
This is `Polynomial.eval₂RingHom'` for `AlgHom`s. -/
@[simps!]
def eval₂AlgHom' (f : A →ₐ[R] B) (b : B) (hf : ∀ a, Commute (f a) b) : A[X]A[X] →ₐ[R] B where
toRingHom := eval₂RingHom' f b hf
commutes' _ := (eval₂_C _ _).trans (f.commutes _)
Polynomial.mapAlgHom
definition
(f : A →ₐ[R] B) : Polynomial A →ₐ[R] Polynomial B
/-- `Polynomial.map` as an `AlgHom` for noncommutative algebras.
This is the algebra version of `Polynomial.mapRingHom`. -/
def mapAlgHom (f : A →ₐ[R] B) : PolynomialPolynomial A →ₐ[R] Polynomial B where
toRingHom := mapRingHom f.toRingHom
commutes' := by simp
Polynomial.coe_mapAlgHom
theorem
(f : A →ₐ[R] B) : ⇑(mapAlgHom f) = map f
@[simp]
theorem coe_mapAlgHom (f : A →ₐ[R] B) : ⇑(mapAlgHom f) = map f :=
rfl
Polynomial.mapAlgHom_id
theorem
: mapAlgHom (AlgHom.id R A) = AlgHom.id R (Polynomial A)
@[simp]
theorem mapAlgHom_id : mapAlgHom (AlgHom.id R A) = AlgHom.id R (Polynomial A) :=
AlgHom.ext fun _x => map_id
Polynomial.mapAlgHom_coe_ringHom
theorem
(f : A →ₐ[R] B) : ↑(mapAlgHom f : _ →ₐ[R] Polynomial B) = (mapRingHom ↑f : Polynomial A →+* Polynomial B)
@[simp]
theorem mapAlgHom_coe_ringHom (f : A →ₐ[R] B) :
↑(mapAlgHom f : _ →ₐ[R] Polynomial B) = (mapRingHom ↑f : PolynomialPolynomial A →+* Polynomial B) :=
rfl
Polynomial.mapAlgHom_comp
theorem
(C : Type z) [Semiring C] [Algebra R C] (f : B →ₐ[R] C) (g : A →ₐ[R] B) :
(mapAlgHom f).comp (mapAlgHom g) = mapAlgHom (f.comp g)
@[simp]
theorem mapAlgHom_comp (C : Type z) [Semiring C] [Algebra R C] (f : B →ₐ[R] C) (g : A →ₐ[R] B) :
(mapAlgHom f).comp (mapAlgHom g) = mapAlgHom (f.comp g) := by
apply AlgHom.ext
intro x
simp [AlgHom.comp_algebraMap, map_map]
congr
Polynomial.mapAlgHom_eq_eval₂AlgHom'_CAlgHom
theorem
(f : A →ₐ[R] B) : mapAlgHom f = eval₂AlgHom' (CAlgHom.comp f) X (fun a => (commute_X (C (f a))).symm)
theorem mapAlgHom_eq_eval₂AlgHom'_CAlgHom (f : A →ₐ[R] B) : mapAlgHom f = eval₂AlgHom'
(CAlgHom.comp f) X (fun a => (commute_X (C (f a))).symm) := by
apply AlgHom.ext
intro x
congr
Polynomial.mapAlgEquiv
definition
(f : A ≃ₐ[R] B) : Polynomial A ≃ₐ[R] Polynomial B
/-- If `A` and `B` are isomorphic as `R`-algebras, then so are their polynomial rings -/
def mapAlgEquiv (f : A ≃ₐ[R] B) : PolynomialPolynomial A ≃ₐ[R] Polynomial B :=
AlgEquiv.ofAlgHom (mapAlgHom f.toAlgHom) (mapAlgHom f.symm.toAlgHom) (by simp) (by simp)
Polynomial.coe_mapAlgEquiv
theorem
(f : A ≃ₐ[R] B) : ⇑(mapAlgEquiv f) = map f
@[simp]
theorem coe_mapAlgEquiv (f : A ≃ₐ[R] B) : ⇑(mapAlgEquiv f) = map f :=
rfl
Polynomial.mapAlgEquiv_id
theorem
: mapAlgEquiv (@AlgEquiv.refl R A _ _ _) = AlgEquiv.refl
@[simp]
theorem mapAlgEquiv_id : mapAlgEquiv (@AlgEquiv.refl R A _ _ _) = AlgEquiv.refl :=
AlgEquiv.ext fun _x => map_id
Polynomial.mapAlgEquiv_coe_ringHom
theorem
(f : A ≃ₐ[R] B) : ↑(mapAlgEquiv f : _ ≃ₐ[R] Polynomial B) = (mapRingHom ↑f : Polynomial A →+* Polynomial B)
@[simp]
theorem mapAlgEquiv_coe_ringHom (f : A ≃ₐ[R] B) :
↑(mapAlgEquiv f : _ ≃ₐ[R] Polynomial B) = (mapRingHom ↑f : PolynomialPolynomial A →+* Polynomial B) :=
rfl
Polynomial.mapAlgEquiv_toAlgHom
theorem
(f : A ≃ₐ[R] B) : (mapAlgEquiv f : Polynomial A →ₐ[R] Polynomial B) = mapAlgHom f
@[simp]
theorem mapAlgEquiv_toAlgHom (f : A ≃ₐ[R] B) :
(mapAlgEquiv f : PolynomialPolynomial A →ₐ[R] Polynomial B) = mapAlgHom f := rfl
Polynomial.mapAlgEquiv_comp
theorem
(C : Type*) [Semiring C] [Algebra R C] (f : A ≃ₐ[R] B) (g : B ≃ₐ[R] C) :
(mapAlgEquiv f).trans (mapAlgEquiv g) = mapAlgEquiv (f.trans g)
@[simp]
theorem mapAlgEquiv_comp (C : Type*) [Semiring C] [Algebra R C] (f : A ≃ₐ[R] B) (g : B ≃ₐ[R] C) :
(mapAlgEquiv f).trans (mapAlgEquiv g) = mapAlgEquiv (f.trans g) := by
apply AlgEquiv.ext
intro x
simp [AlgEquiv.trans_apply, map_map]
congr
Polynomial.aeval
definition
: R[X] →ₐ[R] A
/-- Given a valuation `x` of the variable in an `R`-algebra `A`, `aeval R A x` is
the unique `R`-algebra homomorphism from `R[X]` to `A` sending `X` to `x`.
This is a stronger variant of the linear map `Polynomial.leval`. -/
def aeval : R[X]R[X] →ₐ[R] A :=
eval₂AlgHom' (Algebra.ofId _ _) x (Algebra.commutes · _)
Polynomial.algHom_ext
theorem
{f g : R[X] →ₐ[R] B} (hX : f X = g X) : f = g
@[ext 1200]
theorem algHom_ext {f g : R[X]R[X] →ₐ[R] B} (hX : f X = g X) :
f = g :=
algHom_ext' (Subsingleton.elim _ _) hX
Polynomial.aeval_def
theorem
(p : R[X]) : aeval x p = eval₂ (algebraMap R A) x p
Polynomial.aeval_zero
theorem
: aeval x (0 : R[X]) = 0
theorem aeval_zero : aeval x (0 : R[X]) = 0 :=
map_zero (aeval x)
Polynomial.aeval_X
theorem
: aeval x (X : R[X]) = x
Polynomial.aeval_C
theorem
(r : R) : aeval x (C r) = algebraMap R A r
@[simp]
theorem aeval_C (r : R) : aeval x (C r) = algebraMap R A r :=
eval₂_C _ x
Polynomial.aeval_monomial
theorem
{n : ℕ} {r : R} : aeval x (monomial n r) = algebraMap _ _ r * x ^ n
@[simp]
theorem aeval_monomial {n : ℕ} {r : R} : aeval x (monomial n r) = algebraMap _ _ r * x ^ n :=
eval₂_monomial _ _
Polynomial.aeval_X_pow
theorem
{n : ℕ} : aeval x ((X : R[X]) ^ n) = x ^ n
theorem aeval_X_pow {n : ℕ} : aeval x ((X : R[X]) ^ n) = x ^ n :=
eval₂_X_pow _ _
Polynomial.aeval_add
theorem
: aeval x (p + q) = aeval x p + aeval x q
Polynomial.aeval_one
theorem
: aeval x (1 : R[X]) = 1
Polynomial.aeval_natCast
theorem
(n : ℕ) : aeval x (n : R[X]) = n
theorem aeval_natCast (n : ℕ) : aeval x (n : R[X]) = n :=
map_natCast _ _
Polynomial.aeval_mul
theorem
: aeval x (p * q) = aeval x p * aeval x q
Polynomial.comp_eq_aeval
theorem
: p.comp q = aeval q p
theorem comp_eq_aeval : p.comp q = aeval q p := rfl
Polynomial.aeval_comp
theorem
{A : Type*} [Semiring A] [Algebra R A] (x : A) : aeval x (p.comp q) = aeval (aeval x q) p
theorem aeval_comp {A : Type*} [Semiring A] [Algebra R A] (x : A) :
aeval x (p.comp q) = aeval (aeval x q) p :=
eval₂_comp' x p q
Polynomial.algEquivOfCompEqX
definition
(p q : R[X]) (hpq : p.comp q = X) (hqp : q.comp p = X) : R[X] ≃ₐ[R] R[X]
/-- Two polynomials `p` and `q` such that `p(q(X))=X` and `q(p(X))=X`
induces an automorphism of the polynomial algebra. -/
@[simps!]
def algEquivOfCompEqX (p q : R[X]) (hpq : p.comp q = X) (hqp : q.comp p = X) : R[X]R[X] ≃ₐ[R] R[X] := by
refine AlgEquiv.ofAlgHom (aeval p) (aeval q) ?_ ?_ <;>
exact AlgHom.ext fun _ ↦ by simp [← comp_eq_aeval, comp_assoc, hpq, hqp]
Polynomial.algEquivOfCompEqX_eq_iff
theorem
(p q p' q' : R[X]) (hpq : p.comp q = X) (hqp : q.comp p = X) (hpq' : p'.comp q' = X) (hqp' : q'.comp p' = X) :
algEquivOfCompEqX p q hpq hqp = algEquivOfCompEqX p' q' hpq' hqp' ↔ p = p'
@[simp]
theorem algEquivOfCompEqX_eq_iff (p q p' q' : R[X])
(hpq : p.comp q = X) (hqp : q.comp p = X) (hpq' : p'.comp q' = X) (hqp' : q'.comp p' = X) :
algEquivOfCompEqXalgEquivOfCompEqX p q hpq hqp = algEquivOfCompEqX p' q' hpq' hqp' ↔ p = p' :=
⟨fun h ↦ by simpa using congr($h X), fun h ↦ by ext1; simp [h]⟩
Polynomial.algEquivOfCompEqX_symm
theorem
(p q : R[X]) (hpq : p.comp q = X) (hqp : q.comp p = X) :
(algEquivOfCompEqX p q hpq hqp).symm = algEquivOfCompEqX q p hqp hpq
@[simp]
theorem algEquivOfCompEqX_symm (p q : R[X]) (hpq : p.comp q = X) (hqp : q.comp p = X) :
(algEquivOfCompEqX p q hpq hqp).symm = algEquivOfCompEqX q p hqp hpq := rfl
Polynomial.algEquivCMulXAddC
definition
{R : Type*} [CommRing R] (a b : R) [Invertible a] : R[X] ≃ₐ[R] R[X]
/-- The automorphism of the polynomial algebra given by `p(X) ↦ p(a * X + b)`,
with inverse `p(X) ↦ p(a⁻¹ * (X - b))`. -/
@[simps!]
def algEquivCMulXAddC {R : Type*} [CommRing R] (a b : R) [Invertible a] : R[X]R[X] ≃ₐ[R] R[X] :=
algEquivOfCompEqX (C a * X + C b) (C ⅟ a * (X - C b))
(by simp [← C_mul, ← mul_assoc]) (by simp [← C_mul, ← mul_assoc])
Polynomial.algEquivCMulXAddC_symm_eq
theorem
{R : Type*} [CommRing R] (a b : R) [Invertible a] : (algEquivCMulXAddC a b).symm = algEquivCMulXAddC (⅟ a) (-⅟ a * b)
theorem algEquivCMulXAddC_symm_eq {R : Type*} [CommRing R] (a b : R) [Invertible a] :
(algEquivCMulXAddC a b).symm = algEquivCMulXAddC (⅟ a) (- ⅟ a * b) := by
ext p : 1
simp only [algEquivCMulXAddC_symm_apply, neg_mul, algEquivCMulXAddC_apply, map_neg, map_mul]
congr
simp [mul_add, sub_eq_add_neg]
Polynomial.algEquivAevalXAddC
definition
{R : Type*} [CommRing R] (t : R) : R[X] ≃ₐ[R] R[X]
/-- The automorphism of the polynomial algebra given by `p(X) ↦ p(X+t)`,
with inverse `p(X) ↦ p(X-t)`. -/
@[simps!]
def algEquivAevalXAddC {R : Type*} [CommRing R] (t : R) : R[X]R[X] ≃ₐ[R] R[X] :=
algEquivOfCompEqX (X + C t) (X - C t) (by simp) (by simp)
Polynomial.algEquivAevalXAddC_eq_iff
theorem
{R : Type*} [CommRing R] (t t' : R) : algEquivAevalXAddC t = algEquivAevalXAddC t' ↔ t = t'
@[simp]
theorem algEquivAevalXAddC_eq_iff {R : Type*} [CommRing R] (t t' : R) :
algEquivAevalXAddCalgEquivAevalXAddC t = algEquivAevalXAddC t' ↔ t = t' := by
simp [algEquivAevalXAddC]
Polynomial.algEquivAevalXAddC_symm
theorem
{R : Type*} [CommRing R] (t : R) : (algEquivAevalXAddC t).symm = algEquivAevalXAddC (-t)
@[simp]
theorem algEquivAevalXAddC_symm {R : Type*} [CommRing R] (t : R) :
(algEquivAevalXAddC t).symm = algEquivAevalXAddC (-t) := by
simp [algEquivAevalXAddC, sub_eq_add_neg]
Polynomial.algEquivAevalNegX
definition
{R : Type*} [CommRing R] : R[X] ≃ₐ[R] R[X]
/-- The involutive automorphism of the polynomial algebra given by `p(X) ↦ p(-X)`. -/
@[simps!]
def algEquivAevalNegX {R : Type*} [CommRing R] : R[X]R[X] ≃ₐ[R] R[X] :=
algEquivOfCompEqX (-X) (-X) (by simp) (by simp)
Polynomial.comp_neg_X_comp_neg_X
theorem
{R : Type*} [CommRing R] (p : R[X]) : (p.comp (-X)).comp (-X) = p
Polynomial.aeval_algHom
theorem
(f : A →ₐ[R] B) (x : A) : aeval (f x) = f.comp (aeval x)
theorem aeval_algHom (f : A →ₐ[R] B) (x : A) : aeval (f x) = f.comp (aeval x) :=
algHom_ext <| by simp only [aeval_X, AlgHom.comp_apply]
Polynomial.aeval_X_left
theorem
: aeval (X : R[X]) = AlgHom.id R R[X]
@[simp]
theorem aeval_X_left : aeval (X : R[X]) = AlgHom.id R R[X] :=
algHom_ext <| aeval_X X
Polynomial.aeval_X_left_apply
theorem
(p : R[X]) : aeval X p = p
theorem aeval_X_left_apply (p : R[X]) : aeval X p = p :=
AlgHom.congr_fun (@aeval_X_left R _) p
Polynomial.eval_unique
theorem
(φ : R[X] →ₐ[R] A) (p) : φ p = eval₂ (algebraMap R A) (φ X) p
theorem eval_unique (φ : R[X]R[X] →ₐ[R] A) (p) : φ p = eval₂ (algebraMap R A) (φ X) p := by
rw [← aeval_def, aeval_algHom, aeval_X_left, AlgHom.comp_id]
Polynomial.aeval_algHom_apply
theorem
{F : Type*} [FunLike F A B] [AlgHomClass F R A B] (f : F) (x : A) (p : R[X]) : aeval (f x) p = f (aeval x p)
theorem aeval_algHom_apply {F : Type*} [FunLike F A B] [AlgHomClass F R A B]
(f : F) (x : A) (p : R[X]) :
aeval (f x) p = f (aeval x p) := by
refine Polynomial.induction_on p (by simp [AlgHomClass.commutes]) (fun p q hp hq => ?_)
(by simp [AlgHomClass.commutes])
rw [map_add, hp, hq, ← map_add, ← map_add]
Polynomial.coe_aeval_mk_apply
theorem
{S : Subalgebra R A} (h : x ∈ S) : (aeval (⟨x, h⟩ : S) p : A) = aeval x p
@[simp]
lemma coe_aeval_mk_apply {S : Subalgebra R A} (h : x ∈ S) :
(aeval (⟨x, h⟩ : S) p : A) = aeval x p :=
(aeval_algHom_apply S.val (⟨x, h⟩ : S) p).symm
Polynomial.aeval_algEquiv
theorem
(f : A ≃ₐ[R] B) (x : A) : aeval (f x) = (f : A →ₐ[R] B).comp (aeval x)
theorem aeval_algEquiv (f : A ≃ₐ[R] B) (x : A) : aeval (f x) = (f : A →ₐ[R] B).comp (aeval x) :=
aeval_algHom (f : A →ₐ[R] B) x
Polynomial.aeval_algebraMap_apply_eq_algebraMap_eval
theorem
(x : R) (p : R[X]) : aeval (algebraMap R A x) p = algebraMap R A (p.eval x)
theorem aeval_algebraMap_apply_eq_algebraMap_eval (x : R) (p : R[X]) :
aeval (algebraMap R A x) p = algebraMap R A (p.eval x) :=
aeval_algHom_apply (Algebra.ofId R A) x p
Polynomial.aeval_prod
theorem
(x : A × B) : aeval (R := R) x = (aeval x.1).prod (aeval x.2)
Polynomial.aeval_prod_apply
theorem
(x : A × B) (p : Polynomial R) : p.aeval x = (p.aeval x.1, p.aeval x.2)
/-- Polynomial evaluation on a pair is a pair of evaluations. -/
theorem aeval_prod_apply (x : A × B) (p : Polynomial R) :
p.aeval x = (p.aeval x.1, p.aeval x.2) := by simp [aeval_prod]
Polynomial.aeval_pi
theorem
(x : Π i, A i) : aeval (R := R) x = Pi.algHom R A (fun i ↦ aeval (x i))
/-- Polynomial evaluation on an indexed tuple is the indexed product of the evaluations
on the components.
Generalizes `Polynomial.aeval_prod` to indexed products. -/
theorem aeval_pi (x : Π i, A i) : aeval (R := R) x = Pi.algHom R A (fun i ↦ aeval (x i)) :=
(funext fun i ↦ aeval_algHom (Pi.evalAlgHom R A i) x) ▸
(Pi.algHom_comp R A (Pi.evalAlgHom R A) (aeval x))
Polynomial.aeval_pi_apply₂
theorem
(j : I) : p.aeval x j = p.aeval (x j)
theorem aeval_pi_apply₂ (j : I) : p.aeval x j = p.aeval (x j) :=
aeval_pi (R := R) x ▸ Pi.algHom_apply R A (fun i ↦ aeval (x i)) p j
Polynomial.aeval_pi_apply
theorem
: p.aeval x = fun j ↦ p.aeval (x j)
/-- Polynomial evaluation on an indexed tuple is the indexed tuple of the evaluations
on the components.
Generalizes `Polynomial.aeval_prod_apply` to indexed products. -/
theorem aeval_pi_apply : p.aeval x = fun j ↦ p.aeval (x j) :=
funext fun j ↦ aeval_pi_apply₂ x p j
Polynomial.coe_aeval_eq_eval
theorem
(r : R) : (aeval r : R[X] → R) = eval r
@[simp]
theorem coe_aeval_eq_eval (r : R) : (aeval r : R[X] → R) = eval r :=
rfl
Polynomial.coe_aeval_eq_evalRingHom
theorem
(x : R) : ((aeval x : R[X] →ₐ[R] R) : R[X] →+* R) = evalRingHom x
@[simp]
theorem coe_aeval_eq_evalRingHom (x : R) :
((aeval x : R[X]R[X] →ₐ[R] R) : R[X]R[X] →+* R) = evalRingHom x :=
rfl
Polynomial.aeval_fn_apply
theorem
{X : Type*} (g : R[X]) (f : X → R) (x : X) : ((aeval f) g) x = aeval (f x) g
@[simp]
theorem aeval_fn_apply {X : Type*} (g : R[X]) (f : X → R) (x : X) :
((aeval f) g) x = aeval (f x) g :=
(aeval_algHom_apply (Pi.evalAlgHom R (fun _ => R) x) f g).symm
Polynomial.aeval_subalgebra_coe
theorem
(g : R[X]) {A : Type*} [Semiring A] [Algebra R A] (s : Subalgebra R A) (f : s) : (aeval f g : A) = aeval (f : A) g
@[norm_cast]
theorem aeval_subalgebra_coe (g : R[X]) {A : Type*} [Semiring A] [Algebra R A] (s : Subalgebra R A)
(f : s) : (aeval f g : A) = aeval (f : A) g :=
(aeval_algHom_apply s.val f g).symm
Polynomial.coeff_zero_eq_aeval_zero
theorem
(p : R[X]) : p.coeff 0 = aeval 0 p
theorem coeff_zero_eq_aeval_zero (p : R[X]) : p.coeff 0 = aeval 0 p := by
simp [coeff_zero_eq_eval_zero]
Polynomial.coeff_zero_eq_aeval_zero'
theorem
(p : R[X]) : algebraMap R A (p.coeff 0) = aeval (0 : A) p
theorem coeff_zero_eq_aeval_zero' (p : R[X]) : algebraMap R A (p.coeff 0) = aeval (0 : A) p := by
simp [aeval_def]
Polynomial.map_aeval_eq_aeval_map
theorem
{S T U : Type*} [Semiring S] [CommSemiring T] [Semiring U] [Algebra R S] [Algebra T U] {φ : R →+* T} {ψ : S →+* U}
(h : (algebraMap T U).comp φ = ψ.comp (algebraMap R S)) (p : R[X]) (a : S) : ψ (aeval a p) = aeval (ψ a) (p.map φ)
theorem map_aeval_eq_aeval_map {S T U : Type*} [Semiring S] [CommSemiring T] [Semiring U]
[Algebra R S] [Algebra T U] {φ : R →+* T} {ψ : S →+* U}
(h : (algebraMap T U).comp φ = ψ.comp (algebraMap R S)) (p : R[X]) (a : S) :
ψ (aeval a p) = aeval (ψ a) (p.map φ) := by
conv_rhs => rw [aeval_def, ← eval_map]
rw [map_map, h, ← map_map, eval_map, eval₂_at_apply, aeval_def, eval_map]
Polynomial.aeval_eq_zero_of_dvd_aeval_eq_zero
theorem
[CommSemiring S] [CommSemiring T] [Algebra S T] {p q : S[X]} (h₁ : p ∣ q) {a : T} (h₂ : aeval a p = 0) : aeval a q = 0
theorem aeval_eq_zero_of_dvd_aeval_eq_zero [CommSemiring S] [CommSemiring T] [Algebra S T]
{p q : S[X]} (h₁ : p ∣ q) {a : T} (h₂ : aeval a p = 0) : aeval a q = 0 := by
rw [aeval_def, ← eval_map] at h₂ ⊢
exact eval_eq_zero_of_dvd_of_eval_eq_zero (Polynomial.map_dvd (algebraMap S T) h₁) h₂
Polynomial.aeval_eq_sum_range
theorem
[Algebra R S] {p : R[X]} (x : S) : aeval x p = ∑ i ∈ Finset.range (p.natDegree + 1), p.coeff i • x ^ i
theorem aeval_eq_sum_range [Algebra R S] {p : R[X]} (x : S) :
aeval x p = ∑ i ∈ Finset.range (p.natDegree + 1), p.coeff i • x ^ i := by
simp_rw [Algebra.smul_def]
exact eval₂_eq_sum_range (algebraMap R S) x
Polynomial.aeval_eq_sum_range'
theorem
[Algebra R S] {p : R[X]} {n : ℕ} (hn : p.natDegree < n) (x : S) : aeval x p = ∑ i ∈ Finset.range n, p.coeff i • x ^ i
theorem aeval_eq_sum_range' [Algebra R S] {p : R[X]} {n : ℕ} (hn : p.natDegree < n) (x : S) :
aeval x p = ∑ i ∈ Finset.range n, p.coeff i • x ^ i := by
simp_rw [Algebra.smul_def]
exact eval₂_eq_sum_range' (algebraMap R S) hn x
Polynomial.isRoot_of_eval₂_map_eq_zero
theorem
(hf : Function.Injective f) {r : R} : eval₂ f (f r) p = 0 → p.IsRoot r
theorem isRoot_of_eval₂_map_eq_zero (hf : Function.Injective f) {r : R} :
eval₂ f (f r) p = 0 → p.IsRoot r := by
intro h
apply hf
rw [← eval₂_hom, h, f.map_zero]
Polynomial.isRoot_of_aeval_algebraMap_eq_zero
theorem
[Algebra R S] {p : R[X]} (inj : Function.Injective (algebraMap R S)) {r : R} (hr : aeval (algebraMap R S r) p = 0) :
p.IsRoot r
theorem isRoot_of_aeval_algebraMap_eq_zero [Algebra R S] {p : R[X]}
(inj : Function.Injective (algebraMap R S)) {r : R} (hr : aeval (algebraMap R S r) p = 0) :
p.IsRoot r :=
isRoot_of_eval₂_map_eq_zero inj hr
Polynomial.aevalTower
definition
(f : R →ₐ[S] A') (x : A') : R[X] →ₐ[S] A'
/-- Version of `aeval` for defining algebra homs out of `R[X]` over a smaller base ring
than `R`. -/
def aevalTower (f : R →ₐ[S] A') (x : A') : R[X]R[X] →ₐ[S] A' :=
eval₂AlgHom' f x fun _ => Commute.all _ _
Polynomial.aevalTower_X
theorem
: aevalTower g y X = y
@[simp]
theorem aevalTower_X : aevalTower g y X = y :=
eval₂_X _ _
Polynomial.aevalTower_C
theorem
(x : R) : aevalTower g y (C x) = g x
@[simp]
theorem aevalTower_C (x : R) : aevalTower g y (C x) = g x :=
eval₂_C _ _
Polynomial.aevalTower_comp_C
theorem
: (aevalTower g y : R[X] →+* A').comp C = g
@[simp]
theorem aevalTower_comp_C : (aevalTower g y : R[X]R[X] →+* A').comp C = g :=
RingHom.ext <| aevalTower_C _ _
Polynomial.aevalTower_algebraMap
theorem
(x : R) : aevalTower g y (algebraMap R R[X] x) = g x
theorem aevalTower_algebraMap (x : R) : aevalTower g y (algebraMap R R[X] x) = g x :=
eval₂_C _ _
Polynomial.aevalTower_comp_algebraMap
theorem
: (aevalTower g y : R[X] →+* A').comp (algebraMap R R[X]) = g
theorem aevalTower_comp_algebraMap : (aevalTower g y : R[X]R[X] →+* A').comp (algebraMap R R[X]) = g :=
aevalTower_comp_C _ _
Polynomial.aevalTower_toAlgHom
theorem
(x : R) : aevalTower g y (IsScalarTower.toAlgHom S R R[X] x) = g x
theorem aevalTower_toAlgHom (x : R) : aevalTower g y (IsScalarTower.toAlgHom S R R[X] x) = g x :=
aevalTower_algebraMap _ _ _
Polynomial.aevalTower_comp_toAlgHom
theorem
: (aevalTower g y).comp (IsScalarTower.toAlgHom S R R[X]) = g
@[simp]
theorem aevalTower_comp_toAlgHom : (aevalTower g y).comp (IsScalarTower.toAlgHom S R R[X]) = g :=
AlgHom.coe_ringHom_injective <| aevalTower_comp_algebraMap _ _
Polynomial.aevalTower_id
theorem
: aevalTower (AlgHom.id S S) = aeval
@[simp]
theorem aevalTower_id : aevalTower (AlgHom.id S S) = aeval := by
ext s
simp only [eval_X, aevalTower_X, coe_aeval_eq_eval]
Polynomial.aevalTower_ofId
theorem
: aevalTower (Algebra.ofId S A') = aeval
@[simp]
theorem aevalTower_ofId : aevalTower (Algebra.ofId S A') = aeval := by
ext
simp only [aeval_X, aevalTower_X]
Polynomial.dvd_term_of_dvd_eval_of_dvd_terms
theorem
{z p : S} {f : S[X]} (i : ℕ) (dvd_eval : p ∣ f.eval z) (dvd_terms : ∀ j ≠ i, p ∣ f.coeff j * z ^ j) :
p ∣ f.coeff i * z ^ i
theorem dvd_term_of_dvd_eval_of_dvd_terms {z p : S} {f : S[X]} (i : ℕ) (dvd_eval : p ∣ f.eval z)
(dvd_terms : ∀ j ≠ i, p ∣ f.coeff j * z ^ j) : p ∣ f.coeff i * z ^ i := by
by_cases hi : i ∈ f.support
· rw [eval, eval₂_eq_sum, sum_def] at dvd_eval
rw [← Finset.insert_erase hi, Finset.sum_insert (Finset.not_mem_erase _ _)] at dvd_eval
refine (dvd_add_left ?_).mp dvd_eval
apply Finset.dvd_sum
intro j hj
exact dvd_terms j (Finset.ne_of_mem_erase hj)
· convert dvd_zero p
rw [not_mem_support_iff] at hi
simp [hi]
Polynomial.dvd_term_of_isRoot_of_dvd_terms
theorem
{r p : S} {f : S[X]} (i : ℕ) (hr : f.IsRoot r) (h : ∀ j ≠ i, p ∣ f.coeff j * r ^ j) : p ∣ f.coeff i * r ^ i
theorem dvd_term_of_isRoot_of_dvd_terms {r p : S} {f : S[X]} (i : ℕ) (hr : f.IsRoot r)
(h : ∀ j ≠ i, p ∣ f.coeff j * r ^ j) : p ∣ f.coeff i * r ^ i :=
dvd_term_of_dvd_eval_of_dvd_terms i (Eq.symm hr ▸ dvd_zero p) h
Polynomial.eval_mul_X_sub_C
theorem
{p : R[X]} (r : R) : (p * (X - C r)).eval r = 0
/-- The evaluation map is not generally multiplicative when the coefficient ring is noncommutative,
but nevertheless any polynomial of the form `p * (X - monomial 0 r)` is sent to zero
when evaluated at `r`.
This is the key step in our proof of the Cayley-Hamilton theorem.
-/
theorem eval_mul_X_sub_C {p : R[X]} (r : R) : (p * (X - C r)).eval r = 0 := by
simp only [eval, eval₂_eq_sum, RingHom.id_apply]
have bound :=
calc
(p * (X - C r)).natDegree ≤ p.natDegree + (X - C r).natDegree := natDegree_mul_le
_ ≤ p.natDegree + 1 := add_le_add_left (natDegree_X_sub_C_le _) _
_ < p.natDegree + 2 := lt_add_one _
rw [sum_over_range' _ _ (p.natDegree + 2) bound]
swap
· simp
rw [sum_range_succ']
conv_lhs =>
congr
arg 2
simp [coeff_mul_X_sub_C, sub_mul, mul_assoc, ← pow_succ']
rw [sum_range_sub']
simp [coeff_monomial]
Polynomial.not_isUnit_X_sub_C
theorem
[Nontrivial R] (r : R) : ¬IsUnit (X - C r)
theorem not_isUnit_X_sub_C [Nontrivial R] (r : R) : ¬IsUnit (X - C r) :=
fun ⟨⟨_, g, _hfg, hgf⟩, rfl⟩ => zero_ne_one' R <| by rw [← eval_mul_X_sub_C, hgf, eval_one]
Polynomial.aeval_endomorphism
theorem
{M : Type*} [AddCommGroup M] [Module R M] (f : M →ₗ[R] M) (v : M) (p : R[X]) :
aeval f p v = p.sum fun n b => b • (f ^ n) v
theorem aeval_endomorphism {M : Type*} [AddCommGroup M] [Module R M] (f : M →ₗ[R] M)
(v : M) (p : R[X]) : aeval f p v = p.sum fun n b => b • (f ^ n) v := by
rw [aeval_def, eval₂_eq_sum]
exact map_sum (LinearMap.applyₗ v) _ _
Polynomial.X_sub_C_pow_dvd_iff
theorem
{n : ℕ} : (X - C t) ^ n ∣ p ↔ X ^ n ∣ p.comp (X + C t)
lemma X_sub_C_pow_dvd_iff {n : ℕ} : (X - C t) ^ n ∣ p(X - C t) ^ n ∣ p ↔ X ^ n ∣ p.comp (X + C t) := by
convert (map_dvd_iff <| algEquivAevalXAddC t).symm using 2
simp [C_eq_algebraMap]
Polynomial.comp_X_add_C_eq_zero_iff
theorem
: p.comp (X + C t) = 0 ↔ p = 0
lemma comp_X_add_C_eq_zero_iff : p.comp (X + C t) = 0 ↔ p = 0 :=
EmbeddingLike.map_eq_zero_iff (f := algEquivAevalXAddC t)
Polynomial.comp_X_add_C_ne_zero_iff
theorem
: p.comp (X + C t) ≠ 0 ↔ p ≠ 0
lemma comp_X_add_C_ne_zero_iff : p.comp (X + C t) ≠ 0p.comp (X + C t) ≠ 0 ↔ p ≠ 0 := comp_X_add_C_eq_zero_iff.not
Polynomial.dvd_comp_C_mul_X_add_C_iff
theorem
(p q : R[X]) (a b : R) [Invertible a] : p ∣ q.comp (C a * X + C b) ↔ p.comp (C ⅟ a * (X - C b)) ∣ q
lemma dvd_comp_C_mul_X_add_C_iff (p q : R[X]) (a b : R) [Invertible a] :
p ∣ q.comp (C a * X + C b)p ∣ q.comp (C a * X + C b) ↔ p.comp (C ⅟ a * (X - C b)) ∣ q := by
convert map_dvd_iff <| algEquivCMulXAddC a b using 2
simp [← comp_eq_aeval, comp_assoc, ← mul_assoc, ← C_mul]
Polynomial.dvd_comp_X_sub_C_iff
theorem
(p q : R[X]) (a : R) : p ∣ q.comp (X - C a) ↔ p.comp (X + C a) ∣ q
lemma dvd_comp_X_sub_C_iff (p q : R[X]) (a : R) :
p ∣ q.comp (X - C a)p ∣ q.comp (X - C a) ↔ p.comp (X + C a) ∣ q := by
let _ := invertibleOne (α := R)
simpa using dvd_comp_C_mul_X_add_C_iff p q 1 (-a)
Polynomial.dvd_comp_X_add_C_iff
theorem
(p q : R[X]) (a : R) : p ∣ q.comp (X + C a) ↔ p.comp (X - C a) ∣ q
lemma dvd_comp_X_add_C_iff (p q : R[X]) (a : R) :
p ∣ q.comp (X + C a)p ∣ q.comp (X + C a) ↔ p.comp (X - C a) ∣ q := by
simpa using dvd_comp_X_sub_C_iff p q (-a)
Polynomial.dvd_comp_neg_X_iff
theorem
(p q : R[X]) : p ∣ q.comp (-X) ↔ p.comp (-X) ∣ q
lemma dvd_comp_neg_X_iff (p q : R[X]) : p ∣ q.comp (-X)p ∣ q.comp (-X) ↔ p.comp (-X) ∣ q := by
let _ := invertibleOne (α := R)
let _ := invertibleNeg (R := R) 1
simpa using dvd_comp_C_mul_X_add_C_iff p q (-1) 0
Polynomial.units_coeff_zero_smul
theorem
(c : R[X]ˣ) (p : R[X]) : (c : R[X]).coeff 0 • p = c * p
lemma units_coeff_zero_smul (c : R[X]R[X]ˣ) (p : R[X]) : (c : R[X]).coeff 0 • p = c * p := by
rw [← Polynomial.C_mul', ← Polynomial.eq_C_of_degree_eq_zero (degree_coe_units c)]
Polynomial.aeval_apply_smul_mem_of_le_comap'
theorem
[Semiring A] [Algebra R A] [Module A M] [IsScalarTower R A M] (hm : m ∈ q) (p : R[X]) (a : A)
(hq : q ≤ q.comap (Algebra.lsmul R R M a)) : aeval a p • m ∈ q
lemma aeval_apply_smul_mem_of_le_comap'
[Semiring A] [Algebra R A] [Module A M] [IsScalarTower R A M] (hm : m ∈ q) (p : R[X]) (a : A)
(hq : q ≤ q.comap (Algebra.lsmul R R M a)) :
aevalaeval a p • m ∈ q := by
induction p using Polynomial.induction_on with
| C a => simpa using SMulMemClass.smul_mem a hm
| add f₁ f₂ h₁ h₂ =>
simp_rw [map_add, add_smul]
exact Submodule.add_mem q h₁ h₂
| monomial n t hmq =>
dsimp only at hmq ⊢
rw [pow_succ', mul_left_comm, map_mul, aeval_X, mul_smul]
rw [← q.map_le_iff_le_comap] at hq
exact hq ⟨_, hmq, rfl⟩
Polynomial.aeval_apply_smul_mem_of_le_comap
theorem
(hm : m ∈ q) (p : R[X]) (f : Module.End R M) (hq : q ≤ q.comap f) : aeval f p m ∈ q
lemma aeval_apply_smul_mem_of_le_comap
(hm : m ∈ q) (p : R[X]) (f : Module.End R M) (hq : q ≤ q.comap f) :
aevalaeval f p m ∈ q :=
aeval_apply_smul_mem_of_le_comap' hm p f hq
Polynomial.nmem_nonZeroDivisors_iff
theorem
{P : R[X]} : P ∉ R[X]⁰ ↔ ∃ a : R, a ≠ 0 ∧ a • P = 0
/-- *McCoy theorem*: a polynomial `P : R[X]` is a zerodivisor if and only if there is `a : R`
such that `a ≠ 0` and `a • P = 0`. -/
theorem nmem_nonZeroDivisors_iff {P : R[X]} : P ∉ R[X]⁰P ∉ R[X]⁰ ↔ ∃ a : R, a ≠ 0 ∧ a • P = 0 := by
refine ⟨fun hP ↦ ?_, fun ⟨a, ha, h⟩ h1 ↦ ha <| C_eq_zero.1 <| (h1 _) <| smul_eq_C_mul a ▸ h⟩
by_contra! h
obtain ⟨Q, hQ⟩ := _root_.nmem_nonZeroDivisors_iff.1 hP
refine hQ.2 (eq_zero_of_mul_eq_zero_of_smul P (fun a ha ↦ ?_) Q (mul_comm P _ ▸ hQ.1))
contrapose! ha
exact h a ha
Polynomial.mem_nonZeroDivisors_iff
theorem
{P : R[X]} : P ∈ R[X]⁰ ↔ ∀ a : R, a • P = 0 → a = 0
protected lemma mem_nonZeroDivisors_iff {P : R[X]} : P ∈ R[X]⁰P ∈ R[X]⁰ ↔ ∀ a : R, a • P = 0 → a = 0 := by
simpa [not_imp_not] using (nmem_nonZeroDivisors_iff (P := P)).not
Polynomial.mem_nonzeroDivisors_of_coeff_mem
theorem
{p : R[X]} (n : ℕ) (hp : p.coeff n ∈ R⁰) : p ∈ R[X]⁰
lemma mem_nonzeroDivisors_of_coeff_mem {p : R[X]} (n : ℕ) (hp : p.coeff n ∈ R⁰) :
p ∈ R[X]⁰ :=
Polynomial.mem_nonZeroDivisors_iff.mpr fun r hr ↦ hp _ (by simpa using congr(coeff $hr n))
Polynomial.X_mem_nonzeroDivisors
theorem
: X ∈ R[X]⁰
lemma X_mem_nonzeroDivisors : XX ∈ R[X]⁰ :=
mem_nonzeroDivisors_of_coeff_mem 1 (by simp [one_mem])