l3lab/ntp-mathlib huggingface dataset:
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  

Proof state:
case refine'_1
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
j : Discrete WalkingPair
⊢ (inl ≫ (IsLimit.conePointUniqueUpToIso hb.isLimit (BinaryBiproduct.isLimit X Y)).inv) ≫
      (BinaryBicone.toCone b).π.app j =
    (inl ≫ desc b.inl b.inr) ≫ (BinaryBicone.toCone b).π.app j
case refine'_2
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
j : Discrete WalkingPair
⊢ (inr ≫ (IsLimit.conePointUniqueUpToIso hb.isLimit (BinaryBiproduct.isLimit X Y)).inv) ≫
      (BinaryBicone.toCone b).π.app j =
    (inr ≫ desc b.inl b.inr) ≫ (BinaryBicone.toCone b).π.app j

Next tactic:
all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    rcases j with ⟨⟨⟩⟩
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    

Proof state:
case refine'_1
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
j : Discrete WalkingPair
⊢ (inl ≫ (IsLimit.conePointUniqueUpToIso hb.isLimit (BinaryBiproduct.isLimit X Y)).inv) ≫
      (BinaryBicone.toCone b).π.app j =
    (inl ≫ desc b.inl b.inr) ≫ (BinaryBicone.toCone b).π.app j

Next tactic:
simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    

Proof state:
case refine'_1
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
j : Discrete WalkingPair
⊢ inl ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app j =
    inl ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app j

Next tactic:
rcases j with ⟨⟨⟩⟩
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    

Proof state:
case refine'_2
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
j : Discrete WalkingPair
⊢ (inr ≫ (IsLimit.conePointUniqueUpToIso hb.isLimit (BinaryBiproduct.isLimit X Y)).inv) ≫
      (BinaryBicone.toCone b).π.app j =
    (inr ≫ desc b.inl b.inr) ≫ (BinaryBicone.toCone b).π.app j

Next tactic:
simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    

Proof state:
case refine'_2
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
j : Discrete WalkingPair
⊢ inr ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app j =
    inr ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app j

Next tactic:
rcases j with ⟨⟨⟩⟩
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    rcases j with ⟨⟨⟩⟩
  

Proof state:
case refine'_1.mk.left
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inl ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.left } =
    inl ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.left }
case refine'_1.mk.right
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inl ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.right } =
    inl ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.right }
case refine'_2.mk.left
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inr ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.left } =
    inr ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.left }
case refine'_2.mk.right
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inr ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.right } =
    inr ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.right }

Next tactic:
all_goals simp
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    rcases j with ⟨⟨⟩⟩
  all_goals 

Proof state:
case refine'_1.mk.left
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inl ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.left } =
    inl ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.left }

Next tactic:
simp
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    rcases j with ⟨⟨⟩⟩
  all_goals 

Proof state:
case refine'_1.mk.right
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inl ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.right } =
    inl ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.right }

Next tactic:
simp
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    rcases j with ⟨⟨⟩⟩
  all_goals 

Proof state:
case refine'_2.mk.left
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inr ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.left } =
    inr ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.left }

Next tactic:
simp
/-- Auxiliary lemma for `biprod.uniqueUpToIso`. -/
theorem biprod.conePointUniqueUpToIso_inv (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) :
    (hb.isLimit.conePointUniqueUpToIso (BinaryBiproduct.isLimit _ _)).inv =
      biprod.desc b.inl b.inr := by
  refine' biprod.hom_ext' _ _ (hb.isLimit.hom_ext fun j => _) (hb.isLimit.hom_ext fun j => _)
  all_goals
    simp only [Category.assoc, IsLimit.conePointUniqueUpToIso_inv_comp]
    rcases j with ⟨⟨⟩⟩
  all_goals 

Proof state:
case refine'_2.mk.right
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ inr ≫ (BinaryBicone.toCone (BinaryBiproduct.bicone X Y)).π.app { as := WalkingPair.right } =
    inr ≫ desc b.inl b.inr ≫ (BinaryBicone.toCone b).π.app { as := WalkingPair.right }

Next tactic:
simp
/-- Binary biproducts are unique up to isomorphism. This already follows because bilimits are
    limits, but in the case of biproducts we can give an isomorphism with particularly nice
    definitional properties, namely that `biprod.lift b.fst b.snd` and `biprod.desc b.inl b.inr`
    are inverses of each other. -/
@[simps]
def biprod.uniqueUpToIso (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) : b.pt ≅ X ⊞ Y where
  hom := biprod.lift b.fst b.snd
  inv := biprod.desc b.inl b.inr
  hom_inv_id := by
    

Proof state:
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ lift b.fst b.snd ≫ desc b.inl b.inr = 𝟙 b.pt

Next tactic:
rw [← biprod.conePointUniqueUpToIso_hom X Y hb, ←
      biprod.conePointUniqueUpToIso_inv X Y hb, Iso.hom_inv_id]
/-- Binary biproducts are unique up to isomorphism. This already follows because bilimits are
    limits, but in the case of biproducts we can give an isomorphism with particularly nice
    definitional properties, namely that `biprod.lift b.fst b.snd` and `biprod.desc b.inl b.inr`
    are inverses of each other. -/
@[simps]
def biprod.uniqueUpToIso (X Y : C) [HasBinaryBiproduct X Y] {b : BinaryBicone X Y}
    (hb : b.IsBilimit) : b.pt ≅ X ⊞ Y where
  hom := biprod.lift b.fst b.snd
  inv := biprod.desc b.inl b.inr
  hom_inv_id := by
    rw [← biprod.conePointUniqueUpToIso_hom X Y hb, ←
      biprod.conePointUniqueUpToIso_inv X Y hb, Iso.hom_inv_id]
  inv_hom_id := by
    

Proof state:
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
b : BinaryBicone X Y
hb : BinaryBicone.IsBilimit b
⊢ desc b.inl b.inr ≫ lift b.fst b.snd = 𝟙 (X ⊞ Y)

Next tactic:
rw [← biprod.conePointUniqueUpToIso_hom X Y hb, ←
      biprod.conePointUniqueUpToIso_inv X Y hb, Iso.inv_hom_id]
theorem biprod.isIso_inl_iff_id_eq_fst_comp_inl (X Y : C) [HasBinaryBiproduct X Y] :
    IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ 𝟙 (X ⊞ Y) = biprod.fst ≫ biprod.inl := by
  

Proof state:
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
⊢ IsIso inl ↔ 𝟙 (X ⊞ Y) = fst ≫ inl

Next tactic:
constructor
theorem biprod.isIso_inl_iff_id_eq_fst_comp_inl (X Y : C) [HasBinaryBiproduct X Y] :
    IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ 𝟙 (X ⊞ Y) = biprod.fst ≫ biprod.inl := by
  constructor
  · 

Proof state:
case mp
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
⊢ IsIso inl → 𝟙 (X ⊞ Y) = fst ≫ inl

Next tactic:
intro h
theorem biprod.isIso_inl_iff_id_eq_fst_comp_inl (X Y : C) [HasBinaryBiproduct X Y] :
    IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ 𝟙 (X ⊞ Y) = biprod.fst ≫ biprod.inl := by
  constructor
  · intro h
    

Proof state:
case mp
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
h : IsIso inl
⊢ 𝟙 (X ⊞ Y) = fst ≫ inl

Next tactic:
have := (cancel_epi (inv biprod.inl : X ⊞ Y ⟶ X)).2 <| @biprod.inl_fst _ _ _ X Y _
theorem biprod.isIso_inl_iff_id_eq_fst_comp_inl (X Y : C) [HasBinaryBiproduct X Y] :
    IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ 𝟙 (X ⊞ Y) = biprod.fst ≫ biprod.inl := by
  constructor
  · intro h
    have := (cancel_epi (inv biprod.inl : X ⊞ Y ⟶ X)).2 <| @biprod.inl_fst _ _ _ X Y _
    

Proof state:
case mp
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
h : IsIso inl
this : inv inl ≫ inl ≫ fst = inv inl ≫ 𝟙 X
⊢ 𝟙 (X ⊞ Y) = fst ≫ inl

Next tactic:
rw [IsIso.inv_hom_id_assoc, Category.comp_id] at this
theorem biprod.isIso_inl_iff_id_eq_fst_comp_inl (X Y : C) [HasBinaryBiproduct X Y] :
    IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ 𝟙 (X ⊞ Y) = biprod.fst ≫ biprod.inl := by
  constructor
  · intro h
    have := (cancel_epi (inv biprod.inl : X ⊞ Y ⟶ X)).2 <| @biprod.inl_fst _ _ _ X Y _
    rw [IsIso.inv_hom_id_assoc, Category.comp_id] at this
    

Proof state:
case mp
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
h : IsIso inl
this : fst = inv inl
⊢ 𝟙 (X ⊞ Y) = fst ≫ inl

Next tactic:
rw [this, IsIso.inv_hom_id]
theorem biprod.isIso_inl_iff_id_eq_fst_comp_inl (X Y : C) [HasBinaryBiproduct X Y] :
    IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ 𝟙 (X ⊞ Y) = biprod.fst ≫ biprod.inl := by
  constructor
  · intro h
    have := (cancel_epi (inv biprod.inl : X ⊞ Y ⟶ X)).2 <| @biprod.inl_fst _ _ _ X Y _
    rw [IsIso.inv_hom_id_assoc, Category.comp_id] at this
    rw [this, IsIso.inv_hom_id]
  · 

Proof state:
case mpr
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
⊢ 𝟙 (X ⊞ Y) = fst ≫ inl → IsIso inl

Next tactic:
intro h
theorem biprod.isIso_inl_iff_id_eq_fst_comp_inl (X Y : C) [HasBinaryBiproduct X Y] :
    IsIso (biprod.inl : X ⟶ X ⊞ Y) ↔ 𝟙 (X ⊞ Y) = biprod.fst ≫ biprod.inl := by
  constructor
  · intro h
    have := (cancel_epi (inv biprod.inl : X ⊞ Y ⟶ X)).2 <| @biprod.inl_fst _ _ _ X Y _
    rw [IsIso.inv_hom_id_assoc, Category.comp_id] at this
    rw [this, IsIso.inv_hom_id]
  · intro h
    

Proof state:
case mpr
J : Type w
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasZeroMorphisms C
P Q X Y : C
inst✝ : HasBinaryBiproduct X Y
h : 𝟙 (X ⊞ Y) = fst ≫ inl
⊢ IsIso inl

Next tactic:
exact ⟨⟨biprod.fst, biprod.inl_fst, h.symm⟩⟩
/-- The fork defined in `BinaryBicone.fstKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitFstKernelFork (i : IsLimit c.toCone) : IsLimit c.fstKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.snd, by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.fst 0
⊢ (Fork.ι s ≫ c.snd) ≫ Fork.ι (fstKernelFork c) = Fork.ι s

Next tactic:
apply BinaryFan.IsLimit.hom_ext i
/-- The fork defined in `BinaryBicone.fstKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitFstKernelFork (i : IsLimit c.toCone) : IsLimit c.fstKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.snd, by apply BinaryFan.IsLimit.hom_ext i <;> 

Proof state:
case h₁
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.fst 0
⊢ ((Fork.ι s ≫ c.snd) ≫ Fork.ι (fstKernelFork c)) ≫ BinaryFan.fst (toCone c) = Fork.ι s ≫ BinaryFan.fst (toCone c)

Next tactic:
simp
/-- The fork defined in `BinaryBicone.fstKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitFstKernelFork (i : IsLimit c.toCone) : IsLimit c.fstKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.snd, by apply BinaryFan.IsLimit.hom_ext i <;> 

Proof state:
case h₂
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.fst 0
⊢ ((Fork.ι s ≫ c.snd) ≫ Fork.ι (fstKernelFork c)) ≫ BinaryFan.snd (toCone c) = Fork.ι s ≫ BinaryFan.snd (toCone c)

Next tactic:
simp
/-- The fork defined in `BinaryBicone.fstKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitFstKernelFork (i : IsLimit c.toCone) : IsLimit c.fstKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.snd, by apply BinaryFan.IsLimit.hom_ext i <;> simp, fun hm => by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.fst 0
m✝ :
  ((const WalkingParallelPair).obj s.pt).obj WalkingParallelPair.zero ⟶
    ((const WalkingParallelPair).obj (fstKernelFork c).pt).obj WalkingParallelPair.zero
hm : m✝ ≫ Fork.ι (fstKernelFork c) = Fork.ι s
⊢ m✝ = Fork.ι s ≫ c.snd

Next tactic:
simp [← hm]
/-- The fork defined in `BinaryBicone.sndKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitSndKernelFork (i : IsLimit c.toCone) : IsLimit c.sndKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.fst, by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.snd 0
⊢ (Fork.ι s ≫ c.fst) ≫ Fork.ι (sndKernelFork c) = Fork.ι s

Next tactic:
apply BinaryFan.IsLimit.hom_ext i
/-- The fork defined in `BinaryBicone.sndKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitSndKernelFork (i : IsLimit c.toCone) : IsLimit c.sndKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.fst, by apply BinaryFan.IsLimit.hom_ext i <;> 

Proof state:
case h₁
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.snd 0
⊢ ((Fork.ι s ≫ c.fst) ≫ Fork.ι (sndKernelFork c)) ≫ BinaryFan.fst (toCone c) = Fork.ι s ≫ BinaryFan.fst (toCone c)

Next tactic:
simp
/-- The fork defined in `BinaryBicone.sndKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitSndKernelFork (i : IsLimit c.toCone) : IsLimit c.sndKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.fst, by apply BinaryFan.IsLimit.hom_ext i <;> 

Proof state:
case h₂
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.snd 0
⊢ ((Fork.ι s ≫ c.fst) ≫ Fork.ι (sndKernelFork c)) ≫ BinaryFan.snd (toCone c) = Fork.ι s ≫ BinaryFan.snd (toCone c)

Next tactic:
simp
/-- The fork defined in `BinaryBicone.sndKernelFork` is indeed a kernel. -/
def BinaryBicone.isLimitSndKernelFork (i : IsLimit c.toCone) : IsLimit c.sndKernelFork :=
  Fork.IsLimit.mk' _ fun s =>
    ⟨s.ι ≫ c.fst, by apply BinaryFan.IsLimit.hom_ext i <;> simp, fun hm => by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsLimit (toCone c)
s : Fork c.snd 0
m✝ :
  ((const WalkingParallelPair).obj s.pt).obj WalkingParallelPair.zero ⟶
    ((const WalkingParallelPair).obj (sndKernelFork c).pt).obj WalkingParallelPair.zero
hm : m✝ ≫ Fork.ι (sndKernelFork c) = Fork.ι s
⊢ m✝ = Fork.ι s ≫ c.fst

Next tactic:
simp [← hm]
/-- The cofork defined in `BinaryBicone.inlCokernelCofork` is indeed a cokernel. -/
def BinaryBicone.isColimitInlCokernelCofork (i : IsColimit c.toCocone) :
    IsColimit c.inlCokernelCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨c.inr ≫ s.π, by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsColimit (toCocone c)
s : Cofork c.inl 0
⊢ Cofork.π (inlCokernelCofork c) ≫ c.inr ≫ Cofork.π s = Cofork.π s

Next tactic:
apply BinaryCofan.IsColimit.hom_ext i
/-- The cofork defined in `BinaryBicone.inlCokernelCofork` is indeed a cokernel. -/
def BinaryBicone.isColimitInlCokernelCofork (i : IsColimit c.toCocone) :
    IsColimit c.inlCokernelCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨c.inr ≫ s.π, by apply BinaryCofan.IsColimit.hom_ext i <;> 

Proof state:
case h₁
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsColimit (toCocone c)
s : Cofork c.inl 0
⊢ BinaryCofan.inl (toCocone c) ≫ Cofork.π (inlCokernelCofork c) ≫ c.inr ≫ Cofork.π s =
    BinaryCofan.inl (toCocone c) ≫ Cofork.π s

Next tactic:
simp
/-- The cofork defined in `BinaryBicone.inlCokernelCofork` is indeed a cokernel. -/
def BinaryBicone.isColimitInlCokernelCofork (i : IsColimit c.toCocone) :
    IsColimit c.inlCokernelCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨c.inr ≫ s.π, by apply BinaryCofan.IsColimit.hom_ext i <;> 

Proof state:
case h₂
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsColimit (toCocone c)
s : Cofork c.inl 0
⊢ BinaryCofan.inr (toCocone c) ≫ Cofork.π (inlCokernelCofork c) ≫ c.inr ≫ Cofork.π s =
    BinaryCofan.inr (toCocone c) ≫ Cofork.π s

Next tactic:
simp
/-- The cofork defined in `BinaryBicone.inlCokernelCofork` is indeed a cokernel. -/
def BinaryBicone.isColimitInlCokernelCofork (i : IsColimit c.toCocone) :
    IsColimit c.inlCokernelCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨c.inr ≫ s.π, by apply BinaryCofan.IsColimit.hom_ext i <;> simp, fun hm => by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsColimit (toCocone c)
s : Cofork c.inl 0
m✝ :
  ((const WalkingParallelPair).obj (inlCokernelCofork c).pt).obj WalkingParallelPair.one ⟶
    ((const WalkingParallelPair).obj s.pt).obj WalkingParallelPair.one
hm : Cofork.π (inlCokernelCofork c) ≫ m✝ = Cofork.π s
⊢ m✝ = c.inr ≫ Cofork.π s

Next tactic:
simp [← hm]
/-- The cofork defined in `BinaryBicone.inrCokernelCofork` is indeed a cokernel. -/
def BinaryBicone.isColimitInrCokernelCofork (i : IsColimit c.toCocone) :
    IsColimit c.inrCokernelCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨c.inl ≫ s.π, by 

Proof state:
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsColimit (toCocone c)
s : Cofork c.inr 0
⊢ Cofork.π (inrCokernelCofork c) ≫ c.inl ≫ Cofork.π s = Cofork.π s

Next tactic:
apply BinaryCofan.IsColimit.hom_ext i
/-- The cofork defined in `BinaryBicone.inrCokernelCofork` is indeed a cokernel. -/
def BinaryBicone.isColimitInrCokernelCofork (i : IsColimit c.toCocone) :
    IsColimit c.inrCokernelCofork :=
  Cofork.IsColimit.mk' _ fun s =>
    ⟨c.inl ≫ s.π, by apply BinaryCofan.IsColimit.hom_ext i <;> 

Proof state:
case h₁
J : Type w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasZeroMorphisms C
P Q X Y : C
c : BinaryBicone X Y
i : IsColimit (toCocone c)
s : Cofork c.inr 0
⊢ BinaryCofan.inl (toCocone c) ≫ Cofork.π (inrCokernelCofork c) ≫ c.inl ≫ Cofork.π s =
    BinaryCofan.inl (toCocone c) ≫ Cofork.π s

Next tactic:
simp