Skip to content

Commit

Permalink
feat(category_theory/limits): (co)limits in full subcategories (#16188)
Browse files Browse the repository at this point in the history
  • Loading branch information
TwoFX committed Aug 31, 2022
1 parent 002aa51 commit fe5e4ce
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 25 deletions.
93 changes: 68 additions & 25 deletions src/category_theory/limits/creates.lean
Expand Up @@ -244,6 +244,21 @@ def creates_limit_of_reflects_iso {K : J ⥤ C} {F : C ⥤ D} [reflects_isomorph
exact is_limit.of_iso_limit hd' (as_iso f).symm,
end } }

/--
When `F` is fully faithful, to show that `F` creates the limit for `K` it suffices to exhibit a lift
of a limit cone for `K ⋙ F`.
-/
-- Notice however that even if the isomorphism is `iso.refl _`,
-- this construction will insert additional identity morphisms in the cone maps,
-- so the constructed limits may not be ideal, definitionally.
def creates_limit_of_fully_faithful_of_lift' {K : J ⥤ C} {F : C ⥤ D} [full F] [faithful F]
{l : cone (K ⋙ F)} (hl : is_limit l) (c : cone K) (i : F.map_cone c ≅ l) : creates_limit K F :=
creates_limit_of_reflects_iso (λ c' t,
{ lifted_cone := c,
valid_lift := i ≪≫ is_limit.unique_up_to_iso hl t,
makes_limit := is_limit.of_faithful F (is_limit.of_iso_limit hl i.symm) _
(λ s, F.image_preimage _) })

/--
When `F` is fully faithful, and `has_limit (K ⋙ F)`, to show that `F` creates the limit for `K`
it suffices to exhibit a lift of the chosen limit cone for `K ⋙ F`.
Expand All @@ -254,11 +269,23 @@ it suffices to exhibit a lift of the chosen limit cone for `K ⋙ F`.
def creates_limit_of_fully_faithful_of_lift {K : J ⥤ C} {F : C ⥤ D}
[full F] [faithful F] [has_limit (K ⋙ F)]
(c : cone K) (i : F.map_cone c ≅ limit.cone (K ⋙ F)) : creates_limit K F :=
creates_limit_of_reflects_iso (λ c' t,
{ lifted_cone := c,
valid_lift := i.trans (is_limit.unique_up_to_iso (limit.is_limit _) t),
makes_limit := is_limit.of_faithful F (is_limit.of_iso_limit (limit.is_limit _) i.symm)
(λ s, F.preimage _) (λ s, F.image_preimage _) })
creates_limit_of_fully_faithful_of_lift' (limit.is_limit _) c i

/--
When `F` is fully faithful, to show that `F` creates the limit for `K` it suffices to show that a
limit point is in the essential image of `F`.
-/
-- Notice however that even if the isomorphism is `iso.refl _`,
-- this construction will insert additional identity morphisms in the cone maps,
-- so the constructed limits may not be ideal, definitionally.
def creates_limit_of_fully_faithful_of_iso' {K : J ⥤ C} {F : C ⥤ D} [full F] [faithful F]
{l : cone (K ⋙ F)} (hl : is_limit l) (X : C) (i : F.obj X ≅ l.X) : creates_limit K F :=
creates_limit_of_fully_faithful_of_lift' hl
({ X := X,
π :=
{ app := λ j, F.preimage (i.hom ≫ l.π.app j),
naturality' := λ Y Z f, F.map_injective $ by { dsimp, simpa using (l.w f).symm } } })
(cones.ext i (λ j, by simp only [functor.image_preimage, functor.map_cone_π_app]))

/--
When `F` is fully faithful, and `has_limit (K ⋙ F)`, to show that `F` creates the limit for `K`
Expand All @@ -270,12 +297,7 @@ it suffices to show that the chosen limit point is in the essential image of `F`
def creates_limit_of_fully_faithful_of_iso {K : J ⥤ C} {F : C ⥤ D}
[full F] [faithful F] [has_limit (K ⋙ F)]
(X : C) (i : F.obj X ≅ limit (K ⋙ F)) : creates_limit K F :=
creates_limit_of_fully_faithful_of_lift
({ X := X,
π :=
{ app := λ j, F.preimage (i.hom ≫ limit.π (K ⋙ F) j),
naturality' := λ Y Z f, F.map_injective (by { dsimp, simp, erw limit.w (K ⋙ F), }) }} : cone K)
(by { fapply cones.ext, exact i, tidy, })
creates_limit_of_fully_faithful_of_iso' (limit.is_limit _) X i

/-- `F` preserves the limit of `K` if it creates the limit and `K ⋙ F` has the limit. -/
@[priority 100] -- see Note [lower instance priority]
Expand Down Expand Up @@ -324,6 +346,22 @@ def creates_colimit_of_reflects_iso {K : J ⥤ C} {F : C ⥤ D} [reflects_isomor
exact is_colimit.of_iso_colimit hd' (as_iso f),
end } }

/--
When `F` is fully faithful, to show that `F` creates the colimit for `K` it suffices to exhibit a
lift of a colimit cocone for `K ⋙ F`.
-/
-- Notice however that even if the isomorphism is `iso.refl _`,
-- this construction will insert additional identity morphisms in the cocone maps,
-- so the constructed colimits may not be ideal, definitionally.
def creates_colimit_of_fully_faithful_of_lift' {K : J ⥤ C} {F : C ⥤ D} [full F] [faithful F]
{l : cocone (K ⋙ F)} (hl : is_colimit l) (c : cocone K) (i : F.map_cocone c ≅ l) :
creates_colimit K F :=
creates_colimit_of_reflects_iso (λ c' t,
{ lifted_cocone := c,
valid_lift := i ≪≫ is_colimit.unique_up_to_iso hl t,
makes_colimit := is_colimit.of_faithful F (is_colimit.of_iso_colimit hl i.symm) _
(λ s, F.image_preimage _) })

/--
When `F` is fully faithful, and `has_colimit (K ⋙ F)`, to show that `F` creates the colimit for `K`
it suffices to exhibit a lift of the chosen colimit cocone for `K ⋙ F`.
Expand All @@ -334,12 +372,24 @@ it suffices to exhibit a lift of the chosen colimit cocone for `K ⋙ F`.
def creates_colimit_of_fully_faithful_of_lift {K : J ⥤ C} {F : C ⥤ D}
[full F] [faithful F] [has_colimit (K ⋙ F)]
(c : cocone K) (i : F.map_cocone c ≅ colimit.cocone (K ⋙ F)) : creates_colimit K F :=
creates_colimit_of_reflects_iso (λ c' t,
{ lifted_cocone := c,
valid_lift := i.trans (is_colimit.unique_up_to_iso (colimit.is_colimit _) t),
makes_colimit := is_colimit.of_faithful F
(is_colimit.of_iso_colimit (colimit.is_colimit _) i.symm)
(λ s, F.preimage _) (λ s, F.image_preimage _) })
creates_colimit_of_fully_faithful_of_lift' (colimit.is_colimit _) c i

/--
When `F` is fully faithful, to show that `F` creates the colimit for `K` it suffices to show that
a colimit point is in the essential image of `F`.
-/
-- Notice however that even if the isomorphism is `iso.refl _`,
-- this construction will insert additional identity morphisms in the cocone maps,
-- so the constructed colimits may not be ideal, definitionally.
def creates_colimit_of_fully_faithful_of_iso' {K : J ⥤ C} {F : C ⥤ D} [full F] [faithful F]
{l : cocone (K ⋙ F)} (hl : is_colimit l) (X : C) (i : F.obj X ≅ l.X) : creates_colimit K F :=
creates_colimit_of_fully_faithful_of_lift' hl
({ X := X,
ι :=
{ app := λ j, F.preimage (l.ι.app j ≫ i.inv),
naturality' := λ Y Z f, F.map_injective $
by { dsimp, simpa [← cancel_mono i.hom] using (l.w f) } } })
(cocones.ext i (λ j, by simp))

/--
When `F` is fully faithful, and `has_colimit (K ⋙ F)`, to show that `F` creates the colimit for `K`
Expand All @@ -351,14 +401,7 @@ it suffices to show that the chosen colimit point is in the essential image of `
def creates_colimit_of_fully_faithful_of_iso {K : J ⥤ C} {F : C ⥤ D}
[full F] [faithful F] [has_colimit (K ⋙ F)]
(X : C) (i : F.obj X ≅ colimit (K ⋙ F)) : creates_colimit K F :=
creates_colimit_of_fully_faithful_of_lift
({ X := X,
ι :=
{ app := λ j, F.preimage (colimit.ι (K ⋙ F) j ≫ i.inv : _),
naturality' := λ Y Z f, F.map_injective
(by { erw category.comp_id, simp only [functor.map_comp, functor.image_preimage],
erw colimit.w_assoc (K ⋙ F) }) }} : cocone K)
(by { fapply cocones.ext, exact i, tidy, })
creates_colimit_of_fully_faithful_of_iso' (colimit.is_colimit _) X i


/-- `F` preserves the colimit of `K` if it creates the colimit and `K ⋙ F` has the colimit. -/
Expand Down
128 changes: 128 additions & 0 deletions src/category_theory/limits/full_subcategory.lean
@@ -0,0 +1,128 @@
/-
Copyright (c) 2022 Markus Himmel. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import category_theory.limits.creates

/-!
# Limits in full subcategories
We introduce the notion of a property closed under taking limits and show that if `P` is closed
under taking limits, then limits in `full_subcategory P` can be constructed from limits in `C`.
More precisely, the inclusion creates such limits.
-/

noncomputable theory

universes w' w v u

open category_theory

namespace category_theory.limits

/-- We say that a property is closed under limits of shape `J` if whenever all objects in a
`J`-shaped diagram have the property, any limit of this diagram also has the property. -/
def closed_under_limits_of_shape {C : Type u} [category.{v} C] (J : Type w) [category.{w'} J]
(P : C → Prop) : Prop :=
∀ ⦃F : J ⥤ C⦄ ⦃c : cone F⦄ (hc : is_limit c), (∀ j, P (F.obj j)) → P c.X

/-- We say that a property is closed under colimits of shape `J` if whenever all objects in a
`J`-shaped diagram have the property, any colimit of this diagram also has the property. -/
def closed_under_colimits_of_shape {C : Type u} [category.{v} C] (J : Type w) [category.{w'} J]
(P : C → Prop) : Prop :=
∀ ⦃F : J ⥤ C⦄ ⦃c : cocone F⦄ (hc : is_colimit c), (∀ j, P (F.obj j)) → P c.X

section
variables {C : Type u} [category.{v} C] {J : Type w} [category.{w'} J] {P : C → Prop}

lemma closed_under_limits_of_shape.limit (h : closed_under_limits_of_shape J P) {F : J ⥤ C}
[has_limit F] : (∀ j, P (F.obj j)) → P (limit F) :=
h (limit.is_limit _)

lemma closed_under_colimits_of_shape.colimit (h : closed_under_colimits_of_shape J P) {F : J ⥤ C}
[has_colimit F] : (∀ j, P (F.obj j)) → P (colimit F) :=
h (colimit.is_colimit _)

end

section
variables {J : Type w} [category.{w'} J] {C : Type u} [category.{v} C] {P : C → Prop}

/-- If a `J`-shaped diagram in `full_subcategory P` has a limit cone in `C` whose cone point lives
in the full subcategory, then this defines a limit in the full subcategory. -/
def creates_limit_full_subcategory_inclusion' (F : J ⥤ full_subcategory P)
{c : cone (F ⋙ full_subcategory_inclusion P)} (hc : is_limit c) (h : P c.X) :
creates_limit F (full_subcategory_inclusion P) :=
creates_limit_of_fully_faithful_of_iso' hc ⟨_, h⟩ (iso.refl _)

/-- If a `J`-shaped diagram in `full_subcategory P` has a limit in `C` whose cone point lives in the
full subcategory, then this defines a limit in the full subcategory. -/
def creates_limit_full_subcategory_inclusion (F : J ⥤ full_subcategory P)
[has_limit (F ⋙ full_subcategory_inclusion P)]
(h : P (limit (F ⋙ full_subcategory_inclusion P))) :
creates_limit F (full_subcategory_inclusion P) :=
creates_limit_full_subcategory_inclusion' F (limit.is_limit _) h

/-- If a `J`-shaped diagram in `full_subcategory P` has a colimit cocone in `C` whose cocone point
lives in the full subcategory, then this defines a colimit in the full subcategory. -/
def creates_colimit_full_subcategory_inclusion' (F : J ⥤ full_subcategory P)
{c : cocone (F ⋙ full_subcategory_inclusion P)} (hc : is_colimit c) (h : P c.X) :
creates_colimit F (full_subcategory_inclusion P) :=
creates_colimit_of_fully_faithful_of_iso' hc ⟨_, h⟩ (iso.refl _)

/-- If a `J`-shaped diagram in `full_subcategory P` has a colimit in `C` whose cocone point lives in
the full subcategory, then this defines a colimit in the full subcategory. -/
def creates_colimit_full_subcategory_inclusion (F : J ⥤ full_subcategory P)
[has_colimit (F ⋙ full_subcategory_inclusion P)]
(h : P (colimit (F ⋙ full_subcategory_inclusion P))) :
creates_colimit F (full_subcategory_inclusion P) :=
creates_colimit_full_subcategory_inclusion' F (colimit.is_colimit _) h

/-- If `P` is closed under limits of shape `J`, then the inclusion creates such limits. -/
def creates_limit_full_subcategory_inclusion_of_closed (h : closed_under_limits_of_shape J P)
(F : J ⥤ full_subcategory P) [has_limit (F ⋙ full_subcategory_inclusion P)] :
creates_limit F (full_subcategory_inclusion P) :=
creates_limit_full_subcategory_inclusion F (h.limit (λ j, (F.obj j).property))

/-- If `P` is closed under limits of shape `J`, then the inclusion creates such limits. -/
def creates_limits_of_shape_full_subcategory_inclusion (h : closed_under_limits_of_shape J P)
[has_limits_of_shape J C] : creates_limits_of_shape J (full_subcategory_inclusion P) :=
{ creates_limit := λ F, creates_limit_full_subcategory_inclusion_of_closed h F }

lemma has_limit_of_closed_under_limits (h : closed_under_limits_of_shape J P)
(F : J ⥤ full_subcategory P) [has_limit (F ⋙ full_subcategory_inclusion P)] : has_limit F :=
have creates_limit F (full_subcategory_inclusion P),
from creates_limit_full_subcategory_inclusion_of_closed h F,
by exactI has_limit_of_created F (full_subcategory_inclusion P)

lemma has_limits_of_shape_of_closed_under_limits (h : closed_under_limits_of_shape J P)
[has_limits_of_shape J C] : has_limits_of_shape J (full_subcategory P) :=
{ has_limit := λ F, has_limit_of_closed_under_limits h F }

/-- If `P` is closed under colimits of shape `J`, then the inclusion creates such colimits. -/
def creates_colimit_full_subcategory_inclusion_of_closed (h : closed_under_colimits_of_shape J P)
(F : J ⥤ full_subcategory P) [has_colimit (F ⋙ full_subcategory_inclusion P)] :
creates_colimit F (full_subcategory_inclusion P) :=
creates_colimit_full_subcategory_inclusion F (h.colimit (λ j, (F.obj j).property))

/-- If `P` is closed under colimits of shape `J`, then the inclusion creates such colimits. -/
def creates_colimits_of_shape_full_subcategory_inclusion
(h : closed_under_colimits_of_shape J P) [has_colimits_of_shape J C] :
creates_colimits_of_shape J (full_subcategory_inclusion P) :=
{ creates_colimit := λ F, creates_colimit_full_subcategory_inclusion_of_closed h F }

lemma has_colimit_of_closed_under_colimits (h : closed_under_colimits_of_shape J P)
(F : J ⥤ full_subcategory P) [has_colimit (F ⋙ full_subcategory_inclusion P)] : has_colimit F :=
have creates_colimit F (full_subcategory_inclusion P),
from creates_colimit_full_subcategory_inclusion_of_closed h F,
by exactI has_colimit_of_created F (full_subcategory_inclusion P)

lemma has_colimits_of_shape_of_closed_under_colimits (h : closed_under_colimits_of_shape J P)
[has_colimits_of_shape J C] : has_colimits_of_shape J (full_subcategory P) :=
{ has_colimit := λ F, has_colimit_of_closed_under_colimits h F }

end

end category_theory.limits

0 comments on commit fe5e4ce

Please sign in to comment.