File: Mathlib/CategoryTheory/Limits/Shapes/Pullback/PullbackCone.lean

full_name: CategoryTheory.Limits.PullbackCone
code: /-- A pullback cone is just a cone on the cospan formed by two morphisms `f : X ⟶ Z` and
    `g : Y ⟶ Z`. -/
abbrev PullbackCone (f : X ⟶ Z) (g : Y ⟶ Z) 
goal: Type (max u v)

full_name: CategoryTheory.Limits.PullbackCone.fst
code: /-- The first projection of a pullback cone. -/
abbrev fst (t : PullbackCone f g) : t.pt ⟶ X 
goal: t.pt ⟶ X

full_name: CategoryTheory.Limits.PullbackCone.snd
code: /-- The second projection of a pullback cone. -/
abbrev snd (t : PullbackCone f g) : t.pt ⟶ Y 
goal: t.pt ⟶ Y

full_name: CategoryTheory.Limits.PullbackCone.π_app_left
code: @[simp]
theorem π_app_left (c : PullbackCone f g) : c.π.app WalkingCospan.left = c.fst 
goal: c.π.app CategoryTheory.Limits.WalkingCospan.left = c.fst

full_name: CategoryTheory.Limits.PullbackCone.π_app_right
code: @[simp]
theorem π_app_right (c : PullbackCone f g) : c.π.app WalkingCospan.right = c.snd 
goal: c.π.app CategoryTheory.Limits.WalkingCospan.right = c.snd

full_name: CategoryTheory.Limits.PullbackCone.condition_one
code: @[simp]
theorem condition_one (t : PullbackCone f g) : t.π.app WalkingCospan.one = t.fst ≫ f 
goal: t.π.app CategoryTheory.Limits.WalkingCospan.one = t.fst ≫ f

full_name: CategoryTheory.Limits.PullbackCone.mk_pt
code: /-- A pullback cone on `f` and `g` is determined by morphisms `fst : W ⟶ X` and `snd : W ⟶ Y`
    such that `fst ≫ f = snd ≫ g`. -/
@[simps]
def mk {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) : PullbackCone f g 
goal: (CategoryTheory.Limits.PullbackCone.mk fst snd eq).pt = W

full_name: CategoryTheory.Limits.PullbackCone.mk_π_app
code: /-- A pullback cone on `f` and `g` is determined by morphisms `fst : W ⟶ X` and `snd : W ⟶ Y`
    such that `fst ≫ f = snd ≫ g`. -/
@[simps]
def mk {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) : PullbackCone f g 
goal: (CategoryTheory.Limits.PullbackCone.mk fst snd eq).π.app j =
  Option.casesOn j (fst ≫ f) fun j' => CategoryTheory.Limits.WalkingPair.casesOn j' fst snd

full_name: CategoryTheory.Limits.PullbackCone.mk
code: /-- A pullback cone on `f` and `g` is determined by morphisms `fst : W ⟶ X` and `snd : W ⟶ Y`
    such that `fst ≫ f = snd ≫ g`. -/
@[simps]
def mk {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) : PullbackCone f g 
goal: CategoryTheory.Limits.PullbackCone f g

full_name: CategoryTheory.Limits.PullbackCone.mk_π_app_left
code: @[simp]
theorem mk_π_app_left {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) :
    (mk fst snd eq).π.app WalkingCospan.left = fst 
goal: (CategoryTheory.Limits.PullbackCone.mk fst snd eq).π.app CategoryTheory.Limits.WalkingCospan.left = fst

full_name: CategoryTheory.Limits.PullbackCone.mk_π_app_right
code: @[simp]
theorem mk_π_app_right {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) :
    (mk fst snd eq).π.app WalkingCospan.right = snd 
goal: (CategoryTheory.Limits.PullbackCone.mk fst snd eq).π.app CategoryTheory.Limits.WalkingCospan.right = snd

full_name: CategoryTheory.Limits.PullbackCone.mk_π_app_one
code: @[simp]
theorem mk_π_app_one {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) :
    (mk fst snd eq).π.app WalkingCospan.one = fst ≫ f 
goal: (CategoryTheory.Limits.PullbackCone.mk fst snd eq).π.app CategoryTheory.Limits.WalkingCospan.one = fst ≫ f

full_name: CategoryTheory.Limits.PullbackCone.mk_fst
code: @[simp]
theorem mk_fst {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) :
    (mk fst snd eq).fst = fst 
goal: (CategoryTheory.Limits.PullbackCone.mk fst snd eq).fst = fst

full_name: CategoryTheory.Limits.PullbackCone.mk_snd
code: @[simp]
theorem mk_snd {W : C} (fst : W ⟶ X) (snd : W ⟶ Y) (eq : fst ≫ f = snd ≫ g) :
    (mk fst snd eq).snd = snd 
goal: (CategoryTheory.Limits.PullbackCone.mk fst snd eq).snd = snd

full_name: CategoryTheory.Limits.PullbackCone.condition
code: @[reassoc]
theorem condition (t : PullbackCone f g) : fst t ≫ f = snd t ≫ g 
goal: t.fst ≫ f = t.snd ≫ g

full_name: CategoryTheory.Limits.PullbackCone.equalizer_ext
code: /-- To check whether two morphisms are equalized by the maps of a pullback cone, it suffices to
check it for `fst t` and `snd t` -/
theorem equalizer_ext (t : PullbackCone f g) {W : C} {k l : W ⟶ t.pt} (h₀ : k ≫ fst t = l ≫ fst t)
    (h₁ : k ≫ snd t = l ≫ snd t) : ∀ j : WalkingCospan, k ≫ t.π.app j = l ≫ t.π.app j
  
goal: k ≫ t.π.app j = l ≫ t.π.app j

full_name: CategoryTheory.Limits.PullbackCone.ext
code: /-- To construct an isomorphism of pullback cones, it suffices to construct an isomorphism
of the cone points and check it commutes with `fst` and `snd`. -/
def ext {s t : PullbackCone f g} (i : s.pt ≅ t.pt) (w₁ : s.fst = i.hom ≫ t.fst := by aesop_cat)
    (w₂ : s.snd = i.hom ≫ t.snd := by aesop_cat) : s ≅ t 
goal: s ≅ t

full_name: CategoryTheory.Limits.PullbackCone.eta_hom_hom
code: /-- The natural isomorphism between a pullback cone and the corresponding pullback cone
reconstructed using `PullbackCone.mk`. -/
@[simps!]
def eta (t : PullbackCone f g) : t ≅ mk t.fst t.snd t.condition 
goal: t.eta.hom.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PullbackCone.eta_inv_hom
code: /-- The natural isomorphism between a pullback cone and the corresponding pullback cone
reconstructed using `PullbackCone.mk`. -/
@[simps!]
def eta (t : PullbackCone f g) : t ≅ mk t.fst t.snd t.condition 
goal: t.eta.inv.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PullbackCone.eta
code: /-- The natural isomorphism between a pullback cone and the corresponding pullback cone
reconstructed using `PullbackCone.mk`. -/
@[simps!]
def eta (t : PullbackCone f g) : t ≅ mk t.fst t.snd t.condition 
goal: t ≅ CategoryTheory.Limits.PullbackCone.mk t.fst t.snd ⋯

full_name: CategoryTheory.Limits.PullbackCone.isLimitAux
code: /-- This is a slightly more convenient method to verify that a pullback cone is a limit cone. It
    only asks for a proof of facts that carry any mathematical content -/
def isLimitAux (t : PullbackCone f g) (lift : ∀ s : PullbackCone f g, s.pt ⟶ t.pt)
    (fac_left : ∀ s : PullbackCone f g, lift s ≫ t.fst = s.fst)
    (fac_right : ∀ s : PullbackCone f g, lift s ≫ t.snd = s.snd)
    (uniq : ∀ (s : PullbackCone f g) (m : s.pt ⟶ t.pt)
      (_ : ∀ j : WalkingCospan, m ≫ t.π.app j = s.π.app j), m = lift s) : IsLimit t 
goal: CategoryTheory.Limits.IsLimit t

full_name: CategoryTheory.Limits.PullbackCone.isLimitAux'
code: /-- This is another convenient method to verify that a pullback cone is a limit cone. It
    only asks for a proof of facts that carry any mathematical content, and allows access to the
    same `s` for all parts. -/
def isLimitAux' (t : PullbackCone f g)
    (create :
      ∀ s : PullbackCone f g,
        { l //
          l ≫ t.fst = s.fst ∧
            l ≫ t.snd = s.snd ∧ ∀ {m}, m ≫ t.fst = s.fst → m ≫ t.snd = s.snd → m = l }) :
    Limits.IsLimit t 
goal: CategoryTheory.Limits.IsLimit t

full_name: CategoryTheory.Limits.PullbackCone.IsLimit.mk
code: /-- This is a more convenient formulation to show that a `PullbackCone` constructed using
`PullbackCone.mk` is a limit cone.
-/
def IsLimit.mk {W : C} {fst : W ⟶ X} {snd : W ⟶ Y} (eq : fst ≫ f = snd ≫ g)
    (lift : ∀ s : PullbackCone f g, s.pt ⟶ W)
    (fac_left : ∀ s : PullbackCone f g, lift s ≫ fst = s.fst)
    (fac_right : ∀ s : PullbackCone f g, lift s ≫ snd = s.snd)
    (uniq :
      ∀ (s : PullbackCone f g) (m : s.pt ⟶ W) (_ : m ≫ fst = s.fst) (_ : m ≫ snd = s.snd),
        m = lift s) :
    IsLimit (mk fst snd eq) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.PullbackCone.mk fst snd eq)

full_name: CategoryTheory.Limits.PullbackCone.IsLimit.hom_ext
code: theorem IsLimit.hom_ext {t : PullbackCone f g} (ht : IsLimit t) {W : C} {k l : W ⟶ t.pt}
    (h₀ : k ≫ fst t = l ≫ fst t) (h₁ : k ≫ snd t = l ≫ snd t) : k = l 
goal: k = l

full_name: CategoryTheory.Limits.PullbackCone.IsLimit.lift
code: /-- If `t` is a limit pullback cone over `f` and `g` and `h : W ⟶ X` and `k : W ⟶ Y` are such that
    `h ≫ f = k ≫ g`, then we get `l : W ⟶ t.pt`, which satisfies `l ≫ fst t = h`
    and `l ≫ snd t = k`, see `IsLimit.lift_fst` and `IsLimit.lift_snd`. -/
def IsLimit.lift {t : PullbackCone f g} (ht : IsLimit t) {W : C} (h : W ⟶ X) (k : W ⟶ Y)
    (w : h ≫ f = k ≫ g) : W ⟶ t.pt 
goal: W ⟶ t.pt

full_name: CategoryTheory.Limits.PullbackCone.IsLimit.lift_fst
code: @[reassoc (attr := simp)]
lemma IsLimit.lift_fst {t : PullbackCone f g} (ht : IsLimit t) {W : C} (h : W ⟶ X) (k : W ⟶ Y)
    (w : h ≫ f = k ≫ g) : IsLimit.lift ht h k w ≫ fst t = h 
goal: CategoryTheory.Limits.PullbackCone.IsLimit.lift ht h k w ≫ t.fst = h

full_name: CategoryTheory.Limits.PullbackCone.IsLimit.lift_snd
code: @[reassoc (attr := simp)]
lemma IsLimit.lift_snd {t : PullbackCone f g} (ht : IsLimit t) {W : C} (h : W ⟶ X) (k : W ⟶ Y)
    (w : h ≫ f = k ≫ g) : IsLimit.lift ht h k w ≫ snd t = k 
goal: CategoryTheory.Limits.PullbackCone.IsLimit.lift ht h k w ≫ t.snd = k

full_name: CategoryTheory.Limits.PullbackCone.IsLimit.lift'
code: /-- If `t` is a limit pullback cone over `f` and `g` and `h : W ⟶ X` and `k : W ⟶ Y` are such that
    `h ≫ f = k ≫ g`, then we have `l : W ⟶ t.pt` satisfying `l ≫ fst t = h` and `l ≫ snd t = k`.
    -/
def IsLimit.lift' {t : PullbackCone f g} (ht : IsLimit t) {W : C} (h : W ⟶ X) (k : W ⟶ Y)
    (w : h ≫ f = k ≫ g) : { l : W ⟶ t.pt // l ≫ fst t = h ∧ l ≫ snd t = k } 
goal: { l // l ≫ t.fst = h ∧ l ≫ t.snd = k }

full_name: CategoryTheory.Limits.PullbackCone.mkSelfIsLimit
code: /-- The pullback cone reconstructed using `PullbackCone.mk` from a pullback cone that is a
limit, is also a limit. -/
def mkSelfIsLimit {t : PullbackCone f g} (ht : IsLimit t) : IsLimit (mk t.fst t.snd t.condition) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.PullbackCone.mk t.fst t.snd ⋯)

full_name: CategoryTheory.Limits.PullbackCone.flip
code: /-- The pullback cone obtained by flipping `fst` and `snd`. -/
def flip : PullbackCone g f 
goal: CategoryTheory.Limits.PullbackCone g f

full_name: CategoryTheory.Limits.PullbackCone.flip_pt
code: @[simp] lemma flip_pt : t.flip.pt = t.pt 
goal: t.flip.pt = t.pt

full_name: CategoryTheory.Limits.PullbackCone.flip_fst
code: @[simp] lemma flip_fst : t.flip.fst = t.snd 
goal: t.flip.fst = t.snd

full_name: CategoryTheory.Limits.PullbackCone.flip_snd
code: @[simp] lemma flip_snd : t.flip.snd = t.fst 
goal: t.flip.snd = t.fst

full_name: CategoryTheory.Limits.PullbackCone.flipFlipIso
code: /-- Flipping a pullback cone twice gives an isomorphic cone. -/
def flipFlipIso : t.flip.flip ≅ t 
goal: t.flip.flip ≅ t

full_name: CategoryTheory.Limits.PullbackCone.flipIsLimit
code: /-- The flip of a pullback square is a pullback square. -/
def flipIsLimit (ht : IsLimit t) : IsLimit t.flip 
goal: CategoryTheory.Limits.IsLimit t.flip

full_name: CategoryTheory.Limits.PullbackCone.isLimitOfFlip
code: /-- A square is a pullback square if its flip is. -/
def isLimitOfFlip (ht : IsLimit t.flip) : IsLimit t 
goal: CategoryTheory.Limits.IsLimit t

full_name: CategoryTheory.Limits.Cone.ofPullbackCone
code: /-- This is a helper construction that can be useful when verifying that a category has all
    pullbacks. Given `F : WalkingCospan ⥤ C`, which is really the same as
    `cospan (F.map inl) (F.map inr)`, and a pullback cone on `F.map inl` and `F.map inr`, we
    get a cone on `F`.

    If you're thinking about using this, have a look at `hasPullbacks_of_hasLimit_cospan`,
    which you may find to be an easier way of achieving your goal. -/
@[simps]
def Cone.ofPullbackCone {F : WalkingCospan ⥤ C} (t : PullbackCone (F.map inl) (F.map inr)) :
    Cone F 
goal: CategoryTheory.Limits.Cone F

full_name: CategoryTheory.Limits.Cone.ofPullbackCone_pt
code: /-- This is a helper construction that can be useful when verifying that a category has all
    pullbacks. Given `F : WalkingCospan ⥤ C`, which is really the same as
    `cospan (F.map inl) (F.map inr)`, and a pullback cone on `F.map inl` and `F.map inr`, we
    get a cone on `F`.

    If you're thinking about using this, have a look at `hasPullbacks_of_hasLimit_cospan`,
    which you may find to be an easier way of achieving your goal. -/
@[simps]
def Cone.ofPullbackCone {F : WalkingCospan ⥤ C} (t : PullbackCone (F.map inl) (F.map inr)) :
    Cone F 
goal: (CategoryTheory.Limits.Cone.ofPullbackCone t).pt = t.pt

full_name: CategoryTheory.Limits.Cone.ofPullbackCone_π
code: /-- This is a helper construction that can be useful when verifying that a category has all
    pullbacks. Given `F : WalkingCospan ⥤ C`, which is really the same as
    `cospan (F.map inl) (F.map inr)`, and a pullback cone on `F.map inl` and `F.map inr`, we
    get a cone on `F`.

    If you're thinking about using this, have a look at `hasPullbacks_of_hasLimit_cospan`,
    which you may find to be an easier way of achieving your goal. -/
@[simps]
def Cone.ofPullbackCone {F : WalkingCospan ⥤ C} (t : PullbackCone (F.map inl) (F.map inr)) :
    Cone F 
goal: (CategoryTheory.Limits.Cone.ofPullbackCone t).π = t.π ≫ (CategoryTheory.Limits.diagramIsoCospan F).inv

full_name: CategoryTheory.Limits.PullbackCone.ofCone_π
code: /-- Given `F : WalkingCospan ⥤ C`, which is really the same as `cospan (F.map inl) (F.map inr)`,
    and a cone on `F`, we get a pullback cone on `F.map inl` and `F.map inr`. -/
@[simps]
def PullbackCone.ofCone {F : WalkingCospan ⥤ C} (t : Cone F) :
    PullbackCone (F.map inl) (F.map inr) 
goal: (CategoryTheory.Limits.PullbackCone.ofCone t).π = t.π ≫ (CategoryTheory.Limits.diagramIsoCospan F).hom

full_name: CategoryTheory.Limits.PullbackCone.ofCone_pt
code: /-- Given `F : WalkingCospan ⥤ C`, which is really the same as `cospan (F.map inl) (F.map inr)`,
    and a cone on `F`, we get a pullback cone on `F.map inl` and `F.map inr`. -/
@[simps]
def PullbackCone.ofCone {F : WalkingCospan ⥤ C} (t : Cone F) :
    PullbackCone (F.map inl) (F.map inr) 
goal: (CategoryTheory.Limits.PullbackCone.ofCone t).pt = t.pt

full_name: CategoryTheory.Limits.PullbackCone.ofCone
code: /-- Given `F : WalkingCospan ⥤ C`, which is really the same as `cospan (F.map inl) (F.map inr)`,
    and a cone on `F`, we get a pullback cone on `F.map inl` and `F.map inr`. -/
@[simps]
def PullbackCone.ofCone {F : WalkingCospan ⥤ C} (t : Cone F) :
    PullbackCone (F.map inl) (F.map inr) 
goal: CategoryTheory.Limits.PullbackCone (F.map CategoryTheory.Limits.WalkingCospan.Hom.inl)
  (F.map CategoryTheory.Limits.WalkingCospan.Hom.inr)

full_name: CategoryTheory.Limits.PullbackCone.isoMk
code: /-- 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 : _)) 
goal: (CategoryTheory.Limits.Cones.postcompose (CategoryTheory.Limits.diagramIsoCospan F).hom).obj t ≅
  CategoryTheory.Limits.PullbackCone.mk (t.π.app CategoryTheory.Limits.WalkingCospan.left)
    (t.π.app CategoryTheory.Limits.WalkingCospan.right) ⋯

full_name: CategoryTheory.Limits.PullbackCone.isoMk_hom_hom
code: /-- 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 : _)) 
goal: (CategoryTheory.Limits.PullbackCone.isoMk t).hom.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PullbackCone.isoMk_inv_hom
code: /-- 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 : _)) 
goal: (CategoryTheory.Limits.PullbackCone.isoMk t).inv.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PushoutCocone
code: /-- A pushout cocone is just a cocone on the span formed by two morphisms `f : X ⟶ Y` and
    `g : X ⟶ Z`. -/
abbrev PushoutCocone (f : X ⟶ Y) (g : X ⟶ Z) 
goal: Type (max u v)

full_name: CategoryTheory.Limits.PushoutCocone.inl
code: /-- The first inclusion of a pushout cocone. -/
abbrev inl (t : PushoutCocone f g) : Y ⟶ t.pt 
goal: Y ⟶ t.pt

full_name: CategoryTheory.Limits.PushoutCocone.inr
code: /-- The second inclusion of a pushout cocone. -/
abbrev inr (t : PushoutCocone f g) : Z ⟶ t.pt 
goal: Z ⟶ t.pt

full_name: CategoryTheory.Limits.PushoutCocone.ι_app_left
code: @[simp]
theorem ι_app_left (c : PushoutCocone f g) : c.ι.app WalkingSpan.left = c.inl 
goal: c.ι.app CategoryTheory.Limits.WalkingSpan.left = c.inl

full_name: CategoryTheory.Limits.PushoutCocone.ι_app_right
code: @[simp]
theorem ι_app_right (c : PushoutCocone f g) : c.ι.app WalkingSpan.right = c.inr 
goal: c.ι.app CategoryTheory.Limits.WalkingSpan.right = c.inr

full_name: CategoryTheory.Limits.PushoutCocone.condition_zero
code: @[simp]
theorem condition_zero (t : PushoutCocone f g) : t.ι.app WalkingSpan.zero = f ≫ t.inl 
goal: t.ι.app CategoryTheory.Limits.WalkingSpan.zero = f ≫ t.inl

full_name: CategoryTheory.Limits.PushoutCocone.mk_ι_app
code: /-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g 
goal: (CategoryTheory.Limits.PushoutCocone.mk inl inr eq).ι.app j =
  Option.casesOn j (f ≫ inl) fun j' => CategoryTheory.Limits.WalkingPair.casesOn j' inl inr

full_name: CategoryTheory.Limits.PushoutCocone.mk_pt
code: /-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g 
goal: (CategoryTheory.Limits.PushoutCocone.mk inl inr eq).pt = W

full_name: CategoryTheory.Limits.PushoutCocone.mk
code: /-- A pushout cocone on `f` and `g` is determined by morphisms `inl : Y ⟶ W` and `inr : Z ⟶ W` such
    that `f ≫ inl = g ↠ inr`. -/
@[simps]
def mk {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) : PushoutCocone f g 
goal: CategoryTheory.Limits.PushoutCocone f g

full_name: CategoryTheory.Limits.PushoutCocone.mk_ι_app_left
code: @[simp]
theorem mk_ι_app_left {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) :
    (mk inl inr eq).ι.app WalkingSpan.left = inl 
goal: (CategoryTheory.Limits.PushoutCocone.mk inl inr eq).ι.app CategoryTheory.Limits.WalkingSpan.left = inl

full_name: CategoryTheory.Limits.PushoutCocone.mk_ι_app_right
code: @[simp]
theorem mk_ι_app_right {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) :
    (mk inl inr eq).ι.app WalkingSpan.right = inr 
goal: (CategoryTheory.Limits.PushoutCocone.mk inl inr eq).ι.app CategoryTheory.Limits.WalkingSpan.right = inr

full_name: CategoryTheory.Limits.PushoutCocone.mk_ι_app_zero
code: @[simp]
theorem mk_ι_app_zero {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) :
    (mk inl inr eq).ι.app WalkingSpan.zero = f ≫ inl 
goal: (CategoryTheory.Limits.PushoutCocone.mk inl inr eq).ι.app CategoryTheory.Limits.WalkingSpan.zero = f ≫ inl

full_name: CategoryTheory.Limits.PushoutCocone.mk_inl
code: @[simp]
theorem mk_inl {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) :
    (mk inl inr eq).inl = inl 
goal: (CategoryTheory.Limits.PushoutCocone.mk inl inr eq).inl = inl

full_name: CategoryTheory.Limits.PushoutCocone.mk_inr
code: @[simp]
theorem mk_inr {W : C} (inl : Y ⟶ W) (inr : Z ⟶ W) (eq : f ≫ inl = g ≫ inr) :
    (mk inl inr eq).inr = inr 
goal: (CategoryTheory.Limits.PushoutCocone.mk inl inr eq).inr = inr

full_name: CategoryTheory.Limits.PushoutCocone.condition
code: @[reassoc]
theorem condition (t : PushoutCocone f g) : f ≫ inl t = g ≫ inr t 
goal: f ≫ t.inl = g ≫ t.inr

full_name: CategoryTheory.Limits.PushoutCocone.coequalizer_ext
code: /-- To check whether a morphism is coequalized by the maps of a pushout cocone, it suffices to check
  it for `inl t` and `inr t` -/
theorem coequalizer_ext (t : PushoutCocone f g) {W : C} {k l : t.pt ⟶ W}
    (h₀ : inl t ≫ k = inl t ≫ l) (h₁ : inr t ≫ k = inr t ≫ l) :
    ∀ j : WalkingSpan, t.ι.app j ≫ k = t.ι.app j ≫ l
  
goal: t.ι.app j ≫ k = t.ι.app j ≫ l

full_name: CategoryTheory.Limits.PushoutCocone.ext
code: /-- To construct an isomorphism of pushout cocones, it suffices to construct an isomorphism
of the cocone points and check it commutes with `inl` and `inr`. -/
def ext {s t : PushoutCocone f g} (i : s.pt ≅ t.pt) (w₁ : s.inl ≫ i.hom = t.inl := by aesop_cat)
    (w₂ : s.inr ≫ i.hom = t.inr := by aesop_cat) : s ≅ t 
goal: s ≅ t

full_name: CategoryTheory.Limits.PushoutCocone.eta_inv_hom
code: /-- The natural isomorphism between a pushout cocone and the corresponding pushout cocone
reconstructed using `PushoutCocone.mk`. -/
@[simps!]
def eta (t : PushoutCocone f g) : t ≅ mk t.inl t.inr t.condition 
goal: t.eta.inv.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PushoutCocone.eta_hom_hom
code: /-- The natural isomorphism between a pushout cocone and the corresponding pushout cocone
reconstructed using `PushoutCocone.mk`. -/
@[simps!]
def eta (t : PushoutCocone f g) : t ≅ mk t.inl t.inr t.condition 
goal: t.eta.hom.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PushoutCocone.eta
code: /-- The natural isomorphism between a pushout cocone and the corresponding pushout cocone
reconstructed using `PushoutCocone.mk`. -/
@[simps!]
def eta (t : PushoutCocone f g) : t ≅ mk t.inl t.inr t.condition 
goal: t ≅ CategoryTheory.Limits.PushoutCocone.mk t.inl t.inr ⋯

full_name: CategoryTheory.Limits.PushoutCocone.isColimitAux
code: /-- This is a slightly more convenient method to verify that a pushout cocone is a colimit cocone.
    It only asks for a proof of facts that carry any mathematical content -/
def isColimitAux (t : PushoutCocone f g) (desc : ∀ s : PushoutCocone f g, t.pt ⟶ s.pt)
    (fac_left : ∀ s : PushoutCocone f g, t.inl ≫ desc s = s.inl)
    (fac_right : ∀ s : PushoutCocone f g, t.inr ≫ desc s = s.inr)
    (uniq : ∀ (s : PushoutCocone f g) (m : t.pt ⟶ s.pt)
    (_ : ∀ j : WalkingSpan, t.ι.app j ≫ m = s.ι.app j), m = desc s) : IsColimit t 
goal: CategoryTheory.Limits.IsColimit t

full_name: CategoryTheory.Limits.PushoutCocone.isColimitAux'
code: /-- This is another convenient method to verify that a pushout cocone is a colimit cocone. It
    only asks for a proof of facts that carry any mathematical content, and allows access to the
    same `s` for all parts. -/
def isColimitAux' (t : PushoutCocone f g)
    (create :
      ∀ s : PushoutCocone f g,
        { l //
          t.inl ≫ l = s.inl ∧
            t.inr ≫ l = s.inr ∧ ∀ {m}, t.inl ≫ m = s.inl → t.inr ≫ m = s.inr → m = l }) :
    IsColimit t 
goal: CategoryTheory.Limits.IsColimit t

full_name: CategoryTheory.Limits.PushoutCocone.IsColimit.hom_ext
code: theorem IsColimit.hom_ext {t : PushoutCocone f g} (ht : IsColimit t) {W : C} {k l : t.pt ⟶ W}
    (h₀ : inl t ≫ k = inl t ≫ l) (h₁ : inr t ≫ k = inr t ≫ l) : k = l 
goal: k = l

full_name: CategoryTheory.Limits.PushoutCocone.IsColimit.desc
code: /-- If `t` is a colimit pushout cocone over `f` and `g` and `h : Y ⟶ W` and `k : Z ⟶ W` are
    morphisms satisfying `f ≫ h = g ≫ k`, then we have a factorization `l : t.pt ⟶ W` such that
    `inl t ≫ l = h` and `inr t ≫ l = k`, see `IsColimit.inl_desc` and `IsColimit.inr_desc`-/
def IsColimit.desc {t : PushoutCocone f g} (ht : IsColimit t) {W : C} (h : Y ⟶ W) (k : Z ⟶ W)
    (w : f ≫ h = g ≫ k) : t.pt ⟶ W 
goal: t.pt ⟶ W

full_name: CategoryTheory.Limits.PushoutCocone.IsColimit.inl_desc
code: @[reassoc (attr := simp)]
lemma IsColimit.inl_desc {t : PushoutCocone f g} (ht : IsColimit t) {W : C} (h : Y ⟶ W) (k : Z ⟶ W)
    (w : f ≫ h = g ≫ k) : inl t ≫ IsColimit.desc ht h k w = h 
goal: t.inl ≫ CategoryTheory.Limits.PushoutCocone.IsColimit.desc ht h k w = h

full_name: CategoryTheory.Limits.PushoutCocone.IsColimit.inr_desc
code: @[reassoc (attr := simp)]
lemma IsColimit.inr_desc {t : PushoutCocone f g} (ht : IsColimit t) {W : C} (h : Y ⟶ W) (k : Z ⟶ W)
    (w : f ≫ h = g ≫ k) : inr t ≫ IsColimit.desc ht h k w = k 
goal: t.inr ≫ CategoryTheory.Limits.PushoutCocone.IsColimit.desc ht h k w = k

full_name: CategoryTheory.Limits.PushoutCocone.IsColimit.desc'
code: /-- If `t` is a colimit pushout cocone over `f` and `g` and `h : Y ⟶ W` and `k : Z ⟶ W` are
    morphisms satisfying `f ≫ h = g ≫ k`, then we have a factorization `l : t.pt ⟶ W` such that
    `inl t ≫ l = h` and `inr t ≫ l = k`. -/
def IsColimit.desc' {t : PushoutCocone f g} (ht : IsColimit t) {W : C} (h : Y ⟶ W) (k : Z ⟶ W)
    (w : f ≫ h = g ≫ k) : { l : t.pt ⟶ W // inl t ≫ l = h ∧ inr t ≫ l = k } 
goal: { l // t.inl ≫ l = h ∧ t.inr ≫ l = k }

full_name: CategoryTheory.Limits.PushoutCocone.IsColimit.mk
code: /-- This is a more convenient formulation to show that a `PushoutCocone` constructed using
`PushoutCocone.mk` is a colimit cocone.
-/
def IsColimit.mk {W : C} {inl : Y ⟶ W} {inr : Z ⟶ W} (eq : f ≫ inl = g ≫ inr)
    (desc : ∀ s : PushoutCocone f g, W ⟶ s.pt)
    (fac_left : ∀ s : PushoutCocone f g, inl ≫ desc s = s.inl)
    (fac_right : ∀ s : PushoutCocone f g, inr ≫ desc s = s.inr)
    (uniq :
      ∀ (s : PushoutCocone f g) (m : W ⟶ s.pt) (_ : inl ≫ m = s.inl) (_ : inr ≫ m = s.inr),
        m = desc s) :
    IsColimit (mk inl inr eq) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.PushoutCocone.mk inl inr eq)

full_name: CategoryTheory.Limits.PushoutCocone.mkSelfIsColimit
code: /-- The pushout cocone reconstructed using `PushoutCocone.mk` from a pushout cocone that is a
colimit, is also a colimit. -/
def mkSelfIsColimit {t : PushoutCocone f g} (ht : IsColimit t) :
    IsColimit (mk t.inl t.inr t.condition) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.PushoutCocone.mk t.inl t.inr ⋯)

full_name: CategoryTheory.Limits.PushoutCocone.flip
code: /-- The pushout cocone obtained by flipping `inl` and `inr`. -/
def flip : PushoutCocone g f 
goal: CategoryTheory.Limits.PushoutCocone g f

full_name: CategoryTheory.Limits.PushoutCocone.flip_pt
code: @[simp] lemma flip_pt : t.flip.pt = t.pt 
goal: t.flip.pt = t.pt

full_name: CategoryTheory.Limits.PushoutCocone.flip_inl
code: @[simp] lemma flip_inl : t.flip.inl = t.inr 
goal: t.flip.inl = t.inr

full_name: CategoryTheory.Limits.PushoutCocone.flip_inr
code: @[simp] lemma flip_inr : t.flip.inr = t.inl 
goal: t.flip.inr = t.inl

full_name: CategoryTheory.Limits.PushoutCocone.flipFlipIso
code: /-- Flipping a pushout cocone twice gives an isomorphic cocone. -/
def flipFlipIso : t.flip.flip ≅ t 
goal: t.flip.flip ≅ t

full_name: CategoryTheory.Limits.PushoutCocone.flipIsColimit
code: /-- The flip of a pushout square is a pushout square. -/
def flipIsColimit (ht : IsColimit t) : IsColimit t.flip 
goal: CategoryTheory.Limits.IsColimit t.flip

full_name: CategoryTheory.Limits.PushoutCocone.isColimitOfFlip
code: /-- A square is a pushout square if its flip is. -/
def isColimitOfFlip (ht : IsColimit t.flip) : IsColimit t 
goal: CategoryTheory.Limits.IsColimit t

full_name: CategoryTheory.Limits.Cocone.ofPushoutCocone_ι
code: /-- This is a helper construction that can be useful when verifying that a category has all
    pushout. Given `F : WalkingSpan ⥤ C`, which is really the same as
    `span (F.map fst) (F.map snd)`, and a pushout cocone on `F.map fst` and `F.map snd`,
    we get a cocone on `F`.

    If you're thinking about using this, have a look at `hasPushouts_of_hasColimit_span`, which
    you may find to be an easier way of achieving your goal. -/
@[simps]
def Cocone.ofPushoutCocone {F : WalkingSpan ⥤ C} (t : PushoutCocone (F.map fst) (F.map snd)) :
    Cocone F 
goal: (CategoryTheory.Limits.Cocone.ofPushoutCocone t).ι = (CategoryTheory.Limits.diagramIsoSpan F).hom ≫ t.ι

full_name: CategoryTheory.Limits.Cocone.ofPushoutCocone_pt
code: /-- This is a helper construction that can be useful when verifying that a category has all
    pushout. Given `F : WalkingSpan ⥤ C`, which is really the same as
    `span (F.map fst) (F.map snd)`, and a pushout cocone on `F.map fst` and `F.map snd`,
    we get a cocone on `F`.

    If you're thinking about using this, have a look at `hasPushouts_of_hasColimit_span`, which
    you may find to be an easier way of achieving your goal. -/
@[simps]
def Cocone.ofPushoutCocone {F : WalkingSpan ⥤ C} (t : PushoutCocone (F.map fst) (F.map snd)) :
    Cocone F 
goal: (CategoryTheory.Limits.Cocone.ofPushoutCocone t).pt = t.pt

full_name: CategoryTheory.Limits.Cocone.ofPushoutCocone
code: /-- This is a helper construction that can be useful when verifying that a category has all
    pushout. Given `F : WalkingSpan ⥤ C`, which is really the same as
    `span (F.map fst) (F.map snd)`, and a pushout cocone on `F.map fst` and `F.map snd`,
    we get a cocone on `F`.

    If you're thinking about using this, have a look at `hasPushouts_of_hasColimit_span`, which
    you may find to be an easier way of achieving your goal. -/
@[simps]
def Cocone.ofPushoutCocone {F : WalkingSpan ⥤ C} (t : PushoutCocone (F.map fst) (F.map snd)) :
    Cocone F 
goal: CategoryTheory.Limits.Cocone F

full_name: CategoryTheory.Limits.PushoutCocone.ofCocone_pt
code: /-- Given `F : WalkingSpan ⥤ C`, which is really the same as `span (F.map fst) (F.map snd)`,
    and a cocone on `F`, we get a pushout cocone on `F.map fst` and `F.map snd`. -/
@[simps]
def PushoutCocone.ofCocone {F : WalkingSpan ⥤ C} (t : Cocone F) :
    PushoutCocone (F.map fst) (F.map snd) 
goal: (CategoryTheory.Limits.PushoutCocone.ofCocone t).pt = t.pt

full_name: CategoryTheory.Limits.PushoutCocone.ofCocone_ι
code: /-- Given `F : WalkingSpan ⥤ C`, which is really the same as `span (F.map fst) (F.map snd)`,
    and a cocone on `F`, we get a pushout cocone on `F.map fst` and `F.map snd`. -/
@[simps]
def PushoutCocone.ofCocone {F : WalkingSpan ⥤ C} (t : Cocone F) :
    PushoutCocone (F.map fst) (F.map snd) 
goal: (CategoryTheory.Limits.PushoutCocone.ofCocone t).ι = (CategoryTheory.Limits.diagramIsoSpan F).inv ≫ t.ι

full_name: CategoryTheory.Limits.PushoutCocone.ofCocone
code: /-- Given `F : WalkingSpan ⥤ C`, which is really the same as `span (F.map fst) (F.map snd)`,
    and a cocone on `F`, we get a pushout cocone on `F.map fst` and `F.map snd`. -/
@[simps]
def PushoutCocone.ofCocone {F : WalkingSpan ⥤ C} (t : Cocone F) :
    PushoutCocone (F.map fst) (F.map snd) 
goal: CategoryTheory.Limits.PushoutCocone (F.map CategoryTheory.Limits.WalkingSpan.Hom.fst)
  (F.map CategoryTheory.Limits.WalkingSpan.Hom.snd)

full_name: CategoryTheory.Limits.PushoutCocone.isoMk_hom_hom
code: /-- 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) 
goal: (CategoryTheory.Limits.PushoutCocone.isoMk t).hom.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PushoutCocone.isoMk_inv_hom
code: /-- 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) 
goal: (CategoryTheory.Limits.PushoutCocone.isoMk t).inv.hom = 𝟙 t.pt

full_name: CategoryTheory.Limits.PushoutCocone.isoMk
code: /-- 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) 
goal: (CategoryTheory.Limits.Cocones.precompose (CategoryTheory.Limits.diagramIsoSpan F).inv).obj t ≅
  CategoryTheory.Limits.PushoutCocone.mk (t.ι.app CategoryTheory.Limits.WalkingSpan.left)
    (t.ι.app CategoryTheory.Limits.WalkingSpan.right) ⋯