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

full_name: CategoryTheory.Limits.PullbackCone.mono_snd_of_is_pullback_of_mono
code: /-- Monomorphisms are stable under pullback in the first argument. -/
theorem mono_snd_of_is_pullback_of_mono {t : PullbackCone f g} (ht : IsLimit t) [Mono f] :
    Mono t.snd 
goal: CategoryTheory.Mono t.snd

full_name: CategoryTheory.Limits.PullbackCone.mono_fst_of_is_pullback_of_mono
code: /-- Monomorphisms are stable under pullback in the second argument. -/
theorem mono_fst_of_is_pullback_of_mono {t : PullbackCone f g} (ht : IsLimit t) [Mono g] :
    Mono t.fst 
goal: CategoryTheory.Mono t.fst

full_name: CategoryTheory.Limits.PullbackCone.isLimitMkIdId
code: /--
The pullback cone `(𝟙 X, 𝟙 X)` for the pair `(f, f)` is a limit if `f` is a mono. The converse is
shown in `mono_of_pullback_is_id`.
-/
def isLimitMkIdId (f : X ⟶ Y) [Mono f] : IsLimit (mk (𝟙 X) (𝟙 X) rfl : PullbackCone f f) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.PullbackCone.mk (𝟙 X) (𝟙 X) ⋯)

full_name: CategoryTheory.Limits.PullbackCone.mono_of_isLimitMkIdId
code: /--
`f` is a mono if the pullback cone `(𝟙 X, 𝟙 X)` is a limit for the pair `(f, f)`. The converse is
given in `PullbackCone.is_id_of_mono`.
-/
theorem mono_of_isLimitMkIdId (f : X ⟶ Y) (t : IsLimit (mk (𝟙 X) (𝟙 X) rfl : PullbackCone f f)) :
    Mono f 
goal: CategoryTheory.Mono f

full_name: CategoryTheory.Limits.PullbackCone.isLimitOfFactors
code: /-- Suppose `f` and `g` are two morphisms with a common codomain and `s` is a limit cone over the
    diagram formed by `f` and `g`. Suppose `f` and `g` both factor through a monomorphism `h` via
    `x` and `y`, respectively.  Then `s` is also a limit cone over the diagram formed by `x` and
    `y`.  -/
def isLimitOfFactors (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ Z) [Mono h] (x : X ⟶ W) (y : Y ⟶ W)
    (hxh : x ≫ h = f) (hyh : y ≫ h = g) (s : PullbackCone f g) (hs : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ x = s.snd ≫ y from
          (cancel_mono h).1 <| by simp only [Category.assoc, hxh, hyh, s.condition])) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.PullbackCone.mk s.fst s.snd ⋯)

full_name: CategoryTheory.Limits.PullbackCone.isLimitOfCompMono
code: /-- If `W` is the pullback of `f, g`, it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) 
goal: CategoryTheory.Limits.IsLimit (CategoryTheory.Limits.PullbackCone.mk s.fst s.snd ⋯)

full_name: CategoryTheory.Limits.pullback.fst_of_mono
code: /-- The pullback of a monomorphism is a monomorphism -/
instance pullback.fst_of_mono {X Y Z : C} {f : X ⟶ Z} {g : Y ⟶ Z} [HasPullback f g] [Mono g] :
    Mono (pullback.fst f g) 
goal: CategoryTheory.Mono (CategoryTheory.Limits.pullback.fst f g)

full_name: CategoryTheory.Limits.pullback.snd_of_mono
code: /-- The pullback of a monomorphism is a monomorphism -/
instance pullback.snd_of_mono {X Y Z : C} {f : X ⟶ Z} {g : Y ⟶ Z} [HasPullback f g] [Mono f] :
    Mono (pullback.snd f g) 
goal: CategoryTheory.Mono (CategoryTheory.Limits.pullback.snd f g)

full_name: CategoryTheory.Limits.mono_pullback_to_prod
code: /-- 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 f g) (pullback.snd f g)) 
goal: CategoryTheory.Mono
  (CategoryTheory.Limits.prod.lift (CategoryTheory.Limits.pullback.fst f g) (CategoryTheory.Limits.pullback.snd f g))

full_name: CategoryTheory.Limits.pullbackIsPullbackOfCompMono
code: /-- The pullback of `f, g` is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
noncomputable def pullbackIsPullbackOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i]
    [HasPullback f g] : IsLimit (PullbackCone.mk (pullback.fst f g) (pullback.snd f g)
      -- Porting note: following used to be _
      (show (pullback.fst f g) ≫ f ≫ i = (pullback.snd f g) ≫ g ≫ i from by
        simp only [← Category.assoc]; rw [cancel_mono]; apply pullback.condition)) 
goal: CategoryTheory.Limits.IsLimit
  (CategoryTheory.Limits.PullbackCone.mk (CategoryTheory.Limits.pullback.fst f g)
    (CategoryTheory.Limits.pullback.snd f g) ⋯)

full_name: CategoryTheory.Limits.hasPullback_of_comp_mono
code: instance hasPullback_of_comp_mono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] [HasPullback f g] :
    HasPullback (f ≫ i) (g ≫ i) 
goal: CategoryTheory.Limits.HasPullback (f ≫ i) (g ≫ i)

full_name: CategoryTheory.Limits.hasPullback_of_right_factors_mono
code: instance hasPullback_of_right_factors_mono : HasPullback i (f ≫ i) 
goal: CategoryTheory.Limits.HasPullback i (f ≫ i)

full_name: CategoryTheory.Limits.pullback_snd_iso_of_right_factors_mono
code: instance pullback_snd_iso_of_right_factors_mono :
    IsIso (pullback.snd i (f ≫ i)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pullback.snd i (f ≫ i))

full_name: CategoryTheory.Limits.hasPullback_of_left_factors_mono
code: instance hasPullback_of_left_factors_mono : HasPullback (f ≫ i) i 
goal: CategoryTheory.Limits.HasPullback (f ≫ i) i

full_name: CategoryTheory.Limits.pullback_snd_iso_of_left_factors_mono
code: instance pullback_snd_iso_of_left_factors_mono :
    IsIso (pullback.fst (f ≫ i) i) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pullback.fst (f ≫ i) i)

full_name: CategoryTheory.Limits.has_kernel_pair_of_mono
code: instance has_kernel_pair_of_mono [Mono f] : HasPullback f f 
goal: CategoryTheory.Limits.HasPullback f f

full_name: CategoryTheory.Limits.fst_eq_snd_of_mono_eq
code: theorem fst_eq_snd_of_mono_eq [Mono f] : pullback.fst f f = pullback.snd f f 
goal: CategoryTheory.Limits.pullback.fst f f = CategoryTheory.Limits.pullback.snd f f

full_name: CategoryTheory.Limits.pullbackSymmetry_hom_of_mono_eq
code: @[simp]
theorem pullbackSymmetry_hom_of_mono_eq [Mono f] : (pullbackSymmetry f f).hom = 𝟙 _ 
goal: (CategoryTheory.Limits.pullbackSymmetry f f).hom = 𝟙 (CategoryTheory.Limits.pullback f f)

full_name: CategoryTheory.Limits.fst_iso_of_mono_eq
code: instance fst_iso_of_mono_eq [Mono f] : IsIso (pullback.fst f f) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pullback.fst f f)

full_name: CategoryTheory.Limits.snd_iso_of_mono_eq
code: instance snd_iso_of_mono_eq [Mono f] : IsIso (pullback.snd f f) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pullback.snd f f)

full_name: CategoryTheory.Limits.PushoutCocone.epi_inr_of_is_pushout_of_epi
code: theorem epi_inr_of_is_pushout_of_epi {t : PushoutCocone f g} (ht : IsColimit t) [Epi f] :
    Epi t.inr 
goal: CategoryTheory.Epi t.inr

full_name: CategoryTheory.Limits.PushoutCocone.epi_inl_of_is_pushout_of_epi
code: theorem epi_inl_of_is_pushout_of_epi {t : PushoutCocone f g} (ht : IsColimit t) [Epi g] :
    Epi t.inl 
goal: CategoryTheory.Epi t.inl

full_name: CategoryTheory.Limits.PushoutCocone.isColimitMkIdId
code: /--
The pushout cocone `(𝟙 X, 𝟙 X)` for the pair `(f, f)` is a colimit if `f` is an epi. The converse is
shown in `epi_of_isColimit_mk_id_id`.
-/
def isColimitMkIdId (f : X ⟶ Y) [Epi f] : IsColimit (mk (𝟙 Y) (𝟙 Y) rfl : PushoutCocone f f) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.PushoutCocone.mk (𝟙 Y) (𝟙 Y) ⋯)

full_name: CategoryTheory.Limits.PushoutCocone.epi_of_isColimitMkIdId
code: /-- `f` is an epi if the pushout cocone `(𝟙 X, 𝟙 X)` is a colimit for the pair `(f, f)`.
The converse is given in `PushoutCocone.isColimitMkIdId`.
-/
theorem epi_of_isColimitMkIdId (f : X ⟶ Y)
    (t : IsColimit (mk (𝟙 Y) (𝟙 Y) rfl : PushoutCocone f f)) : Epi f 
goal: CategoryTheory.Epi f

full_name: CategoryTheory.Limits.PushoutCocone.isColimitOfFactors
code: /-- Suppose `f` and `g` are two morphisms with a common domain and `s` is a colimit cocone over the
    diagram formed by `f` and `g`. Suppose `f` and `g` both factor through an epimorphism `h` via
    `x` and `y`, respectively. Then `s` is also a colimit cocone over the diagram formed by `x` and
    `y`.  -/
def isColimitOfFactors (f : X ⟶ Y) (g : X ⟶ Z) (h : X ⟶ W) [Epi h] (x : W ⟶ Y) (y : W ⟶ Z)
    (hhx : h ≫ x = f) (hhy : h ≫ y = g) (s : PushoutCocone f g) (hs : IsColimit s) :
    have reassoc₁ : h ≫ x ≫ inl s = f ≫ inl s := by  -- Porting note: working around reassoc
      rw [← Category.assoc]; apply congrArg (· ≫ inl s) hhx
    have reassoc₂ : h ≫ y ≫ inr s = g ≫ inr s := by
      rw [← Category.assoc]; apply congrArg (· ≫ inr s) hhy
    IsColimit (PushoutCocone.mk _ _ (show x ≫ s.inl = y ≫ s.inr from
          (cancel_epi h).1 <| by rw [reassoc₁, reassoc₂, s.condition])) 
goal: let_fun reassoc₁ := ⋯;
let_fun reassoc₂ := ⋯;
CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.PushoutCocone.mk s.inl s.inr ⋯)

full_name: CategoryTheory.Limits.PushoutCocone.isColimitOfEpiComp
code: /-- 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])) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.PushoutCocone.mk s.inl s.inr ⋯)

full_name: CategoryTheory.Limits.pushout.inl_of_epi
code: /-- The pushout of an epimorphism is an epimorphism -/
instance pushout.inl_of_epi {X Y Z : C} {f : X ⟶ Y} {g : X ⟶ Z} [HasPushout f g] [Epi g] :
    Epi (pushout.inl f g) 
goal: CategoryTheory.Epi (CategoryTheory.Limits.pushout.inl f g)

full_name: CategoryTheory.Limits.pushout.inr_of_epi
code: /-- The pushout of an epimorphism is an epimorphism -/
instance pushout.inr_of_epi {X Y Z : C} {f : X ⟶ Y} {g : X ⟶ Z} [HasPushout f g] [Epi f] :
    Epi (pushout.inr _ _ : Z ⟶ pushout f g) 
goal: CategoryTheory.Epi (CategoryTheory.Limits.pushout.inr f g)

full_name: CategoryTheory.Limits.epi_coprod_to_pushout
code: /-- The map `X ⨿ Y ⟶ X ⨿[Z] Y` is epi. -/
instance epi_coprod_to_pushout {C : Type*} [Category C] {X Y Z : C} (f : X ⟶ Y) (g : X ⟶ Z)
    [HasPushout f g] [HasBinaryCoproduct Y Z] :
    Epi (coprod.desc (pushout.inl f g) (pushout.inr f g)) 
goal: CategoryTheory.Epi
  (CategoryTheory.Limits.coprod.desc (CategoryTheory.Limits.pushout.inl f g) (CategoryTheory.Limits.pushout.inr f g))

full_name: CategoryTheory.Limits.pushoutIsPushoutOfEpiComp
code: /-- The pushout of `f, g` is also the pullback of `h ≫ f, h ≫ g` for any epi `h`. -/
noncomputable def pushoutIsPushoutOfEpiComp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h]
    [HasPushout f g] : IsColimit (PushoutCocone.mk (pushout.inl f g) (pushout.inr f g)
    (show (h ≫ f) ≫ pushout.inl f g = (h ≫ g) ≫ pushout.inr f g from by
    simp only [Category.assoc]; rw [cancel_epi]; exact pushout.condition)) 
goal: CategoryTheory.Limits.IsColimit
  (CategoryTheory.Limits.PushoutCocone.mk (CategoryTheory.Limits.pushout.inl f g)
    (CategoryTheory.Limits.pushout.inr f g) ⋯)

full_name: CategoryTheory.Limits.hasPushout_of_epi_comp
code: instance hasPushout_of_epi_comp (f : X ⟶ Y) (g : X ⟶ Z) (h : W ⟶ X) [Epi h] [HasPushout f g] :
    HasPushout (h ≫ f) (h ≫ g) 
goal: CategoryTheory.Limits.HasPushout (h ≫ f) (h ≫ g)

full_name: CategoryTheory.Limits.hasPushout_of_right_factors_epi
code: instance hasPushout_of_right_factors_epi : HasPushout h (h ≫ f) 
goal: CategoryTheory.Limits.HasPushout h (h ≫ f)

full_name: CategoryTheory.Limits.pushout_inr_iso_of_right_factors_epi
code: instance pushout_inr_iso_of_right_factors_epi :
    IsIso (pushout.inr _ _ : _ ⟶ pushout h (h ≫ f)) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pushout.inr h (h ≫ f))

full_name: CategoryTheory.Limits.hasPushout_of_left_factors_epi
code: instance hasPushout_of_left_factors_epi (f : X ⟶ Y) : HasPushout (h ≫ f) h 
goal: CategoryTheory.Limits.HasPushout (h ≫ f) h

full_name: CategoryTheory.Limits.pushout_inl_iso_of_left_factors_epi
code: instance pushout_inl_iso_of_left_factors_epi (f : X ⟶ Y) :
    IsIso (pushout.inl _ _ : _ ⟶ pushout (h ≫ f) h) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pushout.inl (h ≫ f) h)

full_name: CategoryTheory.Limits.has_cokernel_pair_of_epi
code: instance has_cokernel_pair_of_epi [Epi f] : HasPushout f f 
goal: CategoryTheory.Limits.HasPushout f f

full_name: CategoryTheory.Limits.inl_eq_inr_of_epi_eq
code: theorem inl_eq_inr_of_epi_eq [Epi f] : (pushout.inl _ _ : _ ⟶ pushout f f) = pushout.inr _ _ 
goal: CategoryTheory.Limits.pushout.inl f f = CategoryTheory.Limits.pushout.inr f f

full_name: CategoryTheory.Limits.pullback_symmetry_hom_of_epi_eq
code: @[simp]
theorem pullback_symmetry_hom_of_epi_eq [Epi f] : (pushoutSymmetry f f).hom = 𝟙 _ 
goal: (CategoryTheory.Limits.pushoutSymmetry f f).hom = 𝟙 (CategoryTheory.Limits.pushout f f)

full_name: CategoryTheory.Limits.inl_iso_of_epi_eq
code: instance inl_iso_of_epi_eq [Epi f] : IsIso (pushout.inl _ _ : _ ⟶ pushout f f) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pushout.inl f f)

full_name: CategoryTheory.Limits.inr_iso_of_epi_eq
code: instance inr_iso_of_epi_eq [Epi f] : IsIso (pushout.inr f f) 
goal: CategoryTheory.IsIso (CategoryTheory.Limits.pushout.inr f f)