Theory CZH_UCAT_Universal

(* Copyright 2021 (C) Mihails Milehins *)

section‹Universal arrow›
theory CZH_UCAT_Universal
  imports 
    CZH_UCAT_Introduction
    CZH_Elementary_Categories.CZH_ECAT_FUNCT
    CZH_Elementary_Categories.CZH_ECAT_Hom
begin



subsection‹Background›


text‹
The following section is based, primarily, on the elements of the content 
of Chapter III-1 in cite"mac_lane_categories_2010".
›

named_theorems ua_field_simps

definition UObj :: V where [ua_field_simps]: "UObj = 0"
definition UArr :: V where [ua_field_simps]: "UArr = 1"

lemma [cat_cs_simps]:
  shows UObj_simp: "[a, b]UObj = a"
    and UArr_simp: "[a, b]UArr = b"
  unfolding ua_field_simps by (simp_all add: nat_omega_simps)



subsection‹Universal map›


text‹
The universal map is a convenience utility that allows treating 
a part of the definition of the universal arrow as an arrow in the
category Set›.
›


subsubsection‹Definition and elementary properties›

definition umap_of :: "V  V  V  V  V  V"
  where "umap_of 𝔉 c r u d =
    [
      (λf'Hom (𝔉HomDom) r d. 𝔉ArrMapf' A𝔉HomCodu),
      Hom (𝔉HomDom) r d,
      Hom (𝔉HomCod) c (𝔉ObjMapd)
    ]"

definition umap_fo :: "V  V  V  V  V  V"
  where "umap_fo 𝔉 c r u d = umap_of (op_cf 𝔉) c r u d"


text‹Components.›

lemma (in is_functor) umap_of_components:
  assumes "u : c 𝔅𝔉ObjMapr" (*do not remove*)
  shows "umap_of 𝔉 c r u dArrVal = (λf'Hom 𝔄 r d. 𝔉ArrMapf' A𝔅u)"
    and "umap_of 𝔉 c r u dArrDom = Hom 𝔄 r d"
    and "umap_of 𝔉 c r u dArrCod = Hom 𝔅 c (𝔉ObjMapd)"
  unfolding umap_of_def arr_field_simps
  by (simp_all add: cat_cs_simps nat_omega_simps)

lemma (in is_functor) umap_fo_components:
  assumes "u : 𝔉ObjMapr 𝔅c"
  shows "umap_fo 𝔉 c r u dArrVal = (λf'Hom 𝔄 d r. u A𝔅𝔉ArrMapf')"
    and "umap_fo 𝔉 c r u dArrDom = Hom 𝔄 d r"
    and "umap_fo 𝔉 c r u dArrCod = Hom 𝔅 (𝔉ObjMapd) c"
  unfolding 
    umap_fo_def 
    is_functor.umap_of_components[
      OF is_functor_op, unfolded cat_op_simps, OF assms
      ] 
proof(rule vsv_eqI)
  fix f' assume "f'  𝒟 (λf'Hom 𝔄 d r. 𝔉ArrMapf' Aop_cat 𝔅u)"
  then have f': "f' : d 𝔄r" by simp
  then have 𝔉f': "𝔉ArrMapf' : 𝔉ObjMapd 𝔅𝔉ObjMapr" 
    by (auto intro: cat_cs_intros)
  from f' show 
    "(λf'Hom 𝔄 d r. 𝔉ArrMapf' Aop_cat 𝔅u)f' = 
      (λf'Hom 𝔄 d r. u A𝔅𝔉ArrMapf')f'"
    by (simp add: HomCod.op_cat_Comp[OF assms 𝔉f'])
qed simp_all


text‹Universal maps for the opposite functor.›

lemma (in is_functor) op_umap_of[cat_op_simps]: "umap_of (op_cf 𝔉) = umap_fo 𝔉"
  unfolding umap_fo_def by simp 

lemma (in is_functor) op_umap_fo[cat_op_simps]: "umap_fo (op_cf 𝔉) = umap_of 𝔉"
  unfolding umap_fo_def by (simp add: cat_op_simps)

lemmas [cat_op_simps] = 
  is_functor.op_umap_of
  is_functor.op_umap_fo


subsubsection‹Arrow value›

lemma umap_of_ArrVal_vsv[cat_cs_intros]: "vsv (umap_of 𝔉 c r u dArrVal)"
  unfolding umap_of_def arr_field_simps by (simp add: nat_omega_simps)

lemma umap_fo_ArrVal_vsv[cat_cs_intros]: "vsv (umap_fo 𝔉 c r u dArrVal)"
  unfolding umap_fo_def by (rule umap_of_ArrVal_vsv)

lemma (in is_functor) umap_of_ArrVal_vdomain: 
  assumes "u : c 𝔅𝔉ObjMapr"
  shows "𝒟 (umap_of 𝔉 c r u dArrVal) = Hom 𝔄 r d"
  unfolding umap_of_components[OF assms] by simp

lemmas [cat_cs_simps] = is_functor.umap_of_ArrVal_vdomain

lemma (in is_functor) umap_fo_ArrVal_vdomain:
  assumes "u : 𝔉ObjMapr 𝔅c"
  shows "𝒟 (umap_fo 𝔉 c r u dArrVal) = Hom 𝔄 d r"
  unfolding umap_fo_components[OF assms] by simp

lemmas [cat_cs_simps] = is_functor.umap_fo_ArrVal_vdomain

lemma (in is_functor) umap_of_ArrVal_app: 
  assumes "f' : r 𝔄d" and "u : c 𝔅𝔉ObjMapr"
  shows "umap_of 𝔉 c r u dArrValf' = 𝔉ArrMapf' A𝔅u"
  using assms(1) unfolding umap_of_components[OF assms(2)] by simp

lemmas [cat_cs_simps] = is_functor.umap_of_ArrVal_app

lemma (in is_functor) umap_fo_ArrVal_app: 
  assumes "f' : d 𝔄r" and "u : 𝔉ObjMapr 𝔅c"
  shows "umap_fo 𝔉 c r u dArrValf' = u A𝔅𝔉ArrMapf'"
proof-
  from assms have "𝔉ArrMapf' : 𝔉ObjMapd 𝔅𝔉ObjMapr" 
    by (auto intro: cat_cs_intros)
  from this assms(2) have 𝔉f'[simp]:
    "𝔉ArrMapf' Aop_cat 𝔅u = u A𝔅𝔉ArrMapf'"
    by (simp add: cat_op_simps)
  from
    is_functor_axioms
    is_functor.umap_of_ArrVal_app[
      OF is_functor_op, unfolded cat_op_simps, 
      OF assms
      ] 
  show ?thesis
    by (simp add: cat_op_simps cat_cs_simps)
qed

lemmas [cat_cs_simps] = is_functor.umap_fo_ArrVal_app

lemma (in is_functor) umap_of_ArrVal_vrange: 
  assumes "u : c 𝔅𝔉ObjMapr"
  shows " (umap_of 𝔉 c r u dArrVal)  Hom 𝔅 c (𝔉ObjMapd)"
proof(intro vsubset_antisym vsubsetI)
  interpret vsv umap_of 𝔉 c r u dArrVal 
    unfolding umap_of_components[OF assms] by simp
  fix g assume "g   (umap_of 𝔉 c r u dArrVal)"
  then obtain f' 
    where g_def: "g = umap_of 𝔉 c r u dArrValf'" 
      and f': "f'  𝒟 (umap_of 𝔉 c r u dArrVal)"
    unfolding umap_of_components[OF assms] by auto
  then have f': "f' : r 𝔄d" 
    unfolding umap_of_ArrVal_vdomain[OF assms] by simp
  then have 𝔉f': "𝔉ArrMapf' : 𝔉ObjMapr 𝔅𝔉ObjMapd" 
    by (auto intro!: cat_cs_intros)
  have g_def: "g = 𝔉ArrMapf' A𝔅u"
    unfolding g_def umap_of_ArrVal_app[OF f' assms]..
  from 𝔉f' assms show "g  Hom 𝔅 c (𝔉ObjMapd)" 
    unfolding g_def by (auto intro: cat_cs_intros)
qed

lemma (in is_functor) umap_fo_ArrVal_vrange: 
  assumes "u : 𝔉ObjMapr 𝔅c"
  shows " (umap_fo 𝔉 c r u dArrVal)  Hom 𝔅 (𝔉ObjMapd) c"
  by 
    (
      rule is_functor.umap_of_ArrVal_vrange[
        OF is_functor_op, unfolded cat_op_simps, OF assms, folded umap_fo_def
        ]
    )


subsubsection‹Universal map is an arrow in the category Set›

lemma (in is_functor) cf_arr_Set_umap_of: 
  assumes "category α 𝔄" 
    and "category α 𝔅" 
    and r: "r  𝔄Obj" 
    and d: "d  𝔄Obj"
    and u: "u : c 𝔅𝔉ObjMapr"
  shows "arr_Set α (umap_of 𝔉 c r u d)"
proof(intro arr_SetI)
  interpret HomDom: category α 𝔄 by (rule assms(1))
  interpret HomCod: category α 𝔅 by (rule assms(2))
  note umap_of_components = umap_of_components[OF u]
  from u d have c: "c  𝔅Obj" and 𝔉d: "(𝔉ObjMapd)  𝔅Obj" 
    by (auto intro: cat_cs_intros)
  show "vfsequence (umap_of 𝔉 c r u d)" unfolding umap_of_def by simp
  show "vcard (umap_of 𝔉 c r u d) = 3"
    unfolding umap_of_def by (simp add: nat_omega_simps)
  from umap_of_ArrVal_vrange[OF u] show 
    " (umap_of 𝔉 c r u dArrVal)  umap_of 𝔉 c r u dArrCod"
    unfolding umap_of_components by simp
  from r d show "umap_of 𝔉 c r u dArrDom  Vset α"
    unfolding umap_of_components by (intro HomDom.cat_Hom_in_Vset)
  from c 𝔉d show "umap_of 𝔉 c r u dArrCod  Vset α"
    unfolding umap_of_components by (intro HomCod.cat_Hom_in_Vset)
qed (auto simp: umap_of_components[OF u])

lemma (in is_functor) cf_arr_Set_umap_fo: 
  assumes "category α 𝔄" 
    and "category α 𝔅" 
    and r: "r  𝔄Obj" 
    and d: "d  𝔄Obj"
    and u: "u : 𝔉ObjMapr 𝔅c"
  shows "arr_Set α (umap_fo 𝔉 c r u d)"
proof-
  from assms(1) have 𝔄: "category α (op_cat 𝔄)" 
    by (auto intro: cat_cs_intros)
  from assms(2) have 𝔅: "category α (op_cat 𝔅)" 
    by (auto intro: cat_cs_intros)
  show ?thesis
    by 
      (
        rule 
          is_functor.cf_arr_Set_umap_of[
            OF is_functor_op, unfolded cat_op_simps, OF 𝔄 𝔅 r d u
            ]
      )
qed

lemma (in is_functor) cf_umap_of_is_arr:
  assumes "category α 𝔄" 
    and "category α 𝔅" 
    and "r  𝔄Obj" 
    and "d  𝔄Obj"
    and "u : c 𝔅𝔉ObjMapr"
  shows "umap_of 𝔉 c r u d : Hom 𝔄 r d cat_Set αHom 𝔅 c (𝔉ObjMapd)"
proof(intro cat_Set_is_arrI)
  show "arr_Set α (umap_of 𝔉 c r u d)" 
    by (rule cf_arr_Set_umap_of[OF assms])
qed (simp_all add: umap_of_components[OF assms(5)])

lemma (in is_functor) cf_umap_of_is_arr':
  assumes "category α 𝔄" 
    and "category α 𝔅" 
    and "r  𝔄Obj" 
    and "d  𝔄Obj"
    and "u : c 𝔅𝔉ObjMapr"
    and "A = Hom 𝔄 r d"
    and "B = Hom 𝔅 c (𝔉ObjMapd)"
    and " = cat_Set α"
  shows "umap_of 𝔉 c r u d : A B"
  using assms(1-5) unfolding assms(6-8) by (rule cf_umap_of_is_arr)

lemmas [cat_cs_intros] = is_functor.cf_umap_of_is_arr'

lemma (in is_functor) cf_umap_fo_is_arr:
  assumes "category α 𝔄" 
    and "category α 𝔅" 
    and "r  𝔄Obj" 
    and "d  𝔄Obj"
    and "u : 𝔉ObjMapr 𝔅c"
  shows "umap_fo 𝔉 c r u d : Hom 𝔄 d r cat_Set αHom 𝔅 (𝔉ObjMapd) c"
proof(intro cat_Set_is_arrI)
  show "arr_Set α (umap_fo 𝔉 c r u d)" 
    by (rule cf_arr_Set_umap_fo[OF assms])
qed (simp_all add: umap_fo_components[OF assms(5)])

lemma (in is_functor) cf_umap_fo_is_arr':
  assumes "category α 𝔄" 
    and "category α 𝔅" 
    and "r  𝔄Obj" 
    and "d  𝔄Obj"
    and "u : 𝔉ObjMapr 𝔅c"
    and "A = Hom 𝔄 d r"
    and "B = Hom 𝔅 (𝔉ObjMapd) c"
    and " = cat_Set α"
  shows "umap_fo 𝔉 c r u d : A B"
  using assms(1-5) unfolding assms(6-8) by (rule cf_umap_fo_is_arr)

lemmas [cat_cs_intros] = is_functor.cf_umap_fo_is_arr'



subsection‹Universal arrow: definition and elementary properties›


text‹See Chapter III-1 in cite"mac_lane_categories_2010".›

definition universal_arrow_of :: "V  V  V  V  bool"
  where "universal_arrow_of 𝔉 c r u 
    (
      r  𝔉HomDomObj 
      u : c 𝔉HomCod𝔉ObjMapr 
      (
        r' u'.
          r'  𝔉HomDomObj 
          u' : c 𝔉HomCod𝔉ObjMapr' 
          (∃!f'. f' : r 𝔉HomDomr'  u' = umap_of 𝔉 c r u r'ArrValf')
      )
    )"

definition universal_arrow_fo :: "V  V  V  V  bool"
  where "universal_arrow_fo 𝔉 c r u  universal_arrow_of (op_cf 𝔉) c r u"


text‹Rules.›

mk_ide (in is_functor) rf 
  universal_arrow_of_def[where 𝔉=𝔉, unfolded cf_HomDom cf_HomCod]
  |intro universal_arrow_ofI|
  |dest universal_arrow_ofD[dest]|
  |elim universal_arrow_ofE[elim]|

lemma (in is_functor) universal_arrow_foI:
  assumes "r  𝔄Obj" 
    and "u : 𝔉ObjMapr 𝔅c" 
    and "r' u'.  r'  𝔄Obj; u' : 𝔉ObjMapr' 𝔅c   
      ∃!f'. f' : r' 𝔄r  u' = umap_fo 𝔉 c r u r'ArrValf'"
  shows "universal_arrow_fo 𝔉 c r u"
  by 
    (
      simp add: 
        is_functor.universal_arrow_ofI
          [
            OF is_functor_op, 
            folded universal_arrow_fo_def, 
            unfolded cat_op_simps, 
            OF assms
          ]
    )

lemma (in is_functor) universal_arrow_foD[dest]:
  assumes "universal_arrow_fo 𝔉 c r u"
  shows "r  𝔄Obj" 
    and "u : 𝔉ObjMapr 𝔅c" 
    and "r' u'.  r'  𝔄Obj; u' : 𝔉ObjMapr' 𝔅c   
      ∃!f'. f' : r' 𝔄r  u' = umap_fo 𝔉 c r u r'ArrValf'"
  by
    (
      auto simp: 
        is_functor.universal_arrow_ofD
          [
            OF is_functor_op, 
            folded universal_arrow_fo_def, 
            unfolded cat_op_simps,
            OF assms
          ]
    )

lemma (in is_functor) universal_arrow_foE[elim]:
  assumes "universal_arrow_fo 𝔉 c r u"
  obtains "r  𝔄Obj" 
    and "u : 𝔉ObjMapr 𝔅c" 
    and "r' u'.  r'  𝔄Obj; u' : 𝔉ObjMapr' 𝔅c   
      ∃!f'. f' : r' 𝔄r  u' = umap_fo 𝔉 c r u r'ArrValf'"
  using assms by (auto simp: universal_arrow_foD)


text‹Elementary properties.›

lemma (in is_functor) op_cf_universal_arrow_of[cat_op_simps]: 
  "universal_arrow_of (op_cf 𝔉) c r u  universal_arrow_fo 𝔉 c r u"
  unfolding universal_arrow_fo_def ..

lemma (in is_functor) op_cf_universal_arrow_fo[cat_op_simps]: 
  "universal_arrow_fo (op_cf 𝔉) c r u  universal_arrow_of 𝔉 c r u"
  unfolding universal_arrow_fo_def cat_op_simps ..

lemmas (in is_functor) [cat_op_simps] = 
  is_functor.op_cf_universal_arrow_of
  is_functor.op_cf_universal_arrow_fo



subsection‹Uniqueness›


text‹
The following properties are related to the uniqueness of the 
universal arrow. These properties can be inferred from the content of
Chapter III-1 in cite"mac_lane_categories_2010".
›

lemma (in is_functor) cf_universal_arrow_of_ex_is_iso_arr:
  ―‹The proof is based on the ideas expressed in the proof of Theorem 5.2 
  in Chapter Introduction in \cite{hungerford_algebra_2003}.›
  assumes "universal_arrow_of 𝔉 c r u" and "universal_arrow_of 𝔉 c r' u'"
  obtains f where "f : r iso𝔄r'" and "u' = umap_of 𝔉 c r u r'ArrValf"
proof-

  note ua1 = universal_arrow_ofD[OF assms(1)]
  note ua2 = universal_arrow_ofD[OF assms(2)]

  from ua1(1) have 𝔄r: "𝔄CIdr : r 𝔄r" by (auto intro: cat_cs_intros)
  from ua1(1) have "𝔉ArrMap𝔄CIdr = 𝔅CId𝔉ObjMapr"
    by (auto intro: cat_cs_intros)
  with ua1(1,2) have u_def: "u = umap_of 𝔉 c r u rArrVal𝔄CIdr"
    unfolding umap_of_ArrVal_app[OF 𝔄r ua1(2)] by (auto simp: cat_cs_simps)

  from ua2(1) have 𝔄r': "𝔄CIdr' : r' 𝔄r'" by (auto intro: cat_cs_intros)
  from ua2(1) have "𝔉ArrMap𝔄CIdr' = 𝔅CId𝔉ObjMapr'" 
    by (auto intro: cat_cs_intros)
  with ua2(1,2) have u'_def: "u' = umap_of 𝔉 c r' u' r'ArrVal𝔄CIdr'"
    unfolding umap_of_ArrVal_app[OF 𝔄r' ua2(2)] by (auto simp: cat_cs_simps)

  from 𝔄r u_def universal_arrow_ofD(3)[OF assms(1) ua1(1,2)] have eq_CId_rI: 
    " f' : r 𝔄r; u = umap_of 𝔉 c r u rArrValf'   f' = 𝔄CIdr" 
    for f'
    by blast
  from 𝔄r' u'_def universal_arrow_ofD(3)[OF assms(2) ua2(1,2)] have eq_CId_r'I: 
    " f' : r' 𝔄r'; u' = umap_of 𝔉 c r' u' r'ArrValf'  
      f' = 𝔄CIdr'" 
    for f'
    by blast

  from ua1(3)[OF ua2(1,2)] obtain f 
    where f: "f : r 𝔄r'" 
      and u'_def: "u' = umap_of 𝔉 c r u r'ArrValf"
      and "g : r 𝔄r'  u' = umap_of 𝔉 c r u r'ArrValg  f = g" 
    for g
    by metis
  from ua2(3)[OF ua1(1,2)] obtain f' 
    where f': "f' : r' 𝔄r" 
      and u_def: "u = umap_of 𝔉 c r' u' rArrValf'"
      and "g : r' 𝔄r  u = umap_of 𝔉 c r' u' rArrValg  f' = g" 
    for g
    by metis

  have "f : r iso𝔄r'"
  proof(intro is_iso_arrI is_inverseI)
    show f: "f : r 𝔄r'" by (rule f)
    show f': "f' : r' 𝔄r" by (rule f')
    show "f : r 𝔄r'" by (rule f)
    from f' have 𝔉f': "𝔉ArrMapf' : 𝔉ObjMapr' 𝔅𝔉ObjMapr" 
      by (auto intro: cat_cs_intros)
    from f have 𝔉f: "𝔉ArrMapf : 𝔉ObjMapr 𝔅𝔉ObjMapr'" 
      by (auto intro: cat_cs_intros)
    note u'_def' = u'_def[symmetric, unfolded umap_of_ArrVal_app[OF f ua1(2)]] 
      and u_def' = u_def[symmetric, unfolded umap_of_ArrVal_app[OF f' ua2(2)]]
    show "f' A𝔄f = 𝔄CIdr"
    proof(rule eq_CId_rI)
      from f f' show f'f: "f' A𝔄f : r 𝔄r" 
        by (auto intro: cat_cs_intros)
      from ua1(2) 𝔉f' 𝔉f show "u = umap_of 𝔉 c r u rArrValf' A𝔄f"
        unfolding umap_of_ArrVal_app[OF f'f ua1(2)] cf_ArrMap_Comp[OF f' f]
        by (simp add: HomCod.cat_Comp_assoc u'_def' u_def')
    qed
    show "f A𝔄f' = 𝔄CIdr'"
    proof(rule eq_CId_r'I)
      from f f' show ff': "f A𝔄f' : r' 𝔄r'" 
        by (auto intro: cat_cs_intros)
      from ua2(2) 𝔉f' 𝔉f show "u' = umap_of 𝔉 c r' u' r'ArrValf A𝔄f'"
        unfolding umap_of_ArrVal_app[OF ff' ua2(2)] cf_ArrMap_Comp[OF f f']
        by (simp add: HomCod.cat_Comp_assoc u'_def' u_def')
    qed
  qed
  
  with u'_def that show ?thesis by auto

qed

lemma (in is_functor) cf_universal_arrow_fo_ex_is_iso_arr:
  assumes "universal_arrow_fo 𝔉 c r u"
    and "universal_arrow_fo 𝔉 c r' u'"
  obtains f where "f : r' iso𝔄r" and "u' = umap_fo 𝔉 c r u r'ArrValf"
  by 
    (
      elim 
        is_functor.cf_universal_arrow_of_ex_is_iso_arr[
          OF is_functor_op, unfolded cat_op_simps, OF assms
          ]
    )

lemma (in is_functor) cf_universal_arrow_of_unique:
  assumes "universal_arrow_of 𝔉 c r u"
    and "universal_arrow_of 𝔉 c r' u'"
  shows "∃!f'. f' : r 𝔄r'  u' = umap_of 𝔉 c r u r'ArrValf'"
proof-
  note ua1 = universal_arrow_ofD[OF assms(1)]
  note ua2 = universal_arrow_ofD[OF assms(2)]
  from ua1(3)[OF ua2(1,2)] show ?thesis .
qed

lemma (in is_functor) cf_universal_arrow_fo_unique:
  assumes "universal_arrow_fo 𝔉 c r u"
    and "universal_arrow_fo 𝔉 c r' u'"
  shows "∃!f'. f' : r' 𝔄r  u' = umap_fo 𝔉 c r u r'ArrValf'"
proof-
  note ua1 = universal_arrow_foD[OF assms(1)]
  note ua2 = universal_arrow_foD[OF assms(2)]
  from ua1(3)[OF ua2(1,2)] show ?thesis .
qed

lemma (in is_functor) cf_universal_arrow_of_is_iso_arr:
  assumes "universal_arrow_of 𝔉 c r u"
    and "universal_arrow_of 𝔉 c r' u'"
    and "f : r 𝔄r'" 
    and "u' = umap_of 𝔉 c r u r'ArrValf"
  shows "f : r iso𝔄r'"
proof-
  from assms(3,4) cf_universal_arrow_of_unique[OF assms(1,2)] have eq: 
    "g : r 𝔄r'  u' = umap_of 𝔉 c r u r'ArrValg  f = g" for g
    by blast
  from assms(1,2) obtain f' 
    where iso_f': "f' : r iso𝔄r'" 
      and u'_def: "u' = umap_of 𝔉 c r u r'ArrValf'"
    by (auto elim: cf_universal_arrow_of_ex_is_iso_arr)
  then have f': "f' : r 𝔄r'" by auto
  from iso_f' show ?thesis unfolding eq[OF f' u'_def, symmetric].
qed

lemma (in is_functor) cf_universal_arrow_fo_is_iso_arr:
  assumes "universal_arrow_fo 𝔉 c r u"
    and "universal_arrow_fo 𝔉 c r' u'"
    and "f : r' 𝔄r" 
    and "u' = umap_fo 𝔉 c r u r'ArrValf"
  shows "f : r' iso𝔄r"
  by 
    (
      rule 
        is_functor.cf_universal_arrow_of_is_iso_arr[
          OF is_functor_op, unfolded cat_op_simps, OF assms
          ]
    )

lemma (in is_functor) universal_arrow_of_if_universal_arrow_of:
  assumes "universal_arrow_of 𝔉 c r u" 
    and "f : r iso𝔄r'"
    and "u' = umap_of 𝔉 c r u r'ArrValf"
  shows "universal_arrow_of 𝔉 c r' u'"
proof(intro universal_arrow_ofI assms(2))

  note ua = universal_arrow_ofD[OF assms(1)]
  note f = is_iso_arrD(1)[OF assms(2)]
  from assms(3) ua(1,2) f have u'_def: "u' = 𝔉ArrMapf A𝔅u"
    by (cs_prems cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
  from  ua(2) f show u': "u' : c 𝔅𝔉ObjMapr'"
    unfolding u'_def by (cs_concl cs_intro: cat_cs_intros)

  from f(1) show  "r'  𝔄Obj" by auto

  fix r'' u'' assume prems: "r''  𝔄Obj" "u'' : c 𝔅𝔉ObjMapr''"

  from ua(3)[OF prems] obtain f' 
    where f': "f' : r 𝔄r''"
      and u''_def: "u'' = umap_of 𝔉 c r u r''ArrValf'"
      and f'_unique: "f''.
         f'' : r 𝔄r''; u'' = umap_of 𝔉 c r u r''ArrValf''  
          f'' = f'"
    by metis

  from u''_def f' ua(2) have [cat_cs_simps]: "𝔉ArrMapf' A𝔅u = u''"
    by (cs_prems cs_simp: cat_cs_simps cs_intro: cat_cs_intros) simp

  show "∃!f'. f' : r' 𝔄r''  u'' = umap_of 𝔉 c r' u' r''ArrValf'"
  proof(intro ex1I conjI; (elim conjE)?)
    from f' assms(2) f show "f' A𝔄f¯C𝔄: r' 𝔄r''"
      by (cs_concl cs_intro: cat_cs_intros cat_arrow_cs_intros)
    have 
      "𝔉ArrMapf' A𝔅(𝔉ArrMapf¯C𝔄 A𝔅u') =
        𝔉ArrMapf' A𝔅(𝔉ArrMapf¯C𝔄 A𝔅(𝔉ArrMapf A𝔅u))"
      unfolding u'_def ..
    also from f' assms(2) u' f ua(2) have 
      " = 𝔉ArrMapf' A𝔅(𝔉ArrMapf¯C𝔄A𝔄f) A𝔅u"
      by
        (
          cs_concl 
            cs_simp: cat_cs_simps cs_intro: cat_arrow_cs_intros cat_cs_intros
        )
    also from f' assms(2) f ua(2) have " = u''"
      by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
    finally have [cat_cs_simps]: 
      "𝔉ArrMapf' A𝔅(𝔉ArrMapf¯C𝔄 A𝔅u') = u''".
    from f' assms(2) u' f show 
      "u'' = umap_of 𝔉 c r' u' r''ArrValf' A𝔄f¯C𝔄"
      by
        (
          cs_concl
            cs_simp: cat_cs_simps cs_intro: cat_cs_intros cat_arrow_cs_intros
        )
    fix g assume prems': 
      "g : r' 𝔄r''" "u'' = umap_of 𝔉 c r' u' r''ArrValg"
    from prems'(1) f have gf: "g A𝔄f : r 𝔄r''"
      by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
    from prems'(2,1) assms(2) u' have "u'' = 𝔉ArrMapg A𝔅u'"
      by (cs_prems cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
    also from prems'(1) f ua(2) have 
      " = 𝔉ArrMapg A𝔅𝔉ArrMapf A𝔅u"
      by (cs_concl cs_simp: cat_cs_simps u'_def u''_def cs_intro: cat_cs_intros)
    also from prems'(1) f ua(2) have 
      " = umap_of 𝔉 c r u r''ArrValg A𝔄f"
      by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
    finally have "u'' = umap_of 𝔉 c r u r''ArrValg A𝔄f".
    from f'_unique[OF gf this] have "g A𝔄f = f'".
    then have "(g A𝔄f) A𝔄f¯C𝔄= f' A𝔄f¯C𝔄⇙" by simp
    from this assms(2) prems'(1) u' f ua(2) show "g = f' A𝔄f¯C𝔄⇙"
      by
        (
          cs_prems
            cs_simp: cat_cs_simps cs_intro: cat_arrow_cs_intros cat_cs_intros
        )
  qed

qed

lemma (in is_functor) universal_arrow_fo_if_universal_arrow_fo:
  assumes "universal_arrow_fo 𝔉 c r u" 
    and "f : r' iso𝔄r"
    and "u' = umap_fo 𝔉 c r u r'ArrValf"
  shows "universal_arrow_fo 𝔉 c r' u'"
  by 
    (
      rule is_functor.universal_arrow_of_if_universal_arrow_of[
        OF is_functor_op, unfolded cat_op_simps, OF assms
        ]
    )



subsection‹Universal natural transformation›


subsubsection‹Definition and elementary properties›


text‹
The concept of the universal natural transformation is introduced for the 
statement of the elements of a variant of Proposition 1 in Chapter III-2
in cite"mac_lane_categories_2010".
›

definition ntcf_ua_of :: "V  V  V  V  V  V"
  where "ntcf_ua_of α 𝔉 c r u =
    [
      (λd𝔉HomDomObj. umap_of 𝔉 c r u d),
      HomO.Cα𝔉HomDom(r,-),
      HomO.Cα𝔉HomCod(c,-) CF 𝔉,
      𝔉HomDom,
      cat_Set α
    ]"

definition ntcf_ua_fo :: "V  V  V  V  V  V"
  where "ntcf_ua_fo α 𝔉 c r u = ntcf_ua_of α (op_cf 𝔉) c r u"


text‹Components.›

lemma ntcf_ua_of_components:
  shows "ntcf_ua_of α 𝔉 c r uNTMap = (λd𝔉HomDomObj. umap_of 𝔉 c r u d)"
    and "ntcf_ua_of α 𝔉 c r uNTDom = HomO.Cα𝔉HomDom(r,-)"
    and "ntcf_ua_of α 𝔉 c r uNTCod = HomO.Cα𝔉HomCod(c,-) CF 𝔉"
    and "ntcf_ua_of α 𝔉 c r uNTDGDom = 𝔉HomDom"
    and "ntcf_ua_of α 𝔉 c r uNTDGCod = cat_Set α"
  unfolding ntcf_ua_of_def nt_field_simps by (simp_all add: nat_omega_simps) 

lemma ntcf_ua_fo_components:
  shows "ntcf_ua_fo α 𝔉 c r uNTMap = (λd𝔉HomDomObj. umap_fo 𝔉 c r u d)"
    and "ntcf_ua_fo α 𝔉 c r uNTDom = HomO.Cαop_cat (𝔉HomDom)(r,-)"
    and "ntcf_ua_fo α 𝔉 c r uNTCod =
      HomO.Cαop_cat (𝔉HomCod)(c,-) CF op_cf 𝔉"
    and "ntcf_ua_fo α 𝔉 c r uNTDGDom = op_cat (𝔉HomDom)"
    and "ntcf_ua_fo α 𝔉 c r uNTDGCod = cat_Set α"
  unfolding ntcf_ua_fo_def ntcf_ua_of_components umap_fo_def cat_op_simps 
  by simp_all

context is_functor
begin

lemmas ntcf_ua_of_components' = 
  ntcf_ua_of_components[where α=α and 𝔉=𝔉, unfolded cat_cs_simps]

lemmas [cat_cs_simps] = ntcf_ua_of_components'(2-5)

lemma ntcf_ua_fo_components':
  assumes "c  𝔅Obj" and "r  𝔄Obj" 
  shows "ntcf_ua_fo α 𝔉 c r uNTMap = (λd𝔄Obj. umap_fo 𝔉 c r u d)"
    and [cat_cs_simps]: 
      "ntcf_ua_fo α 𝔉 c r uNTDom = HomO.Cα𝔄(-,r)"
    and [cat_cs_simps]: 
      "ntcf_ua_fo α 𝔉 c r uNTCod = HomO.Cα𝔅(-,c) CF op_cf 𝔉"
    and [cat_cs_simps]: "ntcf_ua_fo α 𝔉 c r uNTDGDom = op_cat 𝔄"
    and [cat_cs_simps]: "ntcf_ua_fo α 𝔉 c r uNTDGCod = cat_Set α"
  unfolding
    ntcf_ua_fo_components cat_cs_simps
    HomDom.cat_op_cat_cf_Hom_snd[OF assms(2)] 
    HomCod.cat_op_cat_cf_Hom_snd[OF assms(1)]
  by simp_all

end

lemmas [cat_cs_simps] = 
  is_functor.ntcf_ua_of_components'(2-5)
  is_functor.ntcf_ua_fo_components'(2-5)


subsubsection‹Natural transformation map›

mk_VLambda (in is_functor) 
  ntcf_ua_of_components(1)[where α=α and 𝔉=𝔉, unfolded cf_HomDom]
  |vsv ntcf_ua_of_NTMap_vsv|
  |vdomain ntcf_ua_of_NTMap_vdomain|
  |app ntcf_ua_of_NTMap_app|

context is_functor
begin

context
  fixes c r
  assumes r: "r  𝔄Obj" and c: "c  𝔅Obj" 
begin

mk_VLambda ntcf_ua_fo_components'(1)[OF c r]
  |vsv ntcf_ua_fo_NTMap_vsv|
  |vdomain ntcf_ua_fo_NTMap_vdomain|
  |app ntcf_ua_fo_NTMap_app|

end

end

lemmas [cat_cs_intros] = 
  is_functor.ntcf_ua_fo_NTMap_vsv
  is_functor.ntcf_ua_of_NTMap_vsv

lemmas [cat_cs_simps] = 
  is_functor.ntcf_ua_fo_NTMap_vdomain
  is_functor.ntcf_ua_fo_NTMap_app
  is_functor.ntcf_ua_of_NTMap_vdomain
  is_functor.ntcf_ua_of_NTMap_app

lemma (in is_functor) ntcf_ua_of_NTMap_vrange:
  assumes "category α 𝔄" 
    and "category α 𝔅" 
    and "r  𝔄Obj" 
    and "u : c 𝔅𝔉ObjMapr"
  shows " (ntcf_ua_of α 𝔉 c r uNTMap)  cat_Set αArr"
proof(rule vsv.vsv_vrange_vsubset, unfold ntcf_ua_of_NTMap_vdomain)
  show "vsv (ntcf_ua_of α 𝔉 c r uNTMap)" by (rule ntcf_ua_of_NTMap_vsv)
  fix d assume prems: "d  𝔄Obj"
  with category_cat_Set is_functor_axioms assms show 
    "ntcf_ua_of α 𝔉 c r uNTMapd  cat_Set αArr"
    by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
qed


subsubsection‹Commutativity of the universal maps and hom›-functions›

lemma (in is_functor) cf_umap_of_cf_hom_commute: 
  assumes "category α 𝔄"
    and "category α 𝔅"
    and "c  𝔅Obj"
    and "r  𝔄Obj"
    and "u : c 𝔅𝔉ObjMapr"
    and "f : a 𝔄b"
  shows 
    "umap_of 𝔉 c r u b Acat_Set αcf_hom 𝔄 [𝔄CIdr, f] =
      cf_hom 𝔅 [𝔅CIdc, 𝔉ArrMapf] Acat_Set αumap_of 𝔉 c r u a"
  (is ?uof_b Acat_Set α?rf = ?cf Acat_Set α?uof_a)
proof-

  from is_functor_axioms category_cat_Set assms(1,2,4-6) have b_rf: 
    "?uof_b Acat_Set α?rf : Hom 𝔄 r a cat_Set αHom 𝔅 c (𝔉ObjMapb)"
    by 
      (
        cs_concl cs_shallow 
          cs_intro: cat_cs_intros cat_op_intros cat_prod_cs_intros
      )
  from is_functor_axioms category_cat_Set assms(1,2,4-6) have cf_a: 
    "?cf Acat_Set α?uof_a : Hom 𝔄 r a cat_Set αHom 𝔅 c (𝔉ObjMapb)"
    by (cs_concl cs_intro: cat_cs_intros cat_op_intros cat_prod_cs_intros)

  show ?thesis
  proof(rule arr_Set_eqI[of α])
    from b_rf show arr_Set_b_rf: "arr_Set α (?uof_b Acat_Set α?rf)"
      by (auto dest: cat_Set_is_arrD(1))
    from b_rf have dom_lhs: 
      "𝒟 ((?uof_b Acat_Set α?rf)ArrVal) = Hom 𝔄 r a"
      by (cs_concl cs_shallow cs_simp: cat_cs_simps)+
    from cf_a show arr_Set_cf_a: "arr_Set α (?cf Acat_Set α?uof_a)"
      by (auto dest: cat_Set_is_arrD(1))
    from cf_a have dom_rhs: 
      "𝒟 ((?cf Acat_Set α?uof_a)ArrVal) = Hom 𝔄 r a"
      by (cs_concl cs_shallow cs_simp: cat_cs_simps)
    show "(?uof_b Acat_Set α?rf)ArrVal = (?cf Acat_Set α?uof_a)ArrVal"
    proof(rule vsv_eqI, unfold dom_lhs dom_rhs in_Hom_iff)
      fix q assume "q : r 𝔄a"
      with is_functor_axioms category_cat_Set assms show 
        "(?uof_b Acat_Set α?rf)ArrValq =
          (?cf Acat_Set α?uof_a)ArrValq"
        by
          (
            cs_concl cs_shallow
              cs_simp: cat_cs_simps cat_op_simps
              cs_intro: cat_cs_intros cat_op_intros cat_prod_cs_intros
         )
    qed (use arr_Set_b_rf arr_Set_cf_a in auto)
  
  qed (use b_rf cf_a in cs_concl cs_shallow cs_simp: cat_cs_simps)+

qed

lemma cf_umap_of_cf_hom_unit_commute:
  assumes "category α "
    and "category α 𝔇"
    and "𝔉 :  ↦↦Cα𝔇"
    and "𝔊 : 𝔇 ↦↦Cα"
    and "η : cf_id  CF 𝔊 CF 𝔉 :  ↦↦Cα"
    and "g : c' c" 
    and "f : d 𝔇d'"
  shows 
    "umap_of 𝔊 c' (𝔉ObjMapc') (ηNTMapc') d' Acat_Set αcf_hom 𝔇 [𝔉ArrMapg, f] =
        cf_hom  [g, 𝔊ArrMapf] Acat_Set αumap_of 𝔊 c (𝔉ObjMapc) (ηNTMapc) d"
  (is ?uof_c'd' Acat_Set α?𝔉gf = ?g𝔊f Acat_Set α?uof_cd)
proof-

  interpret η: is_ntcf α   cf_id  𝔊 CF 𝔉 η by (rule assms(5))

  from assms have c'd'_𝔉gf: "?uof_c'd' Acat_Set α?𝔉gf :
    Hom 𝔇 (𝔉ObjMapc) d cat_Set αHom  c' (𝔊ObjMapd')"
    by
      (
        cs_concl 
          cs_simp: cat_cs_simps 
          cs_intro: cat_cs_intros cat_op_intros cat_prod_cs_intros
      )
  then have dom_lhs:
    "𝒟 ((?uof_c'd' Acat_Set α?𝔉gf)ArrVal) = Hom 𝔇 (𝔉ObjMapc) d"
    by (cs_concl cs_shallow cs_simp: cat_cs_simps)
  from assms have g𝔊f_cd: "?g𝔊f Acat_Set α?uof_cd :
    Hom 𝔇 (𝔉ObjMapc) d cat_Set αHom  c' (𝔊ObjMapd')"
    by 
      (
        cs_concl 
          cs_simp: cat_cs_simps 
          cs_intro: cat_cs_intros cat_op_intros cat_prod_cs_intros
      )
  then have dom_rhs: 
    "𝒟 ((?g𝔊f Acat_Set α?uof_cd)ArrVal) = Hom 𝔇 (𝔉ObjMapc) d"
    by (cs_concl cs_shallow cs_simp: cat_cs_simps)

  show ?thesis
  proof(rule arr_Set_eqI[of α])
    from c'd'_𝔉gf show arr_Set_c'd'_𝔉gf: 
      "arr_Set α (?uof_c'd' Acat_Set α?𝔉gf)"
      by (auto dest: cat_Set_is_arrD(1))
    from g𝔊f_cd show arr_Set_g𝔊f_cd:
      "arr_Set α (?g𝔊f Acat_Set α?uof_cd)"
      by (auto dest: cat_Set_is_arrD(1))
    show 
      "(?uof_c'd' Acat_Set α?𝔉gf)ArrVal =
        (?g𝔊f Acat_Set α?uof_cd)ArrVal"
    proof(rule vsv_eqI, unfold dom_lhs dom_rhs in_Hom_iff)
      fix h assume prems: "h : 𝔉ObjMapc 𝔇d"
      from η.ntcf_Comp_commute[OF assms(6)] assms have [cat_cs_simps]:
        "ηNTMapc Ag = 𝔊ArrMap𝔉ArrMapg AηNTMapc'"
        by 
          (
            cs_prems cs_shallow 
              cs_simp: cat_cs_simps cat_op_simps cs_intro: cat_cs_intros
          )
      from assms prems show 
        "(?uof_c'd' Acat_Set α?𝔉gf)ArrValh =
          (?g𝔊f Acat_Set α?uof_cd)ArrValh"
        by 
          (
            cs_concl
              cs_intro: cat_cs_intros cat_op_intros cat_prod_cs_intros  
              cs_simp: cat_cs_simps
          )
    qed (use arr_Set_c'd'_𝔉gf arr_Set_g𝔊f_cd in auto)
 
  qed (use c'd'_𝔉gf g𝔊f_cd in cs_concl cs_shallow cs_simp: cat_cs_simps)+

qed


subsubsection‹Universal natural transformation is a natural transformation›

lemma (in is_functor) cf_ntcf_ua_of_is_ntcf:
  assumes "r  𝔄Obj"
    and "u : c 𝔅𝔉ObjMapr"
  shows "ntcf_ua_of α 𝔉 c r u :
    HomO.Cα𝔄(r,-) CF HomO.Cα𝔅(c,-) CF 𝔉 : 𝔄 ↦↦Cαcat_Set α"
proof(intro is_ntcfI')
  let ?ua = ntcf_ua_of α 𝔉 c r u
  show "vfsequence (ntcf_ua_of α 𝔉 c r u)" unfolding ntcf_ua_of_def by simp
  show "vcard ?ua = 5" unfolding ntcf_ua_of_def by (simp add: nat_omega_simps)
  from assms(1) show "HomO.Cα𝔄(r,-) : 𝔄 ↦↦Cαcat_Set α"
    by (cs_concl cs_shallow cs_intro: cat_cs_intros)
  from is_functor_axioms assms(2) show 
    "HomO.Cα𝔅(c,-) CF 𝔉 : 𝔄 ↦↦Cαcat_Set α"
    by (cs_concl cs_intro: cat_cs_intros)
  from is_functor_axioms assms show "𝒟 (?uaNTMap) = 𝔄Obj"
    by (cs_concl cs_shallow cs_simp: cat_cs_simps)
  show "?uaNTMapa :
    HomO.Cα𝔄(r,-)ObjMapa cat_Set α(HomO.Cα𝔅(c,-) CF 𝔉)ObjMapa"
    if "a  𝔄Obj" for a
    using is_functor_axioms assms that 
    by (cs_concl cs_simp: cat_cs_simps cat_op_simps cs_intro: cat_cs_intros)
  show "?uaNTMapb Acat_Set αHomO.Cα𝔄(r,-)ArrMapf =
    (HomO.Cα𝔅(c,-) CF 𝔉)ArrMapf Acat_Set α?uaNTMapa"
    if "f : a 𝔄b" for a b f
    using is_functor_axioms assms that 
    by 
      ( 
        cs_concl 
          cs_simp: cf_umap_of_cf_hom_commute cat_cs_simps cat_op_simps 
          cs_intro: cat_cs_intros cat_op_intros
      )
qed (auto simp: ntcf_ua_of_components cat_cs_simps)

lemma (in is_functor) cf_ntcf_ua_fo_is_ntcf:
  assumes "r  𝔄Obj" and "u : 𝔉ObjMapr 𝔅c"
  shows "ntcf_ua_fo α 𝔉 c r u :
    HomO.Cα𝔄(-,r) CF HomO.Cα𝔅(-,c) CF op_cf 𝔉 :
    op_cat 𝔄 ↦↦Cαcat_Set α"
proof-
  from assms(2) have c: "c  𝔅Obj" by auto
  show ?thesis
    by 
      (
        rule is_functor.cf_ntcf_ua_of_is_ntcf
          [
            OF is_functor_op, 
            unfolded cat_op_simps, 
            OF assms(1,2),
            unfolded 
              HomDom.cat_op_cat_cf_Hom_snd[OF assms(1)] 
              HomCod.cat_op_cat_cf_Hom_snd[OF c]
              ntcf_ua_fo_def[symmetric]
          ]
      )
qed


subsubsection‹Universal natural transformation and universal arrow›


text‹
The lemmas in this subsection correspond to 
variants of elements of Proposition 1 in Chapter III-2 in 
cite"mac_lane_categories_2010".
›

lemma (in is_functor) cf_ntcf_ua_of_is_iso_ntcf:
  assumes "universal_arrow_of 𝔉 c r u"
  shows "ntcf_ua_of α 𝔉 c r u :
    HomO.Cα𝔄(r,-) CF.iso HomO.Cα𝔅(c,-) CF 𝔉 : 𝔄 ↦↦Cαcat_Set α"
proof-

  have r: "r  𝔄Obj"
    and u: "u : c 𝔅𝔉ObjMapr"
    and bij: "r' u'.
      
        r'  𝔄Obj; 
        u' : c 𝔅𝔉ObjMapr'
        ∃!f'. f' : r 𝔄r'  u' = umap_of 𝔉 c r u r'ArrValf'"
    by (auto intro!: universal_arrow_ofD[OF assms(1)])

  show ?thesis
  proof(intro is_iso_ntcfI)
    show "ntcf_ua_of α 𝔉 c r u :
      HomO.Cα𝔄(r,-) CF HomO.Cα𝔅(c,-) CF 𝔉 : 𝔄 ↦↦Cαcat_Set α"
      by (rule cf_ntcf_ua_of_is_ntcf[OF r u])
    fix a assume prems: "a  𝔄Obj"
    from is_functor_axioms prems r u have [simp]:
      "umap_of 𝔉 c r u a : Hom 𝔄 r a cat_Set αHom 𝔅 c (𝔉ObjMapa)"
      by (cs_concl cs_shallow cs_intro: cat_cs_intros)
    then have dom: "𝒟 (umap_of 𝔉 c r u aArrVal) = Hom 𝔄 r a"
      by (cs_concl cs_simp: cat_cs_simps)
    have "umap_of 𝔉 c r u a : Hom 𝔄 r a isocat_Set αHom 𝔅 c (𝔉ObjMapa)"
    proof(intro cat_Set_is_iso_arrI, unfold dom)
 
      show umof_a: "v11 (umap_of 𝔉 c r u aArrVal)"
      proof(intro vsv.vsv_valeq_v11I, unfold dom in_Hom_iff)
        fix g f assume prems': 
          "g : r 𝔄a"
          "f : r 𝔄a" 
          "umap_of 𝔉 c r u aArrValg = umap_of 𝔉 c r u aArrValf"
        from is_functor_axioms r u prems'(1) have 𝔉g:
          "𝔉ArrMapg A𝔅u : c 𝔅𝔉ObjMapa"
          by (cs_concl cs_shallow cs_intro: cat_cs_intros)
        from bij[OF prems 𝔉g] have unique:
          "
            f' : r 𝔄a;
            𝔉ArrMapg A𝔅u = umap_of 𝔉 c r u aArrValf' 
             g = f'"
          for f' by (metis prems'(1) u umap_of_ArrVal_app)
        from is_functor_axioms prems'(1,2) u have 𝔉g_u:
          "𝔉ArrMapg A𝔅u = umap_of 𝔉 c r u aArrValf"
          by (cs_concl cs_simp: prems'(3)[symmetric] cat_cs_simps)
        show "g = f" by (rule unique[OF prems'(2) 𝔉g_u])
      qed (auto simp: cat_cs_simps cat_cs_intros)

      interpret umof_a: v11 umap_of 𝔉 c r u aArrVal by (rule umof_a)

      show " (umap_of 𝔉 c r u aArrVal) = Hom 𝔅 c (𝔉ObjMapa)"
      proof(intro vsubset_antisym)
        from u show " (umap_of 𝔉 c r u aArrVal)  Hom 𝔅 c (𝔉ObjMapa)"
          by (rule umap_of_ArrVal_vrange)
        show "Hom 𝔅 c (𝔉ObjMapa)   (umap_of 𝔉 c r u aArrVal)"
        proof(rule vsubsetI, unfold in_Hom_iff )
          fix f assume prems': "f : c 𝔅𝔉ObjMapa"
          from bij[OF prems prems'] obtain f' 
            where f': "f' : r 𝔄a" 
              and f_def: "f = umap_of 𝔉 c r u aArrValf'"
            by auto
          from is_functor_axioms prems prems' u f' have 
            "f'  𝒟 (umap_of 𝔉 c r u aArrVal)"
            by (cs_concl cs_shallow cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
          from this show "f   (umap_of 𝔉 c r u aArrVal)"
            unfolding f_def by (rule umof_a.vsv_vimageI2)
        qed

      qed

    qed simp_all

    from is_functor_axioms prems r u this show 
      "ntcf_ua_of α 𝔉 c r uNTMapa :
        HomO.Cα𝔄(r,-)ObjMapa isocat_Set α(HomO.Cα𝔅(c,-) CF 𝔉)ObjMapa"
      by 
        (
          cs_concl  
            cs_simp: cat_cs_simps cat_op_simps 
            cs_intro: cat_cs_intros cat_op_intros
        )
  qed

qed

lemmas [cat_cs_intros] = is_functor.cf_ntcf_ua_of_is_iso_ntcf

lemma (in is_functor) cf_ntcf_ua_fo_is_iso_ntcf:
  assumes "universal_arrow_fo 𝔉 c r u"
  shows "ntcf_ua_fo α 𝔉 c r u :
    HomO.Cα𝔄(-,r) CF.iso HomO.Cα𝔅(-,c) CF op_cf 𝔉 :
    op_cat 𝔄 ↦↦Cαcat_Set α"
proof-
  from universal_arrow_foD[OF assms] have r: "r  𝔄Obj" and c: "c  𝔅Obj"
    by auto
  show ?thesis
    by 
      (
        rule is_functor.cf_ntcf_ua_of_is_iso_ntcf
          [
            OF is_functor_op, 
            unfolded cat_op_simps, 
            OF assms,
            unfolded 
              HomDom.cat_op_cat_cf_Hom_snd[OF r] 
              HomCod.cat_op_cat_cf_Hom_snd[OF c]
              ntcf_ua_fo_def[symmetric]
          ]
      ) 
qed

lemmas [cat_cs_intros] = is_functor.cf_ntcf_ua_fo_is_iso_ntcf

lemma (in is_functor) cf_ua_of_if_ntcf_ua_of_is_iso_ntcf:
  assumes "r  𝔄Obj"
    and "u : c 𝔅𝔉ObjMapr"
    and "ntcf_ua_of α 𝔉 c r u :
      HomO.Cα𝔄(r,-) CF.iso HomO.Cα𝔅(c,-) CF 𝔉 : 𝔄 ↦↦Cαcat_Set α"
  shows "universal_arrow_of 𝔉 c r u"
proof(rule universal_arrow_ofI)
  interpret ua_of_u: is_iso_ntcf 
    α 
    𝔄 
    cat_Set α
    HomO.Cα𝔄(r,-) 
    HomO.Cα𝔅(c,-) CF 𝔉 
    ntcf_ua_of α 𝔉 c r u
    by (rule assms(3))
  fix r' u' assume prems: "r'  𝔄Obj" "u' : c 𝔅𝔉ObjMapr'"  
  have "ntcf_ua_of α 𝔉 c r uNTMapr' :
    HomO.Cα𝔄(r,-)ObjMapr' isocat_Set α(HomO.Cα𝔅(c,-) CF 𝔉)ObjMapr'"
    by (rule is_iso_ntcf.iso_ntcf_is_iso_arr[OF assms(3) prems(1)])
  from this is_functor_axioms assms(1-2) prems have uof_r':
    "umap_of 𝔉 c r u r' : Hom 𝔄 r r' isocat_Set αHom 𝔅 c (𝔉ObjMapr')"
    by (cs_prems cs_simp: cat_cs_simps cs_intro: cat_cs_intros cat_op_intros)
  note uof_r' = cat_Set_is_iso_arrD[OF uof_r']  
  interpret uof_r': v11 umap_of 𝔉 c r u r'ArrVal by (rule uof_r'(2))  
  from 
    uof_r'.v11_vrange_ex1_eq[
      THEN iffD1, unfolded uof_r'(3,4) in_Hom_iff, OF prems(2)
      ] 
  show "∃!f'. f' : r 𝔄r'  u' = umap_of 𝔉 c r u r'ArrValf'"
    by metis
qed (intro assms)+

lemma (in is_functor) cf_ua_fo_if_ntcf_ua_fo_is_iso_ntcf:
  assumes "r  𝔄Obj"
    and "u : 𝔉ObjMapr 𝔅c"
    and "ntcf_ua_fo α 𝔉 c r u :
      HomO.Cα𝔄(-,r) CF.iso HomO.Cα𝔅(-,c) CF op_cf 𝔉 :
      op_cat 𝔄 ↦↦Cαcat_Set α"
  shows "universal_arrow_fo 𝔉 c r u"
proof-
  from assms(2) have c: "c  𝔅Obj" by auto
  show ?thesis
    by 
      (
        rule is_functor.cf_ua_of_if_ntcf_ua_of_is_iso_ntcf
          [
            OF is_functor_op, 
            unfolded cat_op_simps,
            OF assms(1,2),
            unfolded 
              HomDom.cat_op_cat_cf_Hom_snd[OF assms(1)] 
              HomCod.cat_op_cat_cf_Hom_snd[OF c]
              ntcf_ua_fo_def[symmetric],
            OF assms(3)
          ]
      )
qed

lemma (in is_functor) cf_universal_arrow_of_if_is_iso_ntcf:
  assumes "r  𝔄Obj"
    and "c  𝔅Obj"
    and "φ :
      HomO.Cα𝔄(r,-) CF.iso HomO.Cα𝔅(c,-) CF 𝔉 : 𝔄 ↦↦Cαcat_Set α"
  shows "universal_arrow_of 𝔉 c r (φNTMaprArrVal𝔄CIdr)"
    (is universal_arrow_of 𝔉 c r ?u)
proof-

  interpret φ: is_iso_ntcf 
    α 𝔄 cat_Set α HomO.Cα𝔄(r,-) HomO.Cα𝔅(c,-) CF 𝔉 φ
    by (rule assms(3))

  show ?thesis
  proof(intro universal_arrow_ofI assms)
 
    from assms(1,2) show u: "?u : c 𝔅𝔉ObjMapr"
      by 
        (
          cs_concl cs_shallow  
            cs_simp: cat_cs_simps cat_op_simps cs_intro: cat_cs_intros
        )
    fix r' u' assume prems: "r'  𝔄Obj" "u' : c 𝔅𝔉ObjMapr'"
    have φr'_ArrVal_app[symmetric, cat_cs_simps]:
      "φNTMapr'ArrValf' =
        𝔉ArrMapf' A𝔅φNTMaprArrVal𝔄CIdr"
      if "f' : r 𝔄r'" for f'
    proof-
      have "φNTMapr' Acat_Set αHomO.Cα𝔄(r,-)ArrMapf' =
        (HomO.Cα𝔅(c,-) CF 𝔉)ArrMapf' Acat_Set αφNTMapr"
        using that by (intro φ.ntcf_Comp_commute)
      then have 
        "φNTMapr' Acat_Set αcf_hom 𝔄 [𝔄CIdr, f'] =
          cf_hom 𝔅 [𝔅CIdc, 𝔉ArrMapf'] Acat_Set αφNTMapr" 
        using assms(1,2) that prems
        by 
          (
            cs_prems cs_shallow 
              cs_simp: cat_cs_simps cat_op_simps cs_intro: cat_cs_intros
          )
      then have
        "(φNTMapr' Acat_Set αcf_hom 𝔄 [𝔄CIdr, f'])ArrVal𝔄CIdr =
          (cf_hom 𝔅 [𝔅CIdc, 𝔉ArrMapf'] Acat_Set αφNTMapr)ArrVal𝔄CIdr"
         by simp
      from this assms(1,2) u that show ?thesis
        by
          (
            cs_prems cs_shallow
              cs_simp: cat_cs_simps cat_op_simps 
              cs_intro: cat_cs_intros cat_op_intros cat_prod_cs_intros
          )
    qed 
    
    show "∃!f'. f' : r 𝔄r'  u' = umap_of 𝔉 c r ?u r'ArrValf'"
    proof(intro ex1I conjI; (elim conjE)?)
      from assms prems show 
        "(φNTMapr')¯Ccat_Set αArrValu' : r 𝔄r'"
        by
          (
            cs_concl 
              cs_simp: cat_cs_simps cat_op_simps
              cs_intro: cat_cs_intros cat_arrow_cs_intros
          )
      with assms(1,2) prems show "u' =
        umap_of 𝔉 c r ?u r'ArrVal(φNTMapr')¯Ccat_Set αArrValu'"
        by
          (
            cs_concl cs_shallow
              cs_simp: cat_cs_simps cat_op_simps
              cs_intro: cat_arrow_cs_intros cat_cs_intros cat_op_intros
          )
      fix f' assume prems': 
        "f' : r 𝔄r'"
        "u' = umap_of 𝔉 c r (φNTMaprArrVal𝔄CIdr) r'ArrValf'"
      from prems'(2,1) assms(1,2) have u'_def: 
        "u' = 𝔉ArrMapf' A𝔅φNTMaprArrVal𝔄CIdr"
        by
          (
            cs_prems cs_shallow
              cs_simp: cat_cs_simps cat_op_simps
              cs_intro: cat_cs_intros cat_op_intros
          )
      from prems' show "f' = (φNTMapr')¯Ccat_Set αArrValu'"
        unfolding u'_def φr'_ArrVal_app[OF prems'(1)]
        by
          (
            cs_concl 
              cs_simp: cat_cs_simps
              cs_intro: cat_arrow_cs_intros cat_cs_intros cat_op_intros
          )

    qed

  qed

qed

lemma (in is_functor) cf_universal_arrow_fo_if_is_iso_ntcf:
  assumes "r  𝔄Obj"
    and "c  𝔅Obj"
    and "φ :
      HomO.Cα𝔄(-,r) CF.iso HomO.Cα𝔅(-,c) CF op_cf 𝔉 :
      op_cat 𝔄 ↦↦Cαcat_Set α"
  shows "universal_arrow_fo 𝔉 c r (φNTMaprArrVal𝔄CIdr)"
  by
    (
      rule is_functor.cf_universal_arrow_of_if_is_iso_ntcf
        [
          OF is_functor_op,
          unfolded cat_op_simps,
          OF assms(1,2),
          unfolded 
            HomDom.cat_op_cat_cf_Hom_snd[OF assms(1)] 
            HomCod.cat_op_cat_cf_Hom_snd[OF assms(2)]
            ntcf_ua_fo_def[symmetric],
          OF assms(3)
        ]
  )

text‹\newpage›

end