l3lab/ntp-mathlib huggingface dataset:
theorem isSuccLimitRecOn_succ' (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a)
    {b : α} (hb : ¬IsMax b) : @isSuccLimitRecOn α _ _ C (succ b) hs hl = hs b hb := by
  have hb' := not_isSuccLimit_succ_of_not_isMax hb
  have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb')
  rw [isSuccLimitRecOn]
  simp only [cast_eq_iff_heq, hb', not_false_iff, eq_mpr_eq_cast, dif_neg]
  congr 1 <;> 

Proof state:
case e_1
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : SuccOrder α
a b✝ : α
C : α → Sort u_2
hs : (a : α) → ¬IsMax a → C (succ a)
hl : (a : α) → IsSuccLimit a → C a
b : α
hb : ¬IsMax b
hb' : ¬IsSuccLimit (succ b)
H :
  ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) ∧
    succ (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) = succ b
⊢ Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b) = b

Next tactic:
first |
    exact (succ_eq_succ_iff_of_not_isMax H.left hb).mp H.right |
    exact proof_irrel_heq H.left hb
theorem isSuccLimitRecOn_succ' (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a)
    {b : α} (hb : ¬IsMax b) : @isSuccLimitRecOn α _ _ C (succ b) hs hl = hs b hb := by
  have hb' := not_isSuccLimit_succ_of_not_isMax hb
  have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb')
  rw [isSuccLimitRecOn]
  simp only [cast_eq_iff_heq, hb', not_false_iff, eq_mpr_eq_cast, dif_neg]
  congr 1 <;> first |
    

Proof state:
case e_1
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : SuccOrder α
a b✝ : α
C : α → Sort u_2
hs : (a : α) → ¬IsMax a → C (succ a)
hl : (a : α) → IsSuccLimit a → C a
b : α
hb : ¬IsMax b
hb' : ¬IsSuccLimit (succ b)
H :
  ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) ∧
    succ (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) = succ b
⊢ Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b) = b

Next tactic:
exact (succ_eq_succ_iff_of_not_isMax H.left hb).mp H.right
theorem isSuccLimitRecOn_succ' (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a)
    {b : α} (hb : ¬IsMax b) : @isSuccLimitRecOn α _ _ C (succ b) hs hl = hs b hb := by
  have hb' := not_isSuccLimit_succ_of_not_isMax hb
  have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb')
  rw [isSuccLimitRecOn]
  simp only [cast_eq_iff_heq, hb', not_false_iff, eq_mpr_eq_cast, dif_neg]
  congr 1 <;> 

Proof state:
case e_2
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : SuccOrder α
a b✝ : α
C : α → Sort u_2
hs : (a : α) → ¬IsMax a → C (succ a)
hl : (a : α) → IsSuccLimit a → C a
b : α
hb : ¬IsMax b
hb' : ¬IsSuccLimit (succ b)
H :
  ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) ∧
    succ (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) = succ b
⊢ HEq (_ : ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b))) hb

Next tactic:
first |
    exact (succ_eq_succ_iff_of_not_isMax H.left hb).mp H.right |
    exact proof_irrel_heq H.left hb
theorem isSuccLimitRecOn_succ' (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a)
    {b : α} (hb : ¬IsMax b) : @isSuccLimitRecOn α _ _ C (succ b) hs hl = hs b hb := by
  have hb' := not_isSuccLimit_succ_of_not_isMax hb
  have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb')
  rw [isSuccLimitRecOn]
  simp only [cast_eq_iff_heq, hb', not_false_iff, eq_mpr_eq_cast, dif_neg]
  congr 1 <;> first |
    

Proof state:
case e_2
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : SuccOrder α
a b✝ : α
C : α → Sort u_2
hs : (a : α) → ¬IsMax a → C (succ a)
hl : (a : α) → IsSuccLimit a → C a
b : α
hb : ¬IsMax b
hb' : ¬IsSuccLimit (succ b)
H :
  ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) ∧
    succ (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) = succ b
⊢ HEq (_ : ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b))) hb

Next tactic:
exact (succ_eq_succ_iff_of_not_isMax H.left hb).mp H.right
theorem isSuccLimitRecOn_succ' (hs : ∀ a, ¬IsMax a → C (succ a)) (hl : ∀ a, IsSuccLimit a → C a)
    {b : α} (hb : ¬IsMax b) : @isSuccLimitRecOn α _ _ C (succ b) hs hl = hs b hb := by
  have hb' := not_isSuccLimit_succ_of_not_isMax hb
  have H := Classical.choose_spec (not_isSuccLimit_iff.1 hb')
  rw [isSuccLimitRecOn]
  simp only [cast_eq_iff_heq, hb', not_false_iff, eq_mpr_eq_cast, dif_neg]
  congr 1 <;> first |
    exact (succ_eq_succ_iff_of_not_isMax H.left hb).mp H.right |
    

Proof state:
case e_2
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : SuccOrder α
a b✝ : α
C : α → Sort u_2
hs : (a : α) → ¬IsMax a → C (succ a)
hl : (a : α) → IsSuccLimit a → C a
b : α
hb : ¬IsMax b
hb' : ¬IsSuccLimit (succ b)
H :
  ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) ∧
    succ (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b)) = succ b
⊢ HEq (_ : ¬IsMax (Classical.choose (_ : ∃ b_1, ¬IsMax b_1 ∧ succ b_1 = succ b))) hb

Next tactic:
exact proof_irrel_heq H.left hb
theorem not_isSuccLimit_iff' : ¬IsSuccLimit a ↔ a ∈ range (@succ α _ _) := by
  

Proof state:
α : Type u_1
inst✝² : PartialOrder α
inst✝¹ : SuccOrder α
a b : α
C : α → Sort u_2
inst✝ : NoMaxOrder α
⊢ ¬IsSuccLimit a ↔ a ∈ range succ

Next tactic:
simp_rw [isSuccLimit_iff_succ_ne, not_forall, not_ne_iff]
theorem not_isSuccLimit_iff' : ¬IsSuccLimit a ↔ a ∈ range (@succ α _ _) := by
  simp_rw [isSuccLimit_iff_succ_ne, not_forall, not_ne_iff]
  

Proof state:
α : Type u_1
inst✝² : PartialOrder α
inst✝¹ : SuccOrder α
a b : α
C : α → Sort u_2
inst✝ : NoMaxOrder α
⊢ (∃ x, succ x = a) ↔ a ∈ range succ

Next tactic:
rfl
protected theorem IsSuccLimit.isMin (h : IsSuccLimit a) : IsMin a := fun b hb => by
  

Proof state:
α : Type u_1
inst✝² : PartialOrder α
inst✝¹ : SuccOrder α
a b✝ : α
C : α → Sort u_2
inst✝ : IsSuccArchimedean α
h : IsSuccLimit a
b : α
hb : b ≤ a
⊢ a ≤ b

Next tactic:
revert h
protected theorem IsSuccLimit.isMin (h : IsSuccLimit a) : IsMin a := fun b hb => by
  revert h
  

Proof state:
α : Type u_1
inst✝² : PartialOrder α
inst✝¹ : SuccOrder α
a b✝ : α
C : α → Sort u_2
inst✝ : IsSuccArchimedean α
b : α
hb : b ≤ a
⊢ IsSuccLimit a → a ≤ b

Next tactic:
refine' Succ.rec (fun _ => le_rfl) (fun c _ H hc => _) hb
protected theorem IsSuccLimit.isMin (h : IsSuccLimit a) : IsMin a := fun b hb => by
  revert h
  refine' Succ.rec (fun _ => le_rfl) (fun c _ H hc => _) hb
  

Proof state:
α : Type u_1
inst✝² : PartialOrder α
inst✝¹ : SuccOrder α
a b✝ : α
C : α → Sort u_2
inst✝ : IsSuccArchimedean α
b : α
hb : b ≤ a
c : α
x✝ : b ≤ c
H : IsSuccLimit c → c ≤ b
hc : IsSuccLimit (succ c)
⊢ succ c ≤ b

Next tactic:
have := hc.isMax.succ_eq
protected theorem IsSuccLimit.isMin (h : IsSuccLimit a) : IsMin a := fun b hb => by
  revert h
  refine' Succ.rec (fun _ => le_rfl) (fun c _ H hc => _) hb
  have := hc.isMax.succ_eq
  

Proof state:
α : Type u_1
inst✝² : PartialOrder α
inst✝¹ : SuccOrder α
a b✝ : α
C : α → Sort u_2
inst✝ : IsSuccArchimedean α
b : α
hb : b ≤ a
c : α
x✝ : b ≤ c
H : IsSuccLimit c → c ≤ b
hc : IsSuccLimit (succ c)
this : succ c = c
⊢ succ c ≤ b

Next tactic:
rw [this] at hc ⊢
protected theorem IsSuccLimit.isMin (h : IsSuccLimit a) : IsMin a := fun b hb => by
  revert h
  refine' Succ.rec (fun _ => le_rfl) (fun c _ H hc => _) hb
  have := hc.isMax.succ_eq
  rw [this] at hc ⊢
  

Proof state:
α : Type u_1
inst✝² : PartialOrder α
inst✝¹ : SuccOrder α
a b✝ : α
C : α → Sort u_2
inst✝ : IsSuccArchimedean α
b : α
hb : b ≤ a
c : α
x✝ : b ≤ c
H : IsSuccLimit c → c ≤ b
hc : IsSuccLimit c
this : succ c = c
⊢ c ≤ b

Next tactic:
exact H hc
theorem not_isSuccLimit [NoMinOrder α] : ¬IsSuccLimit a := by 

Proof state:
α : Type u_1
inst✝³ : PartialOrder α
inst✝² : SuccOrder α
a b : α
C : α → Sort u_2
inst✝¹ : IsSuccArchimedean α
inst✝ : NoMinOrder α
⊢ ¬IsSuccLimit a

Next tactic:
simp
theorem not_isPredLimit_iff_exists_covby (a : α) : ¬IsPredLimit a ↔ ∃ b, a ⋖ b := by
  

Proof state:
α : Type u_1
inst✝ : LT α
a✝ a : α
⊢ ¬IsPredLimit a ↔ ∃ b, a ⋖ b

Next tactic:
simp [IsPredLimit]
@[simp]
theorem isSuccLimit_toDual_iff : IsSuccLimit (toDual a) ↔ IsPredLimit a := by
  

Proof state:
α : Type u_1
inst✝ : LT α
a : α
⊢ IsSuccLimit (toDual a) ↔ IsPredLimit a

Next tactic:
simp [IsSuccLimit, IsPredLimit]
@[simp]
theorem isPredLimit_toDual_iff : IsPredLimit (toDual a) ↔ IsSuccLimit a := by
  

Proof state:
α : Type u_1
inst✝ : LT α
a : α
⊢ IsPredLimit (toDual a) ↔ IsSuccLimit a

Next tactic:
simp [IsSuccLimit, IsPredLimit]
protected theorem IsPredLimit.isMin (h : IsPredLimit (pred a)) : IsMin a := by
  

Proof state:
α : Type u_1
inst✝¹ : Preorder α
a : α
inst✝ : PredOrder α
h : IsPredLimit (pred a)
⊢ IsMin a

Next tactic:
by_contra H
protected theorem IsPredLimit.isMin (h : IsPredLimit (pred a)) : IsMin a := by
  by_contra H
  

Proof state:
α : Type u_1
inst✝¹ : Preorder α
a : α
inst✝ : PredOrder α
h : IsPredLimit (pred a)
H : ¬IsMin a
⊢ False

Next tactic:
exact h a (pred_covby_of_not_isMin H)
theorem not_isPredLimit_pred_of_not_isMin (ha : ¬IsMin a) : ¬IsPredLimit (pred a) := by
  

Proof state:
α : Type u_1
inst✝¹ : Preorder α
a : α
inst✝ : PredOrder α
ha : ¬IsMin a
⊢ ¬IsPredLimit (pred a)

Next tactic:
contrapose! ha
theorem not_isPredLimit_pred_of_not_isMin (ha : ¬IsMin a) : ¬IsPredLimit (pred a) := by
  contrapose! ha
  

Proof state:
α : Type u_1
inst✝¹ : Preorder α
a : α
inst✝ : PredOrder α
ha : IsPredLimit (pred a)
⊢ IsMin a

Next tactic:
exact ha.isMin
theorem IsPredLimit.pred_ne (h : IsPredLimit a) (b : α) : pred b ≠ a := by
  

Proof state:
α : Type u_1
inst✝² : Preorder α
a : α
inst✝¹ : PredOrder α
inst✝ : NoMinOrder α
h : IsPredLimit a
b : α
⊢ pred b ≠ a

Next tactic:
rintro rfl
theorem IsPredLimit.pred_ne (h : IsPredLimit a) (b : α) : pred b ≠ a := by
  rintro rfl
  

Proof state:
α : Type u_1
inst✝² : Preorder α
inst✝¹ : PredOrder α
inst✝ : NoMinOrder α
b : α
h : IsPredLimit (pred b)
⊢ False

Next tactic:
exact not_isMin _ h.isMin
theorem not_isPredLimit_of_noMin [NoMinOrder α] [NoMaxOrder α] : ¬IsPredLimit a := by 

Proof state:
α : Type u_1
inst✝⁴ : Preorder α
a : α
inst✝³ : PredOrder α
inst✝² : IsPredArchimedean α
inst✝¹ : NoMinOrder α
inst✝ : NoMaxOrder α
⊢ ¬IsPredLimit a

Next tactic:
simp
theorem not_isPredLimit_iff : ¬IsPredLimit a ↔ ∃ b, ¬IsMin b ∧ pred b = a := by
  

Proof state:
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : PredOrder α
a b : α
C : α → Sort u_2
⊢ ¬IsPredLimit a ↔ ∃ b, ¬IsMin b ∧ pred b = a

Next tactic:
rw [← isSuccLimit_toDual_iff]
theorem not_isPredLimit_iff : ¬IsPredLimit a ↔ ∃ b, ¬IsMin b ∧ pred b = a := by
  rw [← isSuccLimit_toDual_iff]
  

Proof state:
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : PredOrder α
a b : α
C : α → Sort u_2
⊢ ¬IsSuccLimit (toDual a) ↔ ∃ b, ¬IsMin b ∧ pred b = a

Next tactic:
exact not_isSuccLimit_iff
/-- See `not_isPredLimit_iff` for a version that states that `a` is a successor of a value other
than itself. -/
theorem mem_range_pred_of_not_isPredLimit (h : ¬IsPredLimit a) : a ∈ range (@pred α _ _) := by
  

Proof state:
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : PredOrder α
a b : α
C : α → Sort u_2
h : ¬IsPredLimit a
⊢ a ∈ range pred

Next tactic:
cases' not_isPredLimit_iff.1 h with b hb
/-- See `not_isPredLimit_iff` for a version that states that `a` is a successor of a value other
than itself. -/
theorem mem_range_pred_of_not_isPredLimit (h : ¬IsPredLimit a) : a ∈ range (@pred α _ _) := by
  cases' not_isPredLimit_iff.1 h with b hb
  

Proof state:
case intro
α : Type u_1
inst✝¹ : PartialOrder α
inst✝ : PredOrder α
a b✝ : α
C : α → Sort u_2
h : ¬IsPredLimit a
b : α
hb : ¬IsMin b ∧ pred b = a
⊢ a ∈ range pred

Next tactic:
exact ⟨b, hb.2⟩
theorem not_isPredLimit [NoMaxOrder α] : ¬IsPredLimit a := by 

Proof state:
α : Type u_1
inst✝³ : PartialOrder α
inst✝² : PredOrder α
a b : α
C : α → Sort u_2
inst✝¹ : IsPredArchimedean α
inst✝ : NoMaxOrder α
⊢ ¬IsPredLimit a

Next tactic:
simp
/-- The limit cone for the product with a zero object is limiting. -/
def binaryFanZeroLeftIsLimit (X : C) : IsLimit (binaryFanZeroLeft X) :=
  BinaryFan.isLimitMk (fun s => BinaryFan.snd s) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.603, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryFan 0 X), (fun s => BinaryFan.snd s) s ≫ 0 = BinaryFan.fst s

Next tactic:
aesop_cat
/-- The limit cone for the product with a zero object is limiting. -/
def binaryFanZeroLeftIsLimit (X : C) : IsLimit (binaryFanZeroLeft X) :=
  BinaryFan.isLimitMk (fun s => BinaryFan.snd s) (by aesop_cat) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.603, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryFan 0 X), (fun s => BinaryFan.snd s) s ≫ 𝟙 X = BinaryFan.snd s

Next tactic:
aesop_cat
/-- The limit cone for the product with a zero object is limiting. -/
def binaryFanZeroLeftIsLimit (X : C) : IsLimit (binaryFanZeroLeft X) :=
  BinaryFan.isLimitMk (fun s => BinaryFan.snd s) (by aesop_cat) (by aesop_cat)
    (fun s m _ h₂ => by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.603, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : BinaryFan 0 X
m : s.pt ⟶ X
x✝ : m ≫ 0 = BinaryFan.fst s
h₂ : m ≫ 𝟙 X = BinaryFan.snd s
⊢ m = (fun s => BinaryFan.snd s) s

Next tactic:
simpa using h₂
@[simp]
theorem zeroProdIso_inv_snd (X : C) : (zeroProdIso X).inv ≫ prod.snd = 𝟙 X := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ (zeroProdIso X).inv ≫ prod.snd = 𝟙 X

Next tactic:
dsimp [zeroProdIso, binaryFanZeroLeft]
@[simp]
theorem zeroProdIso_inv_snd (X : C) : (zeroProdIso X).inv ≫ prod.snd = 𝟙 X := by
  dsimp [zeroProdIso, binaryFanZeroLeft]
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ (limit.isoLimitCone { cone := BinaryFan.mk 0 (𝟙 X), isLimit := binaryFanZeroLeftIsLimit X }).inv ≫ prod.snd = 𝟙 X

Next tactic:
simp
/-- The limit cone for the product with a zero object is limiting. -/
def binaryFanZeroRightIsLimit (X : C) : IsLimit (binaryFanZeroRight X) :=
  BinaryFan.isLimitMk (fun s => BinaryFan.fst s) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.6289, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryFan X 0), (fun s => BinaryFan.fst s) s ≫ 𝟙 X = BinaryFan.fst s

Next tactic:
aesop_cat
/-- The limit cone for the product with a zero object is limiting. -/
def binaryFanZeroRightIsLimit (X : C) : IsLimit (binaryFanZeroRight X) :=
  BinaryFan.isLimitMk (fun s => BinaryFan.fst s) (by aesop_cat) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.6289, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryFan X 0), (fun s => BinaryFan.fst s) s ≫ 0 = BinaryFan.snd s

Next tactic:
aesop_cat
/-- The limit cone for the product with a zero object is limiting. -/
def binaryFanZeroRightIsLimit (X : C) : IsLimit (binaryFanZeroRight X) :=
  BinaryFan.isLimitMk (fun s => BinaryFan.fst s) (by aesop_cat) (by aesop_cat)
    (fun s m h₁ _ => by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.6289, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : BinaryFan X 0
m : s.pt ⟶ X
h₁ : m ≫ 𝟙 X = BinaryFan.fst s
x✝ : m ≫ 0 = BinaryFan.snd s
⊢ m = (fun s => BinaryFan.fst s) s

Next tactic:
simpa using h₁
@[simp]
theorem prodZeroIso_iso_inv_snd (X : C) : (prodZeroIso X).inv ≫ prod.fst = 𝟙 X := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ (prodZeroIso X).inv ≫ prod.fst = 𝟙 X

Next tactic:
dsimp [prodZeroIso, binaryFanZeroRight]
@[simp]
theorem prodZeroIso_iso_inv_snd (X : C) : (prodZeroIso X).inv ≫ prod.fst = 𝟙 X := by
  dsimp [prodZeroIso, binaryFanZeroRight]
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ (limit.isoLimitCone { cone := BinaryFan.mk (𝟙 X) 0, isLimit := binaryFanZeroRightIsLimit X }).inv ≫ prod.fst = 𝟙 X

Next tactic:
simp
/-- The colimit cocone for the coproduct with a zero object is colimiting. -/
def binaryCofanZeroLeftIsColimit (X : C) : IsColimit (binaryCofanZeroLeft X) :=
  BinaryCofan.isColimitMk (fun s => BinaryCofan.inr s) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.11978, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryCofan 0 X), 0 ≫ (fun s => BinaryCofan.inr s) s = BinaryCofan.inl s

Next tactic:
aesop_cat
/-- The colimit cocone for the coproduct with a zero object is colimiting. -/
def binaryCofanZeroLeftIsColimit (X : C) : IsColimit (binaryCofanZeroLeft X) :=
  BinaryCofan.isColimitMk (fun s => BinaryCofan.inr s) (by aesop_cat) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.11978, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryCofan 0 X), 𝟙 X ≫ (fun s => BinaryCofan.inr s) s = BinaryCofan.inr s

Next tactic:
aesop_cat
/-- The colimit cocone for the coproduct with a zero object is colimiting. -/
def binaryCofanZeroLeftIsColimit (X : C) : IsColimit (binaryCofanZeroLeft X) :=
  BinaryCofan.isColimitMk (fun s => BinaryCofan.inr s) (by aesop_cat) (by aesop_cat)
    (fun s m _ h₂ => by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.11978, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : BinaryCofan 0 X
m : X ⟶ s.pt
x✝ : 0 ≫ m = BinaryCofan.inl s
h₂ : 𝟙 X ≫ m = BinaryCofan.inr s
⊢ m = (fun s => BinaryCofan.inr s) s

Next tactic:
simpa using h₂
@[simp]
theorem inr_zeroCoprodIso_hom (X : C) : coprod.inr ≫ (zeroCoprodIso X).hom = 𝟙 X := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ coprod.inr ≫ (zeroCoprodIso X).hom = 𝟙 X

Next tactic:
dsimp [zeroCoprodIso, binaryCofanZeroLeft]
@[simp]
theorem inr_zeroCoprodIso_hom (X : C) : coprod.inr ≫ (zeroCoprodIso X).hom = 𝟙 X := by
  dsimp [zeroCoprodIso, binaryCofanZeroLeft]
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ coprod.inr ≫
      (colimit.isoColimitCocone { cocone := BinaryCofan.mk 0 (𝟙 X), isColimit := binaryCofanZeroLeftIsColimit X }).hom =
    𝟙 X

Next tactic:
simp
/-- The colimit cocone for the coproduct with a zero object is colimiting. -/
def binaryCofanZeroRightIsColimit (X : C) : IsColimit (binaryCofanZeroRight X) :=
  BinaryCofan.isColimitMk (fun s => BinaryCofan.inl s) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.17961, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryCofan X 0), 𝟙 X ≫ (fun s => BinaryCofan.inl s) s = BinaryCofan.inl s

Next tactic:
aesop_cat
/-- The colimit cocone for the coproduct with a zero object is colimiting. -/
def binaryCofanZeroRightIsColimit (X : C) : IsColimit (binaryCofanZeroRight X) :=
  BinaryCofan.isColimitMk (fun s => BinaryCofan.inl s) (by aesop_cat) (by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.17961, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ ∀ (s : BinaryCofan X 0), 0 ≫ (fun s => BinaryCofan.inl s) s = BinaryCofan.inr s

Next tactic:
aesop_cat
/-- The colimit cocone for the coproduct with a zero object is colimiting. -/
def binaryCofanZeroRightIsColimit (X : C) : IsColimit (binaryCofanZeroRight X) :=
  BinaryCofan.isColimitMk (fun s => BinaryCofan.inl s) (by aesop_cat) (by aesop_cat)
    (fun s m h₁ _ => by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.17961, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : BinaryCofan X 0
m : X ⟶ s.pt
h₁ : 𝟙 X ≫ m = BinaryCofan.inl s
x✝ : 0 ≫ m = BinaryCofan.inr s
⊢ m = (fun s => BinaryCofan.inl s) s

Next tactic:
simpa using h₁
@[simp]
theorem inr_coprodZeroIso_hom (X : C) : coprod.inl ≫ (coprodZeroIso X).hom = 𝟙 X := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ coprod.inl ≫ (coprodZeroIso X).hom = 𝟙 X

Next tactic:
dsimp [coprodZeroIso, binaryCofanZeroRight]
@[simp]
theorem inr_coprodZeroIso_hom (X : C) : coprod.inl ≫ (coprodZeroIso X).hom = 𝟙 X := by
  dsimp [coprodZeroIso, binaryCofanZeroRight]
  

Proof state:
C : Type u_1
inst✝² : Category.{u_2, u_1} C
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ coprod.inl ≫
      (colimit.isoColimitCocone
          { cocone := BinaryCofan.mk (𝟙 X) 0, isColimit := binaryCofanZeroRightIsColimit X }).hom =
    𝟙 X

Next tactic:
simp
@[simp]
theorem pullbackZeroZeroIso_inv_fst (X Y : C) [HasBinaryProduct X Y] :
    (pullbackZeroZeroIso X Y).inv ≫ pullback.fst = prod.fst := by
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryProduct X Y
⊢ (pullbackZeroZeroIso X Y).inv ≫ pullback.fst = prod.fst

Next tactic:
dsimp [pullbackZeroZeroIso]
@[simp]
theorem pullbackZeroZeroIso_inv_fst (X Y : C) [HasBinaryProduct X Y] :
    (pullbackZeroZeroIso X Y).inv ≫ pullback.fst = prod.fst := by
  dsimp [pullbackZeroZeroIso]
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryProduct X Y
⊢ (limit.isoLimitCone
          { cone := PullbackCone.mk prod.fst prod.snd (_ : prod.fst ≫ 0 = prod.snd ≫ 0),
            isLimit :=
              isPullbackOfIsTerminalIsProduct 0 0 prod.fst prod.snd HasZeroObject.zeroIsTerminal
                (prodIsProd X Y) }).inv ≫
      pullback.fst =
    prod.fst

Next tactic:
simp
@[simp]
theorem pullbackZeroZeroIso_inv_snd (X Y : C) [HasBinaryProduct X Y] :
    (pullbackZeroZeroIso X Y).inv ≫ pullback.snd = prod.snd := by
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryProduct X Y
⊢ (pullbackZeroZeroIso X Y).inv ≫ pullback.snd = prod.snd

Next tactic:
dsimp [pullbackZeroZeroIso]
@[simp]
theorem pullbackZeroZeroIso_inv_snd (X Y : C) [HasBinaryProduct X Y] :
    (pullbackZeroZeroIso X Y).inv ≫ pullback.snd = prod.snd := by
  dsimp [pullbackZeroZeroIso]
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryProduct X Y
⊢ (limit.isoLimitCone
          { cone := PullbackCone.mk prod.fst prod.snd (_ : prod.fst ≫ 0 = prod.snd ≫ 0),
            isLimit :=
              isPullbackOfIsTerminalIsProduct 0 0 prod.fst prod.snd HasZeroObject.zeroIsTerminal
                (prodIsProd X Y) }).inv ≫
      pullback.snd =
    prod.snd

Next tactic:
simp
@[simp]
theorem pullbackZeroZeroIso_hom_fst (X Y : C) [HasBinaryProduct X Y] :
    (pullbackZeroZeroIso X Y).hom ≫ prod.fst = pullback.fst := by 

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryProduct X Y
⊢ (pullbackZeroZeroIso X Y).hom ≫ prod.fst = pullback.fst

Next tactic:
simp [← Iso.eq_inv_comp]
@[simp]
theorem pullbackZeroZeroIso_hom_snd (X Y : C) [HasBinaryProduct X Y] :
    (pullbackZeroZeroIso X Y).hom ≫ prod.snd = pullback.snd := by 

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryProduct X Y
⊢ (pullbackZeroZeroIso X Y).hom ≫ prod.snd = pullback.snd

Next tactic:
simp [← Iso.eq_inv_comp]
@[simp]
theorem inl_pushoutZeroZeroIso_hom (X Y : C) [HasBinaryCoproduct X Y] :
    pushout.inl ≫ (pushoutZeroZeroIso X Y).hom = coprod.inl := by
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryCoproduct X Y
⊢ pushout.inl ≫ (pushoutZeroZeroIso X Y).hom = coprod.inl

Next tactic:
dsimp [pushoutZeroZeroIso]
@[simp]
theorem inl_pushoutZeroZeroIso_hom (X Y : C) [HasBinaryCoproduct X Y] :
    pushout.inl ≫ (pushoutZeroZeroIso X Y).hom = coprod.inl := by
  dsimp [pushoutZeroZeroIso]
  

Proof state:
C : Type u_1
inst✝³ : Category.{u_2, u_1} C
inst✝² : HasZeroObject C
inst✝¹ : HasZeroMorphisms C
X Y : C
inst✝ : HasBinaryCoproduct X Y
⊢ pushout.inl ≫
      (colimit.isoColimitCocone
          { cocone := PushoutCocone.mk coprod.inl coprod.inr (_ : 0 ≫ coprod.inl = 0 ≫ coprod.inr),
            isColimit :=
              isPushoutOfIsInitialIsCoproduct coprod.inl coprod.inr 0 0 HasZeroObject.zeroIsInitial
                (coprodIsCoprod X Y) }).hom =
    coprod.inl

Next tactic:
simp