l3lab/ntp-mathlib huggingface dataset:
/-- If `W` is the pushout of `f, g`,
it is also the pushout of `h ≫ f, h ≫ g` for any epi `h`. -/
def isColimitOfEpiComp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h] (s : PushoutCocone f g)
    (H : IsColimit s) :
    IsColimit
      (PushoutCocone.mk _ _
        (show (h ≫ f) ≫ s.inl = (h ≫ g) ≫ s.inr by
          rw [Category.assoc, Category.assoc, s.condition])) := by
  apply PushoutCocone.isColimitAux'
  intro s
  

Proof state:
case create
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Y
g✝ : X ⟶ Z
f : X ⟶ Y
g : X ⟶ Z
h : W ⟶ X
inst✝ : Epi h
s✝ : PushoutCocone f g
H : IsColimit s✝
s : PushoutCocone (h ≫ f) (h ≫ g)
⊢ { l //
    inl (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ l = inl s ∧
      inr (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ l = inr s ∧
        ∀ {m : (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)).pt ⟶ s.pt},
          inl (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inl s →
            inr (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inr s → m = l }

Next tactic:
rcases PushoutCocone.IsColimit.desc' H s.inl s.inr
      ((cancel_epi h).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
/-- If `W` is the pushout of `f, g`,
it is also the pushout of `h ≫ f, h ≫ g` for any epi `h`. -/
def isColimitOfEpiComp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h] (s : PushoutCocone f g)
    (H : IsColimit s) :
    IsColimit
      (PushoutCocone.mk _ _
        (show (h ≫ f) ≫ s.inl = (h ≫ g) ≫ s.inr by
          rw [Category.assoc, Category.assoc, s.condition])) := by
  apply PushoutCocone.isColimitAux'
  intro s
  rcases PushoutCocone.IsColimit.desc' H s.inl s.inr
      ((cancel_epi h).mp (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Y
g✝ : X ⟶ Z
f : X ⟶ Y
g : X ⟶ Z
h : W ⟶ X
inst✝ : Epi h
s✝ : PushoutCocone f g
H : IsColimit s✝
s : PushoutCocone (h ≫ f) (h ≫ g)
⊢ h ≫ f ≫ inl s = h ≫ g ≫ inr s

Next tactic:
simpa using s.condition
/-- If `W` is the pushout of `f, g`,
it is also the pushout of `h ≫ f, h ≫ g` for any epi `h`. -/
def isColimitOfEpiComp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h] (s : PushoutCocone f g)
    (H : IsColimit s) :
    IsColimit
      (PushoutCocone.mk _ _
        (show (h ≫ f) ≫ s.inl = (h ≫ g) ≫ s.inr by
          rw [Category.assoc, Category.assoc, s.condition])) := by
  apply PushoutCocone.isColimitAux'
  intro s
  rcases PushoutCocone.IsColimit.desc' H s.inl s.inr
      ((cancel_epi h).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  

Proof state:
case create.mk.intro
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Y
g✝ : X ⟶ Z
f : X ⟶ Y
g : X ⟶ Z
h : W ⟶ X
inst✝ : Epi h
s✝ : PushoutCocone f g
H : IsColimit s✝
s : PushoutCocone (h ≫ f) (h ≫ g)
l : s✝.pt ⟶ s.pt
h₁ : inl s✝ ≫ l = inl s
h₂ : inr s✝ ≫ l = inr s
⊢ { l //
    inl (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ l = inl s ∧
      inr (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ l = inr s ∧
        ∀ {m : (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)).pt ⟶ s.pt},
          inl (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inl s →
            inr (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inr s → m = l }

Next tactic:
refine' ⟨l, h₁, h₂, _⟩
/-- If `W` is the pushout of `f, g`,
it is also the pushout of `h ≫ f, h ≫ g` for any epi `h`. -/
def isColimitOfEpiComp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h] (s : PushoutCocone f g)
    (H : IsColimit s) :
    IsColimit
      (PushoutCocone.mk _ _
        (show (h ≫ f) ≫ s.inl = (h ≫ g) ≫ s.inr by
          rw [Category.assoc, Category.assoc, s.condition])) := by
  apply PushoutCocone.isColimitAux'
  intro s
  rcases PushoutCocone.IsColimit.desc' H s.inl s.inr
      ((cancel_epi h).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  refine' ⟨l, h₁, h₂, _⟩
  

Proof state:
case create.mk.intro
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Y
g✝ : X ⟶ Z
f : X ⟶ Y
g : X ⟶ Z
h : W ⟶ X
inst✝ : Epi h
s✝ : PushoutCocone f g
H : IsColimit s✝
s : PushoutCocone (h ≫ f) (h ≫ g)
l : s✝.pt ⟶ s.pt
h₁ : inl s✝ ≫ l = inl s
h₂ : inr s✝ ≫ l = inr s
⊢ ∀ {m : (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)).pt ⟶ s.pt},
    inl (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inl s →
      inr (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inr s → m = l

Next tactic:
intro m hm₁ hm₂
/-- If `W` is the pushout of `f, g`,
it is also the pushout of `h ≫ f, h ≫ g` for any epi `h`. -/
def isColimitOfEpiComp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h] (s : PushoutCocone f g)
    (H : IsColimit s) :
    IsColimit
      (PushoutCocone.mk _ _
        (show (h ≫ f) ≫ s.inl = (h ≫ g) ≫ s.inr by
          rw [Category.assoc, Category.assoc, s.condition])) := by
  apply PushoutCocone.isColimitAux'
  intro s
  rcases PushoutCocone.IsColimit.desc' H s.inl s.inr
      ((cancel_epi h).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  refine' ⟨l, h₁, h₂, _⟩
  intro m hm₁ hm₂
  

Proof state:
case create.mk.intro
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X Y Z : C
f✝ : X ⟶ Y
g✝ : X ⟶ Z
f : X ⟶ Y
g : X ⟶ Z
h : W ⟶ X
inst✝ : Epi h
s✝ : PushoutCocone f g
H : IsColimit s✝
s : PushoutCocone (h ≫ f) (h ≫ g)
l : s✝.pt ⟶ s.pt
h₁ : inl s✝ ≫ l = inl s
h₂ : inr s✝ ≫ l = inr s
m : (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)).pt ⟶ s.pt
hm₁ : inl (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inl s
hm₂ : inr (mk (inl s✝) (inr s✝) (_ : (h ≫ f) ≫ inl s✝ = (h ≫ g) ≫ inr s✝)) ≫ m = inr s
⊢ m = l

Next tactic:
exact (PushoutCocone.IsColimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) : _)
/-- A diagram `WalkingCospan ⥤ C` is isomorphic to some `PullbackCone.mk` after
composing with `diagramIsoCospan`. -/
@[simps!]
def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) :
    (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅
      PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
        ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) :=
  Cones.ext (Iso.refl _) <| by
    

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingCospan ⥤ C
t : Cone F
⊢ ∀ (j : WalkingCospan),
    ((Cones.postcompose (diagramIsoCospan F).hom).obj t).π.app j =
      (Iso.refl ((Cones.postcompose (diagramIsoCospan F).hom).obj t).pt).hom ≫
        (mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
                (_ : t.π.app WalkingCospan.left ≫ F.map inl = t.π.app WalkingCospan.right ≫ F.map inr)).π.app
          j

Next tactic:
rintro (_ | (_ | _))
/-- A diagram `WalkingCospan ⥤ C` is isomorphic to some `PullbackCone.mk` after
composing with `diagramIsoCospan`. -/
@[simps!]
def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) :
    (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅
      PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
        ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) :=
  Cones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · 

Proof state:
case none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingCospan ⥤ C
t : Cone F
⊢ ((Cones.postcompose (diagramIsoCospan F).hom).obj t).π.app none =
    (Iso.refl ((Cones.postcompose (diagramIsoCospan F).hom).obj t).pt).hom ≫
      (mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
              (_ : t.π.app WalkingCospan.left ≫ F.map inl = t.π.app WalkingCospan.right ≫ F.map inr)).π.app
        none

Next tactic:
dsimp
/-- A diagram `WalkingCospan ⥤ C` is isomorphic to some `PullbackCone.mk` after
composing with `diagramIsoCospan`. -/
@[simps!]
def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) :
    (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅
      PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
        ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) :=
  Cones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · dsimp
        

Proof state:
case none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingCospan ⥤ C
t : Cone F
⊢ t.π.app none ≫ 𝟙 (F.obj none) = 𝟙 t.pt ≫ t.π.app WalkingCospan.left ≫ F.map inl

Next tactic:
simp
/-- A diagram `WalkingCospan ⥤ C` is isomorphic to some `PullbackCone.mk` after
composing with `diagramIsoCospan`. -/
@[simps!]
def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) :
    (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅
      PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
        ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) :=
  Cones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · 

Proof state:
case some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingCospan ⥤ C
t : Cone F
⊢ ((Cones.postcompose (diagramIsoCospan F).hom).obj t).π.app (some WalkingPair.left) =
    (Iso.refl ((Cones.postcompose (diagramIsoCospan F).hom).obj t).pt).hom ≫
      (mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
              (_ : t.π.app WalkingCospan.left ≫ F.map inl = t.π.app WalkingCospan.right ≫ F.map inr)).π.app
        (some WalkingPair.left)

Next tactic:
dsimp
/-- A diagram `WalkingCospan ⥤ C` is isomorphic to some `PullbackCone.mk` after
composing with `diagramIsoCospan`. -/
@[simps!]
def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) :
    (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅
      PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
        ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) :=
  Cones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · dsimp
        

Proof state:
case some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingCospan ⥤ C
t : Cone F
⊢ t.π.app (some WalkingPair.left) ≫ 𝟙 (F.obj (some WalkingPair.left)) = 𝟙 t.pt ≫ t.π.app WalkingCospan.left

Next tactic:
simp
/-- A diagram `WalkingCospan ⥤ C` is isomorphic to some `PullbackCone.mk` after
composing with `diagramIsoCospan`. -/
@[simps!]
def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) :
    (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅
      PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
        ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) :=
  Cones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · 

Proof state:
case some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingCospan ⥤ C
t : Cone F
⊢ ((Cones.postcompose (diagramIsoCospan F).hom).obj t).π.app (some WalkingPair.right) =
    (Iso.refl ((Cones.postcompose (diagramIsoCospan F).hom).obj t).pt).hom ≫
      (mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
              (_ : t.π.app WalkingCospan.left ≫ F.map inl = t.π.app WalkingCospan.right ≫ F.map inr)).π.app
        (some WalkingPair.right)

Next tactic:
dsimp
/-- A diagram `WalkingCospan ⥤ C` is isomorphic to some `PullbackCone.mk` after
composing with `diagramIsoCospan`. -/
@[simps!]
def PullbackCone.isoMk {F : WalkingCospan ⥤ C} (t : Cone F) :
    (Cones.postcompose (diagramIsoCospan.{v} _).hom).obj t ≅
      PullbackCone.mk (t.π.app WalkingCospan.left) (t.π.app WalkingCospan.right)
        ((t.π.naturality inl).symm.trans (t.π.naturality inr : _)) :=
  Cones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · dsimp
        

Proof state:
case some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingCospan ⥤ C
t : Cone F
⊢ t.π.app (some WalkingPair.right) ≫ 𝟙 (F.obj (some WalkingPair.right)) = 𝟙 t.pt ≫ t.π.app WalkingCospan.right

Next tactic:
simp
/-- A diagram `WalkingSpan ⥤ C` is isomorphic to some `PushoutCocone.mk` after composing with
`diagramIsoSpan`. -/
@[simps!]
def PushoutCocone.isoMk {F : WalkingSpan ⥤ C} (t : Cocone F) :
    (Cocones.precompose (diagramIsoSpan.{v} _).inv).obj t ≅
      PushoutCocone.mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
        ((t.ι.naturality fst).trans (t.ι.naturality snd).symm) :=
  Cocones.ext (Iso.refl _) <| by
    

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingSpan ⥤ C
t : Cocone F
⊢ ∀ (j : WalkingSpan),
    ((Cocones.precompose (diagramIsoSpan F).inv).obj t).ι.app j ≫
        (Iso.refl ((Cocones.precompose (diagramIsoSpan F).inv).obj t).pt).hom =
      (mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
              (_ : F.map fst ≫ t.ι.app WalkingSpan.left = F.map snd ≫ t.ι.app WalkingSpan.right)).ι.app
        j

Next tactic:
rintro (_ | (_ | _))
/-- A diagram `WalkingSpan ⥤ C` is isomorphic to some `PushoutCocone.mk` after composing with
`diagramIsoSpan`. -/
@[simps!]
def PushoutCocone.isoMk {F : WalkingSpan ⥤ C} (t : Cocone F) :
    (Cocones.precompose (diagramIsoSpan.{v} _).inv).obj t ≅
      PushoutCocone.mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
        ((t.ι.naturality fst).trans (t.ι.naturality snd).symm) :=
  Cocones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · 

Proof state:
case none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingSpan ⥤ C
t : Cocone F
⊢ ((Cocones.precompose (diagramIsoSpan F).inv).obj t).ι.app none ≫
      (Iso.refl ((Cocones.precompose (diagramIsoSpan F).inv).obj t).pt).hom =
    (mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
            (_ : F.map fst ≫ t.ι.app WalkingSpan.left = F.map snd ≫ t.ι.app WalkingSpan.right)).ι.app
      none

Next tactic:
dsimp
/-- A diagram `WalkingSpan ⥤ C` is isomorphic to some `PushoutCocone.mk` after composing with
`diagramIsoSpan`. -/
@[simps!]
def PushoutCocone.isoMk {F : WalkingSpan ⥤ C} (t : Cocone F) :
    (Cocones.precompose (diagramIsoSpan.{v} _).inv).obj t ≅
      PushoutCocone.mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
        ((t.ι.naturality fst).trans (t.ι.naturality snd).symm) :=
  Cocones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · dsimp
        

Proof state:
case none
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingSpan ⥤ C
t : Cocone F
⊢ (𝟙 (F.obj WalkingSpan.zero) ≫ t.ι.app none) ≫ 𝟙 t.pt = F.map fst ≫ t.ι.app WalkingSpan.left

Next tactic:
simp
/-- A diagram `WalkingSpan ⥤ C` is isomorphic to some `PushoutCocone.mk` after composing with
`diagramIsoSpan`. -/
@[simps!]
def PushoutCocone.isoMk {F : WalkingSpan ⥤ C} (t : Cocone F) :
    (Cocones.precompose (diagramIsoSpan.{v} _).inv).obj t ≅
      PushoutCocone.mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
        ((t.ι.naturality fst).trans (t.ι.naturality snd).symm) :=
  Cocones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · 

Proof state:
case some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingSpan ⥤ C
t : Cocone F
⊢ ((Cocones.precompose (diagramIsoSpan F).inv).obj t).ι.app (some WalkingPair.left) ≫
      (Iso.refl ((Cocones.precompose (diagramIsoSpan F).inv).obj t).pt).hom =
    (mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
            (_ : F.map fst ≫ t.ι.app WalkingSpan.left = F.map snd ≫ t.ι.app WalkingSpan.right)).ι.app
      (some WalkingPair.left)

Next tactic:
dsimp
/-- A diagram `WalkingSpan ⥤ C` is isomorphic to some `PushoutCocone.mk` after composing with
`diagramIsoSpan`. -/
@[simps!]
def PushoutCocone.isoMk {F : WalkingSpan ⥤ C} (t : Cocone F) :
    (Cocones.precompose (diagramIsoSpan.{v} _).inv).obj t ≅
      PushoutCocone.mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
        ((t.ι.naturality fst).trans (t.ι.naturality snd).symm) :=
  Cocones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · dsimp
        

Proof state:
case some.left
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingSpan ⥤ C
t : Cocone F
⊢ (𝟙 (F.obj WalkingSpan.left) ≫ t.ι.app (some WalkingPair.left)) ≫ 𝟙 t.pt = t.ι.app WalkingSpan.left

Next tactic:
simp
/-- A diagram `WalkingSpan ⥤ C` is isomorphic to some `PushoutCocone.mk` after composing with
`diagramIsoSpan`. -/
@[simps!]
def PushoutCocone.isoMk {F : WalkingSpan ⥤ C} (t : Cocone F) :
    (Cocones.precompose (diagramIsoSpan.{v} _).inv).obj t ≅
      PushoutCocone.mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
        ((t.ι.naturality fst).trans (t.ι.naturality snd).symm) :=
  Cocones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · 

Proof state:
case some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingSpan ⥤ C
t : Cocone F
⊢ ((Cocones.precompose (diagramIsoSpan F).inv).obj t).ι.app (some WalkingPair.right) ≫
      (Iso.refl ((Cocones.precompose (diagramIsoSpan F).inv).obj t).pt).hom =
    (mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
            (_ : F.map fst ≫ t.ι.app WalkingSpan.left = F.map snd ≫ t.ι.app WalkingSpan.right)).ι.app
      (some WalkingPair.right)

Next tactic:
dsimp
/-- A diagram `WalkingSpan ⥤ C` is isomorphic to some `PushoutCocone.mk` after composing with
`diagramIsoSpan`. -/
@[simps!]
def PushoutCocone.isoMk {F : WalkingSpan ⥤ C} (t : Cocone F) :
    (Cocones.precompose (diagramIsoSpan.{v} _).inv).obj t ≅
      PushoutCocone.mk (t.ι.app WalkingSpan.left) (t.ι.app WalkingSpan.right)
        ((t.ι.naturality fst).trans (t.ι.naturality snd).symm) :=
  Cocones.ext (Iso.refl _) <| by
    rintro (_ | (_ | _)) <;>
      · dsimp
        

Proof state:
case some.right
C : Type u
inst✝¹ : Category.{v, u} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
W X Y Z : C
F : WalkingSpan ⥤ C
t : Cocone F
⊢ (𝟙 (F.obj WalkingSpan.right) ≫ t.ι.app (some WalkingPair.right)) ≫ 𝟙 t.pt = t.ι.app WalkingSpan.right

Next tactic:
simp
/-- Given such a diagram, then there is a natural morphism `W ×ₛ X ⟶ Y ×ₜ Z`.

    W ⟶ Y
      ↘      ↘
        S ⟶ T
      ↗      ↗
    X ⟶ Z

-/
abbrev pullback.map {W X Y Z S T : C} (f₁ : W ⟶ S) (f₂ : X ⟶ S) [HasPullback f₁ f₂] (g₁ : Y ⟶ T)
    (g₂ : Z ⟶ T) [HasPullback g₁ g₂] (i₁ : W ⟶ Y) (i₂ : X ⟶ Z) (i₃ : S ⟶ T)
    (eq₁ : f₁ ≫ i₃ = i₁ ≫ g₁) (eq₂ : f₂ ≫ i₃ = i₂ ≫ g₂) : pullback f₁ f₂ ⟶ pullback g₁ g₂ :=
  pullback.lift (pullback.fst ≫ i₁) (pullback.snd ≫ i₂)
    (by 

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
W✝ X✝ Y✝ Z✝ W X Y Z S T : C
f₁ : W ⟶ S
f₂ : X ⟶ S
inst✝¹ : HasPullback f₁ f₂
g₁ : Y ⟶ T
g₂ : Z ⟶ T
inst✝ : HasPullback g₁ g₂
i₁ : W ⟶ Y
i₂ : X ⟶ Z
i₃ : S ⟶ T
eq₁ : f₁ ≫ i₃ = i₁ ≫ g₁
eq₂ : f₂ ≫ i₃ = i₂ ≫ g₂
⊢ (fst ≫ i₁) ≫ g₁ = (snd ≫ i₂) ≫ g₂

Next tactic:
simp [← eq₁, ← eq₂, pullback.condition_assoc]
/-- Given such a diagram, then there is a natural morphism `W ⨿ₛ X ⟶ Y ⨿ₜ Z`.

        W ⟶ Y
      ↗      ↗
    S ⟶ T
      ↘      ↘
        X ⟶ Z

-/
abbrev pushout.map {W X Y Z S T : C} (f₁ : S ⟶ W) (f₂ : S ⟶ X) [HasPushout f₁ f₂] (g₁ : T ⟶ Y)
    (g₂ : T ⟶ Z) [HasPushout g₁ g₂] (i₁ : W ⟶ Y) (i₂ : X ⟶ Z) (i₃ : S ⟶ T) (eq₁ : f₁ ≫ i₁ = i₃ ≫ g₁)
    (eq₂ : f₂ ≫ i₂ = i₃ ≫ g₂) : pushout f₁ f₂ ⟶ pushout g₁ g₂ :=
  pushout.desc (i₁ ≫ pushout.inl) (i₂ ≫ pushout.inr)
    (by
      

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
W✝ X✝ Y✝ Z✝ W X Y Z S T : C
f₁ : S ⟶ W
f₂ : S ⟶ X
inst✝¹ : HasPushout f₁ f₂
g₁ : T ⟶ Y
g₂ : T ⟶ Z
inst✝ : HasPushout g₁ g₂
i₁ : W ⟶ Y
i₂ : X ⟶ Z
i₃ : S ⟶ T
eq₁ : f₁ ≫ i₁ = i₃ ≫ g₁
eq₂ : f₂ ≫ i₂ = i₃ ≫ g₂
⊢ f₁ ≫ i₁ ≫ inl = f₂ ≫ i₂ ≫ inr

Next tactic:
simp only [← Category.assoc, eq₁, eq₂]
/-- Given such a diagram, then there is a natural morphism `W ⨿ₛ X ⟶ Y ⨿ₜ Z`.

        W ⟶ Y
      ↗      ↗
    S ⟶ T
      ↘      ↘
        X ⟶ Z

-/
abbrev pushout.map {W X Y Z S T : C} (f₁ : S ⟶ W) (f₂ : S ⟶ X) [HasPushout f₁ f₂] (g₁ : T ⟶ Y)
    (g₂ : T ⟶ Z) [HasPushout g₁ g₂] (i₁ : W ⟶ Y) (i₂ : X ⟶ Z) (i₃ : S ⟶ T) (eq₁ : f₁ ≫ i₁ = i₃ ≫ g₁)
    (eq₂ : f₂ ≫ i₂ = i₃ ≫ g₂) : pushout f₁ f₂ ⟶ pushout g₁ g₂ :=
  pushout.desc (i₁ ≫ pushout.inl) (i₂ ≫ pushout.inr)
    (by
      simp only [← Category.assoc, eq₁, eq₂]
      

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
W✝ X✝ Y✝ Z✝ W X Y Z S T : C
f₁ : S ⟶ W
f₂ : S ⟶ X
inst✝¹ : HasPushout f₁ f₂
g₁ : T ⟶ Y
g₂ : T ⟶ Z
inst✝ : HasPushout g₁ g₂
i₁ : W ⟶ Y
i₂ : X ⟶ Z
i₃ : S ⟶ T
eq₁ : f₁ ≫ i₁ = i₃ ≫ g₁
eq₂ : f₂ ≫ i₂ = i₃ ≫ g₂
⊢ (i₃ ≫ g₁) ≫ inl = (i₃ ≫ g₂) ≫ inr

Next tactic:
simp [pushout.condition]
/-- The pullback cone built from the pullback projections is a pullback. -/
def pullbackIsPullback {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) [HasPullback f g] :
    IsLimit (PullbackCone.mk (pullback.fst : pullback f g ⟶ _) pullback.snd pullback.condition) :=
  PullbackCone.IsLimit.mk _ (fun s => pullback.lift s.fst s.snd s.condition) (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X✝ Y✝ Z✝ X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
inst✝ : HasPullback f g
⊢ ∀ (s : PullbackCone f g),
    (fun s =>
            pullback.lift (PullbackCone.fst s) (PullbackCone.snd s)
              (_ : PullbackCone.fst s ≫ f = PullbackCone.snd s ≫ g))
          s ≫
        pullback.fst =
      PullbackCone.fst s

Next tactic:
simp
/-- The pullback cone built from the pullback projections is a pullback. -/
def pullbackIsPullback {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) [HasPullback f g] :
    IsLimit (PullbackCone.mk (pullback.fst : pullback f g ⟶ _) pullback.snd pullback.condition) :=
  PullbackCone.IsLimit.mk _ (fun s => pullback.lift s.fst s.snd s.condition) (by simp) (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X✝ Y✝ Z✝ X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
inst✝ : HasPullback f g
⊢ ∀ (s : PullbackCone f g),
    (fun s =>
            pullback.lift (PullbackCone.fst s) (PullbackCone.snd s)
              (_ : PullbackCone.fst s ≫ f = PullbackCone.snd s ≫ g))
          s ≫
        pullback.snd =
      PullbackCone.snd s

Next tactic:
simp
/-- The pullback cone built from the pullback projections is a pullback. -/
def pullbackIsPullback {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z) [HasPullback f g] :
    IsLimit (PullbackCone.mk (pullback.fst : pullback f g ⟶ _) pullback.snd pullback.condition) :=
  PullbackCone.IsLimit.mk _ (fun s => pullback.lift s.fst s.snd s.condition) (by simp) (by simp)
    (by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
W X✝ Y✝ Z✝ X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
inst✝ : HasPullback f g
⊢ ∀ (s : PullbackCone f g) (m : s.pt ⟶ pullback f g),
    m ≫ pullback.fst = PullbackCone.fst s →
      m ≫ pullback.snd = PullbackCone.snd s →
        m =
          (fun s =>
              pullback.lift (PullbackCone.fst s) (PullbackCone.snd s)
                (_ : PullbackCone.fst s ≫ f = PullbackCone.snd s ≫ g))
            s

Next tactic:
aesop_cat
/-- The map `X ×[Z] Y ⟶ X × Y` is mono. -/
instance mono_pullback_to_prod {C : Type*} [Category C] {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z)
    [HasPullback f g] [HasBinaryProduct X Y] :
    Mono (prod.lift pullback.fst pullback.snd : pullback f g ⟶ _) :=
  ⟨fun {W} i₁ i₂ h => by
    

Proof state:
C✝ : Type u
inst✝⁴ : Category.{v, u} C✝
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
W✝ X✝ Y✝ Z✝ : C✝
C : Type u_1
inst✝² : Category.{?u.225702, u_1} C
X Y Z : C
f : X ⟶ Z
g : Y ⟶ Z
inst✝¹ : HasPullback f g
inst✝ : HasBinaryProduct X Y
W : C
i₁ i₂ : W ⟶ pullback f g
h : i₁ ≫ prod.lift pullback.fst pullback.snd = i₂ ≫ prod.lift pullback.fst pullback.snd
⊢ i₁ = i₂

Next tactic:
ext