Theory CZH_UCAT_Complete

(* Copyright 2021 (C) Mihails Milehins *)

section‹Completeness and cocompleteness›
theory CZH_UCAT_Complete
  imports 
    CZH_UCAT_Limit
    CZH_UCAT_Limit_Product
    CZH_UCAT_Limit_Equalizer
begin



subsection‹Limits by products and equalizers›

lemma cat_limit_of_cat_prod_obj_and_cat_equalizer:
  ―‹See Theorem 1 in Chapter V-2 in \cite{mac_lane_categories_2010}.›
  assumes "𝔉 : 𝔍 ↦↦C.tmα"
    and "𝔞 𝔟 𝔤 𝔣.  𝔣 : 𝔞 𝔟; 𝔤 : 𝔞 𝔟  
      E ε. ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
    and "A. tm_cf_discrete α (𝔍Obj) A  
      P π. π : P <CF. A : 𝔍Obj ↦↦Cα"
    and "A. tm_cf_discrete α (𝔍Arr) A  
      P π. π : P <CF. A : 𝔍Arr ↦↦Cα"
  obtains r u where "u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα"
proof-

  let ?L =λu. 𝔉ObjMap𝔍Codu and ?R =λi. 𝔉ObjMapi
  
  interpret 𝔉: is_tm_functor α 𝔍  𝔉 by (rule assms(1))

  have "?R j  Obj" if "j  𝔍Obj" for j
    by (cs_concl cs_shallow cs_intro: cat_cs_intros that)

  have "tm_cf_discrete α (𝔍Obj) ?R "
  proof(intro tm_cf_discreteI)
    show "𝔉ObjMapi  Obj" if "i  𝔍Obj" for i
      by (cs_concl cs_shallow cs_intro: cat_cs_intros that)
    show "VLambda (𝔍Obj) ?R  Vset α"
    proof(rule vbrelation.vbrelation_Limit_in_VsetI)
      show " (VLambda (𝔍Obj) ?R)  Vset α"
      proof-
        have " (VLambda (𝔍Obj) ?R)   (𝔉ObjMap)"
          by (auto simp: 𝔉.cf_ObjMap_vdomain)
        moreover have " (𝔉ObjMap)  Vset α"
          by (force intro: vrange_in_VsetI 𝔉.tm_cf_ObjMap_in_Vset)
        ultimately show ?thesis by auto
      qed
    qed (auto simp: cat_small_cs_intros)
    show "(λi𝔍Obj. CId𝔉ObjMapi)  Vset α"
    proof(rule vbrelation.vbrelation_Limit_in_VsetI)
      show " (λi𝔍Obj. CId𝔉ObjMapi)  Vset α"
      proof-
        have " (λi𝔍Obj. CId𝔉ObjMapi)   (𝔉ArrMap)"
        proof(rule vrange_VLambda_vsubset)
          fix x assume x: "x  𝔍Obj"
          then have "𝔍CIdx  𝒟 (𝔉ArrMap)"
            by (auto intro: cat_cs_intros simp: cat_cs_simps)
          moreover from x have "CId𝔉ObjMapx = 𝔉ArrMap𝔍CIdx"
            by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
          ultimately show "CId𝔉ObjMapx   (𝔉ArrMap)"
            by (simp add: 𝔉.ArrMap.vsv_vimageI2)
        qed
        moreover have " (𝔉ArrMap)  Vset α"
          by (force intro: vrange_in_VsetI 𝔉.tm_cf_ArrMap_in_Vset)
        ultimately show ?thesis by auto
      qed
    qed (auto simp: cat_small_cs_intros)
  qed (auto intro: cat_cs_intros)

  from assms(3)[where A=?R, OF this] obtain PO πO
    where πO: "πO : PO <CF. ?R : 𝔍Obj ↦↦Cα"
    by clarsimp

  interpret πO: is_cat_obj_prod α 𝔍Obj ?R  PO πO by (rule πO)

  have PO: "PO  Obj" by (intro πO.cat_cone_obj)

  have "?L u  Obj" if "u  𝔍Arr" for u
  proof-
    from that obtain a b where "u : a 𝔍b" by auto
    then show ?thesis 
      by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
  qed

  have tm_cf_discrete: "tm_cf_discrete α (𝔍Arr) ?L "
  proof(intro tm_cf_discreteI)
    show "𝔉ObjMap𝔍Codf  Obj" if "f  𝔍Arr" for f
    proof-
      from that obtain a b where "f : a 𝔍b" by auto
      then show ?thesis 
        by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
    qed
 
    show "(λu𝔍Arr. 𝔉ObjMap𝔍Codu)  Vset α"
    proof(rule vbrelation.vbrelation_Limit_in_VsetI)
      show " (λu𝔍Arr. ?L u)  Vset α"
      proof-
        have " (λu𝔍Arr. ?L u)   (𝔉ObjMap)"
        proof(rule vrange_VLambda_vsubset)
          fix f assume "f  𝔍Arr"
          then obtain a b where "f : a 𝔍b" by auto
          then show "𝔉ObjMap𝔍Codf   (𝔉ObjMap)"
            by 
              (
                cs_concl cs_shallow
                  cs_simp: cat_cs_simps cs_intro: V_cs_intros cat_cs_intros
              )
        qed
        moreover have " (𝔉ObjMap)  Vset α"
          by (auto intro: vrange_in_VsetI 𝔉.tm_cf_ObjMap_in_Vset)
        ultimately show ?thesis by auto
      qed
    qed (auto simp: cat_small_cs_intros)

    show "(λi𝔍Arr. CId𝔉ObjMap𝔍Codi)  Vset α"
    proof(rule vbrelation.vbrelation_Limit_in_VsetI)
      show " (λi𝔍Arr. CId𝔉ObjMap𝔍Codi)  Vset α"
      proof-
        have " (λi𝔍Arr. CId𝔉ObjMap𝔍Codi)   (𝔉ArrMap)"
        proof(rule vrange_VLambda_vsubset)
          fix f assume "f  𝔍Arr"
          then obtain a b where f: "f : a 𝔍b" by auto
          then have "𝔍CIdb  𝒟 (𝔉ArrMap)"
            by (auto intro: cat_cs_intros simp: cat_cs_simps)
          moreover from f have 
            "CId𝔉ObjMap𝔍Codf = 𝔉ArrMap𝔍CIdb"
            by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
          ultimately show "CId𝔉ObjMap𝔍Codf   (𝔉ArrMap)"
            by (simp add: 𝔉.ArrMap.vsv_vimageI2)
        qed
        moreover have " (𝔉ArrMap)  Vset α"
          by (force intro: vrange_in_VsetI 𝔉.tm_cf_ArrMap_in_Vset)
        ultimately show ?thesis by auto
      qed
    qed (auto simp: cat_small_cs_intros)
  qed (auto intro: cat_cs_intros)

  from assms(4)[where A=?L, OF this, simplified] obtain PA πA
    where πA: "πA : PA <CF. ?L : 𝔍Arr ↦↦Cα"
    by auto

  interpret πA: is_cat_obj_prod α 𝔍Arr ?L  PA πA by (rule πA)

  let ?F = λu. 𝔉ObjMap𝔍Codu and ?f = λu. πONTMap𝔍Codu 
  let O' = ntcf_obj_prod_base  (:C (𝔍Arr)Obj) ?F PO ?f

  have πO': "O' :
    PO <CF.cone :→: (𝔍Arr) (λu. 𝔉ObjMap𝔍Codu)  :
    :C (𝔍Arr) ↦↦Cα"
    unfolding the_cat_discrete_components(1)
  proof
    (
      intro 
        tm_cf_discrete.tm_cf_discrete_ntcf_obj_prod_base_is_cat_cone 
        tm_cf_discrete
    )
    fix f assume "f  𝔍Arr"
    then obtain a b where "f : a 𝔍b" by auto
    then show "πONTMap𝔍Codf : PO 𝔉ObjMap𝔍Codf"
      by 
        (
          cs_concl cs_shallow
            cs_simp:
              the_cat_discrete_components(1) cat_discrete_cs_simps cat_cs_simps
            cs_intro: cat_cs_intros
        )
  qed (intro PO)

  from πA.cat_obj_prod_unique_cone'[OF πO'] obtain f' 
    where f': "f' : PO PA"
      and πO'_NTMap_app: 
        "j. j  𝔍Arr  O'NTMapj = πANTMapj Af'"
      and unique_f':
        "
          f'' : PO PA;
          j. j  𝔍Arr  O'NTMapj = πANTMapj Af''
           f'' = f'"
      for f''
    by metis

  have πO_NTMap_app_Cod: 
    "πONTMapb = πANTMapf Af'" if "f : a 𝔍b" for f a b 
  proof-
    from that have "f  𝔍Arr" by auto
    from πO'_NTMap_app[OF this] that show ?thesis
      by 
        (
          cs_prems cs_shallow
            cs_simp: cat_cs_simps the_cat_discrete_components(1)
            cs_intro: cat_cs_intros
        )
  qed

  from this[symmetric] have πA_NTMap_Comp_app: 
    "πANTMapf A(f' Aq) = πONTMapb Aq" 
    if "f : a 𝔍b" and "q : c PO" for q f a b c 
    using that f'
    by (intro 𝔉.HomCod.cat_assoc_helper)
      (
        cs_concl cs_shallow
          cs_simp: 
            cat_cs_simps cat_discrete_cs_simps the_cat_discrete_components(1)
          cs_intro: cat_cs_intros
      )+

  let ?g = λu. 𝔉ArrMapu AπONTMap𝔍Domu 
  let O'' = ntcf_obj_prod_base  (:C (𝔍Arr)Obj) ?F PO ?g
  
  have πO'': "O'' : PO <CF.cone :→: (𝔍Arr) ?L  : :C (𝔍Arr) ↦↦Cα"
    unfolding the_cat_discrete_components(1)
  proof
    (
      intro 
        tm_cf_discrete.tm_cf_discrete_ntcf_obj_prod_base_is_cat_cone  
        tm_cf_discrete
    )
    show "𝔉ArrMapf AπONTMap𝔍Domf : PO 𝔉ObjMap𝔍Codf"
      if "f  𝔍Arr" for f
    proof-
      from that obtain a b where "f : a 𝔍b"  by auto
      then show ?thesis
        by  
          (
            cs_concl 
              cs_simp: 
                cat_cs_simps cat_discrete_cs_simps 
                the_cat_discrete_components(1) 
              cs_intro: cat_cs_intros
          )
    qed
  qed (intro PO)

  from πA.cat_obj_prod_unique_cone'[OF πO''] obtain g' 
    where g': "g' : PO PA"
      and πO''_NTMap_app: 
        "j. j  𝔍Arr  O''NTMapj = πANTMapj Ag'"
      and unique_g':
        "
          g'' : PO PA;
          j. j  𝔍Arr  O''NTMapj = πANTMapj Ag''
           g'' = g'"
      for g''
    by (metis (lifting))

  have "𝔉ArrMapf AπONTMapa = πANTMapf Ag'" 
    if "f : a 𝔍b" for f a b 
  proof-
    from that have "f  𝔍Arr" by auto
    from πO''_NTMap_app[OF this] that show ?thesis
      by 
        (
          cs_prems cs_shallow
            cs_simp: cat_cs_simps the_cat_discrete_components(1)
            cs_intro: cat_cs_intros
        )
  qed
  then have πO_NTMap_app_Dom: 
    "𝔉ArrMapf A(πONTMapa Aq) =
      (πANTMapf Ag') Aq" 
    if "f : a 𝔍b" and "q : c PO" for q f a b c 
    using that g' 
    by (intro 𝔉.HomCod.cat_assoc_helper)
      (
        cs_concl 
          cs_simp: 
            cat_cs_simps cat_discrete_cs_simps the_cat_discrete_components(1)
          cs_intro: cat_cs_intros
      )

  from assms(2)[OF f' g'] obtain E ε where ε: 
    "ε : E <CF.eq (PO,PA,g',f') : ↑↑C ↦↦Cα"
    by clarsimp

  interpret ε: is_cat_equalizer_2 α PO PA g' f'  E ε by (rule ε)

  define μ where "μ =
    [(λi𝔍Obj. πONTMapi AεNTMap𝔞PL2), cf_const 𝔍  E, 𝔉, 𝔍, ]"

  have μ_components:
    "μNTMap = (λi𝔍Obj. πONTMapi AεNTMap𝔞PL2)"
    "μNTDom = cf_const 𝔍  E"
    "μNTCod = 𝔉"
    "μNTDGDom = 𝔍"
    "μNTDGCod = "
    unfolding μ_def nt_field_simps by (simp_all add: nat_omega_simps)

  have [cat_cs_simps]: 
    "μNTMapi = πONTMapi AεNTMap𝔞PL2" if "i  𝔍Obj" 
    for i
    using that unfolding μ_components by simp

  have "μ : E <CF.lim 𝔉 : 𝔍 ↦↦Cα"
  proof(intro is_cat_limitI)

    show μ: "μ : E <CF.cone 𝔉 : 𝔍 ↦↦Cα" 
    proof(intro is_cat_coneI is_tm_ntcfI' is_ntcfI')
      show "vfsequence μ" unfolding μ_def by simp 
      show "vcard μ = 5" unfolding μ_def by (simp add: nat_omega_simps)
      show "cf_const 𝔍  E : 𝔍 ↦↦Cα"
        by (cs_concl cs_intro: cat_cs_intros cat_lim_cs_intros)
      show "𝔉 : 𝔍 ↦↦Cα" by (cs_concl cs_shallow cs_intro: cat_cs_intros)
      show "μNTMapa : cf_const 𝔍  EObjMapa 𝔉ObjMapa"
        if "a  𝔍Obj" for a
        using that
        by 
          (
            cs_concl 
              cs_simp: 
                cat_cs_simps 
                cat_discrete_cs_simps 
                cat_parallel_cs_simps 
                the_cat_discrete_components(1) 
              cs_intro: cat_cs_intros cat_lim_cs_intros cat_parallel_cs_intros
          )
      show 
        "μNTMapb Acf_const 𝔍  EArrMapf =
          𝔉ArrMapf AμNTMapa"
        if "f : a 𝔍b" for a b f
        using that ε g' f' 
        by 
          (
            cs_concl 
              cs_simp:
                cat_parallel_cs_simps
                cat_cs_simps 
                the_cat_discrete_components(1) 
                πO_NTMap_app_Cod 
                πO_NTMap_app_Dom 
                ε.cat_eq_2_Comp_eq(1) 
              cs_intro: cat_lim_cs_intros cat_cs_intros cat_parallel_cs_intros
          )

    qed (auto simp: μ_components cat_cs_intros)

    interpret μ: is_cat_cone α E 𝔍  𝔉 μ by (rule μ)

    show "∃!f'. f' : r' E  u' = μ NTCF ntcf_const 𝔍  f'"
      if "u' : r' <CF.cone 𝔉 : 𝔍 ↦↦Cα" for u' r'
    proof-

      interpret u': is_cat_cone α r' 𝔍  𝔉 u' by (rule that)

      let ?u' = λj. u'NTMapj 
      let ?π' = ntcf_obj_prod_base  (𝔍Obj) ?R r' ?u'

      have π'_NTMap_app: "?π'NTMapj = u'NTMapj" if "j  𝔍Obj" for j
        using that 
        unfolding ntcf_obj_prod_base_components the_cat_discrete_components 
        by auto

      have π': "?π' : r' <CF.cone :→: (𝔍Obj) ?R  : :C (𝔍Obj) ↦↦Cα"
        unfolding the_cat_discrete_components(1)
      proof(intro tm_cf_discrete.tm_cf_discrete_ntcf_obj_prod_base_is_cat_cone)
        show "tm_cf_discrete α (𝔍Obj) ?R "
        proof(intro tm_cf_discreteI)
          show "𝔉ObjMapi  Obj" if "i  𝔍Obj" for i
            by (cs_concl cs_simp: cat_cs_simps cs_intro: that cat_cs_intros)
          show "category α " by (auto intro: cat_cs_intros)
          from 𝔉.tm_cf_ObjMap_in_Vset show "(λx𝔍Obj. 𝔉ObjMapx)  Vset α"
            by (auto simp: 𝔉.cf_ObjMap_vdomain)
          show "(λi𝔍Obj. CId𝔉ObjMapi)  Vset α"
          proof(rule vbrelation.vbrelation_Limit_in_VsetI)
            have " (λi𝔍Obj. CId𝔉ObjMapi)   (𝔉ArrMap)"
            proof(intro vsubsetI)
              fix x assume "x   (λi𝔍Obj. CId𝔉ObjMapi)"
              then obtain i where i: "i  𝔍Obj" 
                and x_def: "x = CId𝔉ObjMapi"
                by auto
              from i have "x = 𝔉ArrMap𝔍CIdi"
                by (simp add: x_def 𝔉.cf_ObjMap_CId)
              moreover from i have "𝔍CIdi  𝒟 (𝔉ArrMap)"
                by 
                  (
                    cs_concl cs_shallow 
                      cs_simp: cat_cs_simps cs_intro: cat_cs_intros
                  )
              ultimately show "x   (𝔉ArrMap)"
                by (auto intro: 𝔉.ArrMap.vsv_vimageI2)
            qed
            then show " (λi𝔍Obj. CId𝔉ObjMapi)  Vset α"  
              by
                (
                  auto simp: 
                    𝔉.tm_cf_ArrMap_in_Vset vrange_in_VsetI vsubset_in_VsetI
                )
          qed (auto intro: 𝔉.HomDom.tiny_cat_Obj_in_Vset)
        qed
        show "u'NTMapj : r' 𝔉ObjMapj" if "j  𝔍Obj" for j
          using that 
          by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      qed (auto simp: cat_cs_intros)

      from πO.cat_obj_prod_unique_cone'[OF this] obtain h' 
        where h': "h' : r' PO"
          and π'_NTMap_app': 
            "j. j  (𝔍Obj)  ?π'NTMapj = πONTMapj Ah'"
          and unique_h': "h''.
             
              h'' : r' PO;
              j. j  (𝔍Obj)  ?π'NTMapj = πONTMapj Ah'' 
              h'' = h'"
        by metis

      interpret π':
        is_cat_cone α r' :C (𝔍Obj)  :→: (𝔍Obj) (app (𝔉ObjMap))  ?π'
        by (rule π')

      let ?u'' = λu. u'NTMap𝔍Codu 
      let ?π'' = ntcf_obj_prod_base  (𝔍Arr) ?L r' ?u''

      have π''_NTMap_app: "?π''NTMapf = u'NTMapb"
        if "f : a 𝔍b" for f a b 
        using that 
        unfolding ntcf_obj_prod_base_components the_cat_discrete_components 
        by 
          (
            cs_concl cs_shallow
              cs_simp: V_cs_simps cat_cs_simps cs_intro: cat_cs_intros
          )
      
      have π'': "?π'' : r' <CF.cone :→: (𝔍Arr) ?L  : :C (𝔍Arr) ↦↦Cα"
        unfolding the_cat_discrete_components(1)
      proof
        (
          intro 
            tm_cf_discrete.tm_cf_discrete_ntcf_obj_prod_base_is_cat_cone 
            tm_cf_discrete
        )
        fix f assume "f  𝔍Arr"
        then obtain a b where "f : a 𝔍b" by auto
        then show "u'NTMap𝔍Codf : r' 𝔉ObjMap𝔍Codf"
          by 
            (
              cs_concl cs_shallow
                cs_simp: cat_cs_simps cs_intro: cat_cs_intros
            )
      qed (simp add: cat_cs_intros)

      from πA.cat_obj_prod_unique_cone'[OF this] obtain h'' 
        where h'': "h'' : r' PA"
          and π''_NTMap_app': 
            "j. j  𝔍Arr  ?π''NTMapj = πANTMapj Ah''"
          and unique_h'': "h'''.
             
              h''' : r' PA;
              j. j  𝔍Arr  ?π''NTMapj = πANTMapj Ah''' 
              h''' = h''"
        by metis

      interpret π'': is_cat_cone α r' :C (𝔍Arr)  :→: (𝔍Arr) ?L  ?π''
        by (rule π'')

      have g'h'_f'h': "g' Ah' = f' Ah'"  
      proof-

        from g' h' have g'h': "g' Ah' : r' PA"
          by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
        from f' h' have f'h': "f' Ah' : r' PA"
          by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)

        have "?π''NTMapf = πANTMapf A(g' Ah')"
          if "f  𝔍Arr" for f
        proof-
          from that obtain a b where f: "f : a 𝔍b" by auto
          then have "?π''NTMapf = u'NTMapb"
            by (cs_concl cs_simp: π''_NTMap_app cat_cs_simps)
          also from f have " = 𝔉ArrMapf A?π'NTMapa"
            by 
              (
                cs_concl  
                  cs_simp: π'_NTMap_app cat_cs_simps cat_lim_cs_simps 
                  cs_intro: cat_cs_intros
              )
          also from f g' h' have " = πANTMapf A(g' Ah')" 
            by 
              (
                cs_concl 
                  cs_simp: 
                    cat_cs_simps 
                    cat_discrete_cs_simps
                    the_cat_discrete_components(1) 
                    π'_NTMap_app'
                    πO_NTMap_app_Dom 
                  cs_intro: cat_cs_intros
              )
          finally show ?thesis by simp
        qed
          
        from unique_h''[OF g'h' this, simplified] have g'h'_h'': 
          "g' Ah' = h''".
        have "?π''NTMapf = πANTMapf A(f' Ah')"
          if "f  𝔍Arr" for f
        proof-
          from that obtain a b where f: "f : a 𝔍b" by auto
          then have "?π''NTMapf = u'NTMapb"
            by (cs_concl cs_simp: π''_NTMap_app cat_cs_simps)
          also from f have " = ?π'NTMapb"
            by 
              (
                cs_concl cs_shallow 
                  cs_simp: π'_NTMap_app cs_intro: cat_cs_intros
              )
          also from f have " = πONTMapb Ah'"
            by 
              (
                cs_concl cs_shallow 
                  cs_simp: π'_NTMap_app' cs_intro: cat_cs_intros
              )
          also from f g' h' have " = (πANTMapf Af') Ah'"
            by 
              (
                cs_concl cs_shallow 
                  cs_simp: πO_NTMap_app_Cod cs_intro: cat_cs_intros
              )
          also from that f' h' have " = πANTMapf A(f' Ah')"
            by 
              (
                cs_concl cs_shallow
                  cs_simp: cat_cs_simps the_cat_discrete_components(1) 
                  cs_intro: cat_cs_intros
               )
          finally show ?thesis by simp
        qed
        from unique_h''[OF f'h' this, simplified] have f'h'_h'': 
          "f' Ah' = h''".
        from g'h'_h'' f'h'_h'' show ?thesis by simp
      qed

      let ?II = ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 
        and ?II_II = ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL PO PA g' f'

    define ε' where "ε' =
      [
        (λf?IIObj. (f = 𝔞PL2 ? h' : (f' Ah'))),
        cf_const ?II  r',
        ?II_II,
        ?II,
        
      ]"

    have ε'_components: 
      "ε'NTMap = (λf?IIObj. (f = 𝔞PL2 ? h' : (f' Ah')))"
      "ε'NTDom = cf_const ?II  r'"
      "ε'NTCod = ?II_II"
      "ε'NTDGDom = ?II"
      "ε'NTDGCod = "
      unfolding ε'_def nt_field_simps by (simp_all add: nat_omega_simps)

    have ε'_NTMap_app_I2: "ε'NTMapx = h'" if "x = 𝔞PL2" for x 
    proof-
      have "x  ?IIObj"
        unfolding that by (cs_concl cs_intro: cat_parallel_cs_intros)
      then show ?thesis unfolding ε'_components that by simp
    qed

    have ε'_NTMap_app_sI2: "ε'NTMapx = f' Ah'" if "x = 𝔟PL2" for x 
    proof-
      have "x  ?IIObj"
        unfolding that by (cs_concl cs_shallow cs_intro: cat_parallel_cs_intros)
      with ε.cat_parallel_𝔞𝔟 show ?thesis
        unfolding ε'_components by (cs_concl cs_simp: V_cs_simps that)
    qed

    interpret par: cf_parallel_2 α 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL PO PA g' f' 
      by (intro cf_parallel_2I cat_parallel_2I)
        (simp_all add: cat_cs_intros cat_parallel_cs_intros)

    have "ε' : r' <CF.cone ?II_II : ?II ↦↦Cα"
    proof(intro is_cat_coneI is_tm_ntcfI' is_ntcfI')
      show "vfsequence ε'" unfolding ε'_def by auto
      show "vcard ε' = 5" unfolding ε'_def by (simp add: nat_omega_simps)
      from h' show "cf_const (?II)  r' : ?II ↦↦Cα"
        by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      show "?II_II : ?II ↦↦Cα"
        by 
          (
            cs_concl cs_shallow 
              cs_simp: cat_parallel_cs_simps cs_intro: cat_cs_intros
          )
      from h' show "ε'NTMapa : 
        cf_const ?II  r'ObjMapa ?II_IIObjMapa"
        if "a  ?IIObj" for a 
        using that
        by (elim the_cat_parallel_2_ObjE; simp only:)
          (
            cs_concl 
              cs_simp: 
                ε'_NTMap_app_I2 ε'_NTMap_app_sI2 
                cat_cs_simps cat_parallel_cs_simps 
              cs_intro: cat_cs_intros cat_parallel_cs_intros
          )
      from h' f' g'h'_f'h' show 
        "ε'NTMapb Acf_const ?II  r'ArrMapf =
          ?II_IIArrMapf Aε'NTMapa"
          if "f : a ?IIb" for a b f
          using that
          by (elim ε.the_cat_parallel_2_is_arrE; simp only:)
            (
              cs_concl 
                cs_intro: cat_cs_intros cat_parallel_cs_intros 
                cs_simp:
                  cat_cs_simps
                  cat_parallel_cs_simps
                  ε'_NTMap_app_I2 
                  ε'_NTMap_app_sI2
            )+
      qed 
        (
          simp add: ε'_components | 
          cs_concl 
            cs_simp: cat_cs_simps 
            cs_intro: cat_lim_cs_intros cat_cs_intros cat_small_cs_intros 
        )+
    from ε.cat_eq_2_unique_cone[OF this] obtain t'
      where t': "t' : r' E"
        and ε'_NTMap_app: "ε'NTMap𝔞PL2 = εNTMap𝔞PL2 At'"
        and unique_t':
          " t'' : r' E; ε'NTMap𝔞PL2 = εNTMap𝔞PL2 At''  
            t'' = t'" 
        for t''
      by metis

    show "∃!f'. f' : r' E  u' = μ NTCF ntcf_const 𝔍  f'"
    proof(intro ex1I conjI; (elim conjE)?, (rule t')?)
      show [symmetric, cat_cs_simps]: "u' = μ NTCF ntcf_const 𝔍  t'"
      proof(rule ntcf_eqI[OF u'.is_ntcf_axioms])
        from t' show 
          "μ NTCF ntcf_const 𝔍  t' : cf_const 𝔍  r' CF 𝔉 : 𝔍 ↦↦Cα"
          by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
        show "u'NTMap = (μ NTCF ntcf_const 𝔍  t')NTMap"
        proof(rule vsv_eqI)
          show "vsv ((μ NTCF ntcf_const 𝔍  t')NTMap)"
            by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
          from t' show 
            "𝒟 (u'NTMap) = 𝒟 ((μ NTCF ntcf_const 𝔍  t')NTMap)"
            by 
              (
                cs_concl cs_shallow 
                  cs_simp: cat_cs_simps cs_intro: cat_cs_intros
              )
          show "u'NTMapa = (μ NTCF ntcf_const 𝔍  t')NTMapa"
            if "a  𝒟 (u'NTMap)" for a
          proof-
            from that have "a  𝔍Obj" 
              by (cs_prems cs_shallow cs_simp: cat_cs_simps)
            with t' show "u'NTMapa = (μ NTCF ntcf_const 𝔍  t')NTMapa"
              by 
                (
                  cs_concl 
                    cs_simp:
                      cat_cs_simps 
                      π'_NTMap_app
                      cat_parallel_cs_simps
                      the_cat_discrete_components(1)
                      ε'_NTMap_app[symmetric]
                      ε'_NTMap_app_I2
                      π'_NTMap_app'[symmetric]
                    cs_intro: cat_cs_intros cat_parallel_cs_intros
                )
          qed
        qed auto
      qed simp_all

      fix t'' assume prems': "t'' : r' E" "u' = μ NTCF ntcf_const 𝔍  t''"
      then have u'_NTMap_app_x:
        "u'NTMapx = (μ NTCF ntcf_const 𝔍  t'')NTMapx"
        for x 
        by simp
      have "?π'NTMapj = πONTMapj A(εNTMap𝔞PL2 At'')" 
        if "j  𝔍Obj" for j
        using u'_NTMap_app_x[of j] prems'(1) that
        by 
          (
            cs_prems 
              cs_simp:
                cat_cs_simps 
                cat_discrete_cs_simps 
                cat_parallel_cs_simps 
                the_cat_discrete_components(1) 
              cs_intro: cat_cs_intros cat_parallel_cs_intros
          ) 
          (simp add: π'_NTMap_app[OF that, symmetric])
      moreover from prems'(1) have "εNTMap𝔞PL2 At'' : r' PO"
        by 
          (
            cs_concl 
              cs_simp: cat_cs_simps cat_parallel_cs_simps 
              cs_intro: cat_cs_intros cat_parallel_cs_intros
          )
      ultimately have [cat_cs_simps]: "εNTMap𝔞PL2 At'' = h'" 
        by (intro unique_h') simp
      show "t'' = t'"
        by (rule unique_t', intro prems'(1)) 
          (cs_concl cs_shallow cs_simp: ε'_NTMap_app_I2 cat_cs_simps)
      qed
    qed
 
  qed
  
  then show ?thesis using that by clarsimp

qed

lemma cat_colimit_of_cat_prod_obj_and_cat_coequalizer:
  ―‹See Theorem 1 in Chapter V-2 in \cite{mac_lane_categories_2010}.›
  assumes "𝔉 : 𝔍 ↦↦C.tmα"
    and "𝔞 𝔟 𝔤 𝔣.  𝔣 : 𝔟 𝔞; 𝔤 : 𝔟 𝔞  
      E ε. ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
    and "A. tm_cf_discrete α (𝔍Obj) A  
      P π. π : A >CF. P : 𝔍Obj ↦↦Cα"
    and "A. tm_cf_discrete α (𝔍Arr) A  
      P π. π : A >CF. P : 𝔍Arr ↦↦Cα"
  obtains r u where "u : 𝔉 >CF.colim r : 𝔍 ↦↦Cα"
proof-
  interpret 𝔉: is_tm_functor α 𝔍  𝔉 by (rule assms(1))
  have "E ε. ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cαop_cat "
    if "𝔣 : 𝔟 𝔞" "𝔤 : 𝔟 𝔞" for 𝔞 𝔟 𝔤 𝔣
  proof-
    from assms(2)[OF that(1,2)] obtain E ε 
      where ε: "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
      by clarsimp
    interpret ε: is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε by (rule ε)
    from ε.is_cat_equalizer_2_op[unfolded cat_op_simps] show ?thesis by auto
  qed
  moreover have "P π. π : P <CF. A : 𝔍Obj ↦↦Cαop_cat "
    if "tm_cf_discrete α (𝔍Obj) A (op_cat )" for A
  proof-
    interpret tm_cf_discrete α 𝔍Obj A op_cat  by (rule that)
    from assms(3)[OF tm_cf_discrete_op[unfolded cat_op_simps]] obtain P π 
      where π: "π : A >CF. P : 𝔍Obj ↦↦Cα"
      by clarsimp 
    interpret π: is_cat_obj_coprod α 𝔍Obj A  P π by (rule π)
    from π.is_cat_obj_prod_op show ?thesis by auto
  qed
  moreover have "P π. π : P <CF. A : 𝔍Arr ↦↦Cαop_cat "
    if "tm_cf_discrete α (𝔍Arr) A (op_cat )" for A 
  proof-
    interpret tm_cf_discrete α 𝔍Arr A op_cat  by (rule that)
    from assms(4)[OF tm_cf_discrete_op[unfolded cat_op_simps]] obtain P π 
      where π: "π : A >CF. P : 𝔍Arr ↦↦Cα"
      by clarsimp 
    interpret π: is_cat_obj_coprod α 𝔍Arr A  P π by (rule π)
    from π.is_cat_obj_prod_op show ?thesis by auto
  qed
  ultimately obtain u r where u: 
    "u : r <CF.lim op_cf 𝔉 : op_cat 𝔍 ↦↦Cαop_cat "
    by 
      (
        rule cat_limit_of_cat_prod_obj_and_cat_equalizer[
          OF 𝔉.is_tm_functor_op, unfolded cat_op_simps
          ]
      )
  interpret u: is_cat_limit α op_cat 𝔍 op_cat  op_cf 𝔉 r u by (rule u)
  from u.is_cat_colimit_op[unfolded cat_op_simps] that show ?thesis by simp
qed



subsection‹Small-complete and small-cocomplete category›


subsubsection‹Definition and elementary properties›

locale cat_small_complete = category α  for α  + 
  assumes cat_small_complete: 
    "𝔉 𝔍. 𝔉 : 𝔍 ↦↦C.tmα  u r. u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα"

locale cat_small_cocomplete = category α  for α  + 
  assumes cat_small_cocomplete: 
    "𝔉 𝔍. 𝔉 : 𝔍 ↦↦C.tmα  u r. u : 𝔉 >CF.colim r : 𝔍 ↦↦Cα"


text‹Rules.›

mk_ide rf cat_small_complete_def[unfolded cat_small_complete_axioms_def]
  |intro cat_small_completeI|
  |dest cat_small_completeD[dest]|
  |elim cat_small_completeE[elim]|

lemma cat_small_completeE'[elim]:
  assumes "cat_small_complete α " and "𝔉 : 𝔍 ↦↦C.tmα"
  obtains u r where "u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα"
  using assms by auto

mk_ide rf cat_small_cocomplete_def[unfolded cat_small_cocomplete_axioms_def]
  |intro cat_small_cocompleteI|
  |dest cat_small_cocompleteD[dest]|
  |elim cat_small_cocompleteE[elim]|

lemma cat_small_cocompleteE'[elim]:
  assumes "cat_small_cocomplete α " and "𝔉 : 𝔍 ↦↦C.tmα"
  obtains u r where "u : 𝔉 >CF.colim r : 𝔍 ↦↦Cα"
  using assms by auto


subsubsection‹Duality›

lemma (in cat_small_complete) cat_small_cocomplete_op[cat_op_intros]:
  "cat_small_cocomplete α (op_cat )"
proof(intro cat_small_cocompleteI)
  fix 𝔉 𝔍 assume "𝔉 : 𝔍 ↦↦C.tmαop_cat "
  then interpret 𝔉: is_tm_functor α 𝔍 op_cat  𝔉 .
  from cat_small_complete[OF 𝔉.is_tm_functor_op[unfolded cat_op_simps]]
  obtain u r where u: "u : r <CF.lim op_cf 𝔉 : op_cat 𝔍 ↦↦Cα"
    by auto
  then interpret u: is_cat_limit α op_cat 𝔍  op_cf 𝔉 r u .
  from u.is_cat_colimit_op[unfolded cat_op_simps] show 
    "u r. u : 𝔉 >CF.colim r : 𝔍 ↦↦Cαop_cat "
    by auto
qed (auto intro: cat_cs_intros)

lemmas [cat_op_intros] = cat_small_complete.cat_small_cocomplete_op

lemma (in cat_small_cocomplete) cat_small_complete_op[cat_op_intros]:
  "cat_small_complete α (op_cat )"
proof(intro cat_small_completeI)
  fix 𝔉 𝔍 assume prems: "𝔉 : 𝔍 ↦↦C.tmαop_cat "
  then interpret 𝔉: is_tm_functor α 𝔍 op_cat  𝔉 .
  from cat_small_cocomplete[OF 𝔉.is_tm_functor_op[unfolded cat_op_simps]]
  obtain u r where u: "u : op_cf 𝔉 >CF.colim r : op_cat 𝔍 ↦↦Cα"
    by auto
  interpret u: is_cat_colimit α op_cat 𝔍  op_cf 𝔉 r u by (rule u)
  from u.is_cat_limit_op[unfolded cat_op_simps] show 
    "u r. u : r <CF.lim 𝔉 : 𝔍 ↦↦Cαop_cat "
    by auto
qed (auto intro: cat_cs_intros)

lemmas [cat_op_intros] = cat_small_cocomplete.cat_small_complete_op


subsubsection‹A category with equalizers and small products is small-complete›

lemma (in category) cat_small_complete_if_eq_and_obj_prod:
  ―‹See Corollary 2 in Chapter V-2 in \cite{mac_lane_categories_2010}›
  assumes "𝔞 𝔟 𝔤 𝔣.  𝔣 : 𝔞 𝔟; 𝔤 : 𝔞 𝔟  
      E ε. ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
    and "A I. tm_cf_discrete α I A   P π. π : P <CF. A : I ↦↦Cα"
  shows "cat_small_complete α "
proof(intro cat_small_completeI)
  fix 𝔉 𝔍 assume prems: "𝔉 : 𝔍 ↦↦C.tmα"
  then interpret 𝔉: is_tm_functor α 𝔍  𝔉 .
  show "u r. u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα"
    by (rule cat_limit_of_cat_prod_obj_and_cat_equalizer[OF prems assms(1)])
      (auto intro: assms(2))
qed (auto simp: cat_cs_intros)

lemma (in category) cat_small_cocomplete_if_eq_and_obj_prod:
  assumes "𝔞 𝔟 𝔤 𝔣.  𝔣 : 𝔟 𝔞; 𝔤 : 𝔟 𝔞  
    E ε. ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
    and "A I. tm_cf_discrete α I A   P π. π : A >CF. P : I ↦↦Cα"
  shows "cat_small_cocomplete α "
proof-
  have "E ε. ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cαop_cat "
    if "𝔣 : 𝔟 𝔞" and "𝔤 : 𝔟 𝔞" for 𝔞 𝔟 𝔤 𝔣
  proof-
    from assms(1)[OF that] obtain ε E where 
      ε: "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
      by clarsimp
    interpret ε: is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε by (rule ε)
    from ε.is_cat_equalizer_2_op show ?thesis by auto
  qed
  moreover have "P π. π : P <CF. A : I ↦↦Cαop_cat "
    if "tm_cf_discrete α I A (op_cat )" for A I
  proof-
    interpret tm_cf_discrete α I A op_cat  by (rule that)
    from assms(2)[OF tm_cf_discrete_op[unfolded cat_op_simps]] obtain P π 
      where π: "π : A >CF. P : I ↦↦Cα"
      by auto
    interpret π: is_cat_obj_coprod α I A  P π by (rule π)
    from π.is_cat_obj_prod_op show ?thesis by auto
  qed
  ultimately interpret cat_small_complete α op_cat 
    by 
      (
        rule category.cat_small_complete_if_eq_and_obj_prod[
          OF category_op, unfolded cat_op_simps
          ]
      )
  show ?thesis by (rule cat_small_cocomplete_op[unfolded cat_op_simps])
qed


subsubsection‹
Existence of the initial and terminal objects in 
small-complete and small-cocomplete categories
›

lemma (in cat_small_complete) cat_sc_ex_obj_initial:
  ―‹See Theorem 1 in Chapter V-6 in \cite{mac_lane_categories_2010}.›
  assumes "A  Obj"
    and "A  Vset α"
    and "c. c  Obj  f a. a  A  f : a c"
  obtains z where "obj_initial  z"
proof-
  
  interpret tcd: tm_cf_discrete α A id 
  proof(intro tm_cf_discreteI)
    show "(λiA. CIdid i)  Vset α"
      unfolding id_def
    proof(rule vbrelation.vbrelation_Limit_in_VsetI)
      from assms(1) have "A  𝒟 (CId)" by (simp add: cat_CId_vdomain)
      then have " (VLambda A (app (CId))) = CId ` A" by auto
      moreover have "(aA. bA. Hom  a b)  Vset α"
        by (rule cat_Hom_vifunion_in_Vset[OF assms(1,1,2,2)])
      moreover have "CId ` A  (aA. bA. Hom  a b)"
      proof(intro vsubsetI)
        fix f assume "f  CId ` A"
        then obtain a where a: "a  A" and f_def: "f = CIda" by auto
        from assms(1) a show "f  (aA. bA. Hom  a b)"
          unfolding f_def by (intro vifunionI) (auto simp: cat_CId_is_arr)
      qed
      ultimately show " (VLambda A (app (CId)))  Vset α" by auto
    qed (simp_all add: assms(2))
  qed 
    (
      use assms in 
        auto simp: assms(2) Limit_vid_on_in_Vset intro: cat_cs_intros
    )

  have tcd: ":→: A id  : :C A ↦↦C.tmα"
    by 
      (
        cs_concl cs_shallow cs_intro: 
          cat_small_cs_intros 
          cat_cs_intros 
          cat_small_discrete_cs_intros
          cat_discrete_cs_intros
      )
  from cat_small_complete[OF this] obtain π w 
    where "π : w <CF.lim :→: A id  : :C A ↦↦Cα"
    by auto
  then interpret π: is_cat_obj_prod α A id  w π
    by (intro is_cat_obj_prodI tcd.cf_discrete_axioms)

  let ?ww = Hom  w w

  have CId_w: "CIdw  ?ww"
    by (cs_concl cs_intro: cat_cs_intros cat_lim_cs_intros)
  then have ww_neq_vempty: "?ww  0" by force

  have wd: "h. h : w d" if "d  Obj" for d
  proof-
    from assms(3)[OF that] obtain g a where a: "a  A" and g: "g : a d"
      by clarsimp
    from π.ntcf_NTMap_is_arr[unfolded the_cat_discrete_components, OF a] a g 
    have "πNTMapa : w a"
      by
        (
          cs_prems cs_shallow cs_simp:
            id_apply the_cat_discrete_components(1) 
            cat_discrete_cs_simps cat_cs_simps
        )
    with g have "g AπNTMapa : w d"
      by (cs_concl cs_shallow cs_intro: cat_cs_intros)
    then show ?thesis by (intro exI)
  qed

  have "cf_parallel α (𝔞PL ?ww) (𝔟PL ?ww) ?ww w w (vid_on ?ww) "
    by (intro cat_cf_parallel_𝔞𝔟 π.cat_cone_obj cat_Hom_in_Vset) simp_all
  then have "⇑→⇑CF  (𝔞PL ?ww) (𝔟PL ?ww) ?ww w w (vid_on ?ww) :
    C (𝔞PL ?ww) (𝔟PL ?ww) ?ww ↦↦C.tmα"
    by (intro cf_parallel.cf_parallel_the_cf_parallel_is_tm_functor)
  from cat_small_complete[OF this] obtain ε v where ε: "ε :
    v <CF.lim ⇑→⇑CF  (𝔞PL ?ww) (𝔟PL ?ww) ?ww w w (vid_on ?ww) :
    C (𝔞PL ?ww) (𝔟PL ?ww) ?ww ↦↦Cα"
    by clarsimp
  from is_cat_equalizerI[
      OF
        this
        _ 
        cat_Hom_in_Vset[OF π.cat_cone_obj π.cat_cone_obj]
        ww_neq_vempty
      ]
  interpret ε: is_cat_equalizer α w w ?ww vid_on ?ww  v ε by auto
  note ε_is_monic_arr = 
    is_cat_equalizer.cat_eq_is_monic_arr[OF ε.is_cat_equalizer_axioms]
  note ε_is_monic_arrD = is_monic_arrD[OF ε_is_monic_arr]

  show ?thesis
  proof(rule, intro obj_initialI)

    show "v  Obj" by (rule ε.cat_cone_obj)
    then have CId_v: "CIdv : v v" 
      by (cs_concl cs_shallow cs_intro: cat_cs_intros)

    fix d assume prems: "d  Obj"
    from wd[OF prems] obtain h where h: "h : w d" by auto

    show "∃!f. f : v d"
    proof(rule ex1I)
      define f where "f = h AεNTMap𝔞PL ?ww"
      from ε_is_monic_arrD(1) h show f: "f : v d"
        unfolding f_def by (cs_concl cs_shallow cs_intro: cat_cs_intros)
      fix g assume prems': "g : v d"
      have "cf_parallel_2 α 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL v d g f "
        by (intro cat_cf_parallel_2_cat_equalizer prems' f)
      then have "↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL v d g f :
        ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦C.tmα"
        by (intro cf_parallel_2.cf_parallel_2_the_cf_parallel_2_is_tm_functor)
      from cat_small_complete[OF this] obtain ε' u 
        where "ε' :
          u <CF.lim ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL v d g f :
          ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα"
        by clarsimp
      from is_cat_equalizer_2I[OF this prems' f] interpret ε': 
        is_cat_equalizer_2 α v d g f  u ε'.
      note ε'_is_monic_arr = is_cat_equalizer_2.cat_eq_2_is_monic_arr[
        OF ε'.is_cat_equalizer_2_axioms
        ]
      note ε'_is_monic_arrD = is_monic_arrD[OF ε'_is_monic_arr]
      then have "u  Obj" by auto
      from wd[OF this] obtain s where s: "s : w u" by clarsimp
      from s ε'_is_monic_arrD(1) ε_is_monic_arrD(1) have εε's:
        "εNTMap𝔞PL ?ww Aε'NTMap𝔞PL2 As : w w"
        by (cs_concl cs_shallow cs_intro: cat_cs_intros)
      from s ε'_is_monic_arrD(1) ε_is_monic_arrD(1) have ε'sε:
        "ε'NTMap𝔞PL2 As AεNTMap𝔞PL ?ww : v v"
        by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      from ε_is_monic_arrD(1) ε'_is_monic_arrD(1) s have 
        "εNTMap𝔞PL ?ww A(ε'NTMap𝔞PL2 As AεNTMap𝔞PL ?ww) =
          εNTMap𝔞PL ?ww Aε'NTMap𝔞PL2 As AεNTMap𝔞PL ?ww"
        by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      also from
        ε.cat_eq_Comp_eq
          [
            unfolded in_Hom_iff, OF cat_CId_is_arr[OF π.cat_cone_obj] εε's,
            symmetric
          ]
        εε's π.cat_cone_obj ε_is_monic_arr(1)
      have " = CIdw AεNTMap𝔞PL ?ww"
        by (cs_prems cs_shallow cs_simp: vid_on_atI cs_intro:  cat_cs_intros)
      also from ε.cf_parallel_𝔞' ε_is_monic_arrD(1) have 
        " = εNTMap𝔞PL ?ww ACIdv"
        by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro:  cat_cs_intros)
      finally have
        "εNTMap𝔞PL ?ww A(ε'NTMap𝔞PL2 As AεNTMap𝔞PL ?ww) =
          εNTMap𝔞PL ?ww ACIdv".      
      from 
        is_monic_arrD(2)[OF ε_is_monic_arr ε'sε CId_v this] 
        ε'_is_monic_arrD(1) s ε_is_monic_arrD(1) 
      have ε'sε_is_CId: 
        "ε'NTMap𝔞PL2 A(s AεNTMap𝔞PL ?ww) = CIdv"
        by (cs_prems cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      have ε'_is_iso_arr: "ε'NTMap𝔞PL2 : u isov"
        by 
        (
          intro 
            cat_is_iso_arr_if_is_monic_arr_is_right_inverse 
            ε'_is_monic_arr,
          rule is_right_inverseI[OF _ ε'_is_monic_arrD(1) ε'sε_is_CId]
        )
        (
          use s ε_is_monic_arrD(1) in 
            cs_concl cs_shallow cs_intro: cat_cs_intros
        )
      from ε'.cat_eq_2_Comp_eq(1) have 
        "g Aε'NTMap𝔞PL2 A(ε'NTMap𝔞PL2)¯C=
          f Aε'NTMap𝔞PL2 A(ε'NTMap𝔞PL2)¯C⇙"
        by simp      
      from this f ε'_is_monic_arrD(1) ε'_is_iso_arr prems' show "g = f"
        by
          (
            cs_prems cs_shallow
              cs_simp: cat_cs_simps cs_intro: cat_cs_intros cat_arrow_cs_intros
          )
    qed

  qed

qed

lemma (in cat_small_cocomplete) cat_sc_ex_obj_terminal:
  ―‹See Theorem 1 in Chapter V-6 in \cite{mac_lane_categories_2010}.›
  assumes "A  Obj"
    and "A  Vset α"
    and "c. c  Obj  f a. a  A  f : c a"
  obtains z where "obj_terminal  z"
  using that 
  by 
    (
      rule cat_small_complete.cat_sc_ex_obj_initial[
        OF cat_small_complete_op, unfolded cat_op_simps, OF assms, simplified
        ]
    )


subsubsection‹Creation of limits, continuity and completeness›

lemma
  ―‹See Theorem 2 in Chapter V-4 in \cite{mac_lane_categories_2010}.›
  assumes "𝔊 : 𝔄 ↦↦Cα𝔅"
    and "cat_small_complete α 𝔅"
    and "𝔉 𝔍. 𝔉 : 𝔍 ↦↦C.tmα𝔄  𝔊 CF 𝔉 : 𝔍 ↦↦C.tmα𝔅"
    and "𝔉 𝔍. 𝔉 : 𝔍 ↦↦C.tmα𝔄  cf_creates_limits α 𝔊 𝔉"
  shows is_tm_cf_continuous_if_cf_creates_limits: "is_tm_cf_continuous α 𝔊"
    and cat_small_complete_if_cf_creates_limits: "cat_small_complete α 𝔄"
proof-

  interpret 𝔊: is_functor α 𝔄 𝔅 𝔊 by (rule assms(1))
  interpret 𝔅: cat_small_complete α 𝔅 by (rule assms(2))

  show "is_tm_cf_continuous α 𝔊"
  proof(intro is_tm_cf_continuousI, rule assms)
    fix 𝔉 𝔍 assume prems: "𝔉 : 𝔍 ↦↦C.tmα𝔄"
    then interpret 𝔉: is_tm_functor α 𝔍 𝔄 𝔉 .
    from cat_small_completeD(2)[OF assms(2) assms(3)[OF prems]] obtain ψ r
      where ψ: "ψ : r <CF.lim 𝔊 CF 𝔉 : 𝔍 ↦↦Cα𝔅"
      by clarsimp
    show "cf_preserves_limits α 𝔊 𝔉"
      by 
        (
          rule cf_preserves_limits_if_cf_creates_limits, 
          rule assms(1),
          rule 𝔉.is_functor_axioms,
          rule ψ,
          rule assms(4)[OF prems]
        )
  qed

  show "cat_small_complete α 𝔄"
  proof(intro cat_small_completeI 𝔊.HomDom.category_axioms)
    fix 𝔉 𝔍 assume prems: "𝔉 : 𝔍 ↦↦C.tmα𝔄"
    then interpret 𝔉: is_tm_functor α 𝔍 𝔄 𝔉 .
    from cat_small_completeD(2)[OF assms(2) assms(3)[OF prems]] obtain ψ r
      where ψ: "ψ : r <CF.lim 𝔊 CF 𝔉 : 𝔍 ↦↦Cα𝔅"
      by clarsimp
    from cf_creates_limitsE''[
        OF assms(4)[OF prems] ψ 𝔉.is_functor_axioms assms(1)
        ]
    show "u r. u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα𝔄"
      by metis
  qed

qed



subsection‹Finite-complete and finite-cocomplete category›

locale cat_finite_complete = category α  for α  + 
  assumes cat_finite_complete: 
    "𝔉 𝔍.  finite_category α 𝔍; 𝔉 : 𝔍 ↦↦Cα   
      u r. u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα"

locale cat_finite_cocomplete = category α  for α  + 
  assumes cat_finite_cocomplete: 
    "𝔉 𝔍.  finite_category α 𝔍; 𝔉 : 𝔍 ↦↦Cα   
      u r. u : 𝔉 >CF.colim r : 𝔍 ↦↦Cα"


text‹Rules.›

mk_ide rf cat_finite_complete_def[unfolded cat_finite_complete_axioms_def]
  |intro cat_finite_completeI|
  |dest cat_finite_completeD[dest]|
  |elim cat_finite_completeE[elim]|

lemma cat_finite_completeE'[elim]:
  assumes "cat_finite_complete α " 
    and "finite_category α 𝔍" 
    and "𝔉 : 𝔍 ↦↦Cα"
  obtains u r where "u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα"
  using assms by auto

mk_ide rf cat_finite_cocomplete_def[unfolded cat_finite_cocomplete_axioms_def]
  |intro cat_finite_cocompleteI|
  |dest cat_finite_cocompleteD[dest]|
  |elim cat_finite_cocompleteE[elim]|

lemma cat_finite_cocompleteE'[elim]:
  assumes "cat_finite_cocomplete α " 
    and "finite_category α 𝔍" 
    and "𝔉 : 𝔍 ↦↦Cα"
  obtains u r where "u : 𝔉 >CF.colim r : 𝔍 ↦↦Cα"
  using assms by auto


text‹Elementary properties.›

sublocale cat_small_complete  cat_finite_complete
proof(intro cat_finite_completeI)
  fix 𝔉 𝔍 assume prems: "finite_category α 𝔍" "𝔉 : 𝔍 ↦↦Cα"
  interpret 𝔉: is_functor α 𝔍  𝔉 by (rule prems(2))
  from cat_small_complete_axioms show "u r. u : r <CF.lim 𝔉 : 𝔍 ↦↦Cα" 
    by (auto intro: 𝔉.cf_is_tm_functor_if_HomDom_finite_category[OF prems(1)])
qed (auto intro: cat_cs_intros)

sublocale cat_small_cocomplete  cat_finite_cocomplete
proof(intro cat_finite_cocompleteI)
  fix 𝔉 𝔍 assume prems: "finite_category α 𝔍" "𝔉 : 𝔍 ↦↦Cα"
  interpret 𝔉: is_functor α 𝔍  𝔉 by (rule prems(2))
  from cat_small_cocomplete_axioms show "u r. u : 𝔉 >CF.colim r : 𝔍 ↦↦Cα" 
    by (auto intro: 𝔉.cf_is_tm_functor_if_HomDom_finite_category[OF prems(1)])
qed (auto intro: cat_cs_intros)

text‹\newpage›

end