Skip to content

Commit

Permalink
feat: switch to weaker UnivLE (#8556)
Browse files Browse the repository at this point in the history
Switch from the strong version of UnivLE `∀ α : Type max u v, Small.{v} α` to the weaker version `∀ α : Type u, Small.{v} α`.

Transfer Has/Preserves/Reflects(Co)limitsOfSize from a larger size (higher universe) to a smaller size.

In a few places it's now necessary to make the type explicit (for Lean to infer the `Small` instance, I think).

Also prove a characterization of UnivLE and the totality of the UnivLE relation.

A pared down version of #7695.



Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
  • Loading branch information
3 people committed Nov 24, 2023
1 parent c26fbb1 commit 988870b
Show file tree
Hide file tree
Showing 18 changed files with 311 additions and 184 deletions.
2 changes: 2 additions & 0 deletions Mathlib.lean
Expand Up @@ -2469,6 +2469,7 @@ import Mathlib.Logic.Pairwise
import Mathlib.Logic.Relation
import Mathlib.Logic.Relator
import Mathlib.Logic.Small.Basic
import Mathlib.Logic.Small.Defs
import Mathlib.Logic.Small.Group
import Mathlib.Logic.Small.List
import Mathlib.Logic.Small.Module
Expand Down Expand Up @@ -3126,6 +3127,7 @@ import Mathlib.SetTheory.Cardinal.Divisibility
import Mathlib.SetTheory.Cardinal.Finite
import Mathlib.SetTheory.Cardinal.Ordinal
import Mathlib.SetTheory.Cardinal.SchroederBernstein
import Mathlib.SetTheory.Cardinal.UnivLE
import Mathlib.SetTheory.Game.Basic
import Mathlib.SetTheory.Game.Birthday
import Mathlib.SetTheory.Game.Domineering
Expand Down
23 changes: 22 additions & 1 deletion Mathlib/CategoryTheory/EssentiallySmall.lean
Expand Up @@ -3,9 +3,10 @@ Copyright (c) 2021 Scott Morrison. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Scott Morrison
-/
import Mathlib.Logic.Small.Basic
import Mathlib.CategoryTheory.Category.ULift
import Mathlib.CategoryTheory.Skeletal
import Mathlib.Logic.UnivLE
import Mathlib.Logic.Small.Basic

#align_import category_theory.essentially_small from "leanprover-community/mathlib"@"f7707875544ef1f81b32cb68c79e0e24e45a0e76"

Expand Down Expand Up @@ -33,6 +34,7 @@ namespace CategoryTheory

/-- A category is `EssentiallySmall.{w}` if there exists
an equivalence to some `S : Type w` with `[SmallCategory S]`. -/
@[pp_with_univ]
class EssentiallySmall (C : Type u) [Category.{v} C] : Prop where
/-- An essentially small category is equivalent to some small category. -/
equiv_smallCategory : ∃ (S : Type w) (_ : SmallCategory S), Nonempty (C ≌ S)
Expand All @@ -47,6 +49,7 @@ theorem EssentiallySmall.mk' {C : Type u} [Category.{v} C] {S : Type w} [SmallCa
/-- An arbitrarily chosen small model for an essentially small category.
-/
--@[nolint has_nonempty_instance]
@[pp_with_univ]
def SmallModel (C : Type u) [Category.{v} C] [EssentiallySmall.{w} C] : Type w :=
Classical.choose (@EssentiallySmall.equiv_smallCategory C _ _)
#align category_theory.small_model CategoryTheory.SmallModel
Expand Down Expand Up @@ -89,6 +92,7 @@ theorem essentiallySmallSelf : EssentiallySmall.{max w v u} C :=
See `ShrinkHoms C` for a category instance where every hom set has been replaced by a small model.
-/
@[pp_with_univ]
class LocallySmall (C : Type u) [Category.{v} C] : Prop where
/-- A locally small category has small hom-types. -/
hom_small : ∀ X Y : C, Small.{w} (X ⟶ Y) := by infer_instance
Expand Down Expand Up @@ -118,6 +122,9 @@ instance (priority := 100) locallySmall_self (C : Type u) [Category.{v} C] : Loc
where
#align category_theory.locally_small_self CategoryTheory.locallySmall_self

instance (priority := 100) locallySmall_of_univLE (C : Type u) [Category.{v} C] [UnivLE.{v, w}] :
LocallySmall.{w} C where

theorem locallySmall_max {C : Type u} [Category.{v} C] : LocallySmall.{max v w} C
where
hom_small _ _ := small_max.{w} _
Expand All @@ -131,6 +138,7 @@ instance (priority := 100) locallySmall_of_essentiallySmall (C : Type u) [Catego
we'll put a `Category.{w}` instance on `ShrinkHoms C`.
-/
--@[nolint has_nonempty_instance]
@[pp_with_univ]
def ShrinkHoms (C : Type u) :=
C
#align category_theory.shrink_homs CategoryTheory.ShrinkHoms
Expand Down Expand Up @@ -200,6 +208,17 @@ noncomputable def equivalence : C ≌ ShrinkHoms C :=

end ShrinkHoms

namespace Shrink

noncomputable instance [Small.{w} C] : Category.{v} (Shrink.{w} C) :=
InducedCategory.category (equivShrink C).symm

/-- The categorical equivalence between `C` and `Shrink C`, when `C` is small. -/
noncomputable def equivalence [Small.{w} C] : C ≌ Shrink.{w} C :=
(inducedFunctor (equivShrink C).symm).asEquivalence.symm

end Shrink

/-- A category is essentially small if and only if
the underlying type of its skeleton (i.e. the "set" of isomorphism classes) is small,
and it is locally small.
Expand Down Expand Up @@ -244,4 +263,6 @@ theorem essentiallySmall_iff_of_thin {C : Type u} [Category.{v} C] [Quiver.IsThi
simp [essentiallySmall_iff, CategoryTheory.locallySmall_of_thin]
#align category_theory.essentially_small_iff_of_thin CategoryTheory.essentiallySmall_iff_of_thin

instance [Small.{w} C] : Small.{w} (Discrete C) := small_map discreteEquiv

end CategoryTheory
25 changes: 18 additions & 7 deletions Mathlib/CategoryTheory/Limits/HasLimits.lean
Expand Up @@ -5,6 +5,7 @@ Authors: Reid Barton, Mario Carneiro, Scott Morrison, Floris van Doorn
-/
import Mathlib.CategoryTheory.Limits.IsLimit
import Mathlib.CategoryTheory.Category.ULift
import Mathlib.CategoryTheory.EssentiallySmall

#align_import category_theory.limits.has_limits from "leanprover-community/mathlib"@"2738d2ca56cbc63be80c3bd48e9ed90ad94e947d"

Expand Down Expand Up @@ -617,12 +618,17 @@ theorem hasLimitsOfShape_of_equivalence {J' : Type u₂} [Category.{v₂} J'] (e

variable (C)

/-- A category that has larger limits also has smaller limits. -/
theorem hasLimitsOfSizeOfUnivLE [UnivLE.{v₂, v₁}] [UnivLE.{u₂, u₁}]
[HasLimitsOfSize.{v₁, u₁} C] : HasLimitsOfSize.{v₂, u₂} C where
has_limits_of_shape J {_} := hasLimitsOfShape_of_equivalence
((ShrinkHoms.equivalence J).trans <| Shrink.equivalence _).symm

/-- `hasLimitsOfSizeShrink.{v u} C` tries to obtain `HasLimitsOfSize.{v u} C`
from some other `HasLimitsOfSize C`.
-/
theorem hasLimitsOfSizeShrink [HasLimitsOfSize.{max v₁ v₂, max u₁ u₂} C] :
HasLimitsOfSize.{v₁, u₁} C :=
fun J _ => hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v₂, u₂} J).symm⟩
HasLimitsOfSize.{v₁, u₁} C := hasLimitsOfSizeOfUnivLE.{max v₁ v₂, max u₁ u₂} C
#align category_theory.limits.has_limits_of_size_shrink CategoryTheory.Limits.hasLimitsOfSizeShrink

instance (priority := 100) hasSmallestLimitsOfHasLimits [HasLimits C] : HasLimitsOfSize.{0, 0} C :=
Expand Down Expand Up @@ -1197,17 +1203,22 @@ theorem hasColimitsOfShape_of_equivalence {J' : Type u₂} [Category.{v₂} J']

variable (C)

/-- A category that has larger colimits also has smaller colimits. -/
theorem hasColimitsOfSizeOfUnivLE [UnivLE.{v₂, v₁}] [UnivLE.{u₂, u₁}]
[HasColimitsOfSize.{v₁, u₁} C] : HasColimitsOfSize.{v₂, u₂} C where
has_colimits_of_shape J {_} := hasColimitsOfShape_of_equivalence
((ShrinkHoms.equivalence J).trans <| Shrink.equivalence _).symm

/-- `hasColimitsOfSizeShrink.{v u} C` tries to obtain `HasColimitsOfSize.{v u} C`
from some other `HasColimitsOfSize C`.
-/
theorem hasColimitsOfSize_shrink [HasColimitsOfSize.{max v₁ v₂, max u₁ u₂} C] :
HasColimitsOfSize.{v₁, u₁} C :=
fun J _ => hasColimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v₂, u₂} J).symm⟩
#align category_theory.limits.has_colimits_of_size_shrink CategoryTheory.Limits.hasColimitsOfSize_shrink
theorem hasColimitsOfSizeShrink [HasColimitsOfSize.{max v₁ v₂, max u₁ u₂} C] :
HasColimitsOfSize.{v₁, u₁} C := hasColimitsOfSizeOfUnivLE.{max v₁ v₂, max u₁ u₂} C
#align category_theory.limits.has_colimits_of_size_shrink CategoryTheory.Limits.hasColimitsOfSizeShrink

instance (priority := 100) hasSmallestColimitsOfHasColimits [HasColimits C] :
HasColimitsOfSize.{0, 0} C :=
hasColimitsOfSize_shrink.{0, 0} C
hasColimitsOfSizeShrink.{0, 0} C
#align category_theory.limits.has_smallest_colimits_of_has_colimits CategoryTheory.Limits.hasSmallestColimitsOfHasColimits

end Colimit
Expand Down
37 changes: 28 additions & 9 deletions Mathlib/CategoryTheory/Limits/Preserves/Basic.lean
Expand Up @@ -271,13 +271,18 @@ def preservesLimitsOfShapeOfEquiv {J' : Type w₂} [Category.{w₂'} J'] (e : J
simp [← Functor.map_comp] }
#align category_theory.limits.preserves_limits_of_shape_of_equiv CategoryTheory.Limits.preservesLimitsOfShapeOfEquiv

/-- A functor preserving larger limits also preserves smaller limits. -/
def preservesLimitsOfSizeOfUnivLE (F : C ⥤ D) [UnivLE.{w, w'}] [UnivLE.{w₂, w₂'}]
[PreservesLimitsOfSize.{w', w₂'} F] : PreservesLimitsOfSize.{w, w₂} F where
preservesLimitsOfShape {J} := preservesLimitsOfShapeOfEquiv
((ShrinkHoms.equivalence J).trans <| Shrink.equivalence _).symm F

-- See library note [dsimp, simp].
/-- `PreservesLimitsOfSizeShrink.{w w'} F` tries to obtain `PreservesLimitsOfSize.{w w'} F`
from some other `PreservesLimitsOfSize F`.
-/
def preservesLimitsOfSizeShrink (F : C ⥤ D) [PreservesLimitsOfSize.{max w w₂, max w' w₂'} F] :
PreservesLimitsOfSize.{w, w'} F :=
fun {J} _ => preservesLimitsOfShapeOfEquiv (ULiftHomULiftCategory.equiv.{w₂, w₂'} J).symm F⟩
PreservesLimitsOfSize.{w, w'} F := preservesLimitsOfSizeOfUnivLE.{max w w₂, max w' w₂'} F
#align category_theory.limits.preserves_limits_of_size_shrink CategoryTheory.Limits.preservesLimitsOfSizeShrink

/-- Preserving limits at any universe level implies preserving limits in universe `0`. -/
Expand Down Expand Up @@ -335,15 +340,19 @@ def preservesColimitsOfShapeOfEquiv {J' : Type w₂} [Category.{w₂'} J'] (e :
simp [← Functor.map_comp] }
#align category_theory.limits.preserves_colimits_of_shape_of_equiv CategoryTheory.Limits.preservesColimitsOfShapeOfEquiv

/-- A functor preserving larger colimits also preserves smaller colimits. -/
def preservesColimitsOfSizeOfUnivLE (F : C ⥤ D) [UnivLE.{w, w'}] [UnivLE.{w₂, w₂'}]
[PreservesColimitsOfSize.{w', w₂'} F] : PreservesColimitsOfSize.{w, w₂} F where
preservesColimitsOfShape {J} := preservesColimitsOfShapeOfEquiv
((ShrinkHoms.equivalence J).trans <| Shrink.equivalence _).symm F

-- See library note [dsimp, simp].
/--
`PreservesColimitsOfSizeShrink.{w w'} F` tries to obtain `PreservesColimitsOfSize.{w w'} F`
from some other `PreservesColimitsOfSize F`.
-/
def preservesColimitsOfSizeShrink (F : C ⥤ D) [PreservesColimitsOfSize.{max w w₂, max w' w₂'} F] :
PreservesColimitsOfSize.{w, w'} F :=
fun {J} =>
preservesColimitsOfShapeOfEquiv (ULiftHomULiftCategory.equiv.{w₂, w₂'} J).symm F⟩
PreservesColimitsOfSize.{w, w'} F := preservesColimitsOfSizeOfUnivLE.{max w w₂, max w' w₂'} F
#align category_theory.limits.preserves_colimits_of_size_shrink CategoryTheory.Limits.preservesColimitsOfSizeShrink

/-- Preserving colimits at any universe implies preserving colimits at universe `0`. -/
Expand Down Expand Up @@ -616,12 +625,17 @@ def reflectsLimitsOfShapeOfEquiv {J' : Type w₂} [Category.{w₂'} J'] (e : J
exact IsLimit.whiskerEquivalence t _ }
#align category_theory.limits.reflects_limits_of_shape_of_equiv CategoryTheory.Limits.reflectsLimitsOfShapeOfEquiv

/-- A functor reflecting larger limits also reflects smaller limits. -/
def reflectsLimitsOfSizeOfUnivLE (F : C ⥤ D) [UnivLE.{w, w'}] [UnivLE.{w₂, w₂'}]
[ReflectsLimitsOfSize.{w', w₂'} F] : ReflectsLimitsOfSize.{w, w₂} F where
reflectsLimitsOfShape {J} := reflectsLimitsOfShapeOfEquiv
((ShrinkHoms.equivalence J).trans <| Shrink.equivalence _).symm F

/-- `reflectsLimitsOfSizeShrink.{w w'} F` tries to obtain `reflectsLimitsOfSize.{w w'} F`
from some other `reflectsLimitsOfSize F`.
-/
def reflectsLimitsOfSizeShrink (F : C ⥤ D) [ReflectsLimitsOfSize.{max w w₂, max w' w₂'} F] :
ReflectsLimitsOfSize.{w, w'} F :=
fun {J} => reflectsLimitsOfShapeOfEquiv (ULiftHomULiftCategory.equiv.{w₂, w₂'} J).symm F⟩
ReflectsLimitsOfSize.{w, w'} F := reflectsLimitsOfSizeOfUnivLE.{max w w₂, max w' w₂'} F
#align category_theory.limits.reflects_limits_of_size_shrink CategoryTheory.Limits.reflectsLimitsOfSizeShrink

/-- Reflecting limits at any universe implies reflecting limits at universe `0`. -/
Expand Down Expand Up @@ -726,12 +740,17 @@ def reflectsColimitsOfShapeOfEquiv {J' : Type w₂} [Category.{w₂'} J'] (e : J
exact IsColimit.whiskerEquivalence t _ }
#align category_theory.limits.reflects_colimits_of_shape_of_equiv CategoryTheory.Limits.reflectsColimitsOfShapeOfEquiv

/-- A functor reflecting larger colimits also reflects smaller colimits. -/
def reflectsColimitsOfSizeOfUnivLE (F : C ⥤ D) [UnivLE.{w, w'}] [UnivLE.{w₂, w₂'}]
[ReflectsColimitsOfSize.{w', w₂'} F] : ReflectsColimitsOfSize.{w, w₂} F where
reflectsColimitsOfShape {J} := reflectsColimitsOfShapeOfEquiv
((ShrinkHoms.equivalence J).trans <| Shrink.equivalence _).symm F

/-- `reflectsColimitsOfSizeShrink.{w w'} F` tries to obtain `reflectsColimitsOfSize.{w w'} F`
from some other `reflectsColimitsOfSize F`.
-/
def reflectsColimitsOfSizeShrink (F : C ⥤ D) [ReflectsColimitsOfSize.{max w w₂, max w' w₂'} F] :
ReflectsColimitsOfSize.{w, w'} F :=
fun {J} => reflectsColimitsOfShapeOfEquiv (ULiftHomULiftCategory.equiv.{w₂, w₂'} J).symm F⟩
ReflectsColimitsOfSize.{w, w'} F := reflectsColimitsOfSizeOfUnivLE.{max w w₂, max w' w₂'} F
#align category_theory.limits.reflects_colimits_of_size_shrink CategoryTheory.Limits.reflectsColimitsOfSizeShrink

/-- Reflecting colimits at any universe implies reflecting colimits at universe `0`. -/
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/CategoryTheory/Limits/Shapes/FiniteLimits.lean
Expand Up @@ -101,7 +101,7 @@ instance (priority := 100) hasColimitsOfShape_of_hasFiniteColimits (J : Type w)
instance (priority := 100) hasFiniteColimits_of_hasColimitsOfSize [HasColimitsOfSize.{v', u'} C] :
HasFiniteColimits C where
out := fun J hJ hJ' =>
haveI := hasColimitsOfSize_shrink.{0, 0} C
haveI := hasColimitsOfSizeShrink.{0, 0} C
let F := @FinCategory.equivAsType J (@FinCategory.fintypeObj J hJ hJ') hJ hJ'
@hasColimitsOfShape_of_equivalence (@FinCategory.AsType J (@FinCategory.fintypeObj J hJ hJ'))
(@FinCategory.categoryAsType J (@FinCategory.fintypeObj J hJ hJ') hJ hJ') _ _ J hJ F _
Expand Down
31 changes: 17 additions & 14 deletions Mathlib/CategoryTheory/Limits/Shapes/Types.lean
Expand Up @@ -54,7 +54,7 @@ instance : HasProducts.{v} (Type v) := inferInstance

/-- A restatement of `Types.Limit.lift_π_apply` that uses `Pi.π` and `Pi.lift`. -/
@[simp 1001]
theorem pi_lift_π_apply [UnivLE.{v, u}] {β : Type v} (f : β → Type u) {P : Type u}
theorem pi_lift_π_apply {β : Type v} [Small.{u} β] (f : β → Type u) {P : Type u}
(s : ∀ b, P ⟶ f b) (b : β) (x : P) :
(Pi.π f b : (piObj f) → f b) (@Pi.lift β _ _ f _ P s x) = s b x :=
congr_fun (limit.lift_π (Fan.mk P s) ⟨b⟩) x
Expand All @@ -70,7 +70,7 @@ theorem pi_lift_π_apply' {β : Type v} (f : β → Type v) {P : Type v}

/-- A restatement of `Types.Limit.map_π_apply` that uses `Pi.π` and `Pi.map`. -/
@[simp 1001]
theorem pi_map_π_apply [UnivLE.{v, u}] {β : Type v} {f g : β → Type u}
theorem pi_map_π_apply {β : Type v} [Small.{u} β] {f g : β → Type u}
(α : ∀ j, f j ⟶ g j) (b : β) (x) :
(Pi.π g b : ∏ g → g b) (Pi.map α x) = α b ((Pi.π f b : ∏ f → f b) x) :=
Limit.map_π_apply.{v, u} _ _ _
Expand Down Expand Up @@ -396,45 +396,48 @@ theorem productIso_inv_comp_π {J : Type v} (F : J → TypeMax.{v, u}) (j : J) :
limit.isoLimitCone_inv_π (productLimitCone.{v, u} F) ⟨j⟩
#align category_theory.limits.types.product_iso_inv_comp_π CategoryTheory.Limits.Types.productIso_inv_comp_π

namespace UnivLE
namespace Small

variable {J : Type v} (F : J → Type u) [Small.{u} J]

/--
A variant of `productLimitCone` using a `UnivLE` hypothesis rather than a function to `TypeMax`.
A variant of `productLimitCone` using a `Small` hypothesis rather than a function to `TypeMax`.
-/
noncomputable def productLimitCone {J : Type v} (F : J → Type u) [UnivLE.{v, u}] :
noncomputable def productLimitCone :
Limits.LimitCone (Discrete.functor F) where
cone :=
{ pt := Shrink (∀ j, F j)
π := Discrete.natTrans (fun ⟨j⟩ f => (equivShrink _).symm f j) }
π := Discrete.natTrans (fun ⟨j⟩ f => (equivShrink (∀ j, F j)).symm f j) }
isLimit :=
have : Small.{u} (∀ j, F j) := inferInstance
{ lift := fun s x => (equivShrink _) (fun j => s.π.app ⟨j⟩ x)
uniq := fun s m w => funext fun x => Shrink.ext <| funext fun j => by
simpa using (congr_fun (w ⟨j⟩) x : _) }

/-- The categorical product in `Type u` indexed in `Type v`
is the type theoretic product `Π j, F j`, after shrinking back to `Type u`. -/
noncomputable def productIso {J : Type v} (F : J → Type u) [UnivLE.{v, u}] :
noncomputable def productIso :
(∏ F : Type u) ≅ Shrink.{u} (∀ j, F j) :=
limit.isoLimitCone (productLimitCone.{v, u} F)

@[simp]
theorem productIso_hom_comp_eval {J : Type v} (F : J → Type u) [UnivLE.{v, u}] (j : J) :
((productIso.{v, u} F).hom ≫ fun f => (equivShrink _).symm f j) = Pi.π F j :=
theorem productIso_hom_comp_eval (j : J) :
((productIso.{v, u} F).hom ≫ fun f => (equivShrink (∀ j, F j)).symm f j) = Pi.π F j :=
limit.isoLimitCone_hom_π (productLimitCone.{v, u} F) ⟨j⟩

-- Porting note:
-- `elementwise` seems to be broken. Applied to the previous lemma, it should produce:
@[simp]
theorem productIso_hom_comp_eval_apply {J : Type v} (F : J → Type u) [UnivLE.{v, u}] (j : J) (x) :
(equivShrink _).symm ((productIso F).hom x) j = Pi.π F j x :=
theorem productIso_hom_comp_eval_apply (j : J) (x) :
(equivShrink (∀ j, F j)).symm ((productIso F).hom x) j = Pi.π F j x :=
congr_fun (productIso_hom_comp_eval F j) x

@[elementwise (attr := simp)]
theorem productIso_inv_comp_π {J : Type v} (F : J → Type u) [UnivLE.{v, u}] (j : J) :
(productIso.{v, u} F).inv ≫ Pi.π F j = fun f => ((equivShrink _).symm f) j :=
theorem productIso_inv_comp_π (j : J) :
(productIso.{v, u} F).inv ≫ Pi.π F j = fun f => ((equivShrink (∀ j, F j)).symm f) j :=
limit.isoLimitCone_inv_π (productLimitCone.{v, u} F) ⟨j⟩

end UnivLE
end Small

/-- The category of types has `Σ j, f j` as the coproduct of a type family `f : J → Type`.
-/
Expand Down

0 comments on commit 988870b

Please sign in to comment.