l3lab/ntp-mathlib huggingface dataset:
/-- The square with `0 : 0 ⟶ 0` on the right and `𝟙 X` on the left is a pushout square. -/
@[simp]
theorem zero_right (X : C) : IsPushout (0 : X ⟶ 0) (𝟙 X) (0 : (0 : C) ⟶ 0) (0 : X ⟶ 0) :=
  { w := by simp
    isColimit' :=
      ⟨{  desc := fun s => 0
          fac := fun s => by
            have c :=
              @PushoutCocone.coequalizer_ext _ _ _ _ _ _ _ s _ 0 (𝟙 _)
                (by simp [eq_iff_true_of_subsingleton]) (by simpa using PushoutCocone.condition s)
            

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cocone (span 0 (𝟙 X))
c : ∀ (j : WalkingSpan), s.ι.app j ≫ 0 = s.ι.app j ≫ 𝟙 s.pt
⊢ ∀ (j : WalkingSpan), (PushoutCocone.mk 0 0 (_ : 0 ≫ 0 = 𝟙 X ≫ 0)).ι.app j ≫ (fun s => 0) s = s.ι.app j

Next tactic:
dsimp at c
/-- The square with `0 : 0 ⟶ 0` on the right and `𝟙 X` on the left is a pushout square. -/
@[simp]
theorem zero_right (X : C) : IsPushout (0 : X ⟶ 0) (𝟙 X) (0 : (0 : C) ⟶ 0) (0 : X ⟶ 0) :=
  { w := by simp
    isColimit' :=
      ⟨{  desc := fun s => 0
          fac := fun s => by
            have c :=
              @PushoutCocone.coequalizer_ext _ _ _ _ _ _ _ s _ 0 (𝟙 _)
                (by simp [eq_iff_true_of_subsingleton]) (by simpa using PushoutCocone.condition s)
            dsimp at c
            

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
s : Cocone (span 0 (𝟙 X))
c : ∀ (j : WalkingSpan), s.ι.app j ≫ 0 = s.ι.app j ≫ 𝟙 s.pt
⊢ ∀ (j : WalkingSpan), (PushoutCocone.mk 0 0 (_ : 0 ≫ 0 = 𝟙 X ≫ 0)).ι.app j ≫ (fun s => 0) s = s.ι.app j

Next tactic:
simpa using c
/-- The square with `0 : 0 ⟶ 0` on the right left `𝟙 X` on the right is a pushout square. -/
@[simp]
theorem zero_left (X : C) : IsPushout (0 : 0 ⟶ X) (0 : (0 : C) ⟶ 0) (𝟙 X) (0 : 0 ⟶ X) :=
  of_iso_pushout (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ CommSq 0 0 (𝟙 X) 0

Next tactic:
simp
/-- The square with `0 : 0 ⟶ 0` on the right left `𝟙 X` on the right is a pushout square. -/
@[simp]
theorem zero_left (X : C) : IsPushout (0 : 0 ⟶ X) (0 : (0 : C) ⟶ 0) (𝟙 X) (0 : 0 ⟶ X) :=
  of_iso_pushout (by simp) ((coprodZeroIso X).symm ≪≫ (pushoutZeroZeroIso _ _).symm) (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ 𝟙 X ≫ ((coprodZeroIso X).symm ≪≫ (pushoutZeroZeroIso X 0).symm).hom = pushout.inl

Next tactic:
simp
/-- The square with `0 : 0 ⟶ 0` on the right left `𝟙 X` on the right is a pushout square. -/
@[simp]
theorem zero_left (X : C) : IsPushout (0 : 0 ⟶ X) (0 : (0 : C) ⟶ 0) (𝟙 X) (0 : 0 ⟶ X) :=
  of_iso_pushout (by simp) ((coprodZeroIso X).symm ≪≫ (pushoutZeroZeroIso _ _).symm) (by simp)
    (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X✝ Y P : C
f : Z ⟶ X✝
g : Z ⟶ Y
inl : X✝ ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
X : C
⊢ 0 ≫ ((coprodZeroIso X).symm ≪≫ (pushoutZeroZeroIso X 0).symm).hom = pushout.inr

Next tactic:
simp [eq_iff_true_of_subsingleton]
theorem of_isBilimit {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout (0 : 0 ⟶ X) (0 : 0 ⟶ Y) b.inl b.inr := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout 0 0 b.inl b.inr

Next tactic:
convert IsPushout.of_is_coproduct' h.isColimit HasZeroObject.zeroIsInitial
theorem inl_snd' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.inl (0 : X ⟶ 0) b.snd (0 : 0 ⟶ Y) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout b.inl 0 b.snd 0

Next tactic:
apply flip
theorem inl_snd' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.inl (0 : X ⟶ 0) b.snd (0 : 0 ⟶ Y) := by
  apply flip
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout 0 b.inl 0 b.snd

Next tactic:
refine' of_right _ (by simp) (of_isBilimit h)
theorem inl_snd' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.inl (0 : X ⟶ 0) b.snd (0 : 0 ⟶ Y) := by
  apply flip
  refine' of_right _ (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ 0 ≫ 0 = b.inl ≫ b.snd

Next tactic:
simp
theorem inl_snd' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.inl (0 : X ⟶ 0) b.snd (0 : 0 ⟶ Y) := by
  apply flip
  refine' of_right _ (by simp) (of_isBilimit h)
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout (0 ≫ 0) 0 0 (b.inr ≫ b.snd)

Next tactic:
simp
theorem inr_fst' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.inr (0 : Y ⟶ 0) b.fst (0 : 0 ⟶ X) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout b.inr 0 b.fst 0

Next tactic:
refine' of_bot _ (by simp) (of_isBilimit h)
theorem inr_fst' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.inr (0 : Y ⟶ 0) b.fst (0 : 0 ⟶ X) := by
  refine' of_bot _ (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ b.inr ≫ b.fst = 0 ≫ 0

Next tactic:
simp
theorem inr_fst' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.inr (0 : Y ⟶ 0) b.fst (0 : 0 ⟶ X) := by
  refine' of_bot _ (by simp) (of_isBilimit h)
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout 0 (0 ≫ 0) (b.inl ≫ b.fst) 0

Next tactic:
simp
theorem of_is_bilimit' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.fst b.snd (0 : X ⟶ 0) (0 : Y ⟶ 0) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout b.fst b.snd 0 0

Next tactic:
refine' IsPushout.of_right _ (by simp) (IsPushout.inl_snd' h)
theorem of_is_bilimit' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.fst b.snd (0 : X ⟶ 0) (0 : Y ⟶ 0) := by
  refine' IsPushout.of_right _ (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ b.fst ≫ 0 = b.snd ≫ 0

Next tactic:
simp
theorem of_is_bilimit' {b : BinaryBicone X Y} (h : b.IsBilimit) :
    IsPushout b.fst b.snd (0 : X ⟶ 0) (0 : Y ⟶ 0) := by
  refine' IsPushout.of_right _ (by simp) (IsPushout.inl_snd' h)
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : HasZeroObject C
inst✝ : HasZeroMorphisms C
b : BinaryBicone X Y
h : BinaryBicone.IsBilimit b
⊢ IsPushout (b.inl ≫ b.fst) 0 0 (0 ≫ 0)

Next tactic:
simp
theorem of_horiz_isIso [IsIso f] [IsIso inr] (sq : CommSq f g inl inr) : IsPushout f g inl inr :=
  of_isColimit' sq
    (by
      

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
⊢ IsColimit (CommSq.cocone sq)

Next tactic:
refine'
        PushoutCocone.IsColimit.mk _ (fun s => inv inr ≫ s.inr) (fun s => _)
          (by aesop_cat) (by aesop_cat)
theorem of_horiz_isIso [IsIso f] [IsIso inr] (sq : CommSq f g inl inr) : IsPushout f g inl inr :=
  of_isColimit' sq
    (by
      refine'
        PushoutCocone.IsColimit.mk _ (fun s => inv inr ≫ s.inr) (fun s => _)
          (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
⊢ ∀ (s : PushoutCocone f g), inr ≫ (fun s => inv inr ≫ PushoutCocone.inr s) s = PushoutCocone.inr s

Next tactic:
aesop_cat
theorem of_horiz_isIso [IsIso f] [IsIso inr] (sq : CommSq f g inl inr) : IsPushout f g inl inr :=
  of_isColimit' sq
    (by
      refine'
        PushoutCocone.IsColimit.mk _ (fun s => inv inr ≫ s.inr) (fun s => _)
          (by aesop_cat) (by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
⊢ ∀ (s : PushoutCocone f g) (m : P ⟶ s.pt),
    inl ≫ m = PushoutCocone.inl s → inr ≫ m = PushoutCocone.inr s → m = (fun s => inv inr ≫ PushoutCocone.inr s) s

Next tactic:
aesop_cat
theorem of_horiz_isIso [IsIso f] [IsIso inr] (sq : CommSq f g inl inr) : IsPushout f g inl inr :=
  of_isColimit' sq
    (by
      refine'
        PushoutCocone.IsColimit.mk _ (fun s => inv inr ≫ s.inr) (fun s => _)
          (by aesop_cat) (by aesop_cat)
      

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
Z X Y P : C
f : Z ⟶ X
g : Z ⟶ Y
inl : X ⟶ P
inr : Y ⟶ P
inst✝¹ : IsIso f
inst✝ : IsIso inr
sq : CommSq f g inl inr
s : PushoutCocone f g
⊢ inl ≫ (fun s => inv inr ≫ PushoutCocone.inr s) s = PushoutCocone.inl s

Next tactic:
simp only [← cancel_epi f, s.condition, sq.w_assoc, IsIso.hom_inv_id_assoc]
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ IsLimit (Fork.ofι f (_ : f ≫ g = f ≫ g'))

Next tactic:
fapply Fork.IsLimit.mk
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · 

Proof state:
case lift
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ (s : Fork g g') → s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt

Next tactic:
exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · 

Proof state:
case fac
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ ∀ (s : Fork g g'),
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
        Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) =
      Fork.ι s

Next tactic:
exact fun s => H.isLimit.fac _ WalkingCospan.left
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · 

Proof state:
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
⊢ ∀ (s : Fork g g') (m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt),
    m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s →
      m = IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g'))

Next tactic:
intro s m e
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · intro s m e
    

Proof state:
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ m = IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g'))

Next tactic:
apply PullbackCone.IsLimit.hom_ext H.isLimit
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · intro s m e
    apply PullbackCone.IsLimit.hom_ext H.isLimit <;> 

Proof state:
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ m ≫ PullbackCone.fst (cone H) =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.fst (cone H)

Next tactic:
refine' e.trans _
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · intro s m e
    apply PullbackCone.IsLimit.hom_ext H.isLimit <;> 

Proof state:
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ m ≫ PullbackCone.snd (cone H) =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.snd (cone H)

Next tactic:
refine' e.trans _
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · intro s m e
    apply PullbackCone.IsLimit.hom_ext H.isLimit <;> refine' e.trans _ <;> 

Proof state:
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ Fork.ι s =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.fst (cone H)

Next tactic:
symm
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · intro s m e
    apply PullbackCone.IsLimit.hom_ext H.isLimit <;> refine' e.trans _ <;> 

Proof state:
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ Fork.ι s =
    IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.snd (cone H)

Next tactic:
symm
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · intro s m e
    apply PullbackCone.IsLimit.hom_ext H.isLimit <;> refine' e.trans _ <;> symm <;>
      

Proof state:
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.fst (cone H) =
    Fork.ι s

Next tactic:
exact H.isLimit.fac _ _
/-- If `f : X ⟶ Y`, `g g' : Y ⟶ Z` forms a pullback square, then `f` is the equalizer of
`g` and `g'`. -/
noncomputable def IsPullback.isLimitFork (H : IsPullback f f g g') : IsLimit (Fork.ofι f H.w) := by
  fapply Fork.IsLimit.mk
  · exact fun s => H.isLimit.lift (PullbackCone.mk s.ι s.ι s.condition)
  · exact fun s => H.isLimit.fac _ WalkingCospan.left
  · intro s m e
    apply PullbackCone.IsLimit.hom_ext H.isLimit <;> refine' e.trans _ <;> symm <;>
      

Proof state:
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPullback f f g g'
s : Fork g g'
m : s.pt ⟶ (Fork.ofι f (_ : f ≫ g = f ≫ g')).pt
e : m ≫ Fork.ι (Fork.ofι f (_ : f ≫ g = f ≫ g')) = Fork.ι s
⊢ IsLimit.lift (isLimit H) (PullbackCone.mk (Fork.ι s) (Fork.ι s) (_ : Fork.ι s ≫ g = Fork.ι s ≫ g')) ≫
      PullbackCone.snd (cone H) =
    Fork.ι s

Next tactic:
exact H.isLimit.fac _ _
/-- If `f f' : X ⟶ Y`, `g : Y ⟶ Z` forms a pushout square, then `g` is the coequalizer of
`f` and `f'`. -/
noncomputable def IsPushout.isLimitFork (H : IsPushout f f' g g) :
    IsColimit (Cofork.ofπ g H.w) := by
  

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ IsColimit (Cofork.ofπ g (_ : f ≫ g = f' ≫ g))

Next tactic:
fapply Cofork.IsColimit.mk
/-- If `f f' : X ⟶ Y`, `g : Y ⟶ Z` forms a pushout square, then `g` is the coequalizer of
`f` and `f'`. -/
noncomputable def IsPushout.isLimitFork (H : IsPushout f f' g g) :
    IsColimit (Cofork.ofπ g H.w) := by
  fapply Cofork.IsColimit.mk
  · 

Proof state:
case desc
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ (s : Cofork f f') → (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt

Next tactic:
exact fun s => H.isColimit.desc (PushoutCocone.mk s.π s.π s.condition)
/-- If `f f' : X ⟶ Y`, `g : Y ⟶ Z` forms a pushout square, then `g` is the coequalizer of
`f` and `f'`. -/
noncomputable def IsPushout.isLimitFork (H : IsPushout f f' g g) :
    IsColimit (Cofork.ofπ g H.w) := by
  fapply Cofork.IsColimit.mk
  · exact fun s => H.isColimit.desc (PushoutCocone.mk s.π s.π s.condition)
  · 

Proof state:
case fac
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ ∀ (s : Cofork f f'),
    Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫
        IsColimit.desc (isColimit H)
          (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s)) =
      Cofork.π s

Next tactic:
exact fun s => H.isColimit.fac _ WalkingSpan.left
/-- If `f f' : X ⟶ Y`, `g : Y ⟶ Z` forms a pushout square, then `g` is the coequalizer of
`f` and `f'`. -/
noncomputable def IsPushout.isLimitFork (H : IsPushout f f' g g) :
    IsColimit (Cofork.ofπ g H.w) := by
  fapply Cofork.IsColimit.mk
  · exact fun s => H.isColimit.desc (PushoutCocone.mk s.π s.π s.condition)
  · exact fun s => H.isColimit.fac _ WalkingSpan.left
  · 

Proof state:
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
⊢ ∀ (s : Cofork f f') (m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt),
    Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s →
      m =
        IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))

Next tactic:
intro s m e
/-- If `f f' : X ⟶ Y`, `g : Y ⟶ Z` forms a pushout square, then `g` is the coequalizer of
`f` and `f'`. -/
noncomputable def IsPushout.isLimitFork (H : IsPushout f f' g g) :
    IsColimit (Cofork.ofπ g H.w) := by
  fapply Cofork.IsColimit.mk
  · exact fun s => H.isColimit.desc (PushoutCocone.mk s.π s.π s.condition)
  · exact fun s => H.isColimit.fac _ WalkingSpan.left
  · intro s m e
    

Proof state:
case uniq
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ m = IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))

Next tactic:
apply PushoutCocone.IsColimit.hom_ext H.isColimit
/-- If `f f' : X ⟶ Y`, `g : Y ⟶ Z` forms a pushout square, then `g` is the coequalizer of
`f` and `f'`. -/
noncomputable def IsPushout.isLimitFork (H : IsPushout f f' g g) :
    IsColimit (Cofork.ofπ g H.w) := by
  fapply Cofork.IsColimit.mk
  · exact fun s => H.isColimit.desc (PushoutCocone.mk s.π s.π s.condition)
  · exact fun s => H.isColimit.fac _ WalkingSpan.left
  · intro s m e
    apply PushoutCocone.IsColimit.hom_ext H.isColimit <;> 

Proof state:
case uniq.h₀
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ PushoutCocone.inl (cocone H) ≫ m =
    PushoutCocone.inl (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))

Next tactic:
refine' e.trans _
/-- If `f f' : X ⟶ Y`, `g : Y ⟶ Z` forms a pushout square, then `g` is the coequalizer of
`f` and `f'`. -/
noncomputable def IsPushout.isLimitFork (H : IsPushout f f' g g) :
    IsColimit (Cofork.ofπ g H.w) := by
  fapply Cofork.IsColimit.mk
  · exact fun s => H.isColimit.desc (PushoutCocone.mk s.π s.π s.condition)
  · exact fun s => H.isColimit.fac _ WalkingSpan.left
  · intro s m e
    apply PushoutCocone.IsColimit.hom_ext H.isColimit <;> 

Proof state:
case uniq.h₁
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f f' : X ⟶ Y
g g' : Y ⟶ Z
H : IsPushout f f' g g
s : Cofork f f'
m : (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)).pt ⟶ s.pt
e : Cofork.π (Cofork.ofπ g (_ : f ≫ g = f' ≫ g)) ≫ m = Cofork.π s
⊢ PushoutCocone.inr (cocone H) ≫ m =
    PushoutCocone.inr (cocone H) ≫
      IsColimit.desc (isColimit H) (PushoutCocone.mk (Cofork.π s) (Cofork.π s) (_ : f ≫ Cofork.π s = f' ≫ Cofork.π s))

Next tactic:
refine' e.trans _