l3lab/ntp-mathlib huggingface dataset:
/-- Constructs an equivalence between bounded orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : BddOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : BoundedOrderHom _ _)
  inv := (e.symm : BoundedOrderHom _ _)
  hom_inv_id := by 

Proof state:
α β : BddOrd
e : ↑α.toPartOrd ≃o ↑β.toPartOrd
⊢ ↑e ≫ ↑(OrderIso.symm e) = 𝟙 α

Next tactic:
ext
/-- Constructs an equivalence between bounded orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : BddOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : BoundedOrderHom _ _)
  inv := (e.symm : BoundedOrderHom _ _)
  hom_inv_id := by ext; 

Proof state:
case w
α β : BddOrd
e : ↑α.toPartOrd ≃o ↑β.toPartOrd
x✝ : (forget BddOrd).obj α
⊢ (↑e ≫ ↑(OrderIso.symm e)) x✝ = (𝟙 α) x✝

Next tactic:
exact e.symm_apply_apply _
/-- Constructs an equivalence between bounded orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : BddOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : BoundedOrderHom _ _)
  inv := (e.symm : BoundedOrderHom _ _)
  hom_inv_id := by ext; exact e.symm_apply_apply _
  inv_hom_id := by 

Proof state:
α β : BddOrd
e : ↑α.toPartOrd ≃o ↑β.toPartOrd
⊢ ↑(OrderIso.symm e) ≫ ↑e = 𝟙 β

Next tactic:
ext
/-- Constructs an equivalence between bounded orders from an order isomorphism between them. -/
@[simps]
def Iso.mk {α β : BddOrd.{u}} (e : α ≃o β) : α ≅ β where
  hom := (e : BoundedOrderHom _ _)
  inv := (e.symm : BoundedOrderHom _ _)
  hom_inv_id := by ext; exact e.symm_apply_apply _
  inv_hom_id := by ext; 

Proof state:
case w
α β : BddOrd
e : ↑α.toPartOrd ≃o ↑β.toPartOrd
x✝ : (forget BddOrd).obj β
⊢ (↑(OrderIso.symm e) ≫ ↑e) x✝ = (𝟙 β) x✝

Next tactic:
exact e.apply_symm_apply _
protected theorem nontrivial [IsDomain R] (h : degree f ≠ 0) : Nontrivial (AdjoinRoot f) :=
  Ideal.Quotient.nontrivial
    (by
      

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
h : degree f ≠ 0
⊢ span {f} ≠ ⊤

Next tactic:
simp_rw [Ne.def, span_singleton_eq_top, Polynomial.isUnit_iff, not_exists, not_and]
protected theorem nontrivial [IsDomain R] (h : degree f ≠ 0) : Nontrivial (AdjoinRoot f) :=
  Ideal.Quotient.nontrivial
    (by
      simp_rw [Ne.def, span_singleton_eq_top, Polynomial.isUnit_iff, not_exists, not_and]
      

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
h : degree f ≠ 0
⊢ ∀ (x : R), IsUnit x → ¬C x = f

Next tactic:
rintro x hx rfl
protected theorem nontrivial [IsDomain R] (h : degree f ≠ 0) : Nontrivial (AdjoinRoot f) :=
  Ideal.Quotient.nontrivial
    (by
      simp_rw [Ne.def, span_singleton_eq_top, Polynomial.isUnit_iff, not_exists, not_and]
      rintro x hx rfl
      

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
inst✝ : IsDomain R
x : R
hx : IsUnit x
h : degree (C x) ≠ 0
⊢ False

Next tactic:
exact h (degree_C hx.ne_zero)
theorem smul_of [DistribSMul S R] [IsScalarTower S R R] (a : S) (x : R) :
    a • of f x = of f (a • x) := by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f : R[X]
inst✝¹ : DistribSMul S R
inst✝ : IsScalarTower S R R
a : S
x : R
⊢ a • (of f) x = (of f) (a • x)

Next tactic:
rw [of, RingHom.comp_apply, RingHom.comp_apply, smul_mk, smul_C]
@[simp]
theorem mk_eq_zero {g : R[X]} : mk f g = 0 ↔ f ∣ g :=
  mk_eq_mk.trans <| by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f g : R[X]
⊢ f ∣ g - 0 ↔ f ∣ g

Next tactic:
rw [sub_zero]
@[simp]
theorem mk_self : mk f f = 0 :=
  Quotient.sound' <| QuotientAddGroup.leftRel_apply.mpr (mem_span_singleton.2 <| by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f : R[X]
⊢ f ∣ -f + 0

Next tactic:
simp
@[simp]
theorem aeval_eq (p : R[X]) : aeval (root f) p = mk f p :=
  Polynomial.induction_on p
    (fun x => by
      

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f p : R[X]
x : R
⊢ (aeval (root f)) (C x) = (mk f) (C x)

Next tactic:
rw [aeval_C]
@[simp]
theorem aeval_eq (p : R[X]) : aeval (root f) p = mk f p :=
  Polynomial.induction_on p
    (fun x => by
      rw [aeval_C]
      

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f p : R[X]
x : R
⊢ (algebraMap R (AdjoinRoot f)) x = (mk f) (C x)

Next tactic:
rfl
@[simp]
theorem aeval_eq (p : R[X]) : aeval (root f) p = mk f p :=
  Polynomial.induction_on p
    (fun x => by
      rw [aeval_C]
      rfl)
    (fun p q ihp ihq => by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f p✝ p q : R[X]
ihp : (aeval (root f)) p = (mk f) p
ihq : (aeval (root f)) q = (mk f) q
⊢ (aeval (root f)) (p + q) = (mk f) (p + q)

Next tactic:
rw [AlgHom.map_add, RingHom.map_add, ihp, ihq]
@[simp]
theorem aeval_eq (p : R[X]) : aeval (root f) p = mk f p :=
  Polynomial.induction_on p
    (fun x => by
      rw [aeval_C]
      rfl)
    (fun p q ihp ihq => by rw [AlgHom.map_add, RingHom.map_add, ihp, ihq]) fun n x _ => by
    

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f p : R[X]
n : ℕ
x : R
x✝ : (aeval (root f)) (C x * X ^ n) = (mk f) (C x * X ^ n)
⊢ (aeval (root f)) (C x * X ^ (n + 1)) = (mk f) (C x * X ^ (n + 1))

Next tactic:
rw [AlgHom.map_mul, aeval_C, AlgHom.map_pow, aeval_X, RingHom.map_mul, mk_C, RingHom.map_pow,
      mk_X]
@[simp]
theorem aeval_eq (p : R[X]) : aeval (root f) p = mk f p :=
  Polynomial.induction_on p
    (fun x => by
      rw [aeval_C]
      rfl)
    (fun p q ihp ihq => by rw [AlgHom.map_add, RingHom.map_add, ihp, ihq]) fun n x _ => by
    rw [AlgHom.map_mul, aeval_C, AlgHom.map_pow, aeval_X, RingHom.map_mul, mk_C, RingHom.map_pow,
      mk_X]
    

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f p : R[X]
n : ℕ
x : R
x✝ : (aeval (root f)) (C x * X ^ n) = (mk f) (C x * X ^ n)
⊢ (algebraMap R (AdjoinRoot f)) x * root f ^ (n + 1) = (of f) x * root f ^ (n + 1)

Next tactic:
rfl
theorem adjoinRoot_eq_top : Algebra.adjoin R ({root f} : Set (AdjoinRoot f)) = ⊤ := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f : R[X]
⊢ Algebra.adjoin R {root f} = ⊤

Next tactic:
refine Algebra.eq_top_iff.2 fun x => ?_
theorem adjoinRoot_eq_top : Algebra.adjoin R ({root f} : Set (AdjoinRoot f)) = ⊤ := by
  refine Algebra.eq_top_iff.2 fun x => ?_
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f : R[X]
x : AdjoinRoot f
⊢ x ∈ Algebra.adjoin R {root f}

Next tactic:
induction x using AdjoinRoot.induction_on with
    | ih p => exact (Algebra.adjoin_singleton_eq_range_aeval R (root f)).symm ▸ ⟨p, aeval_eq p⟩
theorem adjoinRoot_eq_top : Algebra.adjoin R ({root f} : Set (AdjoinRoot f)) = ⊤ := by
  refine Algebra.eq_top_iff.2 fun x => ?_
  induction x using AdjoinRoot.induction_on with
    

Proof state:
case ih
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f p : R[X]
⊢ (mk f) p ∈ Algebra.adjoin R {root f}

Next tactic:
| ih p => exact (Algebra.adjoin_singleton_eq_range_aeval R (root f)).symm ▸ ⟨p, aeval_eq p⟩
theorem adjoinRoot_eq_top : Algebra.adjoin R ({root f} : Set (AdjoinRoot f)) = ⊤ := by
  refine Algebra.eq_top_iff.2 fun x => ?_
  induction x using AdjoinRoot.induction_on with
    | ih p => 

Proof state:
case ih
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f p : R[X]
⊢ (mk f) p ∈ Algebra.adjoin R {root f}

Next tactic:
exact (Algebra.adjoin_singleton_eq_range_aeval R (root f)).symm ▸ ⟨p, aeval_eq p⟩
@[simp]
theorem eval₂_root (f : R[X]) : f.eval₂ (of f) (root f) = 0 := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f✝ f : R[X]
⊢ eval₂ (of f) (root f) f = 0

Next tactic:
rw [← algebraMap_eq, ← aeval_def, aeval_eq, mk_self]
theorem isRoot_root (f : R[X]) : IsRoot (f.map (of f)) (root f) := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝ : CommRing R
f✝ f : R[X]
⊢ IsRoot (Polynomial.map (of f) f) (root f)

Next tactic:
rw [IsRoot, eval_map, eval₂_root]
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
hf : degree f ≠ 0
⊢ Function.Injective ⇑(of f)

Next tactic:
rw [injective_iff_map_eq_zero]
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
hf : degree f ≠ 0
⊢ ∀ (a : R), (of f) a = 0 → a = 0

Next tactic:
intro p hp
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
hf : degree f ≠ 0
p : R
hp : (of f) p = 0
⊢ p = 0

Next tactic:
rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
hf : degree f ≠ 0
p : R
hp : f ∣ C p
⊢ p = 0

Next tactic:
by_cases h : f = 0
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  by_cases h : f = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
hf : degree f ≠ 0
p : R
hp : f ∣ C p
h : f = 0
⊢ p = 0

Next tactic:
exact C_eq_zero.mp (eq_zero_of_zero_dvd (by rwa [h] at hp))
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  by_cases h : f = 0
  · exact C_eq_zero.mp (eq_zero_of_zero_dvd (by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
hf : degree f ≠ 0
p : R
hp : f ∣ C p
h : f = 0
⊢ 0 ∣ C p

Next tactic:
rwa [h] at hp
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  by_cases h : f = 0
  · exact C_eq_zero.mp (eq_zero_of_zero_dvd (by rwa [h] at hp))
  · 

Proof state:
case neg
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
hf : degree f ≠ 0
p : R
hp : f ∣ C p
h : ¬f = 0
⊢ p = 0

Next tactic:
contrapose! hf with h_contra
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  by_cases h : f = 0
  · exact C_eq_zero.mp (eq_zero_of_zero_dvd (by rwa [h] at hp))
  · contrapose! hf with h_contra
    

Proof state:
case neg
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
p : R
hp : f ∣ C p
h : ¬f = 0
h_contra : p ≠ 0
⊢ degree f = 0

Next tactic:
rw [← degree_C h_contra]
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  by_cases h : f = 0
  · exact C_eq_zero.mp (eq_zero_of_zero_dvd (by rwa [h] at hp))
  · contrapose! hf with h_contra
    rw [← degree_C h_contra]
    

Proof state:
case neg
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
p : R
hp : f ∣ C p
h : ¬f = 0
h_contra : p ≠ 0
⊢ degree f = degree (C p)

Next tactic:
apply le_antisymm (degree_le_of_dvd hp (by rwa [Ne.def, C_eq_zero])) _
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  by_cases h : f = 0
  · exact C_eq_zero.mp (eq_zero_of_zero_dvd (by rwa [h] at hp))
  · contrapose! hf with h_contra
    rw [← degree_C h_contra]
    apply le_antisymm (degree_le_of_dvd hp (by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
p : R
hp : f ∣ C p
h : ¬f = 0
h_contra : p ≠ 0
⊢ C p ≠ 0

Next tactic:
rwa [Ne.def, C_eq_zero]
theorem of.injective_of_degree_ne_zero [IsDomain R] (hf : f.degree ≠ 0) :
    Function.Injective (AdjoinRoot.of f) := by
  rw [injective_iff_map_eq_zero]
  intro p hp
  rw [AdjoinRoot.of, RingHom.comp_apply, AdjoinRoot.mk_eq_zero] at hp
  by_cases h : f = 0
  · exact C_eq_zero.mp (eq_zero_of_zero_dvd (by rwa [h] at hp))
  · contrapose! hf with h_contra
    rw [← degree_C h_contra]
    apply le_antisymm (degree_le_of_dvd hp (by rwa [Ne.def, C_eq_zero])) _
    

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : IsDomain R
p : R
hp : f ∣ C p
h : ¬f = 0
h_contra : p ≠ 0
⊢ degree (C p) ≤ degree f

Next tactic:
rwa [degree_C h_contra, zero_le_degree_iff]
/-- Lift a ring homomorphism `i : R →+* S` to `AdjoinRoot f →+* S`. -/
def lift (i : R →+* S) (x : S) (h : f.eval₂ i x = 0) : AdjoinRoot f →+* S := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : CommRing S
i : R →+* S
x : S
h : eval₂ i x f = 0
⊢ AdjoinRoot f →+* S

Next tactic:
apply Ideal.Quotient.lift _ (eval₂RingHom i x)
/-- Lift a ring homomorphism `i : R →+* S` to `AdjoinRoot f →+* S`. -/
def lift (i : R →+* S) (x : S) (h : f.eval₂ i x = 0) : AdjoinRoot f →+* S := by
  apply Ideal.Quotient.lift _ (eval₂RingHom i x)
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : CommRing S
i : R →+* S
x : S
h : eval₂ i x f = 0
⊢ ∀ a ∈ span {f}, (eval₂RingHom i x) a = 0

Next tactic:
intro g H
/-- Lift a ring homomorphism `i : R →+* S` to `AdjoinRoot f →+* S`. -/
def lift (i : R →+* S) (x : S) (h : f.eval₂ i x = 0) : AdjoinRoot f →+* S := by
  apply Ideal.Quotient.lift _ (eval₂RingHom i x)
  intro g H
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : CommRing S
i : R →+* S
x : S
h : eval₂ i x f = 0
g : R[X]
H : g ∈ span {f}
⊢ (eval₂RingHom i x) g = 0

Next tactic:
rcases mem_span_singleton.1 H with ⟨y, hy⟩
/-- Lift a ring homomorphism `i : R →+* S` to `AdjoinRoot f →+* S`. -/
def lift (i : R →+* S) (x : S) (h : f.eval₂ i x = 0) : AdjoinRoot f →+* S := by
  apply Ideal.Quotient.lift _ (eval₂RingHom i x)
  intro g H
  rcases mem_span_singleton.1 H with ⟨y, hy⟩
  

Proof state:
case intro
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : CommRing S
i : R →+* S
x : S
h : eval₂ i x f = 0
g : R[X]
H : g ∈ span {f}
y : R[X]
hy : g = f * y
⊢ (eval₂RingHom i x) g = 0

Next tactic:
rw [hy, RingHom.map_mul, coe_eval₂RingHom, h, zero_mul]
@[simp]
theorem lift_root : lift i a h (root f) = a := by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f = 0
⊢ (lift i a h) (root f) = a

Next tactic:
rw [root, lift_mk, eval₂_X]
@[simp]
theorem lift_of {x : R} : lift i a h x = i x := by 

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : CommRing R
f : R[X]
inst✝ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f = 0
x : R
⊢ (lift i a h) ((of f) x) = i x

Next tactic:
rw [← mk_C x, lift_mk, eval₂_C]
@[simp]
theorem aeval_algHom_eq_zero (ϕ : AdjoinRoot f →ₐ[R] S) : aeval (ϕ (root f)) f = 0 := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f = 0
inst✝ : Algebra R S
ϕ : AdjoinRoot f →ₐ[R] S
⊢ (aeval (ϕ (root f))) f = 0

Next tactic:
have h : ϕ.toRingHom.comp (of f) = algebraMap R S := RingHom.ext_iff.mpr ϕ.commutes
@[simp]
theorem aeval_algHom_eq_zero (ϕ : AdjoinRoot f →ₐ[R] S) : aeval (ϕ (root f)) f = 0 := by
  have h : ϕ.toRingHom.comp (of f) = algebraMap R S := RingHom.ext_iff.mpr ϕ.commutes
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h✝ : eval₂ i a f = 0
inst✝ : Algebra R S
ϕ : AdjoinRoot f →ₐ[R] S
h : RingHom.comp (↑ϕ) (of f) = algebraMap R S
⊢ (aeval (ϕ (root f))) f = 0

Next tactic:
rw [aeval_def, ← h, ← RingHom.map_zero ϕ.toRingHom, ← eval₂_root f, hom_eval₂]
@[simp]
theorem aeval_algHom_eq_zero (ϕ : AdjoinRoot f →ₐ[R] S) : aeval (ϕ (root f)) f = 0 := by
  have h : ϕ.toRingHom.comp (of f) = algebraMap R S := RingHom.ext_iff.mpr ϕ.commutes
  rw [aeval_def, ← h, ← RingHom.map_zero ϕ.toRingHom, ← eval₂_root f, hom_eval₂]
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h✝ : eval₂ i a f = 0
inst✝ : Algebra R S
ϕ : AdjoinRoot f →ₐ[R] S
h : RingHom.comp (↑ϕ) (of f) = algebraMap R S
⊢ eval₂ (RingHom.comp (↑ϕ) (of f)) (ϕ (root f)) f = eval₂ (RingHom.comp (↑ϕ) (of f)) (↑ϕ (root f)) f

Next tactic:
rfl
@[simp]
theorem liftHom_eq_algHom (f : R[X]) (ϕ : AdjoinRoot f →ₐ[R] S) :
    liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ) = ϕ := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f✝ : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f✝ = 0
inst✝ : Algebra R S
f : R[X]
ϕ : AdjoinRoot f →ₐ[R] S
⊢ liftHom f (ϕ (root f)) (_ : (aeval (ϕ (root f))) f = 0) = ϕ

Next tactic:
suffices ϕ.equalizer (liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ)) = ⊤ by
    exact (AlgHom.ext fun x => (SetLike.ext_iff.mp this x).mpr Algebra.mem_top).symm
@[simp]
theorem liftHom_eq_algHom (f : R[X]) (ϕ : AdjoinRoot f →ₐ[R] S) :
    liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ) = ϕ := by
  suffices ϕ.equalizer (liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ)) = ⊤ by
    

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f✝ : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f✝ = 0
inst✝ : Algebra R S
f : R[X]
ϕ : AdjoinRoot f →ₐ[R] S
this : AlgHom.equalizer ϕ (liftHom f (ϕ (root f)) (_ : (aeval (ϕ (root f))) f = 0)) = ⊤
⊢ liftHom f (ϕ (root f)) (_ : (aeval (ϕ (root f))) f = 0) = ϕ

Next tactic:
exact (AlgHom.ext fun x => (SetLike.ext_iff.mp this x).mpr Algebra.mem_top).symm
@[simp]
theorem liftHom_eq_algHom (f : R[X]) (ϕ : AdjoinRoot f →ₐ[R] S) :
    liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ) = ϕ := by
  suffices ϕ.equalizer (liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ)) = ⊤ by
    exact (AlgHom.ext fun x => (SetLike.ext_iff.mp this x).mpr Algebra.mem_top).symm
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f✝ : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f✝ = 0
inst✝ : Algebra R S
f : R[X]
ϕ : AdjoinRoot f →ₐ[R] S
⊢ AlgHom.equalizer ϕ (liftHom f (ϕ (root f)) (_ : (aeval (ϕ (root f))) f = 0)) = ⊤

Next tactic:
rw [eq_top_iff, ← adjoinRoot_eq_top, Algebra.adjoin_le_iff, Set.singleton_subset_iff]
@[simp]
theorem liftHom_eq_algHom (f : R[X]) (ϕ : AdjoinRoot f →ₐ[R] S) :
    liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ) = ϕ := by
  suffices ϕ.equalizer (liftHom f (ϕ (root f)) (aeval_algHom_eq_zero f ϕ)) = ⊤ by
    exact (AlgHom.ext fun x => (SetLike.ext_iff.mp this x).mpr Algebra.mem_top).symm
  rw [eq_top_iff, ← adjoinRoot_eq_top, Algebra.adjoin_le_iff, Set.singleton_subset_iff]
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f✝ : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f✝ = 0
inst✝ : Algebra R S
f : R[X]
ϕ : AdjoinRoot f →ₐ[R] S
⊢ root f ∈ ↑(AlgHom.equalizer ϕ (liftHom f (ϕ (root f)) (_ : (aeval (ϕ (root f))) f = 0)))

Next tactic:
exact (@lift_root _ _ _ _ _ _ _ (aeval_algHom_eq_zero f ϕ)).symm
@[simp]
theorem root_isInv (r : R) : of _ r * root (C r * X - 1) = 1 := by
  

Proof state:
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f = 0
inst✝ : Algebra R S
hfx : (aeval a) f = 0
r : R
⊢ (of (C r * X - 1)) r * root (C r * X - 1) = 1

Next tactic:
convert sub_eq_zero.1 ((eval₂_sub _).symm.trans <| eval₂_root <| C r * X - 1)
@[simp]
theorem root_isInv (r : R) : of _ r * root (C r * X - 1) = 1 := by
  convert sub_eq_zero.1 ((eval₂_sub _).symm.trans <| eval₂_root <| C r * X - 1) <;>
    

Proof state:
case h.e'_2
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f = 0
inst✝ : Algebra R S
hfx : (aeval a) f = 0
r : R
⊢ (of (C r * X - 1)) r * root (C r * X - 1) = eval₂ (of (C r * X - 1)) (root (C r * X - 1)) (C r * X)

Next tactic:
simp only [eval₂_mul, eval₂_C, eval₂_X, eval₂_one]
@[simp]
theorem root_isInv (r : R) : of _ r * root (C r * X - 1) = 1 := by
  convert sub_eq_zero.1 ((eval₂_sub _).symm.trans <| eval₂_root <| C r * X - 1) <;>
    

Proof state:
case h.e'_3
R : Type u
S : Type v
K : Type w
inst✝² : CommRing R
f : R[X]
inst✝¹ : CommRing S
i : R →+* S
a : S
h : eval₂ i a f = 0
inst✝ : Algebra R S
hfx : (aeval a) f = 0
r : R
⊢ 1 = eval₂ (of (C r * X - 1)) (root (C r * X - 1)) 1

Next tactic:
simp only [eval₂_mul, eval₂_C, eval₂_X, eval₂_one]
theorem algHom_subsingleton {S : Type*} [CommRing S] [Algebra R S] {r : R} :
    Subsingleton (AdjoinRoot (C r * X - 1) →ₐ[R] S) :=
  ⟨fun f g =>
    algHom_ext
      (@inv_unique _ _ (algebraMap R S r) _ _
        (by 

Proof state:
R : Type u
S✝ : Type v
K : Type w
inst✝⁴ : CommRing R
f✝ : R[X]
inst✝³ : CommRing S✝
i : R →+* S✝
a : S✝
h : eval₂ i a f✝ = 0
inst✝² : Algebra R S✝
hfx : (aeval a) f✝ = 0
S : Type u_1
inst✝¹ : CommRing S
inst✝ : Algebra R S
r : R
f g : AdjoinRoot (C r * X - 1) →ₐ[R] S
⊢ (algebraMap R S) r * f (root (C r * X - 1)) = 1

Next tactic:
rw [← f.commutes, ← f.map_mul, algebraMap_eq, root_isInv, map_one]
theorem algHom_subsingleton {S : Type*} [CommRing S] [Algebra R S] {r : R} :
    Subsingleton (AdjoinRoot (C r * X - 1) →ₐ[R] S) :=
  ⟨fun f g =>
    algHom_ext
      (@inv_unique _ _ (algebraMap R S r) _ _
        (by rw [← f.commutes, ← f.map_mul, algebraMap_eq, root_isInv, map_one])
        (by 

Proof state:
R : Type u
S✝ : Type v
K : Type w
inst✝⁴ : CommRing R
f✝ : R[X]
inst✝³ : CommRing S✝
i : R →+* S✝
a : S✝
h : eval₂ i a f✝ = 0
inst✝² : Algebra R S✝
hfx : (aeval a) f✝ = 0
S : Type u_1
inst✝¹ : CommRing S
inst✝ : Algebra R S
r : R
f g : AdjoinRoot (C r * X - 1) →ₐ[R] S
⊢ (algebraMap R S) r * g (root (C r * X - 1)) = 1

Next tactic:
rw [← g.commutes, ← g.map_mul, algebraMap_eq, root_isInv, map_one]
noncomputable instance field [Fact (Irreducible f)] : Field (AdjoinRoot f) :=
  { Quotient.groupWithZero (span {f} : Ideal K[X]) with
    toCommRing := AdjoinRoot.instCommRing f
    ratCast := fun a => of f (a : K)
    ratCast_mk := fun a b h1 h2 => by
      

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : Field K
f : K[X]
inst✝ : Fact (Irreducible f)
src✝ : GroupWithZero (K[X] ⧸ span {f}) := Quotient.groupWithZero (span {f})
a : ℤ
b : ℕ
h1 : b ≠ 0
h2 : Nat.Coprime (Int.natAbs a) b
⊢ ↑(Rat.mk' a b) = ↑a * (↑b)⁻¹

Next tactic:
letI : GroupWithZero (AdjoinRoot f) := Ideal.Quotient.groupWithZero _
noncomputable instance field [Fact (Irreducible f)] : Field (AdjoinRoot f) :=
  { Quotient.groupWithZero (span {f} : Ideal K[X]) with
    toCommRing := AdjoinRoot.instCommRing f
    ratCast := fun a => of f (a : K)
    ratCast_mk := fun a b h1 h2 => by
      letI : GroupWithZero (AdjoinRoot f) := Ideal.Quotient.groupWithZero _
      -- porting note: was
      -- `rw [Rat.cast_mk' (K := ℚ), _root_.map_mul, _root_.map_intCast, map_inv₀, map_natCast]`
      

Proof state:
R : Type u
S : Type v
K : Type w
inst✝¹ : Field K
f : K[X]
inst✝ : Fact (Irreducible f)
src✝ : GroupWithZero (K[X] ⧸ span {f}) := Quotient.groupWithZero (span {f})
a : ℤ
b : ℕ
h1 : b ≠ 0
h2 : Nat.Coprime (Int.natAbs a) b
this : GroupWithZero (AdjoinRoot f) := Quotient.groupWithZero (span {f})
⊢ ↑(Rat.mk' a b) = ↑a * (↑b)⁻¹

Next tactic:
convert_to ((Rat.mk' a b h1 h2 : K) : AdjoinRoot f) = ((↑a * (↑b)⁻¹ : K) : AdjoinRoot f)