Library UniMath.CategoryTheory.Limits.Cats.Limits


*************************************************
Contents :
Definition of limits

Require Import UniMath.Foundations.PartD.
Require Import UniMath.Foundations.Propositions.
Require Import UniMath.Foundations.Sets.

Require Import UniMath.MoreFoundations.Tactics.
Require Import UniMath.MoreFoundations.Propositions.

Require Import UniMath.CategoryTheory.Core.Categories.
Require Import UniMath.CategoryTheory.Core.Isos.
Require Import UniMath.CategoryTheory.Core.NaturalTransformations.
Require Import UniMath.CategoryTheory.Core.Univalence.
Require Import UniMath.CategoryTheory.Core.Functors.
Require Import UniMath.CategoryTheory.FunctorCategory.

Require Import UniMath.CategoryTheory.Adjunctions.Core.

Local Open Scope cat.

Section lim_def.

Definition cone {J C : precategory} (F : functor J C) (c : C) : UU :=
   (f : (v : J), Cc,F v),
     (u v : J) (e : Ju,v), f u · # F e = f v.

Definition make_cone {J C : precategory} {F : functor J C} {c : C}
  (f : v, Cc, F v) (Hf : u v (e : Ju,v) , f u · # F e = f v) :
  cone F c := tpair _ f Hf.

Definition coneOut {J C : precategory} {F : functor J C} {c : C} (cc : cone F c) :
   v, Cc, F v := pr1 cc.

Lemma coneOutCommutes {J C : precategory} {F : functor J C} {c : C}
  (cc : cone F c) : u v (e : Ju,v), coneOut cc u · # F e = coneOut cc v.
Proof.
apply (pr2 cc).
Qed.

Definition isLimCone {J C : precategory} (F : functor J C)
  (l : C) (cc0 : cone F l) : UU := (c : C) (cc : cone F c),
    iscontr ( x : Cc,l, v, x · coneOut cc0 v = coneOut cc v).

Definition LimCone {J C : precategory} (F : functor J C) : UU :=
   (A : ( l, cone F l)), isLimCone F (pr1 A) (pr2 A).

Definition make_LimCone {J C : precategory} (F : functor J C)
  (c : C) (cc : cone F c) (isCC : isLimCone F c cc) : LimCone F :=
  tpair _ (tpair _ c cc) isCC.

Definition lim {J C : precategory} {F : functor J C} (CC : LimCone F) : C
  := pr1 (pr1 CC).

Definition limCone {J C : precategory} {F : functor J C} (CC : LimCone F) :
  cone F (lim CC) := pr2 (pr1 CC).

Definition limOut {J C : precategory} {F : functor J C} (CC : LimCone F) :
   v, Clim CC,F v := coneOut (limCone CC).

Lemma limOutCommutes {J C : precategory} {F : functor J C}
  (CC : LimCone F) : u v (e : Ju,v),
   limOut CC u · # F e = limOut CC v.
Proof.
exact (coneOutCommutes (limCone CC)).
Qed.

Lemma limUnivProp {J C : precategory} {F : functor J C}
  (CC : LimCone F) : (c : C) (cc : cone F c),
  iscontr ( x : Cc, lim CC, v, x · limOut CC v = coneOut cc v).
Proof.
exact (pr2 CC).
Qed.

Lemma isaprop_isLimCone {J C : precategory} (F : functor J C) (c0 : C)
  (cc0 : cone F c0) : isaprop (isLimCone F c0 cc0).
Proof.
repeat (apply impred; intro).
apply isapropiscontr.
Qed.

Definition isLimCone_LimCone {J C : precategory} {F : functor J C}
  (CC : LimCone F)
  : isLimCone F (lim CC) (tpair _ (limOut CC) (limOutCommutes CC))
  := pr2 CC.

Definition limArrow {J C : precategory} {F : functor J C} (CC : LimCone F)
  (c : C) (cc : cone F c) : Cc, lim CC := pr1 (pr1 (isLimCone_LimCone CC c cc)).

Lemma limArrowCommutes {J C : precategory} {F : functor J C} (CC : LimCone F)
  (c : C) (cc : cone F c) u :
   limArrow CC c cc · limOut CC u = coneOut cc u.
Proof.
exact ((pr2 (pr1 (isLimCone_LimCone CC _ cc))) u).
Qed.

Lemma limArrowUnique {J C : precategory} {F : functor J C} (CC : LimCone F)
  (c : C) (cc : cone F c) (k : Cc, lim CC)
  (Hk : u, k · limOut CC u = coneOut cc u) :
  k = limArrow CC c cc.
Proof.
now apply path_to_ctr, Hk.
Qed.

Lemma Cone_precompose {J C : precategory} {F : functor J C}
  {c : C} (cc : cone F c) (x : C) (f : Cx,c) :
     u v (e : Ju,v), (f · coneOut cc u) · # F e = f · coneOut cc v.
Proof.
now intros u v e; rewrite <- assoc, coneOutCommutes.
Qed.

Lemma limArrowEta {J C : precategory} {F : functor J C} (CC : LimCone F)
  (c : C) (f : Cc, lim CC) :
  f = limArrow CC c (tpair _ (λ u, f · limOut CC u)
                 (Cone_precompose (limCone CC) c f)).
Proof.
now apply limArrowUnique.
Qed.

Definition limOfArrows {J C : precategory} {F1 F2 : functor J C}
  (CC1 : LimCone F1) (CC2 : LimCone F2)
  (f : u, CF1 u,F2 u)
  (fNat : u v (e : Ju,v), f u · # F2 e = # F1 e · f v) :
  Clim CC1 , lim CC2.
Proof.
apply limArrow; use make_cone.
- now intro u; apply (limOut CC1 u · f u).
- abstract (intros u v e; simpl;
            now rewrite <- assoc, fNat, assoc, limOutCommutes).
Defined.

Lemma limOfArrowsOut {J C : precategory} {F1 F2 : functor J C}
  (CC1 : LimCone F1) (CC2 : LimCone F2)
  (f : u, CF1 u,F2 u)
  (fNat : u v (e : Ju,v), f u · # F2 e = # F1 e · f v) :
     u, limOfArrows CC1 CC2 f fNat · limOut CC2 u =
          limOut CC1 u · f u.
Proof.
now unfold limOfArrows; intro u; rewrite limArrowCommutes.
Qed.

Lemma limOfArrows_id {J C : precategory} {F : J C} (CC : LimCone F)
  (id_nat : u v e, identity (F u) · # F e = # F e · identity (F v))
  : limOfArrows CC CC (λ _, identity _) id_nat = identity (lim CC).
Proof.
  symmetry; use limArrowUnique; intro; cbn.
  now rewrite id_left, id_right.
Qed.

Lemma limOfArrows_comp {J C : precategory} {F G H : J C}
  (CC1 : LimCone F) (CC2 : LimCone G) (CC3 : LimCone H)
  (fg : u, CF u,G u) (gh : u, CG u,H u)
  (fg_nat : u v e, fg u · # G e = # F e · fg v)
  (gh_nat : u v e, gh u · # H e = # G e · gh v)
  (fgh_nat : u v e, (fg u · gh u) · # H e = # F e · (fg v · gh v))
  : limOfArrows CC1 CC3 (λ u, fg u · gh u) fgh_nat
    = limOfArrows CC1 CC2 fg fg_nat · limOfArrows CC2 CC3 gh gh_nat.
Proof.
  symmetry; use limArrowUnique; intro; cbn.
  etrans.
  {
    rewrite <- assoc; refine (maponpaths _ _).
    use limOfArrowsOut.
  }
  etrans.
  {
    rewrite assoc; refine (maponpaths (λ x, x·_) _).
    use limOfArrowsOut.
  }
  now rewrite assoc.
Qed.

Lemma postCompWithLimOfArrows_subproof
  {J C : precategory} {F1 F2 : functor J C}
  (CC1 : LimCone F1) (CC2 : LimCone F2)
  (f : u, CF1 u,F2 u)
  (fNat : u v (e : Ju,v), f u · # F2 e = # F1 e · f v)
  (x : C) (cc : cone F1 x) u v (e : Ju,v) :
    (coneOut cc u · f u) · # F2 e = coneOut cc v · f v.
Proof.
now rewrite <- (coneOutCommutes cc u v e), <- assoc, fNat, assoc.
Defined.

Lemma postcompWithLimOfArrows
  {J C : precategory} {F1 F2 : functor J C}
  (CC1 : LimCone F1) (CC2 : LimCone F2)
  (f : u, CF1 u,F2 u)
  (fNat : u v (e : Ju,v), f u · # F2 e = # F1 e · f v)
  (x : C) (cc : cone F1 x) :
     limArrow CC1 x cc · limOfArrows CC1 CC2 f fNat =
       limArrow CC2 x (make_cone (λ u, coneOut cc u · f u)
         (postCompWithLimOfArrows_subproof CC1 CC2 f fNat x cc)).
Proof.
apply limArrowUnique; intro u.
now rewrite <- assoc, limOfArrowsOut, assoc, limArrowCommutes.
Qed.

Lemma postcompWithLimArrow {J C : precategory} {F : functor J C}
 (CC : LimCone F) (c : C) (cc : cone F c) (d : C) (k : Cd,c) :
   k · limArrow CC c cc =
   limArrow CC d (make_cone (λ u, k · coneOut cc u)
              (Cone_precompose cc d k)).
Proof.
apply limArrowUnique.
now intro u; rewrite <- assoc, limArrowCommutes.
Qed.

Lemma lim_endo_is_identity {J C : precategory} {F : functor J C}
  (CC : LimCone F) (k : lim CC --> lim CC)
  (H : u, k · limOut CC u = limOut CC u) :
  identity _ = k.
Proof.
use (uniqueExists (limUnivProp CC _ _)).
- now apply (limCone CC).
- now intros v; apply id_left.
- simpl; now apply H.
Qed.


Definition z_iso_from_lim_to_lim {J C : precategory} {F : functor J C}
  (CC CC' : LimCone F) : z_iso (lim CC) (lim CC').
Proof.
  use make_z_iso.
  - apply limArrow, limCone.
  - apply limArrow, limCone.
  - abstract (now split; apply pathsinv0, lim_endo_is_identity; intro u;
                rewrite <- assoc, limArrowCommutes; eapply pathscomp0; try apply limArrowCommutes).
Defined.

End lim_def.

Section Lims.

Definition Lims (C : precategory) : UU := (J : precategory) (F : functor J C), LimCone F.
Definition hasLims : UU :=
   (J C : precategory) (F : functor J C), ishinh (LimCone F).
Definition Lims_of_shape (J C : precategory) : UU := (F : functor J C), LimCone F.

Section Universal_Unique.

Context (C : univalent_category).

Let H : is_univalent C := pr2 C.

Lemma isaprop_Lims: isaprop (Lims C).
Proof.
apply impred; intro J; apply impred; intro F.
apply invproofirrelevance; intros Hccx Hccy.
apply subtypePath.
- intro; apply isaprop_isLimCone.
- apply (total2_paths_f (isotoid _ H (z_iso_from_lim_to_lim Hccx Hccy))).
  set (B c := v, Cc,F v).
  set (C' (c : C) f := u v (e : Ju,v), @compose _ c _ _ (f u) (# F e) = f v).
  rewrite (@transportf_total2 _ B C').
  apply subtypePath.
  + intro; repeat (apply impred; intro). apply (homset_property C).
  + abstract (simpl; eapply pathscomp0; [apply transportf_isotoid_dep'|]; apply funextsec;
              intro v; rewrite inv_isotoid, idtoiso_isotoid; cbn; apply limArrowCommutes).
Qed.

End Universal_Unique.
End Lims.

Section LimFunctor.

Variable A C : precategory.
Variable hsC : has_homsets C.
Variable (J : precategory).
Variable (D : functor J [A, C, hsC]).

Definition functor_pointwise (a : A) : functor J C.
Proof.
use tpair.
- apply (tpair _ (λ v, pr1 (D v) a)).
  intros u v e; simpl; apply (pr1 (# D e) a).
- abstract (use tpair;
    [ intro x; simpl;
      apply (toforallpaths _ _ _ (maponpaths pr1 (functor_id D x)) a)
    | intros x y z f g; simpl;
      apply (toforallpaths _ _ _ (maponpaths pr1 (functor_comp D f g)) a)]).
Defined.

Variable (HCg : (a : A), LimCone (functor_pointwise a)).

Definition LimFunctor_ob (a : A) : C := lim (HCg a).

Definition LimFunctor_mor (a a' : A) (f : Aa, a') :
  CLimFunctor_ob a,LimFunctor_ob a'.
Proof.
use limOfArrows.
- now intro u; apply (# (pr1 (D u)) f).
- abstract (now intros u v e; simpl; apply (nat_trans_ax (# D e))).
Defined.

Definition LimFunctor_data : functor_data A C := tpair _ _ LimFunctor_mor.

Lemma is_functor_LimFunctor_data : is_functor LimFunctor_data.
Proof.
split.
- intro a; simpl.
  apply pathsinv0, lim_endo_is_identity; intro u.
  unfold LimFunctor_mor; rewrite limOfArrowsOut.
  assert (H : # (pr1 (D u)) (identity a) = identity (pr1 (D u) a)).
    apply (functor_id (D u) a).
  now rewrite H, id_right.
- intros a b c fab fbc; simpl; unfold LimFunctor_mor.
  apply pathsinv0.
  eapply pathscomp0; [now apply postcompWithLimOfArrows|].
  apply pathsinv0, limArrowUnique; intro u.
  rewrite limOfArrowsOut, (functor_comp (D u)); simpl.
  now rewrite <- assoc.
Qed.

Definition LimFunctor : functor A C := tpair _ _ is_functor_LimFunctor_data.

Definition lim_nat_trans_in_data v : [A, C, hsC] LimFunctor, D v .
Proof.
use tpair.
- intro a; exact (limOut (HCg a) v).
- abstract (intros a a' f; apply (limOfArrowsOut (HCg a) (HCg a'))).
Defined.

Definition cone_pointwise (F : [A,C,hsC]) (cc : cone D F) a :
  cone (functor_pointwise a) (pr1 F a).
Proof.
use make_cone.
- now intro v; apply (pr1 (coneOut cc v) a).
- abstract (intros u v e;
    now apply (nat_trans_eq_pointwise (coneOutCommutes cc u v e))).
Defined.

Lemma LimFunctor_unique (F : [A, C, hsC]) (cc : cone D F) :
  iscontr ( x : [A, C, hsC] F, LimFunctor ,
             v, x · lim_nat_trans_in_data v = coneOut cc v).
Proof.
use tpair.
- use tpair.
  + apply (tpair _ (λ a, limArrow (HCg a) _ (cone_pointwise F cc a))).
    abstract (intros a a' f; simpl; apply pathsinv0; eapply pathscomp0;
    [ apply (postcompWithLimOfArrows (HCg a))
    | apply pathsinv0; eapply pathscomp0;
      [ apply postcompWithLimArrow
      | apply limArrowUnique; intro u; eapply pathscomp0;
      [ now apply limArrowCommutes | now use nat_trans_ax]]]).
  + abstract (intro u; apply (nat_trans_eq hsC); simpl; intro a;
              now apply (limArrowCommutes (HCg a))).
- abstract (intro t; destruct t as [t1 t2];
            apply subtypePath; simpl;
              [ intro; apply impred; intro u; apply functor_category_has_homsets
              | apply (nat_trans_eq hsC); simpl; intro a;
                apply limArrowUnique; intro u;
                now apply (nat_trans_eq_pointwise (t2 u))]).
Defined.

Lemma LimFunctorCone : LimCone D.
Proof.
use make_LimCone.
- exact LimFunctor.
- use make_cone.
  + now apply lim_nat_trans_in_data.
  + abstract (now intros u v e; apply (nat_trans_eq hsC);
                  intro a; apply (limOutCommutes (HCg a))).
- now intros F cc; simpl; apply (LimFunctor_unique _ cc).
Defined.

End LimFunctor.

Lemma LimsFunctorCategory (A C : precategory) (hsC : has_homsets C)
  (HC : Lims C) : Lims [A,C,hsC].
Proof.
now intros g d; apply LimFunctorCone.
Defined.

Lemma LimsFunctorCategory_of_shape (J A C : precategory) (hsC : has_homsets C)
  (HC : Lims_of_shape J C) : Lims_of_shape J [A,C,hsC].
Proof.
now intros d; apply LimFunctorCone.
Defined.

Section LimitsAreRightAdjoints.
  Context (J : category) (C : category).
  Context (C_complete : Lims_of_shape J C).

  Definition limit_functor_data : functor_data [J, C] C.
  Proof.
    use tpair.
    - intro F; exact (lim (C_complete F)).
    - intros F G α; use limOfArrows; cbn in α.
      + use α.
      + abstract (symmetry; use (nat_trans_ax α)).
  Defined.

  Lemma limit_functor_is_functor : is_functor limit_functor_data.
  Proof.
    split.
    - intro; use limOfArrows_id.
    - do 5 intro; use limOfArrows_comp.
  Qed.

  Definition limit_functor : [J, C] C
    := make_functor limit_functor_data limit_functor_is_functor.

  Local Definition id_to_const_lim_data
    : nat_trans_data (functor_identity C) (constant_functor_functor limit_functor).
  Proof.
    intro; use limArrow; use make_cone.
    - intro u; use identity.
    - abstract (intros u v e; use id_left).
  Defined.

  Local Lemma id_to_const_lim_is_nat
    : is_nat_trans _ _ id_to_const_lim_data.
  Proof.
    intros A B f; unfold id_to_const_lim_data; cbn.
    etrans; [|symmetry]; use limArrowUnique.
    - use make_cone.
      * intro; use f.
      * intros; use id_right.
    - intro; etrans.
      { rewrite <- assoc; refine (maponpaths _ _); use limArrowCommutes. }
      cbn. use id_right.
    - intro; cbn; etrans.
      {
        rewrite <- assoc; refine (maponpaths _ _).
        use (limOfArrowsOut _ (C_complete (constant_functor _ _ _))).
      }
      rewrite assoc; etrans.
      { refine (maponpaths (λ x, x · _) _); use limArrowCommutes. }
      cbn. use id_left.
  Qed.

  Local Definition id_to_const_lim
    : functor_identity C constant_functor_functor limit_functor
    := make_nat_trans _ _ _ id_to_const_lim_is_nat.

  Local Definition lim_const_to_id_data
    : nat_trans_data (limit_functor constant_functor_functor) (functor_identity [J, C]).
  Proof.
    intro F; use make_nat_trans.
    - intro u; cbn; use limOut.
    - abstract (intros u v e; rewrite id_left; symmetry; use limOutCommutes).
  Defined.

  Local Lemma lim_const_to_id_is_nat
    : is_nat_trans _ _ lim_const_to_id_data.
  Proof.
    intros F F' α; cbn in *.
    apply nat_trans_eq; [use homset_property|]; use limOfArrowsOut.
  Qed.

  Local Definition lim_const_to_id
    : limit_functor constant_functor_functor functor_identity [J, C]
    := make_nat_trans _ _ _ lim_const_to_id_is_nat.

  Local Lemma lim_const_adjunction
    : form_adjunction constant_functor_functor limit_functor
        id_to_const_lim lim_const_to_id.
  Proof.
    split.
    - intro A; cbn.
      apply nat_trans_eq; [use homset_property|]; intro u; cbn.
      use (limArrowCommutes (C_complete (constant_functor_functor A))).
    - intro A; cbn; etrans.
      {
        use limArrowUnique.
        use limCone.
        intro u.
        etrans.
        { rewrite <- assoc; refine (maponpaths _ _); use limOfArrowsOut. }
        cbn; etrans.
        {
          rewrite assoc; refine (maponpaths (λ x, x·_) _).
          use (limArrowCommutes (C_complete (constant_functor_functor _))).
        }
        cbn. use id_left.
      }
      symmetry; use limArrowUnique; intro u.
      use id_left.
  Qed.

  Lemma limit_functor_constant_functor_are_adjoints
    : are_adjoints constant_functor_functor limit_functor.
  Proof.
    use make_are_adjoints.
    - exact id_to_const_lim.
    - exact lim_const_to_id.
    - exact lim_const_adjunction.
  Defined.

  Definition limit_is_right_adjoint
    : is_right_adjoint limit_functor
    := constant_functor_functor ,, limit_functor_constant_functor_are_adjoints.
End LimitsAreRightAdjoints.