Theory CZH_UCAT_Limit_Equalizer

(* Copyright 2021 (C) Mihails Milehins *)

section‹Equalizers and coequalizers as limits and colimits›
theory CZH_UCAT_Limit_Equalizer
  imports 
    CZH_UCAT_Limit
    CZH_Elementary_Categories.CZH_ECAT_Parallel
begin



subsection‹Equalizer and coequalizer›


subsubsection‹Definition and elementary properties›


text‹
See cite"noauthor_wikipedia_2001"\footnote{
\url{https://en.wikipedia.org/wiki/Equaliser_(mathematics)}
}.
›

locale is_cat_equalizer =
  is_cat_limit α C (𝔞PL F) (𝔟PL F) F  ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F' E ε +
  F': vsv F'
  for α 𝔞 𝔟 F F'  E ε +
  assumes cat_eq_F_in_Vset[cat_lim_cs_intros]: "F  Vset α"
    and cat_eq_F_ne[cat_lim_cs_intros]: "F  0"
    and cat_eq_F'_vdomain[cat_lim_cs_simps]: "𝒟 F' = F"
    and cat_eq_F'_app_is_arr[cat_lim_cs_intros]: "𝔣  F  F'𝔣 : 𝔞 𝔟"

syntax "_is_cat_equalizer" :: "V  V  V  V  V  V  V  V  bool"
  ((_ :/ _ <CF.eq '(_,_,_,_') :/ C ↦↦Cı _) [51, 51, 51, 51, 51, 51] 51)
translations "ε : E <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα"  
  "CONST is_cat_equalizer α 𝔞 𝔟 F F'  E ε"

locale is_cat_coequalizer =
  is_cat_colimit α C (𝔟PL F) (𝔞PL F) F  ⇑→⇑CF  (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F' E ε +
  F': vsv F'
  for α 𝔞 𝔟 F F'  E ε +
  assumes cat_coeq_F_in_Vset[cat_lim_cs_intros]: "F  Vset α" 
    and cat_coeq_F_ne[cat_lim_cs_intros]: "F  0"
    and cat_coeq_F'_vdomain[cat_lim_cs_simps]: "𝒟 F' = F"
    and cat_coeq_F'_app_is_arr[cat_lim_cs_intros]: "𝔣  F  F'𝔣 : 𝔟 𝔞"

syntax "_is_cat_coequalizer" :: "V  V  V  V  V  V  V  V  bool"
  ((_ :/ '(_,_,_,_') >CF.coeq _ :/ C ↦↦Cı _) [51, 51, 51, 51, 51, 51] 51)
translations "ε : (𝔞,𝔟,F,F') >CF.coeq E : C ↦↦Cα"  
  "CONST is_cat_coequalizer α 𝔞 𝔟 F F'  E ε"


text‹Rules.›

lemma (in is_cat_equalizer) is_cat_equalizer_axioms'[cat_lim_cs_intros]:
  assumes "α' = α"
    and "E' = E"
    and "𝔞' = 𝔞"
    and "𝔟' = 𝔟"
    and "F'' = F"
    and "F''' = F'"
    and "ℭ' = "
  shows "ε : E' <CF.eq (𝔞',𝔟',F'',F''') : C ↦↦Cα'ℭ'"
  unfolding assms by (rule is_cat_equalizer_axioms)

mk_ide rf is_cat_equalizer_def[unfolded is_cat_equalizer_axioms_def]
  |intro is_cat_equalizerI|
  |dest is_cat_equalizerD[dest]|
  |elim is_cat_equalizerE[elim]|

lemmas [cat_lim_cs_intros] = is_cat_equalizerD(1)

lemma (in is_cat_coequalizer) is_cat_coequalizer_axioms'[cat_lim_cs_intros]:
  assumes "α' = α"
    and "E' = E"
    and "𝔞' = 𝔞"
    and "𝔟' = 𝔟"
    and "F'' = F"
    and "F''' = F'"
    and "ℭ' = "
  shows "ε : (𝔞',𝔟',F'',F''') >CF.coeq E' : C ↦↦Cα'ℭ'"
  unfolding assms by (rule is_cat_coequalizer_axioms)

mk_ide rf is_cat_coequalizer_def[unfolded is_cat_coequalizer_axioms_def]
  |intro is_cat_coequalizerI|
  |dest is_cat_coequalizerD[dest]|
  |elim is_cat_coequalizerE[elim]|

lemmas [cat_lim_cs_intros] = is_cat_coequalizerD(1)


text‹Elementary properties.›

lemma (in is_cat_equalizer) 
  cat_eq_𝔞[cat_lim_cs_intros]: "𝔞  Obj"
  and cat_eq_𝔟[cat_lim_cs_intros]: "𝔟  Obj"
proof-
  from cat_eq_F_ne obtain 𝔣 where 𝔣: "𝔣  F" by force
  have "F'𝔣 : 𝔞 𝔟" by (rule cat_eq_F'_app_is_arr[OF 𝔣])
  then show "𝔞  Obj" "𝔟  Obj" by auto
qed

lemma (in is_cat_coequalizer) 
  cat_coeq_𝔞[cat_lim_cs_intros]: "𝔞  Obj"
  and cat_coeq_𝔟[cat_lim_cs_intros]: "𝔟  Obj"
proof-
  from cat_coeq_F_ne obtain 𝔣 where 𝔣: "𝔣  F" by force
  have "F'𝔣 : 𝔟 𝔞" by (rule cat_coeq_F'_app_is_arr[OF 𝔣])
  then show "𝔞  Obj" "𝔟  Obj" by auto
qed

sublocale is_cat_equalizer  cf_parallel α 𝔞PL F 𝔟PL F F 𝔞 𝔟 F' 
  by (intro cf_parallelI cat_parallelI)
    (
      auto simp:
        cat_lim_cs_simps cat_parallel_cs_intros cat_lim_cs_intros cat_cs_intros
    )

sublocale is_cat_coequalizer  cf_parallel α 𝔟PL F 𝔞PL F F 𝔟 𝔞 F' 
  by (intro cf_parallelI cat_parallelI)
    (
      auto simp:
        cat_lim_cs_simps cat_parallel_cs_intros cat_lim_cs_intros cat_cs_intros
    )


text‹Duality.›

lemma (in is_cat_equalizer) is_cat_coequalizer_op:
  "op_ntcf ε : (𝔞,𝔟,F,F') >CF.coeq E : C ↦↦Cαop_cat "
  by (intro is_cat_coequalizerI)
    (
      cs_concl 
        cs_simp: cat_lim_cs_simps cat_op_simps 
        cs_intro: V_cs_intros cat_op_intros cat_lim_cs_intros
    )+

lemma (in is_cat_equalizer) is_cat_coequalizer_op'[cat_op_intros]:
  assumes "ℭ' = op_cat "
  shows "op_ntcf ε : (𝔞,𝔟,F,F') >CF.coeq E : C ↦↦Cαℭ'"
  unfolding assms by (rule is_cat_coequalizer_op)

lemmas [cat_op_intros] = is_cat_equalizer.is_cat_coequalizer_op'

lemma (in is_cat_coequalizer) is_cat_equalizer_op:
  "op_ntcf ε : E <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cαop_cat "
  by (intro is_cat_equalizerI)
    (
      cs_concl 
        cs_simp: cat_lim_cs_simps cat_op_simps
        cs_intro: V_cs_intros cat_op_intros cat_lim_cs_intros
    )+

lemma (in is_cat_coequalizer) is_cat_equalizer_op'[cat_op_intros]:
  assumes "ℭ' = op_cat "
  shows "op_ntcf ε : E <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cαℭ'"
  unfolding assms by (rule is_cat_equalizer_op)

lemmas [cat_op_intros] = is_cat_coequalizer.is_cat_equalizer_op'


text‹Further properties.›

lemma (in category) cat_cf_parallel_𝔞𝔟:
  assumes "vsv F'"
    and "F  Vset α" 
    and "𝒟 F' = F"
    and "𝔣. 𝔣  F  F'𝔣 : 𝔞 𝔟"
    and "𝔞  Obj"
    and "𝔟  Obj"
  shows "cf_parallel α (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F' "
proof-
  have "𝔞PL F  Vset α" "𝔟PL F  Vset α"
    by (simp_all add: Axiom_of_Pairing 𝔟PL_def 𝔞PL_def assms(2))
  then show ?thesis
    by (intro cf_parallelI cat_parallelI)
      (simp_all add: assms cat_parallel_cs_intros cat_cs_intros)
qed

lemma (in category) cat_cf_parallel_𝔟𝔞:
  assumes "vsv F'"
    and "F  Vset α" 
    and "𝒟 F' = F"
    and "𝔣. 𝔣  F  F'𝔣 : 𝔟 𝔞"
    and "𝔞  Obj"
    and "𝔟  Obj"
  shows "cf_parallel α (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F' "
proof-
  have "𝔞PL F  Vset α" "𝔟PL F  Vset α"
    by (simp_all add: Axiom_of_Pairing 𝔟PL_def 𝔞PL_def assms(2))
  then show ?thesis
    by (intro cf_parallelI cat_parallelI)
      (simp_all add: assms cat_parallel_cs_intros cat_cs_intros)
qed

lemma cat_cone_cf_par_eps_NTMap_app:
  assumes "ε :
    E <CF.cone ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F' :
    C (𝔞PL F) (𝔟PL F) F ↦↦Cα"
    and "vsv F'"
    and "F  Vset α" 
    and "𝒟 F' = F"
    and "𝔣. 𝔣  F  F'𝔣 : 𝔞 𝔟"
    and "𝔣  F"
  shows "εNTMap𝔟PL F = F'𝔣 AεNTMap𝔞PL F" 
proof-
  let ?II = C (𝔞PL F) (𝔟PL F) F 
    and ?II_II = ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F'
  interpret ε: is_cat_cone α E ?II  ?II_II ε by (rule assms(1))
  from assms(5,6) have 𝔞: "𝔞  Obj" and 𝔟: "𝔟  Obj" by auto
  interpret par: cf_parallel α 𝔞PL F 𝔟PL F F 𝔞 𝔟 F'  
    by (intro ε.NTDom.HomCod.cat_cf_parallel_𝔞𝔟 assms 𝔞 𝔟)
  from assms(6) have 𝔣: "𝔣 : 𝔞PL F C (𝔞PL F) (𝔟PL F) F𝔟PL F" 
    by (simp_all add: par.the_cat_parallel_is_arr_𝔞𝔟F)
  note ε.cat_cone_Comp_commute[cat_cs_simps del]
  from ε.ntcf_Comp_commute[OF 𝔣] assms(6) show ?thesis
    by
      (
        cs_prems 
          cs_simp: cat_parallel_cs_simps cat_cs_simps
          cs_intro: cat_cs_intros cat_parallel_cs_intros
      )
qed

lemma cat_cocone_cf_par_eps_NTMap_app:
  assumes "ε :
    ⇑→⇑CF  (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F' >CF.cocone E :
    C (𝔟PL F) (𝔞PL F) F ↦↦Cα"
    and "vsv F'"
    and "F  Vset α"
    and "𝒟 F' = F"
    and "𝔣. 𝔣  F  F'𝔣 : 𝔟 𝔞"
    and "𝔣  F"
  shows "εNTMap𝔟PL F = εNTMap𝔞PL F AF'𝔣"
proof-
  let ?II = C (𝔟PL F) (𝔞PL F) F 
    and ?II_II = ⇑→⇑CF  (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F'
  interpret ε: is_cat_cocone α E ?II  ?II_II ε by (rule assms(1))
  from assms(5,6) 
  have 𝔞: "𝔞  Obj" and 𝔟: "𝔟  Obj" and F'𝔣: "F'𝔣 : 𝔟 𝔞" 
    by auto
  interpret par: cf_parallel α 𝔟PL F 𝔞PL F F 𝔟 𝔞 F' 
    by (intro ε.NTDom.HomCod.cat_cf_parallel_𝔟𝔞 assms 𝔞 𝔟)
  note ε_NTMap_app = 
    cat_cone_cf_par_eps_NTMap_app[
      OF ε.is_cat_cone_op[unfolded cat_op_simps],
      unfolded cat_op_simps,  
      OF assms(2-6),
      simplified
      ]
  from ε_NTMap_app F'𝔣 show ?thesis
    by
      (
        cs_concl cs_shallow
          cs_simp: cat_parallel_cs_simps category.op_cat_Comp[symmetric] 
          cs_intro: cat_cs_intros cat_parallel_cs_intros
      )
qed

lemma (in is_cat_equalizer) cat_eq_eps_NTMap_app:
  assumes "𝔣  F"
  shows "εNTMap𝔟PL F = F'𝔣 AεNTMap𝔞PL F" 
  by 
    (
      intro cat_cone_cf_par_eps_NTMap_app[
        OF 
          is_cat_cone_axioms 
          F'.vsv_axioms 
          cat_eq_F_in_Vset 
          cat_eq_F'_vdomain
          cat_eq_F'_app_is_arr
          assms
        ]
    )+

lemma (in is_cat_coequalizer) cat_coeq_eps_NTMap_app:
  assumes "𝔣  F"
  shows "εNTMap𝔟PL F = εNTMap𝔞PL F AF'𝔣" 
  by 
    (
      intro cat_cocone_cf_par_eps_NTMap_app[
        OF is_cat_cocone_axioms
          F'.vsv_axioms 
          cat_coeq_F_in_Vset 
          cat_coeq_F'_vdomain
          cat_coeq_F'_app_is_arr
          assms
        ]
    )+

lemma (in is_cat_equalizer) cat_eq_Comp_eq: 
  assumes "𝔤  F" and "𝔣  F"
  shows "F'𝔤 AεNTMap𝔞PL F = F'𝔣 AεNTMap𝔞PL F"
  using cat_eq_eps_NTMap_app[OF assms(1)] cat_eq_eps_NTMap_app[OF assms(2)]
  by auto

lemma (in is_cat_coequalizer) cat_coeq_Comp_eq: 
  assumes "𝔤  F" and "𝔣  F"
  shows "εNTMap𝔞PL F AF'𝔤 = εNTMap𝔞PL F AF'𝔣"
  using cat_coeq_eps_NTMap_app[OF assms(1)] cat_coeq_eps_NTMap_app[OF assms(2)]
  by auto


subsubsection‹Universal property›

lemma is_cat_equalizerI':
  assumes "ε :
    E <CF.cone ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F' :
    C (𝔞PL F) (𝔟PL F) F ↦↦Cα"
    and "vsv F'"
    and "F  Vset α" 
    and "𝒟 F' = F"
    and "𝔣. 𝔣  F  F'𝔣 : 𝔞 𝔟"
    and "𝔣  F" 
    and "ε' E'. ε' :
      E' <CF.cone ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F' :
      C (𝔞PL F) (𝔟PL F) F ↦↦Cα 
      ∃!f'. f' : E' E  ε'NTMap𝔞PL F = εNTMap𝔞PL F Af'"
  shows "ε : E <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα"
proof-

  let ?II = C (𝔞PL F) (𝔟PL F) F 
    and ?II_II = ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F'
  interpret ε: is_cat_cone α E ?II  ?II_II ε by (rule assms(1))
  from assms(5,6) have 𝔞: "𝔞  Obj" and 𝔟: "𝔟  Obj" by auto
  interpret par: cf_parallel α 𝔞PL F 𝔟PL F F 𝔞 𝔟 F' 
    by (intro ε.NTDom.HomCod.cat_cf_parallel_𝔞𝔟 assms 𝔞 𝔟) simp
  
  show ?thesis
  proof(intro is_cat_equalizerI is_cat_limitI assms(1-3))
    fix u' r' assume prems: "u' : r' <CF.cone ?II_II : ?II ↦↦Cα"
    interpret u': is_cat_cone α r' ?II  ?II_II u' by (rule prems)
    from assms(7)[OF prems] obtain f'
      where f': "f' : r' E"
        and u'_NTMap_app_𝔞: "u'NTMap𝔞PL F = εNTMap𝔞PL F Af'"
        and unique_f': 
          "f''.
            
              f'' : r' E; 
              u'NTMap𝔞PL F = εNTMap𝔞PL F Af''
              f'' = f'"
      by metis
    show "∃!f'. f' : r' E  u' = ε NTCF ntcf_const ?II  f'"
    proof(intro ex1I conjI; (elim conjE)?)
      show "u' = ε NTCF ntcf_const ?II  f'"
      proof(rule ntcf_eqI)
        show "u' : cf_const ?II  r' CF ?II_II : ?II ↦↦Cα"
          by (rule u'.is_ntcf_axioms)
        from f' show "ε NTCF ntcf_const ?II  f' :
          cf_const ?II  r' CF ?II_II : ?II ↦↦Cα"
          by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros )
        have dom_lhs: "𝒟 (u'NTMap) = ?IIObj"
          unfolding cat_cs_simps by simp
        from f' have dom_rhs:
          "𝒟 ((ε NTCF ntcf_const ?II  f')NTMap) = ?IIObj"
          by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
        show "u'NTMap = (ε NTCF ntcf_const ?II  f')NTMap"
        proof(rule vsv_eqI, unfold dom_lhs dom_rhs)
          fix a assume prems': "a  ?IIObj"
          note [cat_parallel_cs_simps] = 
            cat_cone_cf_par_eps_NTMap_app[
              OF u'.is_cat_cone_axioms assms(2-5), simplified
              ]
            cat_cone_cf_par_eps_NTMap_app[OF assms(1-5), simplified]
            u'_NTMap_app_𝔞
          from prems' f' assms(6) show 
            "u'NTMapa = (ε NTCF ntcf_const ?II  f')NTMapa"
            by (elim the_cat_parallel_ObjE; simp only:)
              (
                cs_concl 
                  cs_simp: cat_parallel_cs_simps cat_cs_simps
                  cs_intro: cat_cs_intros cat_parallel_cs_intros
              )
        qed (cs_concl cs_intro: V_cs_intros cat_cs_intros)+
      qed simp_all
      fix f'' assume prems'': 
        "f'' : r' E" "u' = ε NTCF ntcf_const ?II  f''"
      from prems''(2) have u'_NTMap_a:
        "u'NTMapa = (ε NTCF ntcf_const ?II  f'')NTMapa"
        for a 
        by simp
      have "u'NTMap𝔞PL F = εNTMap𝔞PL F Af''"  
        using u'_NTMap_a[of 𝔞PL F] prems''(1) 
        by 
          (
            cs_prems 
              cs_simp: cat_parallel_cs_simps cat_cs_simps 
              cs_intro: cat_parallel_cs_intros cat_cs_intros
          )
      from unique_f'[OF prems''(1) this] show "f'' = f'".
    qed (rule f')
  qed (use assms in fastforce)+

qed

lemma is_cat_coequalizerI':
  assumes "ε :
    ⇑→⇑CF  (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F' >CF.cocone E : 
    C (𝔟PL F) (𝔞PL F) F ↦↦Cα"
    and "vsv F'"
    and "F  Vset α" 
    and "𝒟 F' = F"
    and "𝔣. 𝔣  F  F'𝔣 : 𝔟 𝔞"
    and "𝔣  F" 
    and "ε' E'. ε' :
      ⇑→⇑CF  (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F' >CF.cocone E' : 
      C (𝔟PL F) (𝔞PL F) F ↦↦Cα 
      ∃!f'. f' : E E'  ε'NTMap𝔞PL F = f' AεNTMap𝔞PL F"
  shows "ε : (𝔞,𝔟,F,F') >CF.coeq E : C ↦↦Cα"
proof-

  let ?op_II = C (𝔟PL F) (𝔞PL F) F 
    and ?op_II_II = ⇑→⇑CF  (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F'
    and ?II = C (𝔞PL F) (𝔟PL F) F
    and ?II_II = ⇑→⇑CF (op_cat ) (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F'
  interpret ε: is_cat_cocone α E ?op_II  ?op_II_II ε by (rule assms(1))
  from assms(5,6) have 𝔞: "𝔞  Obj" and 𝔟: "𝔟  Obj" by auto
  interpret par: cf_parallel α 𝔟PL F 𝔞PL F F 𝔟 𝔞 F' 
    by (intro ε.NTDom.HomCod.cat_cf_parallel_𝔟𝔞 assms 𝔞 𝔟) simp

  interpret op_par: cf_parallel α 𝔞PL F 𝔟PL F F 𝔞 𝔟 F' op_cat 
    by (rule par.cf_parallel_op)
  have assms_4':
    "∃!f'. f' : E E'  ε'NTMap𝔞PL F = εNTMap𝔞PL F Aop_cat f'"
    if "ε' : E' <CF.cone ?II_II : ?II ↦↦Cαop_cat " for ε' E'
  proof-
    have [cat_op_simps]:
      "f' : E E'  ε'NTMap𝔞PL F = εNTMap𝔞PL F Aop_cat f' 
        f' : E E'  ε'NTMap𝔞PL F = f' AεNTMap𝔞PL F"
      for f'
      by (intro iffI conjI; (elim conjE)?)
        (
          cs_concl cs_shallow
            cs_simp: category.op_cat_Comp[symmetric] cat_op_simps cat_cs_simps 
            cs_intro: cat_cs_intros cat_parallel_cs_intros
        )+
    interpret ε': is_cat_cone α E' ?II op_cat  ?II_II ε' by (rule that)
    show ?thesis
      unfolding cat_op_simps
      by 
        (
          rule assms(7)[
            OF ε'.is_cat_cocone_op[unfolded cat_op_simps], 
            unfolded cat_op_simps
            ]
        )
  qed
  interpret op_ε: is_cat_equalizer α 𝔞 𝔟 F F' op_cat  E op_ntcf ε 
    by 
      (
        rule 
          is_cat_equalizerI'
            [
              OF ε.is_cat_cone_op[unfolded cat_op_simps], 
              unfolded cat_op_simps, 
              OF assms(2-6) assms_4',
              simplified
            ]
      )
  show ?thesis by (rule op_ε.is_cat_coequalizer_op[unfolded cat_op_simps])

qed

lemma (in is_cat_equalizer) cat_eq_unique_cone:
  assumes "ε' :
    E' <CF.cone ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F' : C (𝔞PL F) (𝔟PL F) F ↦↦Cα"
    (is ε' : E' <CF.cone ?II_II : ?II ↦↦Cα)
  shows "∃!f'. f' : E' E  ε'NTMap𝔞PL F = εNTMap𝔞PL F Af'"
proof-

  interpret ε': is_cat_cone α E' ?II  ?II_II ε' by (rule assms(1))
  from cat_lim_ua_fo[OF assms(1)] obtain f' where f': "f' : E' E"
    and ε'_def: "ε' = ε NTCF ntcf_const ?II  f'"
    and unique: 
      " f'' : E' E; ε' = ε NTCF ntcf_const ?II  f''   f'' = f'" 
    for f''
    by auto
  from cat_eq_F_ne obtain 𝔣 where 𝔣: "𝔣  F" by force

  show ?thesis
  proof(intro ex1I conjI; (elim conjE)?)
    show f': "f' : E' E" by (rule f')
    from ε'_def have "ε'NTMap𝔞PL F = (ε NTCF ntcf_const ?II  f')NTMap𝔞PL F"
      by simp
    from this f' show ε'_NTMap_app_I: "ε'NTMap𝔞PL F = εNTMap𝔞PL F Af'"
      by 
        (
          cs_prems 
            cs_simp: cat_cs_simps cs_intro: cat_cs_intros cat_parallel_cs_intros
        )
    fix f'' assume prems: 
      "f'' : E' E" "ε'NTMap𝔞PL F = εNTMap𝔞PL F Af''"
    have "ε' = ε NTCF ntcf_const ?II  f''"
    proof(rule ntcf_eqI[OF ])
      show "ε' : cf_const ?II  E' CF ?II_II : ?II ↦↦Cα"
        by (rule ε'.is_ntcf_axioms)
      from f' prems(1) show "ε NTCF ntcf_const ?II  f'' :
        cf_const ?II  E' CF ?II_II : ?II ↦↦Cα"
        by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      show "ε'NTMap = (ε NTCF ntcf_const ?II  f'')NTMap"
      proof(rule vsv_eqI, unfold cat_cs_simps)
        show "vsv ((ε NTCF ntcf_const ?II  f'')NTMap)"
          by (cs_concl cs_intro: cat_cs_intros)
        from prems(1) show "?IIObj = 𝒟 ((ε NTCF ntcf_const ?II  f'')NTMap)"
          by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
        fix a assume prems': "a  ?IIObj"
        note [cat_cs_simps] = 
          cat_eq_eps_NTMap_app[OF 𝔣]
          cat_cone_cf_par_eps_NTMap_app
            [
              OF 
                ε'.is_cat_cone_axioms 
                F'.vsv_axioms 
                cat_eq_F_in_Vset 
                cat_eq_F'_vdomain 
                cat_eq_F'_app_is_arr 𝔣, 
              simplified
            ]
        from prems' prems(1) 𝔣 have [cat_cs_simps]: 
          "ε'NTMapa = εNTMapa Af''"
          by (elim the_cat_parallel_ObjE; simp only:)
            (
                cs_concl 
                  cs_simp: cat_cs_simps cat_parallel_cs_simps prems(2)
                  cs_intro: cat_cs_intros cat_parallel_cs_intros
            )+
        from prems' prems show 
          "ε'NTMapa = (ε NTCF ntcf_const ?II  f'')NTMapa"
          by (cs_concl cs_simp: cat_cs_simps cs_intro: cat_cs_intros)
      qed auto
    qed simp_all
    from unique[OF prems(1) this] show "f'' = f'" .
  qed

qed

lemma (in is_cat_equalizer) cat_eq_unique:
  assumes "ε' : E' <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα"
  shows 
    "∃!f'. f' : E' E  ε' = ε NTCF ntcf_const (C (𝔞PL F) (𝔟PL F) F)  f'"
  by (rule cat_lim_unique[OF is_cat_equalizerD(1)[OF assms]])

lemma (in is_cat_equalizer) cat_eq_unique':
  assumes "ε' : E' <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα"
  shows "∃!f'. f' : E' E  ε'NTMap𝔞PL F = εNTMap𝔞PL F Af'"
proof-
  interpret ε': is_cat_equalizer α 𝔞 𝔟 F F'  E' ε' by (rule assms(1))
  show ?thesis by (rule cat_eq_unique_cone[OF ε'.is_cat_cone_axioms])
qed

lemma (in is_cat_coequalizer) cat_coeq_unique_cocone:
  assumes "ε' :
    ⇑→⇑CF  (𝔟PL F) (𝔞PL F) F 𝔟 𝔞 F' >CF.cocone E' : 
    C (𝔟PL F) (𝔞PL F) F ↦↦Cα"
    (is ε' : ?II_II >CF.cocone E' : ?II ↦↦Cα)
  shows "∃!f'. f' : E E'  ε'NTMap𝔞PL F = f' AεNTMap𝔞PL F"
proof-
  interpret ε': is_cat_cocone α E' ?II  ?II_II ε' by (rule assms(1))
  have [cat_op_simps]:
    "f' : E E'  ε'NTMap𝔞PL F = εNTMap𝔞PL F Aop_cat f' 
      f' : E E'  ε'NTMap𝔞PL F = f' AεNTMap𝔞PL F" 
    for f'
    by (intro iffI conjI; (elim conjE)?)
      (
        cs_concl cs_shallow
          cs_simp: category.op_cat_Comp[symmetric] cat_op_simps cat_cs_simps 
          cs_intro: cat_cs_intros cat_parallel_cs_intros
      )+
  show ?thesis
    by 
      (
        rule is_cat_equalizer.cat_eq_unique_cone[
          OF is_cat_equalizer_op ε'.is_cat_cone_op[unfolded cat_op_simps],
          unfolded cat_op_simps
          ]
     )
qed

lemma (in is_cat_coequalizer) cat_coeq_unique:
  assumes "ε' : (𝔞,𝔟,F,F') >CF.coeq E' : C ↦↦Cα"
  shows "∃!f'.
    f' : E E'  ε' = ntcf_const (C (𝔟PL F) (𝔞PL F) F)  f' NTCF ε"
  by (rule cat_colim_unique[OF is_cat_coequalizerD(1)[OF assms]])

lemma (in is_cat_coequalizer) cat_coeq_unique':
  assumes "ε' : (𝔞,𝔟,F,F') >CF.coeq E' : C ↦↦Cα"
  shows "∃!f'. f' : E E'  ε'NTMap𝔞PL F = f' AεNTMap𝔞PL F"
proof-
  interpret ε': is_cat_coequalizer α 𝔞 𝔟 F F'  E' ε' by (rule assms(1))
  show ?thesis by (rule cat_coeq_unique_cocone[OF ε'.is_cat_cocone_axioms])
qed

lemma cat_equalizer_ex_is_iso_arr:
  assumes "ε : E <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα" 
    and "ε' : E' <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα"
  obtains f where "f : E' isoE"
    and "ε' = ε NTCF ntcf_const (C (𝔞PL F) (𝔟PL F) F)  f"
proof-
  interpret ε: is_cat_equalizer α 𝔞 𝔟 F F'  E ε by (rule assms(1))
  interpret ε': is_cat_equalizer α 𝔞 𝔟 F F'  E' ε' by (rule assms(2))
  from that show ?thesis
    by 
      (
        elim cat_lim_ex_is_iso_arr[
          OF ε.is_cat_limit_axioms ε'.is_cat_limit_axioms
          ]
      )
qed

lemma cat_equalizer_ex_is_iso_arr':
  assumes "ε : E <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα" 
    and "ε' : E' <CF.eq (𝔞,𝔟,F,F') : C ↦↦Cα"
  obtains f where "f : E' isoE"
    and "ε'NTMap𝔞PL F = εNTMap𝔞PL F Af"
    and "ε'NTMap𝔟PL F = εNTMap𝔟PL F Af"
proof-
  interpret ε: is_cat_equalizer α 𝔞 𝔟 F F'  E ε by (rule assms(1))
  interpret ε': is_cat_equalizer α 𝔞 𝔟 F F'  E' ε' by (rule assms(2))
  obtain f where f: "f : E' isoE"
    and "j  C (𝔞PL F) (𝔟PL F) FObj  ε'NTMapj = εNTMapj Af" for j
    by 
      (
        elim cat_lim_ex_is_iso_arr'[
          OF ε.is_cat_limit_axioms ε'.is_cat_limit_axioms
          ]
      )
  then have 
    "ε'NTMap𝔞PL F = εNTMap𝔞PL F Af"
    "ε'NTMap𝔟PL F = εNTMap𝔟PL F Af"
    unfolding the_cat_parallel_components by auto
  with f show ?thesis using that by simp
qed

lemma cat_coequalizer_ex_is_iso_arr:
  assumes "ε : (𝔞,𝔟,F,F') >CF.coeq E : C ↦↦Cα"
    and "ε' : (𝔞,𝔟,F,F') >CF.coeq E' : C ↦↦Cα"
  obtains f where "f : E isoE'" 
    and "ε' = ntcf_const (C (𝔟PL F) (𝔞PL F) F)   f NTCF ε"
proof-
  interpret ε: is_cat_coequalizer α 𝔞 𝔟 F F'  E ε by (rule assms(1))
  interpret ε': is_cat_coequalizer α 𝔞 𝔟 F F'  E' ε' by (rule assms(2))
  from that show ?thesis
    by 
      (
        elim cat_colim_ex_is_iso_arr[
          OF ε.is_cat_colimit_axioms ε'.is_cat_colimit_axioms
          ]
      )
qed

lemma cat_coequalizer_ex_is_iso_arr':
  assumes "ε : (𝔞,𝔟,F,F') >CF.coeq E : C ↦↦Cα"
    and "ε' : (𝔞,𝔟,F,F') >CF.coeq E' : C ↦↦Cα"
  obtains f where "f : E isoE'" 
    and "ε'NTMap𝔞PL F = f AεNTMap𝔞PL F"
    and "ε'NTMap𝔟PL F = f AεNTMap𝔟PL F"
proof-
  interpret ε: is_cat_coequalizer α 𝔞 𝔟 F F'  E ε by (rule assms(1))
  interpret ε': is_cat_coequalizer α 𝔞 𝔟 F F'  E' ε' by (rule assms(2))
  obtain f where f: "f : E isoE'"
    and "j  C (𝔟PL F) (𝔞PL F) FObj  ε'NTMapj = f AεNTMapj" for j
    by
      (
        elim cat_colim_ex_is_iso_arr'[
          OF ε.is_cat_colimit_axioms ε'.is_cat_colimit_axioms
          ]
      )
  then have 
    "ε'NTMap𝔞PL F = f AεNTMap𝔞PL F"
    "ε'NTMap𝔟PL F = f AεNTMap𝔟PL F"
    unfolding the_cat_parallel_components by auto
  with f show ?thesis using that by simp
qed


subsubsection‹Further properties›

lemma (in is_cat_equalizer) cat_eq_is_monic_arr: 
  ―‹See subsection 3.3 in \cite{awodey_category_2010}.›
  "εNTMap𝔞PL F : E mon𝔞"
proof(intro is_monic_arrI)
  show "εNTMap𝔞PL F : E 𝔞"
    by
      (
        cs_concl
          cs_simp: cat_cs_simps cat_parallel_cs_simps 
          cs_intro: cat_cs_intros cat_parallel_cs_intros
      )
  fix f g a
  assume prems:
    "f : a E"
    "g : a E"
    "εNTMap𝔞PL F Af = εNTMap𝔞PL F Ag"
  define ε' where "ε' = ε NTCF ntcf_const (C (𝔞PL F) (𝔟PL F) F)  f"
  from prems(1) have "ε' :
    a <CF.cone ⇑→⇑CF  (𝔞PL F) (𝔟PL F) F 𝔞 𝔟 F' :
    C (𝔞PL F) (𝔟PL F) F ↦↦Cα"
    unfolding ε'_def 
    by (cs_concl cs_shallow cs_intro: is_cat_coneI cat_cs_intros)    
  from cat_eq_unique_cone[OF this] obtain f' 
    where f': "f' : a E"
      and ε'_𝔞: "ε'NTMap𝔞PL F = εNTMap𝔞PL F Af'"
      and unique_f': "f''.
         f'' : a E; ε'NTMap𝔞PL F = εNTMap𝔞PL F Af''  
          f'' = f'"
    by meson
  from prems(1) have unique_f: "ε'NTMap𝔞PL F = εNTMap𝔞PL F Af"
    unfolding ε'_def
    by
      (
        cs_concl 
          cs_simp: cat_cs_simps cs_intro: cat_cs_intros cat_parallel_cs_intros
      )
  from prems(1) have unique_g: "ε'NTMap𝔞PL F = εNTMap𝔞PL F Ag"
    unfolding ε'_def
    by
      (
        cs_concl
          cs_simp: prems(3) cat_cs_simps
          cs_intro: cat_cs_intros cat_parallel_cs_intros
      )
  show "f = g"
    by 
      (
        rule unique_f'
          [
            OF prems(1) unique_f,
            unfolded unique_f'[OF prems(2) unique_g, symmetric]
          ]
      )
qed

lemma (in is_cat_coequalizer) cat_coeq_is_epic_arr: 
  "εNTMap𝔞PL F : 𝔞 epiE"
  by
    (
      rule is_cat_equalizer.cat_eq_is_monic_arr[
        OF is_cat_equalizer_op, unfolded cat_op_simps
        ]
    )



subsection‹Equalizer and coequalizer for two arrows›


subsubsection‹Definition and elementary properties›


text‹
See cite"noauthor_wikipedia_2001"\footnote{
\url{https://en.wikipedia.org/wiki/Equaliser_(mathematics)}
}.
›

locale is_cat_equalizer_2 =
  is_cat_limit α ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL  ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 E ε 
  for α 𝔞 𝔟 𝔤 𝔣  E ε +
  assumes cat_eq_𝔤[cat_lim_cs_intros]: "𝔤 : 𝔞 𝔟"
    and cat_eq_𝔣[cat_lim_cs_intros]: "𝔣 : 𝔞 𝔟"

syntax "_is_cat_equalizer_2" :: "V  V  V  V  V  V  V  V  bool"
  ((_ :/ _ <CF.eq '(_,_,_,_') :/ ↑↑C ↦↦Cı _) [51, 51, 51, 51, 51, 51] 51)
translations "ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"  
  "CONST is_cat_equalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε"

locale is_cat_coequalizer_2 =
  is_cat_colimit 
    α ↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL  ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤 E ε 
  for α 𝔞 𝔟 𝔤 𝔣  E ε +
  assumes cat_coeq_𝔤[cat_lim_cs_intros]: "𝔤 : 𝔟 𝔞"
    and cat_coeq_𝔣[cat_lim_cs_intros]: "𝔣 : 𝔟 𝔞"

syntax "_is_cat_coequalizer_2" :: "V  V  V  V  V  V  V  V  bool"
  ((_ :/ '(_,_,_,_') >CF.coeq _ :/ ↑↑C ↦↦Cı _) [51, 51, 51, 51, 51, 51] 51)
translations "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"  
  "CONST is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε"


text‹Rules.›

lemma (in is_cat_equalizer_2) is_cat_equalizer_2_axioms'[cat_lim_cs_intros]:
  assumes "α' = α"
    and "E' = E"
    and "𝔞' = 𝔞"
    and "𝔟' = 𝔟"
    and "𝔤' = 𝔤"
    and "𝔣' = 𝔣"
    and "ℭ' = "
  shows "ε : E' <CF.eq (𝔞',𝔟',𝔤',𝔣') : ↑↑C ↦↦Cα'ℭ'"
  unfolding assms by (rule is_cat_equalizer_2_axioms)

mk_ide rf is_cat_equalizer_2_def[unfolded is_cat_equalizer_2_axioms_def]
  |intro is_cat_equalizer_2I|
  |dest is_cat_equalizer_2D[dest]|
  |elim is_cat_equalizer_2E[elim]|

lemmas [cat_lim_cs_intros] = is_cat_equalizer_2D(1)

lemma (in is_cat_coequalizer_2) is_cat_coequalizer_2_axioms'[cat_lim_cs_intros]:
  assumes "α' = α"
    and "E' = E"
    and "𝔞' = 𝔞"
    and "𝔟' = 𝔟"
    and "𝔤' = 𝔤"
    and "𝔣' = 𝔣"
    and "ℭ' = "
  shows "ε : (𝔞',𝔟',𝔤',𝔣') >CF.coeq E' : ↑↑C ↦↦Cα'ℭ'"
  unfolding assms by (rule is_cat_coequalizer_2_axioms)

mk_ide rf is_cat_coequalizer_2_def[unfolded is_cat_coequalizer_2_axioms_def]
  |intro is_cat_coequalizer_2I|
  |dest is_cat_coequalizer_2D[dest]|
  |elim is_cat_coequalizer_2E[elim]|

lemmas [cat_lim_cs_intros] = is_cat_coequalizer_2D(1)


text‹Helper lemmas.›

(*FIXME*)
lemma cat_eq_F'_helper:
  "(λfset {𝔣PL, 𝔤PL}. (f = 𝔤PL ? 𝔤 : 𝔣)) =
    (λfset {𝔣PL, 𝔤PL}. (f = 𝔣PL ? 𝔣 : 𝔤))"
  using cat_PL2_𝔤𝔣 by (simp add: VLambda_vdoubleton)


text‹Elementary properties.›

sublocale is_cat_equalizer_2  cf_parallel_2 α 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣  
  by (intro cf_parallel_2I cat_parallel_2I)
    (simp_all add: cat_parallel_cs_intros cat_lim_cs_intros cat_cs_intros)

sublocale is_cat_coequalizer_2  cf_parallel_2 α 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤 
  by (intro cf_parallel_2I cat_parallel_2I)
    (
      auto simp: 
        cat_parallel_cs_intros cat_lim_cs_intros cat_cs_intros 
        cat_PL2_ineq[symmetric]
    )

lemma (in is_cat_equalizer_2) cat_equalizer_2_is_cat_equalizer:
  "ε :
    E <CF.eq (𝔞,𝔟,set {𝔤PL, 𝔣PL},(λfset {𝔤PL, 𝔣PL}. (f = 𝔣PL ? 𝔣 : 𝔤))) : 
    C ↦↦Cα"
  by 
    (
      intro is_cat_equalizerI, 
      rule is_cat_limit_axioms[
        unfolded the_cf_parallel_2_def the_cat_parallel_2_def 𝔞PL2_def 𝔟PL2_def
        ]
    ) 
    (auto simp: Limit_vdoubleton_in_VsetI cat_parallel_cs_intros)

lemma (in is_cat_coequalizer_2) cat_coequalizer_2_is_cat_coequalizer:
  "ε :
    (𝔞,𝔟,set {𝔤PL, 𝔣PL},(λfset {𝔤PL, 𝔣PL}. (f = 𝔣PL ? 𝔣 : 𝔤))) >CF.coeq E :
    C ↦↦Cα"
proof
  (
    intro is_cat_coequalizerI, 
    fold the_cf_parallel_2_def the_cat_parallel_2_def 𝔞PL2_def 𝔟PL2_def
  )
  show "ε :
    ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔤PL 𝔣PL 𝔟 𝔞 𝔤 𝔣 >CF.colim E :
    ↑↑C 𝔟PL2 𝔞PL2 𝔤PL 𝔣PL ↦↦Cα"
    by 
      (
        subst the_cat_parallel_2_commute, 
        subst cf_parallel_2_the_cf_parallel_2_commute[symmetric]
      )
      (intro is_cat_colimit_axioms)
qed (auto simp: Limit_vdoubleton_in_VsetI cat_parallel_cs_intros)

lemma cat_equalizer_is_cat_equalizer_2:
  assumes "ε :
    E <CF.eq (𝔞,𝔟,set {𝔤PL, 𝔣PL},(λfset {𝔤PL, 𝔣PL}. (f = 𝔣PL ? 𝔣 : 𝔤))) :
    C ↦↦Cα"
  shows "ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
proof-
  interpret ε: is_cat_equalizer 
    α 𝔞 𝔟 set {𝔤PL, 𝔣PL} (λfset {𝔤PL, 𝔣PL}. (f = 𝔣PL ? 𝔣 : 𝔤))  E ε
    by (rule assms)
  have 𝔣PL: "𝔣PL  set {𝔤PL, 𝔣PL}" and 𝔤PL: "𝔤PL  set {𝔤PL, 𝔣PL}" by auto
  show ?thesis
    using ε.cat_eq_F'_app_is_arr[OF 𝔤PL] ε.cat_eq_F'_app_is_arr[OF 𝔣PL] 
    by 
      (
        intro 
          is_cat_equalizer_2I 
          ε.is_cat_limit_axioms
            [
              folded 
                the_cf_parallel_2_def the_cat_parallel_2_def 𝔞PL2_def 𝔟PL2_def
            ]
      )
      (auto simp: cat_PL2_𝔤𝔣)
qed

lemma cat_coequalizer_is_cat_coequalizer_2:
  assumes "ε :
    (𝔞,𝔟,set {𝔤PL, 𝔣PL},(λfset {𝔤PL, 𝔣PL}. (f = 𝔣PL ? 𝔣 : 𝔤))) >CF.coeq E :
    C ↦↦Cα"
  shows "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
proof-
  interpret is_cat_coequalizer 
    α 𝔞 𝔟 set {𝔤PL, 𝔣PL} (λfset {𝔤PL, 𝔣PL}. (f = 𝔣PL ? 𝔣 : 𝔤))  E ε
    by (rule assms)
  interpret cf_parallel_2 α 𝔟PL2 𝔞PL2 𝔤PL 𝔣PL 𝔟 𝔞 𝔤 𝔣 
    by 
      (
        rule cf_parallel_is_cf_parallel_2[
          OF cf_parallel_axioms cat_PL2_𝔤𝔣, folded 𝔞PL2_def 𝔟PL2_def
          ]
      )
  show "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
    by
      (
        intro is_cat_coequalizer_2I, 
        subst the_cat_parallel_2_commute, 
        subst cf_parallel_2_the_cf_parallel_2_commute[symmetric], 
        rule is_cat_colimit_axioms[
          folded 𝔞PL2_def 𝔟PL2_def the_cat_parallel_2_def the_cf_parallel_2_def
          ]
      )
      (simp_all add: cf_parallel_𝔣' cf_parallel_𝔤')
qed


text‹Duality.›

lemma (in is_cat_equalizer_2) is_cat_coequalizer_2_op:
  "op_ntcf ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cαop_cat "
  unfolding is_cat_equalizer_def
  by 
    (
      rule cat_coequalizer_is_cat_coequalizer_2
        [
          OF is_cat_equalizer.is_cat_coequalizer_op[
            OF cat_equalizer_2_is_cat_equalizer
          ]
        ]
    )

lemma (in is_cat_equalizer_2) is_cat_coequalizer_2_op'[cat_op_intros]:
  assumes "ℭ' = op_cat "
  shows "op_ntcf ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cαℭ'"
  unfolding assms by (rule is_cat_coequalizer_2_op)

lemmas [cat_op_intros] = is_cat_equalizer_2.is_cat_coequalizer_2_op'

lemma (in is_cat_coequalizer_2) is_cat_equalizer_2_op:
  "op_ntcf ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cαop_cat "
  unfolding is_cat_coequalizer_def
  by 
    (
      rule cat_equalizer_is_cat_equalizer_2
        [
          OF is_cat_coequalizer.is_cat_equalizer_op[
            OF cat_coequalizer_2_is_cat_coequalizer
          ]
        ]
    )

lemma (in is_cat_coequalizer_2) is_cat_equalizer_2_op'[cat_op_intros]:
  assumes "ℭ' = op_cat "
  shows "op_ntcf ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cαℭ'"
  unfolding assms by (rule is_cat_equalizer_2_op)

lemmas [cat_op_intros] = is_cat_coequalizer_2.is_cat_equalizer_2_op'


text‹Further properties.›

lemma (in category) cat_cf_parallel_2_cat_equalizer: 
  assumes "𝔤 : 𝔞 𝔟" and "𝔣 : 𝔞 𝔟"
  shows "cf_parallel_2 α 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 "
  using assms 
  by (intro cf_parallel_2I cat_parallel_2I)
    (auto simp: cat_parallel_cs_intros cat_cs_intros)

lemma (in category) cat_cf_parallel_2_cat_coequalizer: 
  assumes "𝔤 : 𝔟 𝔞" and "𝔣 : 𝔟 𝔞"
  shows "cf_parallel_2 α 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤 "
  using assms 
  by (intro cf_parallel_2I cat_parallel_2I)
    (simp_all add: cat_parallel_cs_intros cat_cs_intros cat_PL2_ineq[symmetric])

lemma cat_cone_cf_par_2_eps_NTMap_app:
  assumes "ε :
    E <CF.cone ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 : ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα"
    and "𝔤 : 𝔞 𝔟" 
    and "𝔣 : 𝔞 𝔟"
  shows 
    "εNTMap𝔟PL2 = 𝔤 AεNTMap𝔞PL2" 
    "εNTMap𝔟PL2 = 𝔣 AεNTMap𝔞PL2"
proof-
  let ?II = ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 
    and ?II_II = ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣
    and ?F = set {𝔤PL, 𝔣PL}
  interpret ε: is_cat_cone α E ?II  ?II_II ε by (rule assms(1))
  from ε.cat_PL2_𝔣 ε.cat_PL2_𝔤 have 𝔤𝔣: "?F  Vset α"
    by (intro Limit_vdoubleton_in_VsetI)  auto
  from assms(2,3) have
    "(𝔣'. 𝔣'  ?F  (λf?F. (f = 𝔣PL ? 𝔣 : 𝔤))𝔣' : 𝔞 𝔟)"
    by auto
  note cat_cone_cf_par_eps_NTMap_app = cat_cone_cf_par_eps_NTMap_app
      [
        OF 
          assms(1)[
            unfolded 
              the_cat_parallel_2_def the_cf_parallel_2_def 𝔞PL2_def 𝔟PL2_def
            ], 
        folded 𝔞PL2_def 𝔟PL2_def, OF _ 𝔤𝔣 _ this,
        simplified
      ]
  from
    cat_cone_cf_par_eps_NTMap_app[of 𝔤PL, simplified]
    cat_cone_cf_par_eps_NTMap_app[of 𝔣PL, simplified]
    cat_PL2_𝔤𝔣
  show 
    "εNTMap𝔟PL2 = 𝔤 AεNTMap𝔞PL2" 
    "εNTMap𝔟PL2 = 𝔣 AεNTMap𝔞PL2"
    by fastforce+
qed

lemma cat_cocone_cf_par_2_eps_NTMap_app:
  assumes "ε :
    ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤 >CF.cocone E :
    ↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL ↦↦Cα"
    and "𝔤 : 𝔟 𝔞" 
    and "𝔣 : 𝔟 𝔞"
  shows 
    "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔤" 
    "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔣"    
proof-
  let ?II = ↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 
    and ?II_II = ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤
    and ?F = set {𝔤PL, 𝔣PL}
  have 𝔣𝔤_𝔤𝔣: "{𝔣PL, 𝔤PL} = {𝔤PL, 𝔣PL}" by auto
  interpret ε: is_cat_cocone α E ?II  ?II_II ε by (rule assms(1))
  from ε.cat_PL2_𝔣 ε.cat_PL2_𝔤 have 𝔤𝔣: "?F  Vset α"
    by (intro Limit_vdoubleton_in_VsetI) auto
  from assms(2,3) have
    "(𝔣'. 𝔣'  ?F  (λf?F. (f = 𝔤PL ? 𝔤 : 𝔣))𝔣' : 𝔟 𝔞)"
    by auto
  note cat_cocone_cf_par_eps_NTMap_app = cat_cocone_cf_par_eps_NTMap_app
    [
      OF assms(1)
        [
          unfolded 
            the_cat_parallel_2_def 
            the_cf_parallel_2_def 
            𝔞PL2_def 𝔟PL2_def 
            insert_commute,
          unfolded 𝔣𝔤_𝔤𝔣
        ],
      folded 𝔞PL2_def 𝔟PL2_def,
      OF _ 𝔤𝔣 _ this,
      simplified
    ]
  from
    cat_cocone_cf_par_eps_NTMap_app[of 𝔤PL, simplified]
    cat_cocone_cf_par_eps_NTMap_app[of 𝔣PL, simplified]
    cat_PL2_𝔤𝔣
  show
    "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔤" 
    "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔣"
    by fastforce+
qed

lemma (in is_cat_equalizer_2) cat_eq_2_eps_NTMap_app:
  "εNTMap𝔟PL2 = 𝔤 AεNTMap𝔞PL2"
  "εNTMap𝔟PL2 = 𝔣 AεNTMap𝔞PL2"
proof-
  have 𝔤PL: "𝔤PL  set {𝔤PL, 𝔣PL}" and 𝔣PL: "𝔣PL  set {𝔤PL, 𝔣PL}" by auto
  note cat_eq_eps_NTMap_app = is_cat_equalizer.cat_eq_eps_NTMap_app
    [
      OF cat_equalizer_2_is_cat_equalizer,
      folded 𝔞PL2_def 𝔟PL2_def
    ]
  from cat_eq_eps_NTMap_app[OF 𝔤PL] cat_eq_eps_NTMap_app[OF 𝔣PL] cat_PL2_𝔤𝔣 show 
    "εNTMap𝔟PL2 = 𝔤 AεNTMap𝔞PL2"
    "εNTMap𝔟PL2 = 𝔣 AεNTMap𝔞PL2"
    by auto
qed

lemma (in is_cat_coequalizer_2) cat_coeq_2_eps_NTMap_app:
  "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔤"
  "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔣"
proof-
  have 𝔤PL: "𝔤PL  set {𝔤PL, 𝔣PL}" and 𝔣PL: "𝔣PL  set {𝔤PL, 𝔣PL}" by auto
  note cat_eq_eps_NTMap_app = is_cat_coequalizer.cat_coeq_eps_NTMap_app
    [
      OF cat_coequalizer_2_is_cat_coequalizer,
      folded 𝔞PL2_def 𝔟PL2_def
    ]
  from cat_eq_eps_NTMap_app[OF 𝔤PL] cat_eq_eps_NTMap_app[OF 𝔣PL] cat_PL2_𝔤𝔣 show 
    "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔤"
    "εNTMap𝔟PL2 = εNTMap𝔞PL2 A𝔣"
    by auto
qed

lemma (in is_cat_equalizer_2) cat_eq_2_Comp_eq: 
  "𝔤 AεNTMap𝔞PL2 = 𝔣 AεNTMap𝔞PL2"
  "𝔣 AεNTMap𝔞PL2 = 𝔤 AεNTMap𝔞PL2"
  unfolding cat_eq_2_eps_NTMap_app[symmetric] by simp_all

lemma (in is_cat_coequalizer_2) cat_coeq_2_Comp_eq: 
  "εNTMap𝔞PL2 A𝔤 = εNTMap𝔞PL2 A𝔣"
  "εNTMap𝔞PL2 A𝔣 = εNTMap𝔞PL2 A𝔤"
  unfolding cat_coeq_2_eps_NTMap_app[symmetric] by simp_all


subsubsection‹Universal property›

lemma is_cat_equalizer_2I':
  assumes "ε :
    E <CF.cone ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 : ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα"
    and "𝔤 : 𝔞 𝔟"
    and "𝔣 : 𝔞 𝔟"
    and "ε' E'. ε' :
      E' <CF.cone ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 :
      ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα 
      ∃!f'. f' : E' E  ε'NTMap𝔞PL2 = εNTMap𝔞PL2 Af'"
  shows "ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
proof-
  let ?II = ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 
    and ?II_II = ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣
    and ?F = set {𝔤PL, 𝔣PL}
  interpret ε: is_cat_cone α E ?II  ?II_II ε by (rule assms(1))
  from ε.cat_PL2_𝔣 ε.cat_PL2_𝔤 have 𝔤𝔣: "?F  Vset α"
    by (intro Limit_vdoubleton_in_VsetI) auto
  from assms(2,3) have "(λf?F. (f = 𝔣PL ? 𝔣 : 𝔤))𝔣' : 𝔞 𝔟" 
    if "𝔣'  ?F" for 𝔣'
    using that by simp
  note is_cat_equalizerI' = is_cat_equalizerI'
      [
        OF 
          assms(1)[
            unfolded 
              the_cat_parallel_2_def the_cf_parallel_2_def 𝔞PL2_def 𝔟PL2_def
            ], 
        folded 𝔞PL2_def 𝔟PL2_def, 
        OF 
          _ 
          𝔤𝔣 
          _ 
          this 
          _ 
          assms(4)[unfolded the_cf_parallel_2_def the_cat_parallel_2_def], 
        of 𝔤PL,
        simplified
      ]
  show ?thesis by (rule cat_equalizer_is_cat_equalizer_2[OF is_cat_equalizerI'])
qed

lemma is_cat_coequalizer_2I':
  assumes "ε :
    ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤 >CF.cocone E :
    ↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL ↦↦Cα"
    and "𝔤 : 𝔟 𝔞"
    and "𝔣 : 𝔟 𝔞"
    and "ε' E'. ε' :
      ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤 >CF.cocone E' :
      ↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL ↦↦Cα 
      ∃!f'. f' : E E'  ε'NTMap𝔞PL2 = f' AεNTMap𝔞PL2"
  shows "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
proof-
  let ?II = ↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 
    and ?II_II = ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤
    and ?F = set {𝔤PL, 𝔣PL}
  have 𝔣𝔤_𝔤𝔣: "{𝔣PL, 𝔤PL} = {𝔤PL, 𝔣PL}" by auto
  interpret ε: is_cat_cocone α E ?II  ?II_II ε by (rule assms(1))
  from ε.cat_PL2_𝔣 ε.cat_PL2_𝔤 have 𝔤𝔣: "?F  Vset α"
    by (intro Limit_vdoubleton_in_VsetI) auto
  from assms(2,3) have "(λfset {𝔤PL, 𝔣PL}. (f = 𝔤PL ? 𝔤 : 𝔣))𝔣' : 𝔟 𝔞"
    if "𝔣'  set {𝔤PL, 𝔣PL}" for 𝔣'
    using that by simp
  note is_cat_coequalizerI'
    [
      OF assms(1)[
        unfolded 
          the_cat_parallel_2_def the_cf_parallel_2_def 𝔞PL2_def 𝔟PL2_def 𝔣𝔤_𝔤𝔣
          ],
      folded 𝔞PL2_def 𝔟PL2_def,
      OF 
        _ 
        𝔤𝔣
        _ 
        this
        _
        assms(4)[unfolded the_cf_parallel_2_def the_cat_parallel_2_def 𝔣𝔤_𝔤𝔣],
      of 𝔤PL,
      simplified
    ]
  with cat_PL2_𝔤𝔣 have
    "ε : (𝔞,𝔟,?F,(λf?F. (f = 𝔣PL ? 𝔣 : 𝔤))) >CF.coeq E : C ↦↦Cα"
    by (auto simp: VLambda_vdoubleton)
  from cat_coequalizer_is_cat_coequalizer_2[OF this] show ?thesis by simp
qed

lemma (in is_cat_equalizer_2) cat_eq_2_unique_cone:
  assumes "ε' :
    E' <CF.cone ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 : 
    ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα"
  shows "∃!f'. f' : E' E  ε'NTMap𝔞PL2 = εNTMap𝔞PL2 Af'"
  by 
    (
      rule is_cat_equalizer.cat_eq_unique_cone
        [
          OF cat_equalizer_2_is_cat_equalizer, 
          folded 𝔞PL2_def 𝔟PL2_def,
          OF assms[unfolded the_cf_parallel_2_def the_cat_parallel_2_def]
        ]
    )

lemma (in is_cat_equalizer_2) cat_eq_2_unique:
  assumes "ε' : E' <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
  shows
    "∃!f'. f' : E' E  ε' = ε NTCF ntcf_const (↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL)  f'"
proof-  
  interpret ε': is_cat_equalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms)
  show ?thesis
    by 
      (
        rule is_cat_equalizer.cat_eq_unique
          [
            OF cat_equalizer_2_is_cat_equalizer,
            folded 𝔞PL2_def 𝔟PL2_def,
            OF ε'.cat_equalizer_2_is_cat_equalizer,
            folded the_cat_parallel_2_def
          ]
      )
qed

lemma (in is_cat_equalizer_2) cat_eq_2_unique':
  assumes "ε' : E' <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
  shows "∃!f'. f' : E' E  ε'NTMap𝔞PL2 = εNTMap𝔞PL2 Af'"
proof-
  interpret ε': is_cat_equalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms)
  show ?thesis
    by 
      (
        rule is_cat_equalizer.cat_eq_unique'
          [
            OF cat_equalizer_2_is_cat_equalizer,
            folded 𝔞PL2_def 𝔟PL2_def,
            OF ε'.cat_equalizer_2_is_cat_equalizer,
            folded the_cat_parallel_2_def
          ]
      )
qed

lemma (in is_cat_coequalizer_2) cat_coeq_2_unique_cocone:
  assumes "ε' :
    ↑↑→↑↑CF  𝔟PL2 𝔞PL2 𝔣PL 𝔤PL 𝔟 𝔞 𝔣 𝔤 >CF.cocone E' :
    ↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL ↦↦Cα"
  shows "∃!f'. f' : E E'  ε'NTMap𝔞PL2 = f' AεNTMap𝔞PL2"
  by 
    (
      rule is_cat_coequalizer.cat_coeq_unique_cocone
        [
          OF cat_coequalizer_2_is_cat_coequalizer,
          folded 𝔞PL2_def 𝔟PL2_def insert_commute,
          OF assms[
            unfolded 
              the_cf_parallel_2_def the_cat_parallel_2_def cat_eq_F'_helper
            ]
        ]
    )

lemma (in is_cat_coequalizer_2) cat_coeq_2_unique:
  assumes "ε' : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E' : ↑↑C ↦↦Cα"
  shows "∃!f'.
    f' : E E' 
    ε' = ntcf_const (↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL)  f' NTCF ε"
proof-
  interpret ε': is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms)
  show ?thesis  
    by 
      (
        rule is_cat_coequalizer.cat_coeq_unique
          [
            OF cat_coequalizer_2_is_cat_coequalizer,
            folded 𝔞PL2_def 𝔟PL2_def,
            OF ε'.cat_coequalizer_2_is_cat_coequalizer,
            folded the_cat_parallel_2_def the_cat_parallel_2_commute
          ]
      )
qed

lemma (in is_cat_coequalizer_2) cat_coeq_2_unique':
  assumes "ε' : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E' : ↑↑C ↦↦Cα"
  shows "∃!f'. f' : E E'  ε'NTMap𝔞PL2 = f' AεNTMap𝔞PL2"
proof-
  interpret ε': is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms)
  show ?thesis
    by 
      (
        rule is_cat_coequalizer.cat_coeq_unique'
          [
            OF cat_coequalizer_2_is_cat_coequalizer,
            folded 𝔞PL2_def 𝔟PL2_def,
            OF ε'.cat_coequalizer_2_is_cat_coequalizer,
            folded the_cat_parallel_2_def
          ]
      )
qed

lemma cat_equalizer_2_ex_is_iso_arr:
  assumes "ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα" 
    and "ε' : E' <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
  obtains f where "f : E' isoE"
    and "ε' = ε NTCF ntcf_const (↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL)  f"
proof-
  interpret ε: is_cat_equalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε by (rule assms(1))
  interpret ε': is_cat_equalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms(2))
  show ?thesis
    using that 
    by 
      (
        rule cat_equalizer_ex_is_iso_arr
          [
            OF 
              ε.cat_equalizer_2_is_cat_equalizer 
              ε'.cat_equalizer_2_is_cat_equalizer,
            folded 𝔞PL2_def 𝔟PL2_def the_cat_parallel_2_def
          ]
      )  
qed

lemma cat_equalizer_2_ex_is_iso_arr':
  assumes "ε : E <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα" 
    and "ε' : E' <CF.eq (𝔞,𝔟,𝔤,𝔣) : ↑↑C ↦↦Cα"
  obtains f where "f : E' isoE"
    and "ε'NTMap𝔞PL2 = εNTMap𝔞PL2 Af"
    and "ε'NTMap𝔟PL2 = εNTMap𝔟PL2 Af"
proof-
  interpret ε: is_cat_equalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε by (rule assms(1))
  interpret ε': is_cat_equalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms(2))
  show ?thesis
    using that 
    by 
      (
        rule cat_equalizer_ex_is_iso_arr'
          [
            OF 
              ε.cat_equalizer_2_is_cat_equalizer 
              ε'.cat_equalizer_2_is_cat_equalizer,
            folded 𝔞PL2_def 𝔟PL2_def the_cat_parallel_2_def
          ]
      )
qed

lemma cat_coequalizer_2_ex_is_iso_arr:
  assumes "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
    and "ε' : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E' : ↑↑C ↦↦Cα"
  obtains f where "f : E isoE'" 
    and "ε' = ntcf_const (↑↑C 𝔟PL2 𝔞PL2 𝔣PL 𝔤PL)  f NTCF ε"
proof-
  interpret ε: is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε by (rule assms(1))
  interpret ε': is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms(2))
  show ?thesis
    using that 
    by 
      (
        rule cat_coequalizer_ex_is_iso_arr
          [
            OF 
              ε.cat_coequalizer_2_is_cat_coequalizer 
              ε'.cat_coequalizer_2_is_cat_coequalizer,
            folded 
              𝔞PL2_def 𝔟PL2_def the_cat_parallel_2_def the_cat_parallel_2_commute
          ]
      )
qed

lemma cat_coequalizer_2_ex_is_iso_arr':
  assumes "ε : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E : ↑↑C ↦↦Cα"
    and "ε' : (𝔞,𝔟,𝔤,𝔣) >CF.coeq E' : ↑↑C ↦↦Cα"
  obtains f where "f : E isoE'" 
    and "ε'NTMap𝔞PL2 = f AεNTMap𝔞PL2"
    and "ε'NTMap𝔟PL2 = f AεNTMap𝔟PL2"
proof-
  interpret ε: is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E ε by (rule assms(1))
  interpret ε': is_cat_coequalizer_2 α 𝔞 𝔟 𝔤 𝔣  E' ε' by (rule assms(2))
  show ?thesis
    using that 
    by 
      (
        rule cat_coequalizer_ex_is_iso_arr'
          [
            OF
              ε.cat_coequalizer_2_is_cat_coequalizer
              ε'.cat_coequalizer_2_is_cat_coequalizer,
            folded 
              𝔞PL2_def 𝔟PL2_def the_cat_parallel_2_def the_cat_parallel_2_commute
          ]
      )
qed


subsubsection‹Further properties›

lemma (in is_cat_equalizer_2) cat_eq_2_is_monic_arr: 
  "εNTMap𝔞PL2 : E mon𝔞"
  by
    (
      rule is_cat_equalizer.cat_eq_is_monic_arr[
        OF cat_equalizer_2_is_cat_equalizer, folded 𝔞PL2_def
        ]
    )

lemma (in is_cat_coequalizer_2) cat_coeq_2_is_epic_arr:
  "εNTMap𝔞PL2 : 𝔞 epiE"
  by
    (
      rule is_cat_coequalizer.cat_coeq_is_epic_arr[
        OF cat_coequalizer_2_is_cat_coequalizer, folded 𝔞PL2_def
        ]
    )



subsection‹Equalizer cone›


subsubsection‹Definition and elementary properties›

definition ntcf_equalizer_base :: "V  V  V  V  V  V  (V  V)  V"
  where "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E e =
    [
      (λx↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PLObj. e x),
      cf_const (↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL)  E,
      ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣,
      ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL,
      
    ]"


text‹Components.›

lemma ntcf_equalizer_base_components:
  shows "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTMap =
    (λx↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PLObj. e x)"
    and [cat_lim_cs_simps]: "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTDom =
      cf_const (↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL)  E"
    and [cat_lim_cs_simps]: "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTCod =
      ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣"
    and [cat_lim_cs_simps]: 
      "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTDGDom = ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL"
    and [cat_lim_cs_simps]: 
      "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTDGCod = "
  unfolding ntcf_equalizer_base_def nt_field_simps 
  by (simp_all add: nat_omega_simps)


subsubsection‹Natural transformation map›

mk_VLambda ntcf_equalizer_base_components(1)
  |vsv ntcf_equalizer_base_NTMap_vsv[cat_lim_cs_intros]|
  |vdomain ntcf_equalizer_base_NTMap_vdomain[cat_lim_cs_simps]|
  |app ntcf_equalizer_base_NTMap_app[cat_lim_cs_simps]|


subsubsection‹Equalizer cone is a cone›

lemma (in category) cat_ntcf_equalizer_base_is_cat_cone:
  assumes "e 𝔞PL2 : E 𝔞"
    and "e 𝔟PL2 : E 𝔟"
    and "e 𝔟PL2 = 𝔤 Ae 𝔞PL2"
    and "e 𝔟PL2 = 𝔣 Ae 𝔞PL2"
    and "𝔤 : 𝔞 𝔟"
    and "𝔣 : 𝔞 𝔟"
  shows "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E e :
    E <CF.cone ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 :
    ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα"
proof-
  interpret par: cf_parallel_2 α 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣  
    by (intro cf_parallel_2I cat_parallel_2I assms(5,6))
      (simp_all add: cat_parallel_cs_intros cat_cs_intros)
  show ?thesis
  proof(intro is_cat_coneI is_tm_ntcfI' is_ntcfI')
    show "vfsequence (ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E e)"
      unfolding ntcf_equalizer_base_def by auto
    show "vcard (ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E e) = 5"
      unfolding ntcf_equalizer_base_def by (simp add: nat_omega_simps)
    from assms(2) show 
      "cf_const (↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL)  E : ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα"
      by 
        (
          cs_concl 
            cs_simp: cat_cs_simps 
            cs_intro: cat_small_cs_intros cat_parallel_cs_intros cat_cs_intros
        )
    from assms show 
      "↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣 : ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL ↦↦Cα"
      by (cs_concl cs_intro: cat_parallel_cs_intros cat_small_cs_intros)
    show 
      "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTMapi :
        cf_const (↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL)  EObjMapi ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣ObjMapi"
      if "i  ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PLObj" for i 
    proof-
      from that assms(1,2,5,6) show ?thesis
        by (elim the_cat_parallel_2_ObjE; simp only:)
          ( 
            cs_concl 
              cs_simp: cat_lim_cs_simps cat_cs_simps cat_parallel_cs_simps 
              cs_intro: cat_cs_intros cat_parallel_cs_intros
          )
    qed
    show 
      "ntcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTMapb' Acf_const (↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PL)  EArrMapf' =
          ↑↑→↑↑CF  𝔞PL2 𝔟PL2 𝔤PL 𝔣PL 𝔞 𝔟 𝔤 𝔣ArrMapf' Antcf_equalizer_base  𝔞 𝔟 𝔤 𝔣 E eNTMapa'"
      if "f' : a' ↑↑C 𝔞PL2 𝔟PL2 𝔤PL 𝔣PLb'" for a' b' f'
      using that assms(1,2,5,6)
      by (elim par.the_cat_parallel_2_is_arrE; simp only:)
        (
          cs_concl 
            cs_simp: 
              cat_cs_simps 
              cat_lim_cs_simps 
              cat_parallel_cs_simps 
              assms(3,4)[symmetric]
            cs_intro: cat_parallel_cs_intros
        )+
  qed 
    (
      use assms(2) in 
        cs_concl 
            cs_intro: cat_lim_cs_intros cat_cs_intros 
            cs_simp: cat_lim_cs_simps
    )+
qed

text‹\newpage›

end