l3lab/ntp-mathlib huggingface dataset:
theorem HasDerivWithinAt.div (hc : HasDerivWithinAt c c' s x) (hd : HasDerivWithinAt d d' s x)
    (hx : d x ≠ 0) :
    HasDerivWithinAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) s x := by
  

Proof state:
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasDerivWithinAt c c' s x
hd : HasDerivWithinAt d d' s x
hx : d x ≠ 0
⊢ HasDerivWithinAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) s x

Next tactic:
convert hc.mul ((hasDerivAt_inv hx).comp_hasDerivWithinAt x hd) using 1
theorem HasDerivWithinAt.div (hc : HasDerivWithinAt c c' s x) (hd : HasDerivWithinAt d d' s x)
    (hx : d x ≠ 0) :
    HasDerivWithinAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) s x := by
  convert hc.mul ((hasDerivAt_inv hx).comp_hasDerivWithinAt x hd) using 1
  · 

Proof state:
case h.e'_6
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasDerivWithinAt c c' s x
hd : HasDerivWithinAt d d' s x
hx : d x ≠ 0
⊢ (fun y => c y / d y) = fun y => c y * ((fun y => y⁻¹) ∘ d) y

Next tactic:
simp only [div_eq_mul_inv, (· ∘ ·)]
theorem HasDerivWithinAt.div (hc : HasDerivWithinAt c c' s x) (hd : HasDerivWithinAt d d' s x)
    (hx : d x ≠ 0) :
    HasDerivWithinAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) s x := by
  convert hc.mul ((hasDerivAt_inv hx).comp_hasDerivWithinAt x hd) using 1
  · simp only [div_eq_mul_inv, (· ∘ ·)]
  · 

Proof state:
case h.e'_7
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasDerivWithinAt c c' s x
hd : HasDerivWithinAt d d' s x
hx : d x ≠ 0
⊢ (c' * d x - c x * d') / d x ^ 2 = c' * ((fun y => y⁻¹) ∘ d) x + c x * (-(d x ^ 2)⁻¹ * d')

Next tactic:
field_simp
theorem HasDerivWithinAt.div (hc : HasDerivWithinAt c c' s x) (hd : HasDerivWithinAt d d' s x)
    (hx : d x ≠ 0) :
    HasDerivWithinAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) s x := by
  convert hc.mul ((hasDerivAt_inv hx).comp_hasDerivWithinAt x hd) using 1
  · simp only [div_eq_mul_inv, (· ∘ ·)]
  · field_simp
    

Proof state:
case h.e'_7
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasDerivWithinAt c c' s x
hd : HasDerivWithinAt d d' s x
hx : d x ≠ 0
⊢ (c' * d x - c x * d') * (d x * d x ^ 2) = (c' * d x ^ 2 + -(c x * d' * d x)) * d x ^ 2

Next tactic:
ring
theorem HasStrictDerivAt.div (hc : HasStrictDerivAt c c' x) (hd : HasStrictDerivAt d d' x)
    (hx : d x ≠ 0) : HasStrictDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x := by
  

Proof state:
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasStrictDerivAt c c' x
hd : HasStrictDerivAt d d' x
hx : d x ≠ 0
⊢ HasStrictDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x

Next tactic:
convert hc.mul ((hasStrictDerivAt_inv hx).comp x hd) using 1
theorem HasStrictDerivAt.div (hc : HasStrictDerivAt c c' x) (hd : HasStrictDerivAt d d' x)
    (hx : d x ≠ 0) : HasStrictDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x := by
  convert hc.mul ((hasStrictDerivAt_inv hx).comp x hd) using 1
  · 

Proof state:
case h.e'_6
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasStrictDerivAt c c' x
hd : HasStrictDerivAt d d' x
hx : d x ≠ 0
⊢ (fun y => c y / d y) = fun y => c y * (Inv.inv ∘ d) y

Next tactic:
simp only [div_eq_mul_inv, (· ∘ ·)]
theorem HasStrictDerivAt.div (hc : HasStrictDerivAt c c' x) (hd : HasStrictDerivAt d d' x)
    (hx : d x ≠ 0) : HasStrictDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x := by
  convert hc.mul ((hasStrictDerivAt_inv hx).comp x hd) using 1
  · simp only [div_eq_mul_inv, (· ∘ ·)]
  · 

Proof state:
case h.e'_7
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasStrictDerivAt c c' x
hd : HasStrictDerivAt d d' x
hx : d x ≠ 0
⊢ (c' * d x - c x * d') / d x ^ 2 = c' * (Inv.inv ∘ d) x + c x * (-(d x ^ 2)⁻¹ * d')

Next tactic:
field_simp
theorem HasStrictDerivAt.div (hc : HasStrictDerivAt c c' x) (hd : HasStrictDerivAt d d' x)
    (hx : d x ≠ 0) : HasStrictDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x := by
  convert hc.mul ((hasStrictDerivAt_inv hx).comp x hd) using 1
  · simp only [div_eq_mul_inv, (· ∘ ·)]
  · field_simp
    

Proof state:
case h.e'_7
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasStrictDerivAt c c' x
hd : HasStrictDerivAt d d' x
hx : d x ≠ 0
⊢ (c' * d x - c x * d') * (d x * d x ^ 2) = (c' * d x ^ 2 + -(c x * d' * d x)) * d x ^ 2

Next tactic:
ring
theorem HasDerivAt.div (hc : HasDerivAt c c' x) (hd : HasDerivAt d d' x) (hx : d x ≠ 0) :
    HasDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x := by
  

Proof state:
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasDerivAt c c' x
hd : HasDerivAt d d' x
hx : d x ≠ 0
⊢ HasDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x

Next tactic:
rw [← hasDerivWithinAt_univ] at *
theorem HasDerivAt.div (hc : HasDerivAt c c' x) (hd : HasDerivAt d d' x) (hx : d x ≠ 0) :
    HasDerivAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) x := by
  rw [← hasDerivWithinAt_univ] at *
  

Proof state:
𝕜 : Type u
inst✝⁶ : NontriviallyNormedField 𝕜
F : Type v
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
E : Type w
inst✝³ : NormedAddCommGroup E
inst✝² : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L : Filter 𝕜
𝕜' : Type u_1
inst✝¹ : NontriviallyNormedField 𝕜'
inst✝ : NormedAlgebra 𝕜 𝕜'
c d : 𝕜 → 𝕜'
c' d' : 𝕜'
hc : HasDerivWithinAt c c' univ x
hd : HasDerivWithinAt d d' univ x
hx : d x ≠ 0
⊢ HasDerivWithinAt (fun y => c y / d y) ((c' * d x - c x * d') / d x ^ 2) univ x

Next tactic:
exact hc.div hd hx
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by 

Proof state:
G H : AddCommGroupCat
⊢ ∀ ⦃X Y : Discrete WalkingPair⦄ (f : X ⟶ Y),
    ((Functor.const (Discrete WalkingPair)).obj (of (↑G × ↑H))).map f ≫
        (fun j => Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H))
          Y =
      (fun j => Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H)) X ≫
        (pair G H).map f

Next tactic:
rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> 

Proof state:
case mk.left.mk.left.up.up.refl
G H : AddCommGroupCat
⊢ ((Functor.const (Discrete WalkingPair)).obj (of (↑G × ↑H))).map
        { down := { down := (_ : { as := WalkingPair.left }.as = { as := WalkingPair.left }.as) } } ≫
      (fun j => Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H))
        { as := WalkingPair.left } =
    (fun j => Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H))
        { as := WalkingPair.left } ≫
      (pair G H).map { down := { down := (_ : { as := WalkingPair.left }.as = { as := WalkingPair.left }.as) } }

Next tactic:
rfl
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> 

Proof state:
case mk.right.mk.right.up.up.refl
G H : AddCommGroupCat
⊢ ((Functor.const (Discrete WalkingPair)).obj (of (↑G × ↑H))).map
        { down := { down := (_ : { as := WalkingPair.right }.as = { as := WalkingPair.right }.as) } } ≫
      (fun j => Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H))
        { as := WalkingPair.right } =
    (fun j => Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H))
        { as := WalkingPair.right } ≫
      (pair G H).map { down := { down := (_ : { as := WalkingPair.right }.as = { as := WalkingPair.right }.as) } }

Next tactic:
rfl
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> rfl } }
  isLimit :=
    { lift := fun s => AddMonoidHom.prod (s.π.app ⟨WalkingPair.left⟩) (s.π.app ⟨WalkingPair.right⟩)
      fac := by 

Proof state:
G H : AddCommGroupCat
⊢ ∀ (s : Cone (pair G H)) (j : Discrete WalkingPair),
    (fun s => AddMonoidHom.prod (s.π.app { as := WalkingPair.left }) (s.π.app { as := WalkingPair.right })) s ≫
        { pt := of (↑G × ↑H),
                π :=
                  NatTrans.mk fun j =>
                    Discrete.casesOn j fun j =>
                      WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H) }.π.app
          j =
      s.π.app j

Next tactic:
rintro s (⟨⟩ | ⟨⟩)
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> rfl } }
  isLimit :=
    { lift := fun s => AddMonoidHom.prod (s.π.app ⟨WalkingPair.left⟩) (s.π.app ⟨WalkingPair.right⟩)
      fac := by rintro s (⟨⟩ | ⟨⟩) <;> 

Proof state:
case mk.left
G H : AddCommGroupCat
s : Cone (pair G H)
⊢ (fun s => AddMonoidHom.prod (s.π.app { as := WalkingPair.left }) (s.π.app { as := WalkingPair.right })) s ≫
      { pt := of (↑G × ↑H),
              π :=
                NatTrans.mk fun j =>
                  Discrete.casesOn j fun j =>
                    WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H) }.π.app
        { as := WalkingPair.left } =
    s.π.app { as := WalkingPair.left }

Next tactic:
rfl
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> rfl } }
  isLimit :=
    { lift := fun s => AddMonoidHom.prod (s.π.app ⟨WalkingPair.left⟩) (s.π.app ⟨WalkingPair.right⟩)
      fac := by rintro s (⟨⟩ | ⟨⟩) <;> 

Proof state:
case mk.right
G H : AddCommGroupCat
s : Cone (pair G H)
⊢ (fun s => AddMonoidHom.prod (s.π.app { as := WalkingPair.left }) (s.π.app { as := WalkingPair.right })) s ≫
      { pt := of (↑G × ↑H),
              π :=
                NatTrans.mk fun j =>
                  Discrete.casesOn j fun j =>
                    WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H) }.π.app
        { as := WalkingPair.right } =
    s.π.app { as := WalkingPair.right }

Next tactic:
rfl
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> rfl } }
  isLimit :=
    { lift := fun s => AddMonoidHom.prod (s.π.app ⟨WalkingPair.left⟩) (s.π.app ⟨WalkingPair.right⟩)
      fac := by rintro s (⟨⟩ | ⟨⟩) <;> rfl
      uniq := fun s m w => by
        

Proof state:
G H : AddCommGroupCat
s : Cone (pair G H)
m :
  s.pt ⟶
    { pt := of (↑G × ↑H),
        π :=
          NatTrans.mk fun j =>
            Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H) }.pt
w :
  ∀ (j : Discrete WalkingPair),
    m ≫
        { pt := of (↑G × ↑H),
                π :=
                  NatTrans.mk fun j =>
                    Discrete.casesOn j fun j =>
                      WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H) }.π.app
          j =
      s.π.app j
⊢ m = (fun s => AddMonoidHom.prod (s.π.app { as := WalkingPair.left }) (s.π.app { as := WalkingPair.right })) s

Next tactic:
simp_rw [← w ⟨WalkingPair.left⟩, ← w ⟨WalkingPair.right⟩]
/-- Construct limit data for a binary product in `AddCommGroupCat`, using
`AddCommGroupCat.of (G × H)`.
-/
@[simps cone_pt isLimit_lift]
def binaryProductLimitCone (G H : AddCommGroupCat.{u}) : Limits.LimitCone (pair G H) where
  cone :=
    { pt := AddCommGroupCat.of (G × H)
      π :=
        { app := fun j =>
            Discrete.casesOn j fun j =>
              WalkingPair.casesOn j (AddMonoidHom.fst G H) (AddMonoidHom.snd G H)
          naturality := by rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ ⟨⟨⟨⟩⟩⟩ <;> rfl } }
  isLimit :=
    { lift := fun s => AddMonoidHom.prod (s.π.app ⟨WalkingPair.left⟩) (s.π.app ⟨WalkingPair.right⟩)
      fac := by rintro s (⟨⟩ | ⟨⟩) <;> rfl
      uniq := fun s m w => by
        simp_rw [← w ⟨WalkingPair.left⟩, ← w ⟨WalkingPair.right⟩]
        

Proof state:
G H : AddCommGroupCat
s : Cone (pair G H)
m :
  s.pt ⟶
    { pt := of (↑G × ↑H),
        π :=
          NatTrans.mk fun j =>
            Discrete.casesOn j fun j => WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H) }.pt
w :
  ∀ (j : Discrete WalkingPair),
    m ≫
        { pt := of (↑G × ↑H),
                π :=
                  NatTrans.mk fun j =>
                    Discrete.casesOn j fun j =>
                      WalkingPair.casesOn j (AddMonoidHom.fst ↑G ↑H) (AddMonoidHom.snd ↑G ↑H) }.π.app
          j =
      s.π.app j
⊢ m = AddMonoidHom.prod (m ≫ AddMonoidHom.fst ↑G ↑H) (m ≫ AddMonoidHom.snd ↑G ↑H)

Next tactic:
rfl
/-- The map from an arbitrary cone over an indexed family of abelian groups
to the cartesian product of those groups.
-/
@[simps]
def lift (s : Fan f) : s.pt ⟶ AddCommGroupCat.of (∀ j, f j) where
  toFun x j := s.π.app ⟨j⟩ x
  map_zero' := by
    

Proof state:
J : Type w
f : J → AddCommGroupCat
s : Fan f
⊢ (fun x j => (s.π.app { as := j }) x) 0 = 0

Next tactic:
simp only [Functor.const_obj_obj, map_zero]
/-- The map from an arbitrary cone over an indexed family of abelian groups
to the cartesian product of those groups.
-/
@[simps]
def lift (s : Fan f) : s.pt ⟶ AddCommGroupCat.of (∀ j, f j) where
  toFun x j := s.π.app ⟨j⟩ x
  map_zero' := by
    simp only [Functor.const_obj_obj, map_zero]
    

Proof state:
J : Type w
f : J → AddCommGroupCat
s : Fan f
⊢ (fun j => 0) = 0

Next tactic:
rfl
/-- The map from an arbitrary cone over an indexed family of abelian groups
to the cartesian product of those groups.
-/
@[simps]
def lift (s : Fan f) : s.pt ⟶ AddCommGroupCat.of (∀ j, f j) where
  toFun x j := s.π.app ⟨j⟩ x
  map_zero' := by
    simp only [Functor.const_obj_obj, map_zero]
    rfl
  map_add' x y := by
    

Proof state:
J : Type w
f : J → AddCommGroupCat
s : Fan f
x y : ↑s.pt
⊢ ZeroHom.toFun
      { toFun := fun x j => (s.π.app { as := j }) x, map_zero' := (_ : (fun x j => (s.π.app { as := j }) x) 0 = 0) }
      (x + y) =
    ZeroHom.toFun
        { toFun := fun x j => (s.π.app { as := j }) x, map_zero' := (_ : (fun x j => (s.π.app { as := j }) x) 0 = 0) }
        x +
      ZeroHom.toFun
        { toFun := fun x j => (s.π.app { as := j }) x, map_zero' := (_ : (fun x j => (s.π.app { as := j }) x) 0 = 0) } y

Next tactic:
simp only [Functor.const_obj_obj, map_add]
/-- The map from an arbitrary cone over an indexed family of abelian groups
to the cartesian product of those groups.
-/
@[simps]
def lift (s : Fan f) : s.pt ⟶ AddCommGroupCat.of (∀ j, f j) where
  toFun x j := s.π.app ⟨j⟩ x
  map_zero' := by
    simp only [Functor.const_obj_obj, map_zero]
    rfl
  map_add' x y := by
    simp only [Functor.const_obj_obj, map_add]
    

Proof state:
J : Type w
f : J → AddCommGroupCat
s : Fan f
x y : ↑s.pt
⊢ (fun j => (s.π.app { as := j }) x + (s.π.app { as := j }) y) =
    (fun j => (s.π.app { as := j }) x) + fun j => (s.π.app { as := j }) y

Next tactic:
rfl
/-- Construct limit data for a product in `AddCommGroupCat`, using
`AddCommGroupCat.of (∀ j, F.obj j)`.
-/
@[simps]
def productLimitCone : Limits.LimitCone (Discrete.functor f) where
  cone :=
    { pt := AddCommGroupCat.of (∀ j, f j)
      π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => f j) j.as }
  isLimit :=
    { lift := lift.{_, u} f
      fac := fun s j => rfl
      uniq := fun s m w => by
        

Proof state:
J : Type w
f : J → AddCommGroupCat
s : Cone (Discrete.functor f)
m :
  s.pt ⟶ { pt := of ((j : J) → ↑(f j)), π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => ↑(f j)) j.as }.pt
w :
  ∀ (j : Discrete J),
    m ≫
        { pt := of ((j : J) → ↑(f j)),
                π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => ↑(f j)) j.as }.π.app
          j =
      s.π.app j
⊢ m = lift f s

Next tactic:
ext x
/-- Construct limit data for a product in `AddCommGroupCat`, using
`AddCommGroupCat.of (∀ j, F.obj j)`.
-/
@[simps]
def productLimitCone : Limits.LimitCone (Discrete.functor f) where
  cone :=
    { pt := AddCommGroupCat.of (∀ j, f j)
      π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => f j) j.as }
  isLimit :=
    { lift := lift.{_, u} f
      fac := fun s j => rfl
      uniq := fun s m w => by
        ext x
        

Proof state:
case w
J : Type w
f : J → AddCommGroupCat
s : Cone (Discrete.functor f)
m :
  s.pt ⟶ { pt := of ((j : J) → ↑(f j)), π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => ↑(f j)) j.as }.pt
w :
  ∀ (j : Discrete J),
    m ≫
        { pt := of ((j : J) → ↑(f j)),
                π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => ↑(f j)) j.as }.π.app
          j =
      s.π.app j
x : ↑s.pt
⊢ m x = (lift f s) x

Next tactic:
funext j
/-- Construct limit data for a product in `AddCommGroupCat`, using
`AddCommGroupCat.of (∀ j, F.obj j)`.
-/
@[simps]
def productLimitCone : Limits.LimitCone (Discrete.functor f) where
  cone :=
    { pt := AddCommGroupCat.of (∀ j, f j)
      π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => f j) j.as }
  isLimit :=
    { lift := lift.{_, u} f
      fac := fun s j => rfl
      uniq := fun s m w => by
        ext x
        funext j
        

Proof state:
case w.h
J : Type w
f : J → AddCommGroupCat
s : Cone (Discrete.functor f)
m :
  s.pt ⟶ { pt := of ((j : J) → ↑(f j)), π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => ↑(f j)) j.as }.pt
w :
  ∀ (j : Discrete J),
    m ≫
        { pt := of ((j : J) → ↑(f j)),
                π := Discrete.natTrans fun j => Pi.evalAddMonoidHom (fun j => ↑(f j)) j.as }.π.app
          j =
      s.π.app j
x : ↑s.pt
j : J
⊢ m x j = (lift f s) x j

Next tactic:
exact congr_arg (fun g : s.pt ⟶ f j => (g : s.pt → f j) x) (w ⟨j⟩)
/-- The image of a set under a multiplicative homomorphism is a ring homomorphism
with respect to the pointwise operations on sets. -/
def imageHom [MulOneClass α] [MulOneClass β] (f : α →* β) : SetSemiring α →+* SetSemiring β
    where
  toFun s := up (image f (down s))
  map_zero' := image_empty _
  map_one' := by
    

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : MulOneClass α
inst✝ : MulOneClass β
f : α →* β
⊢ (fun s => up (⇑f '' down s)) 1 = 1

Next tactic:
dsimp only
/-- The image of a set under a multiplicative homomorphism is a ring homomorphism
with respect to the pointwise operations on sets. -/
def imageHom [MulOneClass α] [MulOneClass β] (f : α →* β) : SetSemiring α →+* SetSemiring β
    where
  toFun s := up (image f (down s))
  map_zero' := image_empty _
  map_one' := by
    dsimp only  -- porting note: structures do not do this automatically any more
    

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : MulOneClass α
inst✝ : MulOneClass β
f : α →* β
⊢ up (⇑f '' down 1) = 1

Next tactic:
rw [down_one, image_one, map_one, singleton_one, up_one]