Theory CZH_UCAT_Limit_Pullback

(* Copyright 2021 (C) Mihails Milehins *)

section‹Pullbacks and pushouts as limits and colimits›
theory CZH_UCAT_Limit_Pullback
  imports 
    CZH_UCAT_Limit
    CZH_Elementary_Categories.CZH_ECAT_SS
begin



subsection‹Pullback and pushout›


subsubsection‹Definition and elementary properties›


text‹
The definitions and the elementary properties of the pullbacks and the 
pushouts can be found, for example, in Chapter III-3 and Chapter III-4 in 
cite"mac_lane_categories_2010". 
›

locale is_cat_pullback =
  is_cat_limit α →∙←C  𝔞𝔤𝔬𝔣𝔟CF⇙› X x + 
  cf_scospan α 𝔞 𝔤 𝔬 𝔣 𝔟 
  for α 𝔞 𝔤 𝔬 𝔣 𝔟  X x 

syntax "_is_cat_pullback" :: "V  V  V  V  V  V  V  V  V  bool"
  ((_ :/ _ <CF.pb _____ ↦↦Cı _) [51, 51, 51, 51, 51, 51, 51, 51] 51)
translations "x : X <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"  
  "CONST is_cat_pullback α 𝔞 𝔤 𝔬 𝔣 𝔟  X x"
                        
locale is_cat_pushout =
  is_cat_colimit α ←∙→C  𝔞𝔤𝔬𝔣𝔟CF⇙› X x +
  cf_sspan α 𝔞 𝔤 𝔬 𝔣 𝔟 
  for α 𝔞 𝔤 𝔬 𝔣 𝔟  X x

syntax "_is_cat_pushout" :: "V  V  V  V  V  V  V  V  V  bool"
  ((_ :/ _____ >CF.po _ ↦↦Cı _) [51, 51, 51, 51, 51, 51, 51, 51] 51)
translations "x : 𝔞𝔤𝔬𝔣𝔟 >CF.po X ↦↦Cα"  
  "CONST is_cat_pushout α 𝔞 𝔤 𝔬 𝔣 𝔟  X x"


text‹Rules.›

lemma (in is_cat_pullback) is_cat_pullback_axioms'[cat_lim_cs_intros]:
  assumes "α' = α"
    and "𝔞' = 𝔞"
    and "𝔤' = 𝔤"
    and "𝔬' = 𝔬"
    and "𝔣' = 𝔣"
    and "𝔟' = 𝔟"
    and "ℭ' = "
    and "X' = X"
  shows "x : X' <CF.pb 𝔞'𝔤'𝔬'𝔣'𝔟' ↦↦Cα'ℭ'"
  unfolding assms by (rule is_cat_pullback_axioms)

mk_ide rf is_cat_pullback_def
  |intro is_cat_pullbackI|
  |dest is_cat_pullbackD[dest]|
  |elim is_cat_pullbackE[elim]|

lemmas [cat_lim_cs_intros] = is_cat_pullbackD

lemma (in is_cat_pushout) is_cat_pushout_axioms'[cat_lim_cs_intros]:
  assumes "α' = α"
    and "𝔞' = 𝔞"
    and "𝔤' = 𝔤"
    and "𝔬' = 𝔬"
    and "𝔣' = 𝔣"
    and "𝔟' = 𝔟"
    and "ℭ' = "
    and "X' = X"
  shows "x : 𝔞'𝔤'𝔬'𝔣'𝔟' >CF.po X' ↦↦Cα'ℭ'"
  unfolding assms by (rule is_cat_pushout_axioms)

mk_ide rf is_cat_pushout_def
  |intro is_cat_pushoutI|
  |dest is_cat_pushoutD[dest]|
  |elim is_cat_pushoutE[elim]|

lemmas [cat_lim_cs_intros] = is_cat_pushoutD


text‹Duality.›

lemma (in is_cat_pullback) is_cat_pushout_op:
  "op_ntcf x : 𝔞𝔤𝔬𝔣𝔟 >CF.po X ↦↦Cαop_cat "
  by (intro is_cat_pushoutI) 
    (cs_concl cs_shallow cs_simp: cat_op_simps cs_intro: cat_op_intros)+

lemma (in is_cat_pullback) is_cat_pushout_op'[cat_op_intros]:
  assumes "ℭ' = op_cat "
  shows "op_ntcf x : 𝔞𝔤𝔬𝔣𝔟 >CF.po X ↦↦Cαℭ'"
  unfolding assms by (rule is_cat_pushout_op)

lemmas [cat_op_intros] = is_cat_pullback.is_cat_pushout_op'

lemma (in is_cat_pushout) is_cat_pullback_op:
  "op_ntcf x : X <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cαop_cat "
  by (intro is_cat_pullbackI) 
    (cs_concl cs_shallow cs_simp: cat_op_simps cs_intro: cat_op_intros)+

lemma (in is_cat_pushout) is_cat_pullback_op'[cat_op_intros]:
  assumes "ℭ' = op_cat "
  shows "op_ntcf x : X <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cαℭ'"
  unfolding assms by (rule is_cat_pullback_op)

lemmas [cat_op_intros] = is_cat_pushout.is_cat_pullback_op'


text‹Elementary properties.›

lemma cat_cone_cospan:
  assumes "x : X <CF.cone 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα"
    and "cf_scospan α 𝔞 𝔤 𝔬 𝔣 𝔟 "
  shows "xNTMap𝔬SS = 𝔤 AxNTMap𝔞SS"
    and "xNTMap𝔬SS = 𝔣 AxNTMap𝔟SS"
    and "𝔤 AxNTMap𝔞SS = 𝔣 AxNTMap𝔟SS"
proof-
  interpret x: is_cat_cone α X →∙←C  𝔞𝔤𝔬𝔣𝔟CF⇙› x 
    by (rule assms(1))
  interpret cospan: cf_scospan α 𝔞 𝔤 𝔬 𝔣 𝔟  by (rule assms(2))
  have 𝔤SS: "𝔤SS : 𝔞SS →∙←C𝔬SS" and 𝔣SS: "𝔣SS : 𝔟SS →∙←C𝔬SS" 
    by (cs_concl cs_intro: cat_ss_cs_intros)+
  note x.cat_cone_Comp_commute[cat_cs_simps del]
  from x.ntcf_Comp_commute[OF 𝔤SS] 𝔤SS 𝔣SS show
    "xNTMap𝔬SS = 𝔤 AxNTMap𝔞SS"
    by 
      (
        cs_prems cs_shallow
          cs_simp: cat_ss_cs_simps cat_cs_simps cs_intro: cat_cs_intros
      )
  moreover from x.ntcf_Comp_commute[OF 𝔣SS] 𝔤SS 𝔣SS show 
    "xNTMap𝔬SS = 𝔣 AxNTMap𝔟SS"
    by 
      (
        cs_prems cs_shallow 
          cs_simp: cat_ss_cs_simps cat_cs_simps cs_intro: cat_cs_intros
      )
  ultimately show "𝔤 AxNTMap𝔞SS = 𝔣 AxNTMap𝔟SS" by simp
qed

lemma (in is_cat_pullback) cat_pb_cone_cospan:
  shows "xNTMap𝔬SS = 𝔤 AxNTMap𝔞SS"
    and "xNTMap𝔬SS = 𝔣 AxNTMap𝔟SS"
    and "𝔤 AxNTMap𝔞SS = 𝔣 AxNTMap𝔟SS"
  by (allrule cat_cone_cospan[OF is_cat_cone_axioms cf_scospan_axioms])

lemma cat_cocone_span:
  assumes "x : 𝔞𝔤𝔬𝔣𝔟CF>CF.cocone X : ←∙→C ↦↦Cα"
    and "cf_sspan α 𝔞 𝔤 𝔬 𝔣 𝔟 "
  shows "xNTMap𝔬SS = xNTMap𝔞SS A𝔤"
    and "xNTMap𝔬SS = xNTMap𝔟SS A𝔣"
    and "xNTMap𝔞SS A𝔤 = xNTMap𝔟SS A𝔣"
proof-
  interpret x: is_cat_cocone α X ←∙→C  𝔞𝔤𝔬𝔣𝔟CF⇙› x
    by (rule assms(1))
  interpret span: cf_sspan α 𝔞 𝔤 𝔬 𝔣 𝔟  by (rule assms(2))
  note op = 
    cat_cone_cospan
      [
        OF 
          x.is_cat_cone_op[unfolded cat_op_simps] 
          span.cf_scospan_op, 
          unfolded cat_op_simps
      ]
  from op(1) show "xNTMap𝔬SS = xNTMap𝔞SS A𝔤"
    by 
      (
        cs_prems  
          cs_simp: cat_ss_cs_simps cat_op_simps 
          cs_intro: cat_cs_intros cat_ss_cs_intros
      )
  moreover from op(2) show "xNTMap𝔬SS = xNTMap𝔟SS A𝔣"
    by 
      (
        cs_prems 
          cs_simp: cat_ss_cs_simps cat_op_simps 
          cs_intro: cat_cs_intros cat_ss_cs_intros
      )
  ultimately show "xNTMap𝔞SS A𝔤 = xNTMap𝔟SS A𝔣" by auto
qed

lemma (in is_cat_pushout) cat_po_cocone_span:
  shows "xNTMap𝔬SS = xNTMap𝔞SS A𝔤"
    and "xNTMap𝔬SS = xNTMap𝔟SS A𝔣"
    and "xNTMap𝔞SS A𝔤 = xNTMap𝔟SS A𝔣"
  by (allrule cat_cocone_span[OF is_cat_cocone_axioms cf_sspan_axioms])


subsubsection‹Universal property›

lemma is_cat_pullbackI':
  assumes "x : X <CF.cone 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα"
    and "cf_scospan α 𝔞 𝔤 𝔬 𝔣 𝔟 "
    and "x' X'. x' : X' <CF.cone 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα 
      ∃!f'.
        f' : X' X 
        x'NTMap𝔞SS = xNTMap𝔞SS Af' 
        x'NTMap𝔟SS = xNTMap𝔟SS Af'"
  shows "x : X <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"
proof(intro is_cat_pullbackI is_cat_limitI)

  show "x : X <CF.cone 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα" 
    by (rule assms(1))
  interpret x: is_cat_cone α X →∙←C  𝔞𝔤𝔬𝔣𝔟CF⇙› x 
    by (rule assms(1))
  show "cf_scospan α 𝔞 𝔤 𝔬 𝔣 𝔟 " by (rule assms(2))
  interpret cospan: cf_scospan α 𝔞 𝔤 𝔬 𝔣 𝔟  by (rule assms(2))

  fix u' r' assume prems:
    "u' : r' <CF.cone 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα"

  interpret u': is_cat_cone α r' →∙←C  𝔞𝔤𝔬𝔣𝔟CF⇙› u' 
    by (rule prems)

  from assms(3)[OF prems] obtain f' 
    where f': "f' : r' X"
      and u'_𝔞SS: "u'NTMap𝔞SS = xNTMap𝔞SS Af'"
      and u'_𝔟SS: "u'NTMap𝔟SS = xNTMap𝔟SS Af'"
      and unique_f': "f''.
        
          f'' : r' X;
          u'NTMap𝔞SS = xNTMap𝔞SS Af'';
          u'NTMap𝔟SS = xNTMap𝔟SS Af''
          f'' = f'"
    by metis

  show "∃!f'. f' : r' X  u' = x NTCF ntcf_const →∙←C  f'"
  proof(intro ex1I conjI; (elim conjE)?)

    show "u' = x NTCF ntcf_const →∙←C  f'"
    proof(rule ntcf_eqI)
      show "u' : cf_const →∙←C  r' CF 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα"
        by (rule u'.is_ntcf_axioms)
      from f' show 
        "x NTCF ntcf_const →∙←C  f' :
          cf_const →∙←C  r' CF 𝔞𝔤𝔬𝔣𝔟CF:
          →∙←C ↦↦Cα"
        by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      from f' have dom_rhs: 
        "𝒟 ((x NTCF ntcf_const →∙←C  f')NTMap) = →∙←CObj"
        by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      show "u'NTMap = (x NTCF ntcf_const →∙←C  f')NTMap"
      proof(rule vsv_eqI, unfold cat_cs_simps dom_rhs)
        fix a assume prems': "a  →∙←CObj"
        from this f' x.is_ntcf_axioms show
          "u'NTMapa = (x NTCF ntcf_const →∙←C  f')NTMapa"
          by (elim the_cat_scospan_ObjE; simp only:)
            (
              cs_concl 
                cs_simp:
                  cat_cs_simps cat_ss_cs_simps 
                  u'_𝔟SS u'_𝔞SS 
                  cat_cone_cospan(1)[OF assms(1,2)] 
                  cat_cone_cospan(1)[OF prems assms(2)] 
                cs_intro: cat_cs_intros cat_ss_cs_intros
            )+
      qed (cs_concl cs_intro: cat_cs_intros | auto)+
    qed simp_all

    fix f'' assume prems: 
      "f'' : r' X" "u' = x NTCF ntcf_const →∙←C  f''"
    have 𝔞SS: "𝔞SS  →∙←CObj" and 𝔟SS: "𝔟SS  →∙←CObj" 
      by (cs_concl cs_intro: cat_ss_cs_intros)+
    have "u'NTMapa = xNTMapa Af''" if "a  →∙←CObj" for a
    proof-
      from prems(2) have 
        "u'NTMapa = (x NTCF ntcf_const →∙←C  f'')NTMapa"
        by simp
      from this that prems(1) show "u'NTMapa = xNTMapa Af''"
        by (cs_prems cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
    qed
    from unique_f'[OF prems(1) this[OF 𝔞SS] this[OF 𝔟SS]] show "f'' = f'".

  qed (intro f')

qed

lemma is_cat_pushoutI':
  assumes "x : 𝔞𝔤𝔬𝔣𝔟CF>CF.cocone X : ←∙→C ↦↦Cα"
    and "cf_sspan α 𝔞 𝔤 𝔬 𝔣 𝔟 "
    and "x' X'. x' : 𝔞𝔤𝔬𝔣𝔟CF>CF.cocone X' : ←∙→C ↦↦Cα 
      ∃!f'.
        f' : X X' 
        x'NTMap𝔞SS = f' AxNTMap𝔞SS 
        x'NTMap𝔟SS = f' AxNTMap𝔟SS"
  shows "x : 𝔞𝔤𝔬𝔣𝔟 >CF.po X ↦↦Cα"
proof-
  interpret x: is_cat_cocone α X ←∙→C  𝔞𝔤𝔬𝔣𝔟CF⇙› x 
    by (rule assms(1))
  interpret span: cf_sspan α 𝔞 𝔤 𝔬 𝔣 𝔟  by (rule assms(2))
  have assms_3': 
    "∃!f'.
      f' : X X' 
      x'NTMap𝔞SS = xNTMap𝔞SS Aop_cat f' 
      x'NTMap𝔟SS = xNTMap𝔟SS Aop_cat f'"
    if "x' : X' <CF.cone 𝔞𝔤𝔬𝔣𝔟CFop_cat : →∙←C ↦↦Cαop_cat "
    for x' X'
  proof-
    from that(1) have [cat_op_simps]:
      "f' : X X'  
      x'NTMap𝔞SS = xNTMap𝔞SS Aop_cat f' 
      x'NTMap𝔟SS = xNTMap𝔟SS Aop_cat f' 
        f' : X X' 
        x'NTMap𝔞SS = f' AxNTMap𝔞SS 
        x'NTMap𝔟SS = f' AxNTMap𝔟SS" 
      for f'
      by (intro iffI conjI; (elim conjE)?)
        (
          cs_concl 
            cs_simp: category.op_cat_Comp[symmetric] cat_op_simps cat_cs_simps 
            cs_intro: cat_cs_intros cat_ss_cs_intros
        )+
    interpret x': 
      is_cat_cone α X' →∙←C op_cat  𝔞𝔤𝔬𝔣𝔟CFop_cat ⇙› x'
      by (rule that)
    show ?thesis
      unfolding cat_op_simps
      by 
        (
          rule assms(3)[
            OF x'.is_cat_cocone_op[unfolded cat_op_simps], 
            unfolded cat_op_simps
            ]
        )
  qed
  interpret op_x: is_cat_pullback α 𝔞 𝔤 𝔬 𝔣 𝔟 op_cat  X op_ntcf x 
    using 
      is_cat_pullbackI'
        [
          OF x.is_cat_cone_op[unfolded cat_op_simps] 
          span.cf_scospan_op, 
          unfolded cat_op_simps, 
          OF assms_3'
        ]
    by simp
  show "x : 𝔞𝔤𝔬𝔣𝔟 >CF.po X ↦↦Cα"
    by (rule op_x.is_cat_pushout_op[unfolded cat_op_simps])
qed
                   
lemma (in is_cat_pullback) cat_pb_unique_cone:
  assumes "x' : X' <CF.cone 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα"
  shows "∃!f'.
    f' : X' X 
    x'NTMap𝔞SS = xNTMap𝔞SS Af' 
    x'NTMap𝔟SS = xNTMap𝔟SS Af'"
proof-
  interpret x': is_cat_cone α X' →∙←C  𝔞𝔤𝔬𝔣𝔟CF⇙› x' 
    by (rule assms)
  from cat_lim_ua_fo[OF assms] obtain f'
    where f': "f' : X' X" 
      and x'_def: "x' = x NTCF ntcf_const →∙←C  f'"
      and unique_f': "f''.
         f'' : X' X; x' = x NTCF ntcf_const →∙←C  f''  
        f'' = f'"
    by auto
  have 𝔞SS: "𝔞SS  →∙←CObj" and 𝔟SS: "𝔟SS  →∙←CObj"
    by (cs_concl cs_intro: cat_ss_cs_intros)+
  show ?thesis
  proof(intro ex1I conjI; (elim conjE)?)
    show "f' : X' X" by (rule f')
    have "x'NTMapa = xNTMapa Af'" if "a  →∙←CObj" for a
    proof-
      from x'_def have 
        "x'NTMapa = (x NTCF ntcf_const →∙←C  f')NTMapa"
        by simp
      from this that f' show "x'NTMapa = xNTMapa Af'"
        by (cs_prems cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
    qed
    from this[OF 𝔞SS] this[OF 𝔟SS] show 
      "x'NTMap𝔞SS = xNTMap𝔞SS Af'"
      "x'NTMap𝔟SS = xNTMap𝔟SS Af'"
      by auto
    fix f'' assume prems': 
      "f'' : X' X"
      "x'NTMap𝔞SS = xNTMap𝔞SS Af''"
      "x'NTMap𝔟SS = xNTMap𝔟SS Af''"
    have "x' = x NTCF ntcf_const →∙←C  f''"
    proof(rule ntcf_eqI)
      show "x' : cf_const →∙←C  X' CF 𝔞𝔤𝔬𝔣𝔟CF: →∙←C ↦↦Cα"
        by (rule x'.is_ntcf_axioms)
      from prems'(1) show
        "x NTCF ntcf_const →∙←C  f'' :
          cf_const →∙←C  X' CF 𝔞𝔤𝔬𝔣𝔟CF:
          →∙←C ↦↦Cα"
        by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      have dom_lhs: "𝒟 (x'NTMap) = →∙←CObj" 
        by (cs_concl cs_shallow cs_simp: cat_cs_simps)
      from prems'(1) have dom_rhs:
        "𝒟 ((x NTCF ntcf_const →∙←C  f'')NTMap) = →∙←CObj"
        by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      show "x'NTMap = (x NTCF ntcf_const →∙←C  f'')NTMap"
      proof(rule vsv_eqI, unfold dom_lhs dom_rhs)
        fix a assume prems'': "a  →∙←CObj"
        from this prems'(1) show 
          "x'NTMapa = (x NTCF ntcf_const →∙←C  f'')NTMapa"
          by (elim the_cat_scospan_ObjE; simp only:)
            (
              cs_concl 
                cs_simp: 
                  prems'(2,3)
                  cat_cone_cospan(1,2)[OF assms cf_scospan_axioms] 
                  cat_pb_cone_cospan 
                  cat_ss_cs_simps cat_cs_simps 
                cs_intro: cat_ss_cs_intros cat_cs_intros
            )+
      qed (auto simp: cat_cs_intros)
    qed simp_all
    from unique_f'[OF prems'(1) this] show "f'' = f'".
  qed
qed

lemma (in is_cat_pullback) cat_pb_unique:
  assumes "x' : X' <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"
  shows "∃!f'. f' : X' X  x' = x NTCF ntcf_const →∙←C  f'"
  by (rule cat_lim_unique[OF is_cat_pullbackD(1)[OF assms]])

lemma (in is_cat_pullback) cat_pb_unique':
  assumes "x' : X' <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"
  shows "∃!f'.
    f' : X' X 
    x'NTMap𝔞SS = xNTMap𝔞SS Af' 
    x'NTMap𝔟SS = xNTMap𝔟SS Af'"
proof-
  interpret x': is_cat_pullback α 𝔞 𝔤 𝔬 𝔣 𝔟  X' x' by (rule assms(1))
  show ?thesis by (rule cat_pb_unique_cone[OF x'.is_cat_cone_axioms])
qed

lemma (in is_cat_pushout) cat_po_unique_cocone:
  assumes "x' : 𝔞𝔤𝔬𝔣𝔟CF>CF.cocone X' : ←∙→C ↦↦Cα"
  shows "∃!f'.
    f' : X X' 
    x'NTMap𝔞SS = f' AxNTMap𝔞SS 
    x'NTMap𝔟SS = f' AxNTMap𝔟SS"
proof-
  interpret x': is_cat_cocone α X' ←∙→C  𝔞𝔤𝔬𝔣𝔟CF⇙› x'
    by (rule assms(1))
  have [cat_op_simps]:
    "f' : X X' 
    x'NTMap𝔞SS = xNTMap𝔞SS Aop_cat f' 
    x'NTMap𝔟SS = xNTMap𝔟SS Aop_cat f' 
      f' : X X' 
      x'NTMap𝔞SS = f' AxNTMap𝔞SS 
      x'NTMap𝔟SS = f' AxNTMap𝔟SS" 
    for f'
    by (intro iffI conjI; (elim conjE)?)
      (
        cs_concl 
          cs_simp: category.op_cat_Comp[symmetric] cat_op_simps cat_cs_simps  
          cs_intro: cat_cs_intros cat_ss_cs_intros
      )+
  show ?thesis
    by 
      (
        rule is_cat_pullback.cat_pb_unique_cone[
          OF is_cat_pullback_op x'.is_cat_cone_op[unfolded cat_op_simps], 
          unfolded cat_op_simps
          ]
     )
qed

lemma (in is_cat_pushout) cat_po_unique:
  assumes "x' : 𝔞𝔤𝔬𝔣𝔟 >CF.po X' ↦↦Cα"
  shows "∃!f'. f' : X X'  x' = ntcf_const ←∙→C  f' NTCF x"
  by (rule cat_colim_unique[OF is_cat_pushoutD(1)[OF assms]])

lemma (in is_cat_pushout) cat_po_unique':
  assumes "x' : 𝔞𝔤𝔬𝔣𝔟 >CF.po X' ↦↦Cα"
  shows "∃!f'.
    f' : X X' 
    x'NTMap𝔞SS = f' AxNTMap𝔞SS 
    x'NTMap𝔟SS = f' AxNTMap𝔟SS"
proof-
  interpret x': is_cat_pushout α 𝔞 𝔤 𝔬 𝔣 𝔟  X' x' by (rule assms(1))
  show ?thesis by (rule cat_po_unique_cocone[OF x'.is_cat_cocone_axioms])
qed

lemma cat_pullback_ex_is_iso_arr:
  assumes "x : X <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"
    and "x' : X' <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"
  obtains f where "f : X' isoX" 
    and "x' = x NTCF ntcf_const →∙←C   f"
proof-
  interpret x: is_cat_pullback α 𝔞 𝔤 𝔬 𝔣 𝔟  X x by (rule assms(1))
  interpret x': is_cat_pullback α 𝔞 𝔤 𝔬 𝔣 𝔟  X' x' by (rule assms(2))
  from that show ?thesis
    by 
      (
        elim cat_lim_ex_is_iso_arr[
          OF x.is_cat_limit_axioms x'.is_cat_limit_axioms
          ]
      )
qed

lemma cat_pullback_ex_is_iso_arr':
  assumes "x : X <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"
    and "x' : X' <CF.pb 𝔞𝔤𝔬𝔣𝔟 ↦↦Cα"
  obtains f where "f : X' isoX" 
    and "x'NTMap𝔞SS = xNTMap𝔞SS Af"
    and "x'NTMap𝔟SS = xNTMap𝔟SS Af"
proof-
  interpret x: is_cat_pullback α 𝔞 𝔤 𝔬 𝔣 𝔟  X x by (rule assms(1))
  interpret x': is_cat_pullback α 𝔞 𝔤 𝔬 𝔣 𝔟  X' x' by (rule assms(2))
  obtain f where f: "f : X' isoX"
    and "j  →∙←CObj  x'NTMapj = xNTMapj Af" for j
    by 
      (
        elim cat_lim_ex_is_iso_arr'[
          OF x.is_cat_limit_axioms x'.is_cat_limit_axioms
          ]
      )
  then have 
    "x'NTMap𝔞SS = xNTMap𝔞SS Af" 
    "x'NTMap𝔟SS = xNTMap𝔟SS Af"
    by (auto simp: cat_ss_cs_intros)
  with f show ?thesis using that by simp
qed

lemma cat_pushout_ex_is_iso_arr:
  assumes "x : 𝔞𝔤𝔬𝔣𝔟 >CF.po X ↦↦Cα"
    and "x' : 𝔞𝔤𝔬𝔣𝔟 >CF.po X' ↦↦Cα"
  obtains f where "f : X isoX'" 
    and "x' = ntcf_const ←∙→C  f NTCF x"
proof-
  interpret x: is_cat_pushout α 𝔞 𝔤 𝔬 𝔣 𝔟  X x by (rule assms(1))
  interpret x': is_cat_pushout α 𝔞 𝔤 𝔬 𝔣 𝔟  X' x' by (rule assms(2))
  from that show ?thesis
    by 
      (
        elim cat_colim_ex_is_iso_arr[
          OF x.is_cat_colimit_axioms x'.is_cat_colimit_axioms
          ]
      )
qed

lemma cat_pushout_ex_is_iso_arr':
  assumes "x : 𝔞𝔤𝔬𝔣𝔟 >CF.po X ↦↦Cα"
    and "x' : 𝔞𝔤𝔬𝔣𝔟 >CF.po X' ↦↦Cα"
  obtains f where "f : X isoX'" 
    and "x'NTMap𝔞SS = f AxNTMap𝔞SS"
    and "x'NTMap𝔟SS = f AxNTMap𝔟SS"
proof-
  interpret x: is_cat_pushout α 𝔞 𝔤 𝔬 𝔣 𝔟  X x by (rule assms(1))
  interpret x': is_cat_pushout α 𝔞 𝔤 𝔬 𝔣 𝔟  X' x' by (rule assms(2))
  obtain f where f: "f : X isoX'"
    and "j  ←∙→CObj  x'NTMapj = f AxNTMapj" for j
    by 
      (
        elim cat_colim_ex_is_iso_arr'[
          OF x.is_cat_colimit_axioms x'.is_cat_colimit_axioms
          ]
      )
  then have "x'NTMap𝔞SS = f AxNTMap𝔞SS"
    and "x'NTMap𝔟SS = f AxNTMap𝔟SS"
    by (auto simp: cat_ss_cs_intros)
  with f show ?thesis using that by simp
qed

text‹\newpage›

end