l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem units_inv_mem_center [Monoid M] {a : Mˣ} (ha : ↑a ∈ Set.center M) :
    ↑a⁻¹ ∈ Set.center M := by
  rw [Semigroup.mem_center_iff] at *
  

Proof state:
M : Type u_1
inst✝ : Monoid M
a : Mˣ
ha : ∀ (g : M), g * ↑a = ↑a * g
⊢ ∀ (g : M), g * ↑a⁻¹ = ↑a⁻¹ * g

Next tactic:
exact (Commute.units_inv_right <| ha ·)
@[simp]
theorem invOf_mem_center [Monoid M] {a : M} [Invertible a] (ha : a ∈ Set.center M) :
    ⅟a ∈ Set.center M := by
  

Proof state:
M : Type u_1
inst✝¹ : Monoid M
a : M
inst✝ : Invertible a
ha : a ∈ center M
⊢ ⅟a ∈ center M

Next tactic:
rw [Semigroup.mem_center_iff] at *
@[simp]
theorem invOf_mem_center [Monoid M] {a : M} [Invertible a] (ha : a ∈ Set.center M) :
    ⅟a ∈ Set.center M := by
  rw [Semigroup.mem_center_iff] at *
  

Proof state:
M : Type u_1
inst✝¹ : Monoid M
a : M
inst✝ : Invertible a
ha : ∀ (g : M), g * a = a * g
⊢ ∀ (g : M), g * ⅟a = ⅟a * g

Next tactic:
exact (Commute.invOf_right <| ha ·)
@[simp]
theorem inv_mem_center₀ [GroupWithZero M] {a : M} (ha : a ∈ Set.center M) : a⁻¹ ∈ Set.center M := by
  

Proof state:
M : Type u_1
inst✝ : GroupWithZero M
a : M
ha : a ∈ center M
⊢ a⁻¹ ∈ center M

Next tactic:
obtain rfl | ha0 := eq_or_ne a 0
@[simp]
theorem inv_mem_center₀ [GroupWithZero M] {a : M} (ha : a ∈ Set.center M) : a⁻¹ ∈ Set.center M := by
  obtain rfl | ha0 := eq_or_ne a 0
  · 

Proof state:
case inl
M : Type u_1
inst✝ : GroupWithZero M
ha : 0 ∈ center M
⊢ 0⁻¹ ∈ center M

Next tactic:
rw [inv_zero]
@[simp]
theorem inv_mem_center₀ [GroupWithZero M] {a : M} (ha : a ∈ Set.center M) : a⁻¹ ∈ Set.center M := by
  obtain rfl | ha0 := eq_or_ne a 0
  · rw [inv_zero]
    

Proof state:
case inl
M : Type u_1
inst✝ : GroupWithZero M
ha : 0 ∈ center M
⊢ 0 ∈ center M

Next tactic:
exact zero_mem_center M
@[simp]
theorem inv_mem_center₀ [GroupWithZero M] {a : M} (ha : a ∈ Set.center M) : a⁻¹ ∈ Set.center M := by
  obtain rfl | ha0 := eq_or_ne a 0
  · rw [inv_zero]
    exact zero_mem_center M
  · 

Proof state:
case inr
M : Type u_1
inst✝ : GroupWithZero M
a : M
ha : a ∈ center M
ha0 : a ≠ 0
⊢ a⁻¹ ∈ center M

Next tactic:
lift a to Mˣ using IsUnit.mk0 _ ha0
@[simp]
theorem inv_mem_center₀ [GroupWithZero M] {a : M} (ha : a ∈ Set.center M) : a⁻¹ ∈ Set.center M := by
  obtain rfl | ha0 := eq_or_ne a 0
  · rw [inv_zero]
    exact zero_mem_center M
  · lift a to Mˣ using IsUnit.mk0 _ ha0
    

Proof state:
case inr.intro
M : Type u_1
inst✝ : GroupWithZero M
a : Mˣ
ha : ↑a ∈ center M
ha0 : ↑a ≠ 0
⊢ (↑a)⁻¹ ∈ center M

Next tactic:
simpa only [Units.val_inv_eq_inv_val] using units_inv_mem_center ha
@[to_additive (attr := simp) sub_mem_addCenter]
theorem div_mem_center [Group M] {a b : M} (ha : a ∈ Set.center M) (hb : b ∈ Set.center M) :
    a / b ∈ Set.center M := by
  

Proof state:
M : Type u_1
inst✝ : Group M
a b : M
ha : a ∈ center M
hb : b ∈ center M
⊢ a / b ∈ center M

Next tactic:
rw [div_eq_mul_inv]
@[to_additive (attr := simp) sub_mem_addCenter]
theorem div_mem_center [Group M] {a b : M} (ha : a ∈ Set.center M) (hb : b ∈ Set.center M) :
    a / b ∈ Set.center M := by
  rw [div_eq_mul_inv]
  

Proof state:
M : Type u_1
inst✝ : Group M
a b : M
ha : a ∈ center M
hb : b ∈ center M
⊢ a * b⁻¹ ∈ center M

Next tactic:
exact mul_mem_center ha (inv_mem_center hb)
@[simp]
theorem div_mem_center₀ [GroupWithZero M] {a b : M} (ha : a ∈ Set.center M)
    (hb : b ∈ Set.center M) : a / b ∈ Set.center M := by
  

Proof state:
M : Type u_1
inst✝ : GroupWithZero M
a b : M
ha : a ∈ center M
hb : b ∈ center M
⊢ a / b ∈ center M

Next tactic:
rw [div_eq_mul_inv]
@[simp]
theorem div_mem_center₀ [GroupWithZero M] {a b : M} (ha : a ∈ Set.center M)
    (hb : b ∈ Set.center M) : a / b ∈ Set.center M := by
  rw [div_eq_mul_inv]
  

Proof state:
M : Type u_1
inst✝ : GroupWithZero M
a b : M
ha : a ∈ center M
hb : b ∈ center M
⊢ a * b⁻¹ ∈ center M

Next tactic:
exact mul_mem_center ha (inv_mem_center₀ hb)
@[to_additive]
theorem mem_center_iff {z : M} : z ∈ center M ↔ ∀ g, g * z = z * g := by
  

Proof state:
M : Type u_1
inst✝ : Semigroup M
z : M
⊢ z ∈ center M ↔ ∀ (g : M), g * z = z * g

Next tactic:
rw [← Semigroup.mem_center_iff]
@[to_additive]
theorem mem_center_iff {z : M} : z ∈ center M ↔ ∀ g, g * z = z * g := by
  rw [← Semigroup.mem_center_iff]
  

Proof state:
M : Type u_1
inst✝ : Semigroup M
z : M
⊢ z ∈ center M ↔ z ∈ Set.center M

Next tactic:
exact Iff.rfl
instance semiringObj (F : J ⥤ SemiRingCatMax.{v, u}) (j) :
    Semiring ((F ⋙ forget SemiRingCat).obj j) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ SemiRingCatMax
j : J
⊢ Semiring ((F ⋙ forget SemiRingCat).obj j)

Next tactic:
change Semiring (F.obj j)
instance semiringObj (F : J ⥤ SemiRingCatMax.{v, u}) (j) :
    Semiring ((F ⋙ forget SemiRingCat).obj j) := by
  change Semiring (F.obj j)
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ SemiRingCatMax
j : J
⊢ Semiring ↑(F.obj j)

Next tactic:
infer_instance
/-- Witness that the limit cone in `SemiRingCat` is a limit cone.
(Internal use only; use the limits API.)
-/
def limitConeIsLimit (F : J ⥤ SemiRingCatMax.{v, u}) : IsLimit (limitCone F) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ SemiRingCatMax
⊢ IsLimit (limitCone F)

Next tactic:
refine IsLimit.ofFaithful (forget SemiRingCatMax.{v, u}) (Types.limitConeIsLimit.{v, u} _)
    (fun s : Cone F => ofHom
      { toFun := _
        map_one' := Subtype.ext <| funext fun j => by exact (s.π.app j).map_one
        map_mul' := fun x y => Subtype.ext <| funext fun j => by exact (s.π.app j).map_mul x y
        map_zero' := Subtype.ext <| funext fun j => by exact (s.π.app j).map_zero
        map_add' := fun x y => Subtype.ext <| funext fun j => by exact (s.π.app j).map_add x y })
    fun s => rfl
/-- Witness that the limit cone in `SemiRingCat` is a limit cone.
(Internal use only; use the limits API.)
-/
def limitConeIsLimit (F : J ⥤ SemiRingCatMax.{v, u}) : IsLimit (limitCone F) := by
  refine IsLimit.ofFaithful (forget SemiRingCatMax.{v, u}) (Types.limitConeIsLimit.{v, u} _)
    (fun s : Cone F => ofHom
      { toFun := _
        map_one' := Subtype.ext <| funext fun j => by 

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ SemiRingCatMax
s : Cone F
j : J
⊢ ↑{ val := fun j => ((forget SemiRingCatMax).mapCone s).π.app j 1,
          property :=
            (_ :
              ∀ {j j' : J} (f : j ⟶ j'),
                (((forget SemiRingCatMax).mapCone s).π.app j ≫ (F ⋙ forget SemiRingCatMax).map f) 1 =
                  ((forget SemiRingCatMax).mapCone s).π.app j' 1) }
      j =
    ↑1 j

Next tactic:
exact (s.π.app j).map_one
/--
Auxiliary lemma to prove the cone induced by `limitCone` is a limit cone.
-/
def forget₂AddCommMonPreservesLimitsAux (F : J ⥤ SemiRingCatMax.{v, u}) :
    IsLimit ((forget₂ SemiRingCat AddCommMonCat).mapCone (limitCone F)) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ SemiRingCatMax
⊢ IsLimit ((forget₂ SemiRingCat AddCommMonCat).mapCone (limitCone F))

Next tactic:
apply AddCommMonCat.limitConeIsLimit.{v, u}
/-- An auxiliary declaration to speed up typechecking.
-/
def forget₂MonPreservesLimitsAux (F : J ⥤ SemiRingCatMax.{v, u}) :
    IsLimit ((forget₂ SemiRingCat MonCat).mapCone (limitCone F)) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ SemiRingCatMax
⊢ IsLimit ((forget₂ SemiRingCat MonCat).mapCone (limitCone F))

Next tactic:
apply MonCat.HasLimits.limitConeIsLimit (F ⋙ forget₂ SemiRingCat MonCat.{max v u})
instance commSemiringObj (F : J ⥤ CommSemiRingCatMax.{v, u}) (j) :
    CommSemiring ((F ⋙ forget CommSemiRingCat).obj j) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ CommSemiRingCatMax
j : J
⊢ CommSemiring ((F ⋙ forget CommSemiRingCat).obj j)

Next tactic:
change CommSemiring (F.obj j)
instance commSemiringObj (F : J ⥤ CommSemiRingCatMax.{v, u}) (j) :
    CommSemiring ((F ⋙ forget CommSemiRingCat).obj j) := by
  change CommSemiring (F.obj j)
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ CommSemiRingCatMax
j : J
⊢ CommSemiring ↑(F.obj j)

Next tactic:
infer_instance
/-- We show that the forgetful functor `CommSemiRingCat ⥤ SemiRingCat` creates limits.

All we need to do is notice that the limit point has a `CommSemiring` instance available,
and then reuse the existing limit.
-/
instance (F : J ⥤ CommSemiRingCatMax.{v, u}) :
    CreatesLimit F (forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}) :=
  -- Porting note : `CommSemiRingCat ⥤ Type` reflecting isomorphism is needed to make Lean see that
  -- `CommSemiRingCat ⥤ SemiRingCat` reflects isomorphism. `CommSemiRingCat ⥤ Type` reflecting
  -- isomorphism is added manually since Lean can't see it, but even with this addition Lean can not
  -- see `CommSemiRingCat ⥤ SemiRingCat` reflects isomorphism, so this instance is also added.
  letI : ReflectsIsomorphisms (forget CommSemiRingCatMax.{v, u}) :=
    CommSemiRingCat.forgetReflectIsos.{max v u}
  letI : ReflectsIsomorphisms
    (forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}) :=
    CategoryTheory.reflectsIsomorphisms_forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}
  let c : Cone F :=
    { pt := CommSemiRingCat.of (Types.limitCone (F ⋙ forget _)).pt
      π :=
        { app := fun j => CommSemiRingCat.ofHom <| SemiRingCat.limitπRingHom.{v, u} (J := J)
            (F ⋙ forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}) j
          naturality := (SemiRingCat.HasLimits.limitCone.{v, u}
            (F ⋙ forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u})).π.naturality } }
  createsLimitOfReflectsIso fun c' t =>
    { liftedCone := c
      validLift := IsLimit.uniqueUpToIso (SemiRingCat.HasLimits.limitConeIsLimit.{v, u} _) t
      makesLimit := by
        

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ CommSemiRingCatMax
this✝ : ReflectsIsomorphisms (forget CommSemiRingCatMax) := forgetReflectIsos
this : ReflectsIsomorphisms (forget₂ CommSemiRingCatMax SemiRingCatMax) :=
  reflectsIsomorphisms_forget₂ CommSemiRingCatMax SemiRingCatMax
c : Cone F :=
  { pt := of (Types.limitCone (F ⋙ forget CommSemiRingCatMax)).pt,
    π := NatTrans.mk fun j => ofHom (SemiRingCat.limitπRingHom (F ⋙ forget₂ CommSemiRingCatMax SemiRingCatMax) j) }
c' : Cone (F ⋙ forget₂ CommSemiRingCatMax SemiRingCatMax)
t : IsLimit c'
⊢ IsLimit
    { liftedCone := c,
        validLift :=
          IsLimit.uniqueUpToIso (SemiRingCat.HasLimits.limitConeIsLimit (F ⋙ forget₂ CommSemiRingCatMax SemiRingCatMax))
            t }.liftedCone

Next tactic:
refine IsLimit.ofFaithful (forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u})
          (SemiRingCat.HasLimits.limitConeIsLimit.{v, u} _)
          (fun s : Cone F => CommSemiRingCat.ofHom
            { toFun := _
              map_one' := Subtype.ext <| funext fun j => by exact (s.π.app j).map_one
              map_mul' := fun x y => Subtype.ext <| funext fun j => by exact (s.π.app j).map_mul x y
              map_zero' := Subtype.ext <| funext fun j => by exact (s.π.app j).map_zero
              map_add' := fun x y => Subtype.ext <| funext fun j => by exact (s.π.app j).map_add x y
              })
          fun s => rfl
/-- We show that the forgetful functor `CommSemiRingCat ⥤ SemiRingCat` creates limits.

All we need to do is notice that the limit point has a `CommSemiring` instance available,
and then reuse the existing limit.
-/
instance (F : J ⥤ CommSemiRingCatMax.{v, u}) :
    CreatesLimit F (forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}) :=
  -- Porting note : `CommSemiRingCat ⥤ Type` reflecting isomorphism is needed to make Lean see that
  -- `CommSemiRingCat ⥤ SemiRingCat` reflects isomorphism. `CommSemiRingCat ⥤ Type` reflecting
  -- isomorphism is added manually since Lean can't see it, but even with this addition Lean can not
  -- see `CommSemiRingCat ⥤ SemiRingCat` reflects isomorphism, so this instance is also added.
  letI : ReflectsIsomorphisms (forget CommSemiRingCatMax.{v, u}) :=
    CommSemiRingCat.forgetReflectIsos.{max v u}
  letI : ReflectsIsomorphisms
    (forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}) :=
    CategoryTheory.reflectsIsomorphisms_forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}
  let c : Cone F :=
    { pt := CommSemiRingCat.of (Types.limitCone (F ⋙ forget _)).pt
      π :=
        { app := fun j => CommSemiRingCat.ofHom <| SemiRingCat.limitπRingHom.{v, u} (J := J)
            (F ⋙ forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u}) j
          naturality := (SemiRingCat.HasLimits.limitCone.{v, u}
            (F ⋙ forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u})).π.naturality } }
  createsLimitOfReflectsIso fun c' t =>
    { liftedCone := c
      validLift := IsLimit.uniqueUpToIso (SemiRingCat.HasLimits.limitConeIsLimit.{v, u} _) t
      makesLimit := by
        refine IsLimit.ofFaithful (forget₂ CommSemiRingCatMax.{v, u} SemiRingCatMax.{v, u})
          (SemiRingCat.HasLimits.limitConeIsLimit.{v, u} _)
          (fun s : Cone F => CommSemiRingCat.ofHom
            { toFun := _
              map_one' := Subtype.ext <| funext fun j => by 

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ CommSemiRingCatMax
this✝ : ReflectsIsomorphisms (forget CommSemiRingCatMax) := forgetReflectIsos
this : ReflectsIsomorphisms (forget₂ CommSemiRingCatMax SemiRingCatMax) :=
  reflectsIsomorphisms_forget₂ CommSemiRingCatMax SemiRingCatMax
c : Cone F :=
  { pt := of (Types.limitCone (F ⋙ forget CommSemiRingCatMax)).pt,
    π := NatTrans.mk fun j => ofHom (SemiRingCat.limitπRingHom (F ⋙ forget₂ CommSemiRingCatMax SemiRingCatMax) j) }
c' : Cone (F ⋙ forget₂ CommSemiRingCatMax SemiRingCatMax)
t : IsLimit c'
s : Cone F
j : J
⊢ ↑{
          val := fun j =>
            ((forget SemiRingCatMax).mapCone ((forget₂ CommSemiRingCatMax SemiRingCatMax).mapCone s)).π.app j 1,
          property :=
            (_ :
              ∀ {j j' : J} (f : j ⟶ j'),
                (((forget SemiRingCatMax).mapCone ((forget₂ CommSemiRingCatMax SemiRingCatMax).mapCone s)).π.app j ≫
                      ((F ⋙ forget₂ CommSemiRingCatMax SemiRingCatMax) ⋙ forget SemiRingCatMax).map f)
                    1 =
                  ((forget SemiRingCatMax).mapCone ((forget₂ CommSemiRingCatMax SemiRingCatMax).mapCone s)).π.app j'
                    1) }
      j =
    ↑1 j

Next tactic:
exact (s.π.app j).map_one
instance ringObj (F : J ⥤ RingCatMax.{v, u}) (j) : Ring ((F ⋙ forget RingCat).obj j) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ RingCatMax
j : J
⊢ Ring ((F ⋙ forget RingCat).obj j)

Next tactic:
change Ring (F.obj j)
instance ringObj (F : J ⥤ RingCatMax.{v, u}) (j) : Ring ((F ⋙ forget RingCat).obj j) := by
  change Ring (F.obj j)
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ RingCatMax
j : J
⊢ Ring ↑(F.obj j)

Next tactic:
infer_instance
/-- We show that the forgetful functor `CommRingCat ⥤ RingCat` creates limits.

All we need to do is notice that the limit point has a `Ring` instance available,
and then reuse the existing limit.
-/
instance (F : J ⥤ RingCatMax.{v, u}) :
    CreatesLimit F (forget₂ RingCatMax.{v, u} SemiRingCatMax.{v, u}) :=
  letI : ReflectsIsomorphisms (forget₂ RingCatMax SemiRingCatMax) :=
    CategoryTheory.reflectsIsomorphisms_forget₂ _ _
  letI c : Cone F :=
  { pt := RingCat.of (Types.limitCone (F ⋙ forget _)).pt
    π :=
      { app := fun x => SemiRingCat.ofHom _
        naturality := (SemiRingCat.HasLimits.limitCone
          (F ⋙ forget₂ RingCat SemiRingCat.{max v u})).π.naturality } }
  createsLimitOfReflectsIso fun c' t =>
    { liftedCone := c
      validLift := by 

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ RingCatMax
this : ReflectsIsomorphisms (forget₂ RingCatMax SemiRingCatMax) :=
  reflectsIsomorphisms_forget₂ RingCatMax SemiRingCatMax
c : Cone F :=
  { pt := of (Types.limitCone (F ⋙ forget RingCatMax)).pt,
    π :=
      NatTrans.mk fun x =>
        SemiRingCat.ofHom ((SemiRingCat.HasLimits.limitCone (F ⋙ forget₂ RingCat SemiRingCat)).π.app x) }
c' : Cone (F ⋙ forget₂ RingCatMax SemiRingCatMax)
t : IsLimit c'
⊢ (forget₂ RingCatMax SemiRingCatMax).mapCone c ≅ c'

Next tactic:
apply IsLimit.uniqueUpToIso (SemiRingCat.HasLimits.limitConeIsLimit _) t
/-- We show that the forgetful functor `CommRingCat ⥤ RingCat` creates limits.

All we need to do is notice that the limit point has a `Ring` instance available,
and then reuse the existing limit.
-/
instance (F : J ⥤ RingCatMax.{v, u}) :
    CreatesLimit F (forget₂ RingCatMax.{v, u} SemiRingCatMax.{v, u}) :=
  letI : ReflectsIsomorphisms (forget₂ RingCatMax SemiRingCatMax) :=
    CategoryTheory.reflectsIsomorphisms_forget₂ _ _
  letI c : Cone F :=
  { pt := RingCat.of (Types.limitCone (F ⋙ forget _)).pt
    π :=
      { app := fun x => SemiRingCat.ofHom _
        naturality := (SemiRingCat.HasLimits.limitCone
          (F ⋙ forget₂ RingCat SemiRingCat.{max v u})).π.naturality } }
  createsLimitOfReflectsIso fun c' t =>
    { liftedCone := c
      validLift := by apply IsLimit.uniqueUpToIso (SemiRingCat.HasLimits.limitConeIsLimit _) t
      makesLimit :=
        IsLimit.ofFaithful (forget₂ RingCat SemiRingCat.{max v u})
          (by 

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ RingCatMax
this : ReflectsIsomorphisms (forget₂ RingCatMax SemiRingCatMax) :=
  reflectsIsomorphisms_forget₂ RingCatMax SemiRingCatMax
c : Cone F :=
  { pt := of (Types.limitCone (F ⋙ forget RingCatMax)).pt,
    π :=
      NatTrans.mk fun x =>
        SemiRingCat.ofHom ((SemiRingCat.HasLimits.limitCone (F ⋙ forget₂ RingCat SemiRingCat)).π.app x) }
c' : Cone (F ⋙ forget₂ RingCatMax SemiRingCatMax)
t : IsLimit c'
⊢ IsLimit
    ((forget₂ RingCat SemiRingCat).mapCone
      { liftedCone := c,
          validLift :=
            IsLimit.uniqueUpToIso (SemiRingCat.HasLimits.limitConeIsLimit (F ⋙ forget₂ RingCatMax SemiRingCatMax))
              t }.liftedCone)

Next tactic:
apply SemiRingCat.HasLimits.limitConeIsLimit _
/-- An auxiliary declaration to speed up typechecking.
-/
def forget₂AddCommGroupPreservesLimitsAux (F : J ⥤ RingCatMax.{v, u}) :
    IsLimit ((forget₂ RingCatMax.{v, u} AddCommGroupCat).mapCone (limitCone.{v, u} F)) := by
  -- Porting note : inline `f` would not compile
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ RingCatMax
⊢ IsLimit ((forget₂ RingCatMax AddCommGroupCat).mapCone (limitCone F))

Next tactic:
letI f := (F ⋙ forget₂ RingCatMax.{v, u} AddCommGroupCat.{max v u})
/-- An auxiliary declaration to speed up typechecking.
-/
def forget₂AddCommGroupPreservesLimitsAux (F : J ⥤ RingCatMax.{v, u}) :
    IsLimit ((forget₂ RingCatMax.{v, u} AddCommGroupCat).mapCone (limitCone.{v, u} F)) := by
  -- Porting note : inline `f` would not compile
  letI f := (F ⋙ forget₂ RingCatMax.{v, u} AddCommGroupCat.{max v u})
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ RingCatMax
f : J ⥤ AddCommGroupCat := F ⋙ forget₂ RingCatMax AddCommGroupCat
⊢ IsLimit ((forget₂ RingCatMax AddCommGroupCat).mapCone (limitCone F))

Next tactic:
apply AddCommGroupCat.limitConeIsLimit.{v, u} f
instance commRingObj (F : J ⥤ CommRingCatMax.{v, u}) (j) :
    CommRing ((F ⋙ forget CommRingCat).obj j) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ CommRingCatMax
j : J
⊢ CommRing ((F ⋙ forget CommRingCat).obj j)

Next tactic:
change CommRing (F.obj j)
instance commRingObj (F : J ⥤ CommRingCatMax.{v, u}) (j) :
    CommRing ((F ⋙ forget CommRingCat).obj j) := by
  change CommRing (F.obj j)
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ CommRingCatMax
j : J
⊢ CommRing ↑(F.obj j)

Next tactic:
infer_instance
/-- An auxiliary declaration to speed up typechecking.
-/
def forget₂CommSemiRingPreservesLimitsAux (F : J ⥤ CommRingCatMax.{v, u}) :
    IsLimit ((forget₂ CommRingCat CommSemiRingCat).mapCone (limitCone F)) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ CommRingCatMax
⊢ IsLimit ((forget₂ CommRingCat CommSemiRingCat).mapCone (limitCone F))

Next tactic:
apply CommSemiRingCat.limitConeIsLimit (F ⋙ forget₂ CommRingCat CommSemiRingCat.{max v u})
@[simp]
theorem mirror_zero : (0 : R[X]).mirror = 0 := by 

Proof state:
R : Type u_1
inst✝ : Semiring R
p q : R[X]
⊢ mirror 0 = 0

Next tactic:
simp [mirror]
theorem mirror_monomial (n : ℕ) (a : R) : (monomial n a).mirror = monomial n a := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
p q : R[X]
n : ℕ
a : R
⊢ mirror ((monomial n) a) = (monomial n) a

Next tactic:
classical
    by_cases ha : a = 0
    · rw [ha, monomial_zero_right, mirror_zero]
    · rw [mirror, reverse, natDegree_monomial n a, if_neg ha, natTrailingDegree_monomial ha, ←
        C_mul_X_pow_eq_monomial, reflect_C_mul_X_pow, revAt_le (le_refl n), tsub_self, pow_zero,
        mul_one]
theorem mirror_monomial (n : ℕ) (a : R) : (monomial n a).mirror = monomial n a := by
  classical
    

Proof state:
R : Type u_1
inst✝ : Semiring R
p q : R[X]
n : ℕ
a : R
⊢ mirror ((monomial n) a) = (monomial n) a

Next tactic:
by_cases ha : a = 0
theorem mirror_monomial (n : ℕ) (a : R) : (monomial n a).mirror = monomial n a := by
  classical
    by_cases ha : a = 0
    · 

Proof state:
case pos
R : Type u_1
inst✝ : Semiring R
p q : R[X]
n : ℕ
a : R
ha : a = 0
⊢ mirror ((monomial n) a) = (monomial n) a

Next tactic:
rw [ha, monomial_zero_right, mirror_zero]
theorem mirror_monomial (n : ℕ) (a : R) : (monomial n a).mirror = monomial n a := by
  classical
    by_cases ha : a = 0
    · rw [ha, monomial_zero_right, mirror_zero]
    · 

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
p q : R[X]
n : ℕ
a : R
ha : ¬a = 0
⊢ mirror ((monomial n) a) = (monomial n) a

Next tactic:
rw [mirror, reverse, natDegree_monomial n a, if_neg ha, natTrailingDegree_monomial ha, ←
        C_mul_X_pow_eq_monomial, reflect_C_mul_X_pow, revAt_le (le_refl n), tsub_self, pow_zero,
        mul_one]
theorem mirror_natDegree : p.mirror.natDegree = p.natDegree := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
p q : R[X]
⊢ natDegree (mirror p) = natDegree p

Next tactic:
by_cases hp : p = 0
theorem mirror_natDegree : p.mirror.natDegree = p.natDegree := by
  by_cases hp : p = 0
  · 

Proof state:
case pos
R : Type u_1
inst✝ : Semiring R
p q : R[X]
hp : p = 0
⊢ natDegree (mirror p) = natDegree p

Next tactic:
rw [hp, mirror_zero]
theorem mirror_natDegree : p.mirror.natDegree = p.natDegree := by
  by_cases hp : p = 0
  · rw [hp, mirror_zero]
  

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
p q : R[X]
hp : ¬p = 0
⊢ natDegree (mirror p) = natDegree p

Next tactic:
nontriviality R
theorem mirror_natDegree : p.mirror.natDegree = p.natDegree := by
  by_cases hp : p = 0
  · rw [hp, mirror_zero]
  nontriviality R
  

Proof state:
R : Type u_1
inst✝ : Semiring R
p q : R[X]
hp : ¬p = 0
✝ : Nontrivial R
⊢ natDegree (mirror p) = natDegree p

Next tactic:
rw [mirror, natDegree_mul', reverse_natDegree, natDegree_X_pow,
    tsub_add_cancel_of_le p.natTrailingDegree_le_natDegree]
theorem mirror_natDegree : p.mirror.natDegree = p.natDegree := by
  by_cases hp : p = 0
  · rw [hp, mirror_zero]
  nontriviality R
  rw [mirror, natDegree_mul', reverse_natDegree, natDegree_X_pow,
    tsub_add_cancel_of_le p.natTrailingDegree_le_natDegree]
  

Proof state:
R : Type u_1
inst✝ : Semiring R
p q : R[X]
hp : ¬p = 0
✝ : Nontrivial R
⊢ leadingCoeff (reverse p) * leadingCoeff (X ^ natTrailingDegree p) ≠ 0

Next tactic:
rwa [leadingCoeff_X_pow, mul_one, reverse_leadingCoeff, Ne, trailingCoeff_eq_zero]
theorem mirror_natTrailingDegree : p.mirror.natTrailingDegree = p.natTrailingDegree := by
  

Proof state:
R : Type u_1
inst✝ : Semiring R
p q : R[X]
⊢ natTrailingDegree (mirror p) = natTrailingDegree p

Next tactic:
by_cases hp : p = 0
theorem mirror_natTrailingDegree : p.mirror.natTrailingDegree = p.natTrailingDegree := by
  by_cases hp : p = 0
  · 

Proof state:
case pos
R : Type u_1
inst✝ : Semiring R
p q : R[X]
hp : p = 0
⊢ natTrailingDegree (mirror p) = natTrailingDegree p

Next tactic:
rw [hp, mirror_zero]
theorem mirror_natTrailingDegree : p.mirror.natTrailingDegree = p.natTrailingDegree := by
  by_cases hp : p = 0
  · rw [hp, mirror_zero]
  · 

Proof state:
case neg
R : Type u_1
inst✝ : Semiring R
p q : R[X]
hp : ¬p = 0
⊢ natTrailingDegree (mirror p) = natTrailingDegree p

Next tactic:
rw [mirror, natTrailingDegree_mul_X_pow ((mt reverse_eq_zero.mp) hp),
      reverse_natTrailingDegree, zero_add]