l3lab/ntp-mathlib huggingface dataset:
/-- A certain linear combination of the previous three identities,
which we'll want later.
-/
theorem variance (n : ℕ) :
    (∑ ν in Finset.range (n + 1), (n • Polynomial.X - (ν : R[X])) ^ 2 * bernsteinPolynomial R n ν) =
      n • Polynomial.X * ((1 : R[X]) - Polynomial.X) := by
  have p : ((((Finset.range (n + 1)).sum fun ν => (ν * (ν - 1)) • bernsteinPolynomial R n ν) +
      (1 - (2 * n) • Polynomial.X) * (Finset.range (n + 1)).sum fun ν =>
        ν • bernsteinPolynomial R n ν) + n ^ 2 • X ^ 2 *
          (Finset.range (n + 1)).sum fun ν => bernsteinPolynomial R n ν) = _ :=
    rfl
  conv at p =>
    lhs
    rw [Finset.mul_sum, Finset.mul_sum, ← Finset.sum_add_distrib, ← Finset.sum_add_distrib]
    simp only [← nat_cast_mul]
    simp only [← mul_assoc]
    simp only [← add_mul]
  conv at p =>
    rhs
    rw [sum, sum_smul, sum_mul_smul, ← nat_cast_mul]
  calc
    _ = _ := Finset.sum_congr rfl fun k m => ?_
    _ = _ := p
    _ = _ := ?_
  · congr 1; simp only [← nat_cast_mul, push_cast]
    cases k <;> · simp; ring
  · simp only [← nat_cast_mul, push_cast]
    cases n
    · 

Proof state:
case calc_2.zero
R : Type u_1
inst✝ : CommRing R
p :
  ∑ x in Finset.range (Nat.zero + 1),
      (↑(x * (x - 1)) + (1 - ↑(2 * Nat.zero) * X) * ↑x + ↑(Nat.zero ^ 2) * X ^ 2) * bernsteinPolynomial R Nat.zero x =
    ↑(Nat.zero * (Nat.zero - 1)) * X ^ 2 + (1 - (2 * Nat.zero) • X) * Nat.zero • X + Nat.zero ^ 2 • X ^ 2 * 1
⊢ ↑Nat.zero * ↑(Nat.zero - 1) * X ^ 2 + (1 - 2 * ↑Nat.zero * X) * (↑Nat.zero * X) + ↑Nat.zero ^ 2 * X ^ 2 * 1 =
    ↑Nat.zero * X * (1 - X)

Next tactic:
simp
/-- A certain linear combination of the previous three identities,
which we'll want later.
-/
theorem variance (n : ℕ) :
    (∑ ν in Finset.range (n + 1), (n • Polynomial.X - (ν : R[X])) ^ 2 * bernsteinPolynomial R n ν) =
      n • Polynomial.X * ((1 : R[X]) - Polynomial.X) := by
  have p : ((((Finset.range (n + 1)).sum fun ν => (ν * (ν - 1)) • bernsteinPolynomial R n ν) +
      (1 - (2 * n) • Polynomial.X) * (Finset.range (n + 1)).sum fun ν =>
        ν • bernsteinPolynomial R n ν) + n ^ 2 • X ^ 2 *
          (Finset.range (n + 1)).sum fun ν => bernsteinPolynomial R n ν) = _ :=
    rfl
  conv at p =>
    lhs
    rw [Finset.mul_sum, Finset.mul_sum, ← Finset.sum_add_distrib, ← Finset.sum_add_distrib]
    simp only [← nat_cast_mul]
    simp only [← mul_assoc]
    simp only [← add_mul]
  conv at p =>
    rhs
    rw [sum, sum_smul, sum_mul_smul, ← nat_cast_mul]
  calc
    _ = _ := Finset.sum_congr rfl fun k m => ?_
    _ = _ := p
    _ = _ := ?_
  · congr 1; simp only [← nat_cast_mul, push_cast]
    cases k <;> · simp; ring
  · simp only [← nat_cast_mul, push_cast]
    cases n
    · simp
    · 

Proof state:
case calc_2.succ
R : Type u_1
inst✝ : CommRing R
n✝ : ℕ
p :
  ∑ x in Finset.range (Nat.succ n✝ + 1),
      (↑(x * (x - 1)) + (1 - ↑(2 * Nat.succ n✝) * X) * ↑x + ↑(Nat.succ n✝ ^ 2) * X ^ 2) *
        bernsteinPolynomial R (Nat.succ n✝) x =
    ↑(Nat.succ n✝ * (Nat.succ n✝ - 1)) * X ^ 2 + (1 - (2 * Nat.succ n✝) • X) * Nat.succ n✝ • X +
      Nat.succ n✝ ^ 2 • X ^ 2 * 1
⊢ ↑(Nat.succ n✝) * ↑(Nat.succ n✝ - 1) * X ^ 2 + (1 - 2 * ↑(Nat.succ n✝) * X) * (↑(Nat.succ n✝) * X) +
      ↑(Nat.succ n✝) ^ 2 * X ^ 2 * 1 =
    ↑(Nat.succ n✝) * X * (1 - X)

Next tactic:
simp
/-- A certain linear combination of the previous three identities,
which we'll want later.
-/
theorem variance (n : ℕ) :
    (∑ ν in Finset.range (n + 1), (n • Polynomial.X - (ν : R[X])) ^ 2 * bernsteinPolynomial R n ν) =
      n • Polynomial.X * ((1 : R[X]) - Polynomial.X) := by
  have p : ((((Finset.range (n + 1)).sum fun ν => (ν * (ν - 1)) • bernsteinPolynomial R n ν) +
      (1 - (2 * n) • Polynomial.X) * (Finset.range (n + 1)).sum fun ν =>
        ν • bernsteinPolynomial R n ν) + n ^ 2 • X ^ 2 *
          (Finset.range (n + 1)).sum fun ν => bernsteinPolynomial R n ν) = _ :=
    rfl
  conv at p =>
    lhs
    rw [Finset.mul_sum, Finset.mul_sum, ← Finset.sum_add_distrib, ← Finset.sum_add_distrib]
    simp only [← nat_cast_mul]
    simp only [← mul_assoc]
    simp only [← add_mul]
  conv at p =>
    rhs
    rw [sum, sum_smul, sum_mul_smul, ← nat_cast_mul]
  calc
    _ = _ := Finset.sum_congr rfl fun k m => ?_
    _ = _ := p
    _ = _ := ?_
  · congr 1; simp only [← nat_cast_mul, push_cast]
    cases k <;> · simp; ring
  · simp only [← nat_cast_mul, push_cast]
    cases n
    · simp
    · simp; 

Proof state:
case calc_2.succ
R : Type u_1
inst✝ : CommRing R
n✝ : ℕ
p :
  ∑ x in Finset.range (Nat.succ n✝ + 1),
      (↑(x * (x - 1)) + (1 - ↑(2 * Nat.succ n✝) * X) * ↑x + ↑(Nat.succ n✝ ^ 2) * X ^ 2) *
        bernsteinPolynomial R (Nat.succ n✝) x =
    ↑(Nat.succ n✝ * (Nat.succ n✝ - 1)) * X ^ 2 + (1 - (2 * Nat.succ n✝) • X) * Nat.succ n✝ • X +
      Nat.succ n✝ ^ 2 • X ^ 2 * 1
⊢ (↑n✝ + 1) * ↑n✝ * X ^ 2 + (1 - 2 * (↑n✝ + 1) * X) * ((↑n✝ + 1) * X) + (↑n✝ + 1) ^ 2 * X ^ 2 = (↑n✝ + 1) * X * (1 - X)

Next tactic:
ring
instance (M : FGModuleCat R) : AddCommGroup M := by
  

Proof state:
R : Type u
inst✝ : Ring R
M : FGModuleCat R
⊢ AddCommGroup ↑M

Next tactic:
change AddCommGroup M.obj
instance (M : FGModuleCat R) : AddCommGroup M := by
  change AddCommGroup M.obj
  

Proof state:
R : Type u
inst✝ : Ring R
M : FGModuleCat R
⊢ AddCommGroup ↑M.obj

Next tactic:
infer_instance
instance (M : FGModuleCat R) : Module R M := by
  

Proof state:
R : Type u
inst✝ : Ring R
M : FGModuleCat R
⊢ Module R ↑M

Next tactic:
change Module R M.obj
instance (M : FGModuleCat R) : Module R M := by
  change Module R M.obj
  

Proof state:
R : Type u
inst✝ : Ring R
M : FGModuleCat R
⊢ Module R ↑M.obj

Next tactic:
infer_instance
instance : LargeCategory (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ LargeCategory (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : LargeCategory (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ LargeCategory (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
instance : ConcreteCategory (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ ConcreteCategory (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : ConcreteCategory (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ ConcreteCategory (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
instance : Preadditive (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ Preadditive (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : Preadditive (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ Preadditive (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
/-- Lift an unbundled finitely generated module to `FGModuleCat R`. -/
def of (V : Type u) [AddCommGroup V] [Module R V] [Module.Finite R V] : FGModuleCat R :=
  ⟨ModuleCat.of R V, by 

Proof state:
R : Type u
inst✝³ : Ring R
V : Type u
inst✝² : AddCommGroup V
inst✝¹ : Module R V
inst✝ : Module.Finite R V
⊢ Module.Finite R ↑(ModuleCat.of R V)

Next tactic:
change Module.Finite R V
/-- Lift an unbundled finitely generated module to `FGModuleCat R`. -/
def of (V : Type u) [AddCommGroup V] [Module R V] [Module.Finite R V] : FGModuleCat R :=
  ⟨ModuleCat.of R V, by change Module.Finite R V; 

Proof state:
R : Type u
inst✝³ : Ring R
V : Type u
inst✝² : AddCommGroup V
inst✝¹ : Module R V
inst✝ : Module.Finite R V
⊢ Module.Finite R V

Next tactic:
infer_instance
instance : HasForget₂ (FGModuleCat.{u} R) (ModuleCat.{u} R) := by
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ HasForget₂ (FGModuleCat R) (ModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : HasForget₂ (FGModuleCat.{u} R) (ModuleCat.{u} R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : Ring R
⊢ HasForget₂ (FullSubcategory fun V => Module.Finite R ↑V) (ModuleCat R)

Next tactic:
infer_instance
/-- Converts a `LinearEquiv` to an isomorphism in the category `FGModuleCat R`. -/
@[simps]
def _root_.LinearEquiv.toFGModuleCatIso
    {V W : Type u} [AddCommGroup V] [Module R V] [Module.Finite R V]
    [AddCommGroup W] [Module R W] [Module.Finite R W] (e : V ≃ₗ[R] W) :
    FGModuleCat.of R V ≅ FGModuleCat.of R W where
  hom := e.toLinearMap
  inv := e.symm.toLinearMap
  hom_inv_id := by 

Proof state:
R : Type u
inst✝⁶ : Ring R
V W : Type u
inst✝⁵ : AddCommGroup V
inst✝⁴ : Module R V
inst✝³ : Module.Finite R V
inst✝² : AddCommGroup W
inst✝¹ : Module R W
inst✝ : Module.Finite R W
e : V ≃ₗ[R] W
⊢ ↑e ≫ ↑(LinearEquiv.symm e) = 𝟙 (of R V)

Next tactic:
ext x
/-- Converts a `LinearEquiv` to an isomorphism in the category `FGModuleCat R`. -/
@[simps]
def _root_.LinearEquiv.toFGModuleCatIso
    {V W : Type u} [AddCommGroup V] [Module R V] [Module.Finite R V]
    [AddCommGroup W] [Module R W] [Module.Finite R W] (e : V ≃ₗ[R] W) :
    FGModuleCat.of R V ≅ FGModuleCat.of R W where
  hom := e.toLinearMap
  inv := e.symm.toLinearMap
  hom_inv_id := by ext x; 

Proof state:
case w
R : Type u
inst✝⁶ : Ring R
V W : Type u
inst✝⁵ : AddCommGroup V
inst✝⁴ : Module R V
inst✝³ : Module.Finite R V
inst✝² : AddCommGroup W
inst✝¹ : Module R W
inst✝ : Module.Finite R W
e : V ≃ₗ[R] W
x : (forget (FGModuleCat R)).obj (of R V)
⊢ (↑e ≫ ↑(LinearEquiv.symm e)) x = (𝟙 (of R V)) x

Next tactic:
exact e.left_inv x
/-- Converts a `LinearEquiv` to an isomorphism in the category `FGModuleCat R`. -/
@[simps]
def _root_.LinearEquiv.toFGModuleCatIso
    {V W : Type u} [AddCommGroup V] [Module R V] [Module.Finite R V]
    [AddCommGroup W] [Module R W] [Module.Finite R W] (e : V ≃ₗ[R] W) :
    FGModuleCat.of R V ≅ FGModuleCat.of R W where
  hom := e.toLinearMap
  inv := e.symm.toLinearMap
  hom_inv_id := by ext x; exact e.left_inv x
  inv_hom_id := by 

Proof state:
R : Type u
inst✝⁶ : Ring R
V W : Type u
inst✝⁵ : AddCommGroup V
inst✝⁴ : Module R V
inst✝³ : Module.Finite R V
inst✝² : AddCommGroup W
inst✝¹ : Module R W
inst✝ : Module.Finite R W
e : V ≃ₗ[R] W
⊢ ↑(LinearEquiv.symm e) ≫ ↑e = 𝟙 (of R W)

Next tactic:
ext x
/-- Converts a `LinearEquiv` to an isomorphism in the category `FGModuleCat R`. -/
@[simps]
def _root_.LinearEquiv.toFGModuleCatIso
    {V W : Type u} [AddCommGroup V] [Module R V] [Module.Finite R V]
    [AddCommGroup W] [Module R W] [Module.Finite R W] (e : V ≃ₗ[R] W) :
    FGModuleCat.of R V ≅ FGModuleCat.of R W where
  hom := e.toLinearMap
  inv := e.symm.toLinearMap
  hom_inv_id := by ext x; exact e.left_inv x
  inv_hom_id := by ext x; 

Proof state:
case w
R : Type u
inst✝⁶ : Ring R
V W : Type u
inst✝⁵ : AddCommGroup V
inst✝⁴ : Module R V
inst✝³ : Module.Finite R V
inst✝² : AddCommGroup W
inst✝¹ : Module R W
inst✝ : Module.Finite R W
e : V ≃ₗ[R] W
x : (forget (FGModuleCat R)).obj (of R W)
⊢ (↑(LinearEquiv.symm e) ≫ ↑e) x = (𝟙 (of R W)) x

Next tactic:
exact e.right_inv x
instance : Linear R (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Linear R (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : Linear R (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Linear R (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
instance : MonoidalCategory (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ MonoidalCategory (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : MonoidalCategory (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ MonoidalCategory (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
instance : SymmetricCategory (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ SymmetricCategory (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : SymmetricCategory (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ SymmetricCategory (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
instance : MonoidalPreadditive (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ MonoidalPreadditive (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : MonoidalPreadditive (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ MonoidalPreadditive (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
instance : MonoidalLinear R (FGModuleCat R) := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ MonoidalLinear R (FGModuleCat R)

Next tactic:
dsimp [FGModuleCat]
instance : MonoidalLinear R (FGModuleCat R) := by
  dsimp [FGModuleCat]
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ MonoidalLinear R (FullSubcategory fun V => Module.Finite R ↑V)

Next tactic:
infer_instance
instance forget₂Monoidal_faithful : Faithful (forget₂Monoidal R).toFunctor := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Faithful (forget₂Monoidal R).toLaxMonoidalFunctor.toFunctor

Next tactic:
dsimp [forget₂Monoidal]
instance forget₂Monoidal_faithful : Faithful (forget₂Monoidal R).toFunctor := by
  dsimp [forget₂Monoidal]
  -- Porting note: was `infer_instance`
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Faithful (fullSubcategoryInclusion fun V => Module.Finite R ↑V)

Next tactic:
exact FullSubcategory.faithful _
instance forget₂Monoidal_additive : (forget₂Monoidal R).toFunctor.Additive := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Functor.Additive (forget₂Monoidal R).toLaxMonoidalFunctor.toFunctor

Next tactic:
dsimp [forget₂Monoidal]
instance forget₂Monoidal_additive : (forget₂Monoidal R).toFunctor.Additive := by
  dsimp [forget₂Monoidal]
  -- Porting note: was `infer_instance`
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Functor.Additive (fullSubcategoryInclusion fun V => Module.Finite R ↑V)

Next tactic:
exact Functor.fullSubcategoryInclusion_additive _
instance forget₂Monoidal_linear : (forget₂Monoidal R).toFunctor.Linear R := by
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Functor.Linear R (forget₂Monoidal R).toLaxMonoidalFunctor.toFunctor

Next tactic:
dsimp [forget₂Monoidal]
instance forget₂Monoidal_linear : (forget₂Monoidal R).toFunctor.Linear R := by
  dsimp [forget₂Monoidal]
  -- Porting note: was `infer_instance`
  

Proof state:
R : Type u
inst✝ : CommRing R
⊢ Functor.Linear R (fullSubcategoryInclusion fun V => Module.Finite R ↑V)

Next tactic:
exact Functor.fullSubcategoryInclusionLinear _ _
instance (V W : FGModuleCat K) : Module.Finite K (V ⟶ W) :=
  (by 

Proof state:
K : Type u
inst✝ : Field K
V W : FGModuleCat K
⊢ Module.Finite K (↑V →ₗ[K] ↑W)

Next tactic:
infer_instance
instance : MonoidalClosed (FGModuleCat K) := by
  

Proof state:
K : Type u
inst✝ : Field K
⊢ MonoidalClosed (FGModuleCat K)

Next tactic:
dsimp [FGModuleCat]
instance : MonoidalClosed (FGModuleCat K) := by
  dsimp [FGModuleCat]
  -- Porting note: was `infer_instance`
  

Proof state:
K : Type u
inst✝ : Field K
⊢ MonoidalClosed (FullSubcategory fun V => Module.Finite K ↑V)

Next tactic:
exact MonoidalCategory.fullMonoidalClosedSubcategory
    (fun V : ModuleCat.{u} K => Module.Finite K V)
private theorem coevaluation_evaluation :
    letI V' : FGModuleCat K := FGModuleCatDual K V
    (𝟙 V' ⊗ FGModuleCatCoevaluation K V) ≫ (α_ V' V V').inv ≫ (FGModuleCatEvaluation K V ⊗ 𝟙 V') =
      (ρ_ V').hom ≫ (λ_ V').inv := by
  

Proof state:
K : Type u
inst✝ : Field K
V W : FGModuleCat K
⊢ (𝟙 (FGModuleCatDual K V) ⊗ FGModuleCatCoevaluation K V) ≫
      (α_ (FGModuleCatDual K V) V (FGModuleCatDual K V)).inv ≫ (FGModuleCatEvaluation K V ⊗ 𝟙 (FGModuleCatDual K V)) =
    (ρ_ (FGModuleCatDual K V)).hom ≫ (λ_ (FGModuleCatDual K V)).inv

Next tactic:
apply contractLeft_assoc_coevaluation K V
private theorem evaluation_coevaluation :
    (FGModuleCatCoevaluation K V ⊗ 𝟙 V) ≫
        (α_ V (FGModuleCatDual K V) V).hom ≫ (𝟙 V ⊗ FGModuleCatEvaluation K V) =
      (λ_ V).hom ≫ (ρ_ V).inv := by
  

Proof state:
K : Type u
inst✝ : Field K
V W : FGModuleCat K
⊢ (FGModuleCatCoevaluation K V ⊗ 𝟙 V) ≫ (α_ V (FGModuleCatDual K V) V).hom ≫ (𝟙 V ⊗ FGModuleCatEvaluation K V) =
    (λ_ V).hom ≫ (ρ_ V).inv

Next tactic:
apply contractLeft_assoc_coevaluation' K V
/-- If an element `x` is a root of a nonzero polynomial `p`, then the degree of `p` is at least the
degree of the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.degree_le_of_ne_zero`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem degree_le_of_ne_zero {p : A[X]} (pnz : p ≠ 0) (hp : Polynomial.aeval x p = 0) :
    degree (minpoly A x) ≤ degree p :=
  calc
    degree (minpoly A x) ≤ degree (p * C (leadingCoeff p)⁻¹) :=
      min A x (monic_mul_leadingCoeff_inv pnz) (by 

Proof state:
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pnz : p ≠ 0
hp : (Polynomial.aeval x) p = 0
⊢ (Polynomial.aeval x) (p * C (leadingCoeff p)⁻¹) = 0

Next tactic:
simp [hp]
/-- The minimal polynomial of an element `x` is uniquely characterized by its defining property:
if there is another monic polynomial of minimal degree that has `x` as a root, then this polynomial
is equal to the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.Minpoly.unique`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem unique {p : A[X]} (pmonic : p.Monic) (hp : Polynomial.aeval x p = 0)
    (pmin : ∀ q : A[X], q.Monic → Polynomial.aeval x q = 0 → degree p ≤ degree q) :
    p = minpoly A x := by
  

Proof state:
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pmonic : Monic p
hp : (Polynomial.aeval x) p = 0
pmin : ∀ (q : A[X]), Monic q → (Polynomial.aeval x) q = 0 → degree p ≤ degree q
⊢ p = minpoly A x

Next tactic:
have hx : IsIntegral A x := ⟨p, pmonic, hp⟩
/-- The minimal polynomial of an element `x` is uniquely characterized by its defining property:
if there is another monic polynomial of minimal degree that has `x` as a root, then this polynomial
is equal to the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.Minpoly.unique`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem unique {p : A[X]} (pmonic : p.Monic) (hp : Polynomial.aeval x p = 0)
    (pmin : ∀ q : A[X], q.Monic → Polynomial.aeval x q = 0 → degree p ≤ degree q) :
    p = minpoly A x := by
  have hx : IsIntegral A x := ⟨p, pmonic, hp⟩
  

Proof state:
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pmonic : Monic p
hp : (Polynomial.aeval x) p = 0
pmin : ∀ (q : A[X]), Monic q → (Polynomial.aeval x) q = 0 → degree p ≤ degree q
hx : IsIntegral A x
⊢ p = minpoly A x

Next tactic:
symm
/-- The minimal polynomial of an element `x` is uniquely characterized by its defining property:
if there is another monic polynomial of minimal degree that has `x` as a root, then this polynomial
is equal to the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.Minpoly.unique`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem unique {p : A[X]} (pmonic : p.Monic) (hp : Polynomial.aeval x p = 0)
    (pmin : ∀ q : A[X], q.Monic → Polynomial.aeval x q = 0 → degree p ≤ degree q) :
    p = minpoly A x := by
  have hx : IsIntegral A x := ⟨p, pmonic, hp⟩
  symm; 

Proof state:
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pmonic : Monic p
hp : (Polynomial.aeval x) p = 0
pmin : ∀ (q : A[X]), Monic q → (Polynomial.aeval x) q = 0 → degree p ≤ degree q
hx : IsIntegral A x
⊢ minpoly A x = p

Next tactic:
apply eq_of_sub_eq_zero
/-- The minimal polynomial of an element `x` is uniquely characterized by its defining property:
if there is another monic polynomial of minimal degree that has `x` as a root, then this polynomial
is equal to the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.Minpoly.unique`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem unique {p : A[X]} (pmonic : p.Monic) (hp : Polynomial.aeval x p = 0)
    (pmin : ∀ q : A[X], q.Monic → Polynomial.aeval x q = 0 → degree p ≤ degree q) :
    p = minpoly A x := by
  have hx : IsIntegral A x := ⟨p, pmonic, hp⟩
  symm; apply eq_of_sub_eq_zero
  

Proof state:
case h
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pmonic : Monic p
hp : (Polynomial.aeval x) p = 0
pmin : ∀ (q : A[X]), Monic q → (Polynomial.aeval x) q = 0 → degree p ≤ degree q
hx : IsIntegral A x
⊢ minpoly A x - p = 0

Next tactic:
by_contra hnz
/-- The minimal polynomial of an element `x` is uniquely characterized by its defining property:
if there is another monic polynomial of minimal degree that has `x` as a root, then this polynomial
is equal to the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.Minpoly.unique`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem unique {p : A[X]} (pmonic : p.Monic) (hp : Polynomial.aeval x p = 0)
    (pmin : ∀ q : A[X], q.Monic → Polynomial.aeval x q = 0 → degree p ≤ degree q) :
    p = minpoly A x := by
  have hx : IsIntegral A x := ⟨p, pmonic, hp⟩
  symm; apply eq_of_sub_eq_zero
  by_contra hnz
  

Proof state:
case h
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pmonic : Monic p
hp : (Polynomial.aeval x) p = 0
pmin : ∀ (q : A[X]), Monic q → (Polynomial.aeval x) q = 0 → degree p ≤ degree q
hx : IsIntegral A x
hnz : ¬minpoly A x - p = 0
⊢ False

Next tactic:
have hd := degree_le_of_ne_zero A x hnz (by simp [hp])
/-- The minimal polynomial of an element `x` is uniquely characterized by its defining property:
if there is another monic polynomial of minimal degree that has `x` as a root, then this polynomial
is equal to the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.Minpoly.unique`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem unique {p : A[X]} (pmonic : p.Monic) (hp : Polynomial.aeval x p = 0)
    (pmin : ∀ q : A[X], q.Monic → Polynomial.aeval x q = 0 → degree p ≤ degree q) :
    p = minpoly A x := by
  have hx : IsIntegral A x := ⟨p, pmonic, hp⟩
  symm; apply eq_of_sub_eq_zero
  by_contra hnz
  have hd := degree_le_of_ne_zero A x hnz (by 

Proof state:
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pmonic : Monic p
hp : (Polynomial.aeval x) p = 0
pmin : ∀ (q : A[X]), Monic q → (Polynomial.aeval x) q = 0 → degree p ≤ degree q
hx : IsIntegral A x
hnz : ¬minpoly A x - p = 0
⊢ (Polynomial.aeval x) (minpoly A x - p) = 0

Next tactic:
simp [hp]
/-- The minimal polynomial of an element `x` is uniquely characterized by its defining property:
if there is another monic polynomial of minimal degree that has `x` as a root, then this polynomial
is equal to the minimal polynomial of `x`. See also `minpoly.IsIntegrallyClosed.Minpoly.unique`
which relaxes the assumptions on `A` in exchange for stronger assumptions on `B`. -/
theorem unique {p : A[X]} (pmonic : p.Monic) (hp : Polynomial.aeval x p = 0)
    (pmin : ∀ q : A[X], q.Monic → Polynomial.aeval x q = 0 → degree p ≤ degree q) :
    p = minpoly A x := by
  have hx : IsIntegral A x := ⟨p, pmonic, hp⟩
  symm; apply eq_of_sub_eq_zero
  by_contra hnz
  have hd := degree_le_of_ne_zero A x hnz (by simp [hp])
  

Proof state:
case h
A : Type u_1
B : Type u_2
inst✝² : Field A
inst✝¹ : Ring B
inst✝ : Algebra A B
x : B
p : A[X]
pmonic : Monic p
hp : (Polynomial.aeval x) p = 0
pmin : ∀ (q : A[X]), Monic q → (Polynomial.aeval x) q = 0 → degree p ≤ degree q
hx : IsIntegral A x
hnz : ¬minpoly A x - p = 0
hd : degree (minpoly A x) ≤ degree (minpoly A x - p)
⊢ False

Next tactic:
contrapose! hd