File: Mathlib/RingTheory/IsAdjoinRoot.lean

full_name: IsAdjoinRoot.map_surjective
code: /-- `IsAdjoinRoot S f` states that the ring `S` can be constructed by adjoining a specified root
of the polynomial `f : R[X]` to `R`.

Compare `PowerBasis R S`, which does not explicitly specify which polynomial we adjoin a root of
(in particular `f` does not need to be the minimal polynomial of the root we adjoin),
and `AdjoinRoot` which constructs a new type.

This is not a typeclass because the choice of root given `S` and `f` is not unique.
-/
-- Porting note(#5171): this linter isn't ported yet.
-- @[nolint has_nonempty_instance]
structure IsAdjoinRoot {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S]
    (f : R[X]) : Type max u v where
  map : R[X] →+* S
  map_surjective : Function.Surjective map
  ker_map : RingHom.ker map = Ideal.span {f}
  algebraMap_eq : algebraMap R S = map.comp Polynomial.C
goal: Function.Surjective ⇑self.map

full_name: IsAdjoinRoot
code: /-- `IsAdjoinRoot S f` states that the ring `S` can be constructed by adjoining a specified root
of the polynomial `f : R[X]` to `R`.

Compare `PowerBasis R S`, which does not explicitly specify which polynomial we adjoin a root of
(in particular `f` does not need to be the minimal polynomial of the root we adjoin),
and `AdjoinRoot` which constructs a new type.

This is not a typeclass because the choice of root given `S` and `f` is not unique.
-/
-- Porting note(#5171): this linter isn't ported yet.
-- @[nolint has_nonempty_instance]
structure IsAdjoinRoot {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S]
    (f : R[X]) : Type max u v where
  map : R[X] →+* S
  map_surjective : Function.Surjective map
  ker_map : RingHom.ker map = Ideal.span {f}
  algebraMap_eq : algebraMap R S = map.comp Polynomial.C
goal: Type (max u v)

full_name: IsAdjoinRoot.map
code: /-- `IsAdjoinRoot S f` states that the ring `S` can be constructed by adjoining a specified root
of the polynomial `f : R[X]` to `R`.

Compare `PowerBasis R S`, which does not explicitly specify which polynomial we adjoin a root of
(in particular `f` does not need to be the minimal polynomial of the root we adjoin),
and `AdjoinRoot` which constructs a new type.

This is not a typeclass because the choice of root given `S` and `f` is not unique.
-/
-- Porting note(#5171): this linter isn't ported yet.
-- @[nolint has_nonempty_instance]
structure IsAdjoinRoot {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S]
    (f : R[X]) : Type max u v where
  map : R[X] →+* S
  map_surjective : Function.Surjective map
  ker_map : RingHom.ker map = Ideal.span {f}
  algebraMap_eq : algebraMap R S = map.comp Polynomial.C
goal: R[X] →+* S

full_name: IsAdjoinRoot.algebraMap_eq
code: /-- `IsAdjoinRoot S f` states that the ring `S` can be constructed by adjoining a specified root
of the polynomial `f : R[X]` to `R`.

Compare `PowerBasis R S`, which does not explicitly specify which polynomial we adjoin a root of
(in particular `f` does not need to be the minimal polynomial of the root we adjoin),
and `AdjoinRoot` which constructs a new type.

This is not a typeclass because the choice of root given `S` and `f` is not unique.
-/
-- Porting note(#5171): this linter isn't ported yet.
-- @[nolint has_nonempty_instance]
structure IsAdjoinRoot {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S]
    (f : R[X]) : Type max u v where
  map : R[X] →+* S
  map_surjective : Function.Surjective map
  ker_map : RingHom.ker map = Ideal.span {f}
  algebraMap_eq : algebraMap R S = map.comp Polynomial.C
goal: algebraMap R S = self.map.comp Polynomial.C

full_name: IsAdjoinRoot.ker_map
code: /-- `IsAdjoinRoot S f` states that the ring `S` can be constructed by adjoining a specified root
of the polynomial `f : R[X]` to `R`.

Compare `PowerBasis R S`, which does not explicitly specify which polynomial we adjoin a root of
(in particular `f` does not need to be the minimal polynomial of the root we adjoin),
and `AdjoinRoot` which constructs a new type.

This is not a typeclass because the choice of root given `S` and `f` is not unique.
-/
-- Porting note(#5171): this linter isn't ported yet.
-- @[nolint has_nonempty_instance]
structure IsAdjoinRoot {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S]
    (f : R[X]) : Type max u v where
  map : R[X] →+* S
  map_surjective : Function.Surjective map
  ker_map : RingHom.ker map = Ideal.span {f}
  algebraMap_eq : algebraMap R S = map.comp Polynomial.C
goal: RingHom.ker self.map = Ideal.span {f}

full_name: IsAdjoinRootMonic
code: /-- `IsAdjoinRootMonic S f` states that the ring `S` can be constructed by adjoining a specified
root of the monic polynomial `f : R[X]` to `R`.

As long as `f` is monic, there is a well-defined representation of elements of `S` as polynomials
in `R[X]` of degree lower than `deg f` (see `modByMonicHom` and `coeff`). In particular,
we have `IsAdjoinRootMonic.powerBasis`.

Bundling `Monic` into this structure is very useful when working with explicit `f`s such as
`X^2 - C a * X - C b` since it saves you carrying around the proofs of monicity.
-/
-- @[nolint has_nonempty_instance] -- Porting note: This linter does not exist yet.
structure IsAdjoinRootMonic {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S]
    (f : R[X]) extends IsAdjoinRoot S f where
  Monic : Monic f
goal: Type (max u v)

full_name: IsAdjoinRootMonic.Monic
code: /-- `IsAdjoinRootMonic S f` states that the ring `S` can be constructed by adjoining a specified
root of the monic polynomial `f : R[X]` to `R`.

As long as `f` is monic, there is a well-defined representation of elements of `S` as polynomials
in `R[X]` of degree lower than `deg f` (see `modByMonicHom` and `coeff`). In particular,
we have `IsAdjoinRootMonic.powerBasis`.

Bundling `Monic` into this structure is very useful when working with explicit `f`s such as
`X^2 - C a * X - C b` since it saves you carrying around the proofs of monicity.
-/
-- @[nolint has_nonempty_instance] -- Porting note: This linter does not exist yet.
structure IsAdjoinRootMonic {R : Type u} (S : Type v) [CommSemiring R] [Semiring S] [Algebra R S]
    (f : R[X]) extends IsAdjoinRoot S f where
  Monic : Monic f
goal: f.Monic

full_name: IsAdjoinRoot.root
code: /-- `(h : IsAdjoinRoot S f).root` is the root of `f` that can be adjoined to generate `S`. -/
def root (h : IsAdjoinRoot S f) : S 
goal: S

full_name: IsAdjoinRoot.subsingleton
code: theorem subsingleton (h : IsAdjoinRoot S f) [Subsingleton R] : Subsingleton S 
goal: Subsingleton S

full_name: IsAdjoinRoot.algebraMap_apply
code: theorem algebraMap_apply (h : IsAdjoinRoot S f) (x : R) :
    algebraMap R S x = h.map (Polynomial.C x) 
goal: (algebraMap R S) x = h.map (Polynomial.C x)

full_name: IsAdjoinRoot.mem_ker_map
code: @[simp]
theorem mem_ker_map (h : IsAdjoinRoot S f) {p} : p ∈ RingHom.ker h.map ↔ f ∣ p 
goal: p ∈ RingHom.ker h.map ↔ f ∣ p

full_name: IsAdjoinRoot.map_eq_zero_iff
code: theorem map_eq_zero_iff (h : IsAdjoinRoot S f) {p} : h.map p = 0 ↔ f ∣ p 
goal: h.map p = 0 ↔ f ∣ p

full_name: IsAdjoinRoot.map_X
code: @[simp]
theorem map_X (h : IsAdjoinRoot S f) : h.map X = h.root 
goal: h.map Polynomial.X = h.root

full_name: IsAdjoinRoot.map_self
code: @[simp]
theorem map_self (h : IsAdjoinRoot S f) : h.map f = 0 
goal: h.map f = 0

full_name: IsAdjoinRoot.aeval_eq
code: @[simp]
theorem aeval_eq (h : IsAdjoinRoot S f) (p : R[X]) : aeval h.root p = h.map p 
goal: (Polynomial.aeval h.root) p = h.map p

full_name: IsAdjoinRoot.aeval_root
code: theorem aeval_root (h : IsAdjoinRoot S f) : aeval h.root f = 0 
goal: (Polynomial.aeval h.root) f = 0

full_name: IsAdjoinRoot.repr
code: /-- Choose an arbitrary representative so that `h.map (h.repr x) = x`.

If `f` is monic, use `IsAdjoinRootMonic.modByMonicHom` for a unique choice of representative.
-/
def repr (h : IsAdjoinRoot S f) (x : S) : R[X] 
goal: R[X]

full_name: IsAdjoinRoot.map_repr
code: theorem map_repr (h : IsAdjoinRoot S f) (x : S) : h.map (h.repr x) = x 
goal: h.map (h.repr x) = x

full_name: IsAdjoinRoot.repr_zero_mem_span
code: /-- `repr` preserves zero, up to multiples of `f` -/
theorem repr_zero_mem_span (h : IsAdjoinRoot S f) : h.repr 0 ∈ Ideal.span ({f} : Set R[X]) 
goal: h.repr 0 ∈ Ideal.span {f}

full_name: IsAdjoinRoot.repr_add_sub_repr_add_repr_mem_span
code: /-- `repr` preserves addition, up to multiples of `f` -/
theorem repr_add_sub_repr_add_repr_mem_span (h : IsAdjoinRoot S f) (x y : S) :
    h.repr (x + y) - (h.repr x + h.repr y) ∈ Ideal.span ({f} : Set R[X]) 
goal: h.repr (x + y) - (h.repr x + h.repr y) ∈ Ideal.span {f}

full_name: IsAdjoinRoot.ext_map
code: /-- Extensionality of the `IsAdjoinRoot` structure itself. See `IsAdjoinRootMonic.ext_elem`
for extensionality of the ring elements. -/
theorem ext_map (h h' : IsAdjoinRoot S f) (eq : ∀ x, h.map x = h'.map x) : h = h' 
goal: h = h'

full_name: IsAdjoinRoot.ext
code: /-- Extensionality of the `IsAdjoinRoot` structure itself. See `IsAdjoinRootMonic.ext_elem`
for extensionality of the ring elements. -/
@[ext]
theorem ext (h h' : IsAdjoinRoot S f) (eq : h.root = h'.root) : h = h' 
goal: h = h'

full_name: IsAdjoinRoot.eval₂_repr_eq_eval₂_of_map_eq
code: /-- Auxiliary lemma for `IsAdjoinRoot.lift` -/
theorem eval₂_repr_eq_eval₂_of_map_eq (h : IsAdjoinRoot S f) (z : S) (w : R[X])
    (hzw : h.map w = z) : (h.repr z).eval₂ i x = w.eval₂ i x 
goal: Polynomial.eval₂ i x (h.repr z) = Polynomial.eval₂ i x w

full_name: IsAdjoinRoot.lift
code: /-- Lift a ring homomorphism `R →+* T` to `S →+* T` by specifying a root `x` of `f` in `T`,
where `S` is given by adjoining a root of `f` to `R`. -/
def lift (h : IsAdjoinRoot S f) : S →+* T 
goal: S →+* T

full_name: IsAdjoinRoot.lift_map
code: @[simp]
theorem lift_map (h : IsAdjoinRoot S f) (z : R[X]) : h.lift i x hx (h.map z) = z.eval₂ i x 
goal: (IsAdjoinRoot.lift i x hx h) (h.map z) = Polynomial.eval₂ i x z

full_name: IsAdjoinRoot.lift_root
code: @[simp]
theorem lift_root (h : IsAdjoinRoot S f) : h.lift i x hx h.root = x 
goal: (IsAdjoinRoot.lift i x hx h) h.root = x

full_name: IsAdjoinRoot.lift_algebraMap
code: @[simp]
theorem lift_algebraMap (h : IsAdjoinRoot S f) (a : R) :
    h.lift i x hx (algebraMap R S a) = i a 
goal: (IsAdjoinRoot.lift i x hx h) ((algebraMap R S) a) = i a

full_name: IsAdjoinRoot.apply_eq_lift
code: /-- Auxiliary lemma for `apply_eq_lift` -/
theorem apply_eq_lift (h : IsAdjoinRoot S f) (g : S →+* T) (hmap : ∀ a, g (algebraMap R S a) = i a)
    (hroot : g h.root = x) (a : S) : g a = h.lift i x hx a 
goal: g a = (IsAdjoinRoot.lift i x hx h) a

full_name: IsAdjoinRoot.eq_lift
code: /-- Unicity of `lift`: a map that agrees on `R` and `h.root` agrees with `lift` everywhere. -/
theorem eq_lift (h : IsAdjoinRoot S f) (g : S →+* T) (hmap : ∀ a, g (algebraMap R S a) = i a)
    (hroot : g h.root = x) : g = h.lift i x hx 
goal: g = IsAdjoinRoot.lift i x hx h

full_name: IsAdjoinRoot.liftHom
code: /-- Lift the algebra map `R → T` to `S →ₐ[R] T` by specifying a root `x` of `f` in `T`,
where `S` is given by adjoining a root of `f` to `R`. -/
def liftHom (h : IsAdjoinRoot S f) : S →ₐ[R] T 
goal: S →ₐ[R] T

full_name: IsAdjoinRoot.coe_liftHom
code: @[simp]
theorem coe_liftHom (h : IsAdjoinRoot S f) :
    (h.liftHom x hx' : S →+* T) = h.lift (algebraMap R T) x hx' 
goal: ↑(IsAdjoinRoot.liftHom x hx' h) = IsAdjoinRoot.lift (algebraMap R T) x hx' h

full_name: IsAdjoinRoot.lift_algebraMap_apply
code: theorem lift_algebraMap_apply (h : IsAdjoinRoot S f) (z : S) :
    h.lift (algebraMap R T) x hx' z = h.liftHom x hx' z 
goal: (IsAdjoinRoot.lift (algebraMap R T) x hx' h) z = (IsAdjoinRoot.liftHom x hx' h) z

full_name: IsAdjoinRoot.liftHom_map
code: @[simp]
theorem liftHom_map (h : IsAdjoinRoot S f) (z : R[X]) : h.liftHom x hx' (h.map z) = aeval x z 
goal: (IsAdjoinRoot.liftHom x hx' h) (h.map z) = (Polynomial.aeval x) z

full_name: IsAdjoinRoot.liftHom_root
code: @[simp]
theorem liftHom_root (h : IsAdjoinRoot S f) : h.liftHom x hx' h.root = x 
goal: (IsAdjoinRoot.liftHom x hx' h) h.root = x

full_name: IsAdjoinRoot.eq_liftHom
code: /-- Unicity of `liftHom`: a map that agrees on `h.root` agrees with `liftHom` everywhere. -/
theorem eq_liftHom (h : IsAdjoinRoot S f) (g : S →ₐ[R] T) (hroot : g h.root = x) :
    g = h.liftHom x hx' 
goal: g = IsAdjoinRoot.liftHom x hx' h

full_name: AdjoinRoot.isAdjoinRoot
code: /-- `AdjoinRoot f` is indeed given by adjoining a root of `f`. -/
protected def isAdjoinRoot : IsAdjoinRoot (AdjoinRoot f) f 
goal: IsAdjoinRoot (AdjoinRoot f) f

full_name: AdjoinRoot.isAdjoinRootMonic
code: /-- `AdjoinRoot f` is indeed given by adjoining a root of `f`. If `f` is monic this is more
powerful than `AdjoinRoot.isAdjoinRoot`. -/
protected def isAdjoinRootMonic (hf : Monic f) : IsAdjoinRootMonic (AdjoinRoot f) f 
goal: IsAdjoinRootMonic (AdjoinRoot f) f

full_name: AdjoinRoot.isAdjoinRoot_map_eq_mk
code: @[simp]
theorem isAdjoinRoot_map_eq_mk : (AdjoinRoot.isAdjoinRoot f).map = AdjoinRoot.mk f 
goal: (AdjoinRoot.isAdjoinRoot f).map = AdjoinRoot.mk f

full_name: AdjoinRoot.isAdjoinRootMonic_map_eq_mk
code: @[simp]
theorem isAdjoinRootMonic_map_eq_mk (hf : f.Monic) :
    (AdjoinRoot.isAdjoinRootMonic f hf).map = AdjoinRoot.mk f 
goal: (AdjoinRoot.isAdjoinRootMonic f hf).map = AdjoinRoot.mk f

full_name: AdjoinRoot.isAdjoinRoot_root_eq_root
code: @[simp]
theorem isAdjoinRoot_root_eq_root : (AdjoinRoot.isAdjoinRoot f).root = AdjoinRoot.root f 
goal: (AdjoinRoot.isAdjoinRoot f).root = AdjoinRoot.root f

full_name: AdjoinRoot.isAdjoinRootMonic_root_eq_root
code: @[simp]
theorem isAdjoinRootMonic_root_eq_root (hf : Monic f) :
    (AdjoinRoot.isAdjoinRootMonic f hf).root = AdjoinRoot.root f 
goal: (AdjoinRoot.isAdjoinRootMonic f hf).root = AdjoinRoot.root f

full_name: IsAdjoinRootMonic.map_modByMonic
code: theorem map_modByMonic (h : IsAdjoinRootMonic S f) (g : R[X]) : h.map (g %ₘ f) = h.map g 
goal: h.map (g %ₘ f) = h.map g

full_name: IsAdjoinRootMonic.modByMonic_repr_map
code: theorem modByMonic_repr_map (h : IsAdjoinRootMonic S f) (g : R[X]) :
    h.repr (h.map g) %ₘ f = g %ₘ f 
goal: h.repr (h.map g) %ₘ f = g %ₘ f

full_name: IsAdjoinRootMonic.modByMonicHom
code: /-- `IsAdjoinRoot.modByMonicHom` sends the equivalence class of `f` mod `g` to `f %ₘ g`. -/
def modByMonicHom (h : IsAdjoinRootMonic S f) : S →ₗ[R] R[X] 
goal: S →ₗ[R] R[X]

full_name: IsAdjoinRootMonic.modByMonicHom_map
code: @[simp]
theorem modByMonicHom_map (h : IsAdjoinRootMonic S f) (g : R[X]) :
    h.modByMonicHom (h.map g) = g %ₘ f 
goal: h.modByMonicHom (h.map g) = g %ₘ f

full_name: IsAdjoinRootMonic.map_modByMonicHom
code: @[simp]
theorem map_modByMonicHom (h : IsAdjoinRootMonic S f) (x : S) : h.map (h.modByMonicHom x) = x 
goal: h.map (h.modByMonicHom x) = x

full_name: IsAdjoinRootMonic.modByMonicHom_root_pow
code: @[simp]
theorem modByMonicHom_root_pow (h : IsAdjoinRootMonic S f) {n : ℕ} (hdeg : n < natDegree f) :
    h.modByMonicHom (h.root ^ n) = X ^ n 
goal: h.modByMonicHom (h.root ^ n) = Polynomial.X ^ n

full_name: IsAdjoinRootMonic.modByMonicHom_root
code: @[simp]
theorem modByMonicHom_root (h : IsAdjoinRootMonic S f) (hdeg : 1 < natDegree f) :
    h.modByMonicHom h.root = X 
goal: h.modByMonicHom h.root = Polynomial.X

full_name: IsAdjoinRootMonic.basis
code: /-- The basis on `S` generated by powers of `h.root`.

Auxiliary definition for `IsAdjoinRootMonic.powerBasis`. -/
def basis (h : IsAdjoinRootMonic S f) : Basis (Fin (natDegree f)) R S 
goal: Basis (Fin f.natDegree) R S

full_name: IsAdjoinRootMonic.basis_apply
code: @[simp]
theorem basis_apply (h : IsAdjoinRootMonic S f) (i) : h.basis i = h.root ^ (i : ℕ) 
goal: h.basis i = h.root ^ ↑i

full_name: IsAdjoinRootMonic.deg_pos
code: theorem deg_pos [Nontrivial S] (h : IsAdjoinRootMonic S f) : 0 < natDegree f 
goal: 0 < f.natDegree

full_name: IsAdjoinRootMonic.deg_ne_zero
code: theorem deg_ne_zero [Nontrivial S] (h : IsAdjoinRootMonic S f) : natDegree f ≠ 0 
goal: f.natDegree ≠ 0

full_name: IsAdjoinRootMonic.powerBasis_dim
code: /-- If `f` is monic, the powers of `h.root` form a basis. -/
@[simps! gen dim basis]
def powerBasis (h : IsAdjoinRootMonic S f) : PowerBasis R S 
goal: h.powerBasis.dim = f.natDegree

full_name: IsAdjoinRootMonic.powerBasis
code: /-- If `f` is monic, the powers of `h.root` form a basis. -/
@[simps! gen dim basis]
def powerBasis (h : IsAdjoinRootMonic S f) : PowerBasis R S 
goal: PowerBasis R S

full_name: IsAdjoinRootMonic.powerBasis_basis
code: /-- If `f` is monic, the powers of `h.root` form a basis. -/
@[simps! gen dim basis]
def powerBasis (h : IsAdjoinRootMonic S f) : PowerBasis R S 
goal: h.powerBasis.basis = h.basis

full_name: IsAdjoinRootMonic.powerBasis_gen
code: /-- If `f` is monic, the powers of `h.root` form a basis. -/
@[simps! gen dim basis]
def powerBasis (h : IsAdjoinRootMonic S f) : PowerBasis R S 
goal: h.powerBasis.gen = h.root

full_name: IsAdjoinRootMonic.basis_repr
code: @[simp]
theorem basis_repr (h : IsAdjoinRootMonic S f) (x : S) (i : Fin (natDegree f)) :
    h.basis.repr x i = (h.modByMonicHom x).coeff (i : ℕ) 
goal: (h.basis.repr x) i = (h.modByMonicHom x).coeff ↑i

full_name: IsAdjoinRootMonic.basis_one
code: theorem basis_one (h : IsAdjoinRootMonic S f) (hdeg : 1 < natDegree f) :
    h.basis ⟨1, hdeg⟩ = h.root 
goal: h.basis ⟨1, hdeg⟩ = h.root

full_name: IsAdjoinRootMonic.liftPolyₗ_apply
code: /-- `IsAdjoinRootMonic.liftPolyₗ` lifts a linear map on polynomials to a linear map on `S`. -/
@[simps!]
def liftPolyₗ {T : Type*} [AddCommGroup T] [Module R T] (h : IsAdjoinRootMonic S f)
    (g : R[X] →ₗ[R] T) : S →ₗ[R] T 
goal: ∀ (a : S), (h.liftPolyₗ g) a = g (h.modByMonicHom a)

full_name: IsAdjoinRootMonic.liftPolyₗ
code: /-- `IsAdjoinRootMonic.liftPolyₗ` lifts a linear map on polynomials to a linear map on `S`. -/
@[simps!]
def liftPolyₗ {T : Type*} [AddCommGroup T] [Module R T] (h : IsAdjoinRootMonic S f)
    (g : R[X] →ₗ[R] T) : S →ₗ[R] T 
goal: S →ₗ[R] T

full_name: IsAdjoinRootMonic.coeff
code: /-- `IsAdjoinRootMonic.coeff h x i` is the `i`th coefficient of the representative of `x : S`.
-/
def coeff (h : IsAdjoinRootMonic S f) : S →ₗ[R] ℕ → R 
goal: S →ₗ[R] ℕ → R

full_name: IsAdjoinRootMonic.coeff_apply_lt
code: theorem coeff_apply_lt (h : IsAdjoinRootMonic S f) (z : S) (i : ℕ) (hi : i < natDegree f) :
    h.coeff z i = h.basis.repr z ⟨i, hi⟩ 
goal: h.coeff z i = (h.basis.repr z) ⟨i, hi⟩

full_name: IsAdjoinRootMonic.coeff_apply_coe
code: theorem coeff_apply_coe (h : IsAdjoinRootMonic S f) (z : S) (i : Fin (natDegree f)) :
    h.coeff z i = h.basis.repr z i 
goal: h.coeff z ↑i = (h.basis.repr z) i

full_name: IsAdjoinRootMonic.coeff_apply_le
code: theorem coeff_apply_le (h : IsAdjoinRootMonic S f) (z : S) (i : ℕ) (hi : natDegree f ≤ i) :
    h.coeff z i = 0 
goal: h.coeff z i = 0

full_name: IsAdjoinRootMonic.coeff_apply
code: theorem coeff_apply (h : IsAdjoinRootMonic S f) (z : S) (i : ℕ) :
    h.coeff z i = if hi : i < natDegree f then h.basis.repr z ⟨i, hi⟩ else 0 
goal: h.coeff z i = if hi : i < f.natDegree then (h.basis.repr z) ⟨i, hi⟩ else 0

full_name: IsAdjoinRootMonic.coeff_root_pow
code: theorem coeff_root_pow (h : IsAdjoinRootMonic S f) {n} (hn : n < natDegree f) :
    h.coeff (h.root ^ n) = Pi.single n 1 
goal: h.coeff (h.root ^ n) = Pi.single n 1

full_name: IsAdjoinRootMonic.coeff_one
code: theorem coeff_one [Nontrivial S] (h : IsAdjoinRootMonic S f) : h.coeff 1 = Pi.single 0 1 
goal: h.coeff 1 = Pi.single 0 1

full_name: IsAdjoinRootMonic.coeff_root
code: theorem coeff_root (h : IsAdjoinRootMonic S f) (hdeg : 1 < natDegree f) :
    h.coeff h.root = Pi.single 1 1 
goal: h.coeff h.root = Pi.single 1 1

full_name: IsAdjoinRootMonic.coeff_algebraMap
code: theorem coeff_algebraMap [Nontrivial S] (h : IsAdjoinRootMonic S f) (x : R) :
    h.coeff (algebraMap R S x) = Pi.single 0 x 
goal: h.coeff ((algebraMap R S) x) = Pi.single 0 x

full_name: IsAdjoinRootMonic.ext_elem
code: theorem ext_elem (h : IsAdjoinRootMonic S f) ⦃x y : S⦄
    (hxy : ∀ i < natDegree f, h.coeff x i = h.coeff y i) : x = y 
goal: x = y

full_name: IsAdjoinRootMonic.ext_elem_iff
code: theorem ext_elem_iff (h : IsAdjoinRootMonic S f) {x y : S} :
    x = y ↔ ∀ i < natDegree f, h.coeff x i = h.coeff y i 
goal: x = y ↔ ∀ i < f.natDegree, h.coeff x i = h.coeff y i

full_name: IsAdjoinRootMonic.coeff_injective
code: theorem coeff_injective (h : IsAdjoinRootMonic S f) : Function.Injective h.coeff 
goal: Function.Injective ⇑h.coeff

full_name: IsAdjoinRootMonic.isIntegral_root
code: theorem isIntegral_root (h : IsAdjoinRootMonic S f) : IsIntegral R h.root 
goal: IsIntegral R h.root

full_name: IsAdjoinRoot.lift_self_apply
code: @[simp]
theorem lift_self_apply (h : IsAdjoinRoot S f) (x : S) :
    h.lift (algebraMap R S) h.root h.aeval_root x = x 
goal: (IsAdjoinRoot.lift (algebraMap R S) h.root ⋯ h) x = x

full_name: IsAdjoinRoot.lift_self
code: theorem lift_self (h : IsAdjoinRoot S f) :
    h.lift (algebraMap R S) h.root h.aeval_root = RingHom.id S 
goal: IsAdjoinRoot.lift (algebraMap R S) h.root ⋯ h = RingHom.id S

full_name: IsAdjoinRoot.aequiv
code: /-- Adjoining a root gives a unique ring up to algebra isomorphism.

This is the converse of `IsAdjoinRoot.ofEquiv`: this turns an `IsAdjoinRoot` into an
`AlgEquiv`, and `IsAdjoinRoot.ofEquiv` turns an `AlgEquiv` into an `IsAdjoinRoot`.
-/
def aequiv (h : IsAdjoinRoot S f) (h' : IsAdjoinRoot T f) : S ≃ₐ[R] T 
goal: S ≃ₐ[R] T

full_name: IsAdjoinRoot.aequiv_map
code: @[simp]
theorem aequiv_map (h : IsAdjoinRoot S f) (h' : IsAdjoinRoot T f) (z : R[X]) :
    h.aequiv h' (h.map z) = h'.map z 
goal: (h.aequiv h') (h.map z) = h'.map z

full_name: IsAdjoinRoot.aequiv_root
code: @[simp]
theorem aequiv_root (h : IsAdjoinRoot S f) (h' : IsAdjoinRoot T f) :
    h.aequiv h' h.root = h'.root 
goal: (h.aequiv h') h.root = h'.root

full_name: IsAdjoinRoot.aequiv_self
code: @[simp]
theorem aequiv_self (h : IsAdjoinRoot S f) : h.aequiv h = AlgEquiv.refl 
goal: h.aequiv h = AlgEquiv.refl

full_name: IsAdjoinRoot.aequiv_symm
code: @[simp]
theorem aequiv_symm (h : IsAdjoinRoot S f) (h' : IsAdjoinRoot T f) :
    (h.aequiv h').symm = h'.aequiv h 
goal: (h.aequiv h').symm = h'.aequiv h

full_name: IsAdjoinRoot.lift_aequiv
code: @[simp]
theorem lift_aequiv {U : Type*} [CommRing U] (h : IsAdjoinRoot S f) (h' : IsAdjoinRoot T f)
    (i : R →+* U) (x hx z) : h'.lift i x hx (h.aequiv h' z) = h.lift i x hx z 
goal: (IsAdjoinRoot.lift i x hx h') ((h.aequiv h') z) = (IsAdjoinRoot.lift i x hx h) z

full_name: IsAdjoinRoot.liftHom_aequiv
code: @[simp]
theorem liftHom_aequiv {U : Type*} [CommRing U] [Algebra R U] (h : IsAdjoinRoot S f)
    (h' : IsAdjoinRoot T f) (x : U) (hx z) : h'.liftHom x hx (h.aequiv h' z) = h.liftHom x hx z 
goal: (IsAdjoinRoot.liftHom x hx h') ((h.aequiv h') z) = (IsAdjoinRoot.liftHom x hx h) z

full_name: IsAdjoinRoot.aequiv_aequiv
code: @[simp]
theorem aequiv_aequiv {U : Type*} [CommRing U] [Algebra R U] (h : IsAdjoinRoot S f)
    (h' : IsAdjoinRoot T f) (h'' : IsAdjoinRoot U f) (x) :
    (h'.aequiv h'') (h.aequiv h' x) = h.aequiv h'' x 
goal: (h'.aequiv h'') ((h.aequiv h') x) = (h.aequiv h'') x

full_name: IsAdjoinRoot.aequiv_trans
code: @[simp]
theorem aequiv_trans {U : Type*} [CommRing U] [Algebra R U] (h : IsAdjoinRoot S f)
    (h' : IsAdjoinRoot T f) (h'' : IsAdjoinRoot U f) :
    (h.aequiv h').trans (h'.aequiv h'') = h.aequiv h'' 
goal: (h.aequiv h').trans (h'.aequiv h'') = h.aequiv h''

full_name: IsAdjoinRoot.ofEquiv
code: /-- Transfer `IsAdjoinRoot` across an algebra isomorphism.

This is the converse of `IsAdjoinRoot.aequiv`: this turns an `AlgEquiv` into an `IsAdjoinRoot`,
and `IsAdjoinRoot.aequiv` turns an `IsAdjoinRoot` into an `AlgEquiv`.
-/
@[simps! map_apply]
def ofEquiv (h : IsAdjoinRoot S f) (e : S ≃ₐ[R] T) : IsAdjoinRoot T f 
goal: IsAdjoinRoot T f

full_name: IsAdjoinRoot.ofEquiv_map_apply
code: /-- Transfer `IsAdjoinRoot` across an algebra isomorphism.

This is the converse of `IsAdjoinRoot.aequiv`: this turns an `AlgEquiv` into an `IsAdjoinRoot`,
and `IsAdjoinRoot.aequiv` turns an `IsAdjoinRoot` into an `AlgEquiv`.
-/
@[simps! map_apply]
def ofEquiv (h : IsAdjoinRoot S f) (e : S ≃ₐ[R] T) : IsAdjoinRoot T f 
goal: ∀ (a : R[X]), (h.ofEquiv e).map a = e (h.map a)

full_name: IsAdjoinRoot.ofEquiv_root
code: @[simp]
theorem ofEquiv_root (h : IsAdjoinRoot S f) (e : S ≃ₐ[R] T) : (h.ofEquiv e).root = e h.root 
goal: (h.ofEquiv e).root = e h.root

full_name: IsAdjoinRoot.aequiv_ofEquiv
code: @[simp]
theorem aequiv_ofEquiv {U : Type*} [CommRing U] [Algebra R U] (h : IsAdjoinRoot S f)
    (h' : IsAdjoinRoot T f) (e : T ≃ₐ[R] U) : h.aequiv (h'.ofEquiv e) = (h.aequiv h').trans e 
goal: h.aequiv (h'.ofEquiv e) = (h.aequiv h').trans e

full_name: IsAdjoinRoot.ofEquiv_aequiv
code: @[simp]
theorem ofEquiv_aequiv {U : Type*} [CommRing U] [Algebra R U] (h : IsAdjoinRoot S f)
    (h' : IsAdjoinRoot U f) (e : S ≃ₐ[R] T) :
    (h.ofEquiv e).aequiv h' = e.symm.trans (h.aequiv h') 
goal: (h.ofEquiv e).aequiv h' = e.symm.trans (h.aequiv h')

full_name: IsAdjoinRootMonic.minpoly_eq
code: theorem minpoly_eq [IsDomain R] [IsDomain S] [NoZeroSMulDivisors R S] [IsIntegrallyClosed R]
    (h : IsAdjoinRootMonic S f) (hirr : Irreducible f) : minpoly R h.root = f 
goal: minpoly R h.root = f

full_name: Algebra.adjoin.powerBasis'_minpoly_gen
code: theorem Algebra.adjoin.powerBasis'_minpoly_gen [IsDomain R] [IsDomain S] [NoZeroSMulDivisors R S]
    [IsIntegrallyClosed R] {x : S} (hx' : IsIntegral R x) :
    minpoly R x = minpoly R (Algebra.adjoin.powerBasis' hx').gen 
goal: minpoly R x = minpoly R (Algebra.adjoin.powerBasis' hx').gen