Theory CZH_DG_PDigraph

(* Copyright 2021 (C) Mihails Milehins *)

section‹Product digraph›
theory CZH_DG_PDigraph
  imports 
    CZH_DG_TDGHM
    CZH_DG_Small_Digraph
begin



subsection‹Background›


text‹
The concept of a product digraph, as presented in this work, 
is a generalization of the concept of a product category,
as presented in Chapter II-3 in cite"mac_lane_categories_2010".
›

named_theorems dg_prod_cs_simps
named_theorems dg_prod_cs_intros



subsection‹Product digraph: definition and elementary properties›

definition dg_prod :: "V  (V  V)  V"
  where "dg_prod I 𝔄 =
    [
      (iI. 𝔄 iObj),
      (iI. 𝔄 iArr),
      (λf(iI. 𝔄 iArr). (λiI. 𝔄 iDomfi)),
      (λf(iI. 𝔄 iArr). (λiI. 𝔄 iCodfi))
    ]"

syntax "_PDIGRAPH" :: "pttrn  V  (V  V)  V"
  ((3DG__./ _) [0, 0, 10] 10)
translations "DGiI. 𝔄"  "CONST dg_prod I (λi. 𝔄)"


text‹Components.›

lemma dg_prod_components:
  shows "(DGiI. 𝔄 i)Obj = (iI. 𝔄 iObj)"
    and "(DGiI. 𝔄 i)Arr = (iI. 𝔄 iArr)"
    and "(DGiI. 𝔄 i)Dom =
      (λf(iI. 𝔄 iArr). (λiI. 𝔄 iDomfi))"
    and "(DGiI. 𝔄 i)Cod =
      (λf(iI. 𝔄 iArr). (λiI. 𝔄 iCodfi))"
  unfolding dg_prod_def dg_field_simps by (simp_all add: nat_omega_simps)



subsection‹Local assumptions for a product digraph›

locale pdigraph_base = 𝒵 α for α I and 𝔄 :: "V  V" +
  assumes pdg_digraphs[dg_prod_cs_intros]: "i  I  digraph α (𝔄 i)"
    and pdg_index_in_Vset[dg_cs_intros]: "I  Vset α"


text‹Rules.›

lemma (in pdigraph_base) pdigraph_base_axioms'[dg_prod_cs_intros]: 
  assumes "α' = α" and "I' = I"
  shows "pdigraph_base α' I' 𝔄"
  unfolding assms by (rule pdigraph_base_axioms)

mk_ide rf pdigraph_base_def[unfolded pdigraph_base_axioms_def]
  |intro pdigraph_baseI|
  |dest pdigraph_baseD[dest]|
  |elim pdigraph_baseE[elim]|


text‹Elementary properties.›

lemma (in pdigraph_base) pdg_Obj_in_Vset: 
  assumes "𝒵 β" and "α  β" 
  shows "(iI. 𝔄 iObj)  Vset β"
proof(rule Vset_trans)
  interpret β: 𝒵 β by (rule assms(1))
  show "(iI. 𝔄 iObj)  Vset (succ (succ α))"
  proof
    (
      rule vsubset_in_VsetI,
      rule Limit_vproduct_vsubset_Vset_succI,
      rule Limit_α,
      intro dg_cs_intros
    )
    show "Vset (succ α)  Vset (succ (succ α))" 
      by (cs_concl cs_shallow cs_intro: V_cs_intros)
    fix i assume "i  I"
    then interpret digraph α 𝔄 i
      by (cs_concl cs_shallow cs_intro: dg_cs_intros dg_prod_cs_intros)
    show "𝔄 iObj  Vset α" by (rule dg_Obj_vsubset_Vset)
  qed
  from assms(2) show "Vset (succ (succ α))  Vset β"
    by (cs_concl cs_shallow cs_intro: V_cs_intros succ_in_Limit_iff[THEN iffD2])
qed

lemma (in pdigraph_base) pdg_Arr_in_Vset: 
  assumes "𝒵 β" and "α  β" 
  shows "(iI. 𝔄 iArr)  Vset β"
proof(rule Vset_trans)
  interpret β: 𝒵 β by (rule assms(1))
  show "(iI. 𝔄 iArr)  Vset (succ (succ α))"
  proof
    (
      rule vsubset_in_VsetI,
      rule Limit_vproduct_vsubset_Vset_succI,
      rule Limit_α,
      intro dg_cs_intros
    )
    fix i assume "i  I"
    then interpret digraph α 𝔄 i 
      by (cs_concl cs_shallow cs_intro: dg_prod_cs_intros)
    show "𝔄 iArr  Vset α" by (rule dg_Arr_vsubset_Vset)
  qed (cs_concl cs_shallow cs_intro: V_cs_intros)
  from assms(2) show "Vset (succ (succ α))  Vset β"
    by (cs_concl cs_shallow cs_intro: V_cs_intros succ_in_Limit_iff[THEN iffD2])
qed

lemmas_with (in pdigraph_base) [folded dg_prod_components]:
  pdg_dg_prod_Obj_in_Vset[dg_cs_intros] = pdg_Obj_in_Vset
  and pdg_dg_prod_Arr_in_Vset[dg_cs_intros] = pdg_Arr_in_Vset

lemma (in pdigraph_base) pdg_vsubset_index_pdigraph_base:
  assumes "J  I"
  shows "pdigraph_base α J 𝔄"
  using assms
  by (intro pdigraph_baseI)
    (auto simp: vsubset_in_VsetI dg_cs_intros intro: dg_prod_cs_intros)


subsubsection‹Object›

lemma dg_prod_ObjI:
  assumes "vsv a" and "𝒟 a = I" and "i. i  I  ai  𝔄 iObj"
  shows "a  (DGiI. 𝔄 i)Obj"
  using assms unfolding dg_prod_components by auto

lemma dg_prod_ObjD:
  assumes "a  (DGiI. 𝔄 i)Obj" 
  shows "vsv a" and "𝒟 a = I" and "i. i  I  ai  𝔄 iObj"
  using assms unfolding dg_prod_components by auto

lemma dg_prod_ObjE:
  assumes "a  (DGiI. 𝔄 i)Obj" 
  obtains "vsv a" and "𝒟 a = I" and "i. i  I  ai  𝔄 iObj"
  using assms by (auto dest: dg_prod_ObjD)

lemma dg_prod_Obj_cong:
  assumes "g  (DGiI. 𝔄 i)Obj"
    and "f  (DGiI. 𝔄 i)Obj"
    and "i. i  I  gi = fi"
  shows "g = f"
  using assms by (intro vsv_eqI[of g f]) (force simp: dg_prod_components)+


subsubsection‹Arrow›

lemma dg_prod_ArrI:
  assumes "vsv f" and "𝒟 f = I" and "i. i  I  fi  𝔄 iArr"
  shows "f  (DGiI. 𝔄 i)Arr"
  using assms unfolding dg_prod_components by auto

lemma dg_prod_ArrD:
  assumes "f  (DGiI. 𝔄 i)Arr" 
  shows "vsv f" and "𝒟 f = I" and "i. i  I  fi  𝔄 iArr"
  using assms unfolding dg_prod_components by auto

lemma dg_prod_ArrE:
  assumes "f  (DGiI. 𝔄 i)Arr" 
  obtains "vsv f" and "𝒟 f = I" and "i. i  I  fi  𝔄 iArr"
  using assms by (auto dest: dg_prod_ArrD)

lemma dg_prod_Arr_cong:
  assumes "g  (DGiI. 𝔄 i)Arr"
    and "f  (DGiI. 𝔄 i)Arr"
    and "i. i  I  gi = fi"
  shows "g = f"
  using assms by (intro vsv_eqI[of g f]) (force simp: dg_prod_components)+


subsubsection‹Domain›

mk_VLambda dg_prod_components(3)
  |vsv dg_prod_Dom_vsv[dg_cs_intros]|
  |vdomain dg_prod_Dom_vdomain[folded dg_prod_components, dg_cs_simps]|
  |app dg_prod_Dom_app[folded dg_prod_components]|

lemma (in pdigraph_base) dg_prod_Dom_app_in_Obj[dg_cs_intros]:
  assumes "f  (DGiI. 𝔄 i)Arr"
  shows "(DGiI. 𝔄 i)Domf  (DGiI. 𝔄 i)Obj"
  unfolding dg_prod_components(1) dg_prod_Dom_app[OF assms]
proof(intro vproductI ballI)
  fix i assume prems: "i  I" 
  interpret digraph α 𝔄 i 
    by (auto simp: prems intro: dg_prod_cs_intros)
  from assms prems show "(λiI. 𝔄 iDomfi)i  𝔄 iObj"
    unfolding dg_prod_components(2) by force
qed simp_all

lemma dg_prod_Dom_app_component_app[dg_cs_simps]:
  assumes "f  (DGiI. 𝔄 i)Arr" and "i  I"
  shows "(DGiI. 𝔄 i)Domfi = 𝔄 iDomfi"
  using assms(2) unfolding dg_prod_Dom_app[OF assms(1)] by simp


subsubsection‹Codomain›

mk_VLambda dg_prod_components(4)
  |vsv dg_prod_Cod_vsv[dg_cs_intros]|
  |vdomain dg_prod_Cod_vdomain[folded dg_prod_components, dg_cs_simps]|
  |app dg_prod_Cod_app[folded dg_prod_components]|

lemma (in pdigraph_base) dg_prod_Cod_app_in_Obj[dg_cs_intros]:
  assumes "f  (DGiI. 𝔄 i)Arr"
  shows "(DGiI. 𝔄 i)Codf  (DGiI. 𝔄 i)Obj"
  unfolding dg_prod_components(1) dg_prod_Cod_app[OF assms]
proof(rule vproductI)
  show "iI. (λiI. 𝔄 iCodfi)i  𝔄 iObj"
  proof(intro ballI)
    fix i assume prems: "i  I" 
    then interpret digraph α 𝔄 i 
      by (auto intro: dg_prod_cs_intros)
    from assms prems show "(λiI. 𝔄 iCodfi)i  𝔄 iObj"
      unfolding dg_prod_components(2) by force
  qed
qed simp_all

lemma dg_prod_Cod_app_component_app[dg_cs_simps]:
  assumes "f  (DGiI. 𝔄 i)Arr" and "i  I"
  shows "(DGiI. 𝔄 i)Codfi = 𝔄 iCodfi"
  using assms(2) unfolding dg_prod_Cod_app[OF assms(1)] by simp


subsubsection‹A product α›-digraph is a tiny β›-digraph›

lemma (in pdigraph_base) pdg_tiny_digraph_dg_prod:
  assumes "𝒵 β" and "α  β" 
  shows "tiny_digraph β (DGiI. 𝔄 i)"
proof(intro tiny_digraphI)
  show "vfsequence (DGiI. 𝔄 i)" unfolding dg_prod_def by simp
  show "vcard (DGiI. 𝔄 i) = 4"
    unfolding dg_prod_def by (simp add: nat_omega_simps)
  show vsv_dg_prod_Dom: "vsv ((DGiI. 𝔄 i)Dom)" 
    unfolding dg_prod_components by simp
  show vdomain_dg_prod_Dom: "𝒟 ((DGiI. 𝔄 i)Dom) = (DGiI. 𝔄 i)Arr"
    unfolding dg_prod_components by simp
  show " ((DGiI. 𝔄 i)Dom)  (DGiI. 𝔄 i)Obj"  
    by (rule vsubsetI)
      (
        metis 
          dg_prod_Dom_app_in_Obj 
          dg_prod_Dom_vdomain 
          vsv.vrange_atE 
          vsv_dg_prod_Dom
      )
  show vsv_dg_prod_Cod: "vsv ((DGiI. 𝔄 i)Cod)" 
    unfolding dg_prod_components by auto
  show vdomain_dg_prod_Cod: "𝒟 ((DGiI. 𝔄 i)Cod) = (DGiI. 𝔄 i)Arr"
    unfolding dg_prod_components by auto
  show " ((DGiI. 𝔄 i)Cod)  (DGiI. 𝔄 i)Obj"  
    by (rule vsubsetI)
      (
        metis 
          dg_prod_Cod_app_in_Obj 
          vdomain_dg_prod_Cod 
          vsv.vrange_atE 
          vsv_dg_prod_Cod
      )
qed 
  (
    auto simp:
      dg_cs_intros
      assms 
      pdg_dg_prod_Arr_in_Vset[OF assms(1,2)]
      pdg_dg_prod_Obj_in_Vset[OF assms(1,2)]
  )


lemma (in pdigraph_base) pdg_tiny_digraph_dg_prod': 
  "tiny_digraph (α + ω) (DGiI. 𝔄 i)"
  by (rule pdg_tiny_digraph_dg_prod)
    (simp_all add: 𝒵_α_αω 𝒵.intro 𝒵_Limit_αω 𝒵_ω_αω)


subsubsection‹Arrow with a domain and a codomain›

lemma (in pdigraph_base) dg_prod_is_arrI:
  assumes "vsv f"
    and "𝒟 f = I"
    and "vsv a"
    and "𝒟 a = I"
    and "vsv b"
    and "𝒟 b = I"
    and "i. i  I  fi : ai 𝔄 ibi"
  shows "f : a DGiI. 𝔄 ib"
proof(intro is_arrI)
  interpret f: vsv f by (rule assms(1))
  interpret a: vsv a by (rule assms(3))
  interpret b: vsv b by (rule assms(5))
  from assms(7) have f_components: "i. i  I  fi  𝔄 iArr" by auto
  from assms(7) have a_components: "i. i  I  ai  𝔄 iObj"
    by (meson digraph.dg_is_arrD(2) pdg_digraphs)
  from assms(7) have b_components: "i. i  I  bi  𝔄 iObj"
    by (meson digraph.dg_is_arrD(3) pdg_digraphs)
  show f_in_Arr: "f  (DGiI. 𝔄 i)Arr"
    unfolding dg_prod_components
    by (intro vproductI)
      (auto simp: f_components assms(2) f.vsv_vrange_vsubset_vifunion_app)
  show "(DGiI. 𝔄 i)Domf = a"
  proof(rule vsv_eqI)
    from dg_prod_Dom_app_in_Obj[OF f_in_Arr] show "vsv ((DGiI. 𝔄 i)Domf)"
      unfolding dg_prod_components by clarsimp
    from dg_prod_Dom_app_in_Obj[OF f_in_Arr] assms(4) show [simp]:
      "𝒟 ((DGiI. 𝔄 i)Domf) = 𝒟 a"
      unfolding dg_prod_components by clarsimp
    fix i assume "i  𝒟 ((DGiI. 𝔄 i)Domf)"
    then have i: "i  I" by (simp add: assms(4))
    from a_components assms(7) i show "(DGiI. 𝔄 i)Domfi = ai"
      unfolding dg_prod_Dom_app_component_app[OF f_in_Arr i] by auto
  qed auto
  show "(DGiI. 𝔄 i)Codf = b"
  proof(rule vsv_eqI)
    from dg_prod_Cod_app_in_Obj[OF f_in_Arr] show "vsv ((DGiI. 𝔄 i)Codf)"
      unfolding dg_prod_components by clarsimp
    from dg_prod_Cod_app_in_Obj[OF f_in_Arr] assms(6) show [simp]:
      "𝒟 ((DGiI. 𝔄 i)Codf) = 𝒟 b"
      unfolding dg_prod_components by clarsimp
    fix i assume "i  𝒟 ((DGiI. 𝔄 i)Codf)"
    then have i: "i  I" by (simp add: assms(6))
    from b_components assms(7) i show "(DGiI. 𝔄 i)Codfi = bi"
      unfolding dg_prod_Cod_app_component_app[OF f_in_Arr i] by auto
  qed auto
qed

lemma (in pdigraph_base) dg_prod_is_arrD[dest]:
  assumes "f : a DGiI. 𝔄 ib"
  shows "vsv f"
    and "𝒟 f = I"
    and "vsv a"
    and "𝒟 a = I"
    and "vsv b"
    and "𝒟 b = I"
    and "i. i  I  fi : ai 𝔄 ibi"
proof-
  from is_arrD[OF assms] have f: "f  (DGiI. 𝔄 i)Arr"
    and a: "a  (DGiI. 𝔄 i)Obj" 
    and b: "b  (DGiI. 𝔄 i)Obj" 
    by (auto intro: dg_cs_intros)
  then show "𝒟 f = I" "𝒟 a = I" "𝒟 b = I" "vsv f" "vsv a" "vsv b"
    unfolding dg_prod_components by auto
  fix i assume prems: "i  I"
  show "fi : ai 𝔄 ibi"
  proof(intro is_arrI)
    from assms(1) have f: "f  (DGiI. 𝔄 i)Arr"
      and a: "a  (DGiI. 𝔄 i)Obj"
      and b: "b  (DGiI. 𝔄 i)Obj"
    by (auto intro: dg_cs_intros)
    from f prems show "fi  𝔄 iArr"
      unfolding dg_prod_components by clarsimp
    from a b assms(1) prems dg_prod_components(2,3,4) show 
      "𝔄 iDomfi = ai" "𝔄 iCodfi = bi"
      by fastforce+
  qed
qed

lemma (in pdigraph_base) dg_prod_is_arrE[elim]:
  assumes "f : a DGiI. 𝔄 ib"
  obtains "vsv f"
    and "𝒟 f = I"
    and "vsv a"
    and "𝒟 a = I"
    and "vsv b"
    and "𝒟 b = I"
    and "i. i  I  fi : ai 𝔄 ibi"
  using assms by auto



subsection‹Further local assumptions for product digraphs›


subsubsection‹Definition and elementary properties›

locale pdigraph = pdigraph_base α I 𝔄 for α I 𝔄 +
  assumes pdg_Obj_vsubset_Vset: "J  I  (DGiJ. 𝔄 i)Obj  Vset α"
    and pdg_Hom_vifunion_in_Vset: 
      "
        J  I;
        A  (DGiJ. 𝔄 i)Obj;
        B  (DGiJ. 𝔄 i)Obj;
        A  Vset α;
        B  Vset α
        (aA. bB. Hom (DGiJ. 𝔄 i) a b)  Vset α"


text‹Rules.›

lemma (in pdigraph) pdigraph_axioms'[dg_prod_cs_intros]: 
  assumes "α' = α" and "I' = I"
  shows "pdigraph α' I' 𝔄"
  unfolding assms by (rule pdigraph_axioms)

mk_ide rf pdigraph_def[unfolded pdigraph_axioms_def]
  |intro pdigraphI|
  |dest pdigraphD[dest]|
  |elim pdigraphE[elim]|

lemmas [dg_prod_cs_intros] = pdigraphD(1)


text‹Elementary properties.›

lemma (in pdigraph) pdg_Obj_vsubset_Vset': "(DGiI. 𝔄 i)Obj  Vset α"
  by (rule pdg_Obj_vsubset_Vset) simp

lemma (in pdigraph) pdg_Hom_vifunion_in_Vset':
  assumes "A  (DGiI. 𝔄 i)Obj"
    and "B  (DGiI. 𝔄 i)Obj"
    and "A  Vset α"
    and "B  Vset α"
  shows "(aA. bB. Hom (DGiI. 𝔄 i) a b)  Vset α"
  using assms by (intro pdg_Hom_vifunion_in_Vset) simp_all

lemma (in pdigraph) pdg_vsubset_index_pdigraph:
  assumes "J  I"
  shows "pdigraph α J 𝔄"
proof(intro pdigraphI)
  show "dg_prod J' 𝔄Obj  Vset α" if J'  J for J'
  proof-
    from that assms have "J'  I" by simp
    then show "dg_prod J' 𝔄Obj  Vset α" by (rule pdg_Obj_vsubset_Vset)
  qed
  fix A B J' assume prems: 
    "J'  J"
    "A  (DGiJ'. 𝔄 i)Obj"
    "B  (DGiJ'. 𝔄 i)Obj"
    "A  Vset α" 
    "B  Vset α"
  show "(aA. bB. Hom (DGiJ'. 𝔄 i) a b)  Vset α"
  proof-
    from prems(1) assms have "J'  I" by simp
    from pdg_Hom_vifunion_in_Vset[OF this prems(2-5)] show ?thesis.
  qed
qed (rule pdg_vsubset_index_pdigraph_base[OF assms])


subsubsection‹A product α›-digraph is an α›-digraph›

lemma (in pdigraph) pdg_digraph_dg_prod: "digraph α (DGiI. 𝔄 i)"
proof-
  interpret tiny_digraph α + ω DGiI. 𝔄 i
    by (intro pdg_tiny_digraph_dg_prod) 
      (auto simp: 𝒵_α_αω 𝒵.intro 𝒵_Limit_αω 𝒵_ω_αω)
  show ?thesis
    by (rule digraph_if_digraph)  
      (
        auto 
          intro!: pdg_Hom_vifunion_in_Vset pdg_Obj_vsubset_Vset
          intro: dg_cs_intros
      )
qed



subsection‹Local assumptions for a finite product digraph›


subsubsection‹Definition and elementary properties›

locale finite_pdigraph = pdigraph_base α I 𝔄 for α I 𝔄 +
  assumes fin_pdg_index_vfinite: "vfinite I"


text‹Rules.›

lemma (in finite_pdigraph) finite_pdigraph_axioms'[dg_prod_cs_intros]: 
  assumes "α' = α" and "I' = I"
  shows "finite_pdigraph α' I' 𝔄"
  unfolding assms by (rule finite_pdigraph_axioms)

mk_ide rf finite_pdigraph_def[unfolded finite_pdigraph_axioms_def]
  |intro finite_pdigraphI|
  |dest finite_pdigraphD[dest]|
  |elim finite_pdigraphE[elim]|

lemmas [dg_prod_cs_intros] = finite_pdigraphD(1)


subsubsection‹
Local assumptions for a finite product digraph and local
assumptions for an arbitrary product digraph
›

sublocale finite_pdigraph  pdigraph α I 𝔄
proof(intro pdigraphI)
  show "(DGiJ. 𝔄 i)Obj  Vset α" if "J  I" for J
    unfolding dg_prod_components
  proof-
    from that fin_pdg_index_vfinite have J: "vfinite J"
      by (cs_concl cs_shallow cs_intro: vfinite_vsubset)
    show "(iJ. 𝔄 iObj)  Vset α"
    proof(intro vsubsetI)
      fix A assume prems: "A  (iJ. 𝔄 iObj)"
      note A = vproductD[OF prems, rule_format]
      show "A  Vset α"
      proof(rule vsv.vsv_Limit_vsv_in_VsetI)
        from that show "𝒟 A  Vset α" 
          unfolding A(2) by (auto intro: pdg_index_in_Vset)
        show " A  Vset α"
        proof(intro vsv.vsv_vrange_vsubset, unfold A(2))
          fix i assume prems': "i  J"
          with that have i: "i  I" by auto
          interpret digraph α 𝔄 i
            by (cs_concl cs_shallow cs_intro: dg_prod_cs_intros i)
          have "Ai  𝔄 iObj" by (rule A(3)[OF prems'])
          then show "Ai  Vset α" by (cs_concl cs_intro: dg_cs_intros)
        qed (intro A(1))
      qed (auto simp: A(2) intro!: J A(1))
    qed
  qed
  show "(aA. bB. Hom (DGiJ. 𝔄 i) a b)  Vset α"
    if J: "J  I"
      and A: "A  (DGiJ. 𝔄 i)Obj"
      and B: "B  (DGiJ. 𝔄 i)Obj"
      and A_in_Vset: "A  Vset α"
      and B_in_Vset: "B  Vset α"
    for J A B 
  proof-
    interpret J: pdigraph_base α J 𝔄 
      by (intro J pdg_vsubset_index_pdigraph_base)
    let ?UA = ((A)) and ?UB = ((B))
    from that(4) have UA: "?UA  Vset α" by (intro VUnion_in_VsetI)
    from that(5) have UB: "?UB  Vset α" by (intro VUnion_in_VsetI)
    have "(iJ. (a?UA. b?UB. Hom (𝔄 i) a b))  Vset α"
    proof(intro Limit_vproduct_in_VsetI)
      from that(1) show "J  Vset α" by (auto intro!: pdg_index_in_Vset)
      show "(a?UA. b?UB. Hom (𝔄 i) a b)  Vset α" if i: "i  J" for i
      proof-
        from i J have i: "i  I" by auto
        interpret digraph α 𝔄 i 
          using i by (cs_concl cs_intro: dg_prod_cs_intros)
        have [dg_cs_simps]: "(a?UA. b?UB. Hom (𝔄 i) a b) 
          (a?UA  𝔄 iObj. b?UB  𝔄 iObj. Hom (𝔄 i) a b)"
        proof(intro vsubsetI)
          fix f assume "f  (a?UA. b?UB. Hom (𝔄 i) a b)"
          then obtain a b
            where a: "a  ?UA" and b: "b  ?UB" and f: "f : a 𝔄 ib" 
            by (elim vifunionE, unfold in_Hom_iff)
          then show
            "f  (a?UA  𝔄 iObj. b?UB  𝔄 iObj. Hom (𝔄 i) a b)"
            by (intro vifunionI, unfold in_Hom_iff) (auto intro!: f b a)
        qed
        moreover from UA UB have 
          "(a?UA  𝔄 iObj. b?UB  𝔄 iObj. Hom (𝔄 i) a b)  
            Vset α"
          by (intro dg_Hom_vifunion_in_Vset) auto
        ultimately show ?thesis by auto
      qed
      from J show "vfinite J"
        by (rule vfinite_vsubset[OF fin_pdg_index_vfinite])
    qed auto
    moreover have 
      "(aA. bB. Hom (DGiJ. 𝔄 i) a b) 
        (iJ. (a?UA. b?UB. Hom (𝔄 i) a b))"
    proof(intro vsubsetI)
      fix f assume "f  (aA. bB. Hom (DGiJ. 𝔄 i) a b)"
      then obtain a b 
        where a: "a  A" and b: "b  B" and f: "f  Hom (DGiJ. 𝔄 i) a b"
        by auto
      from f have f: "f : a (DGiJ. 𝔄 i)b" by simp
      show "f  (iJ. (a?UA. b?UB. Hom (𝔄 i) a b))"
      proof
        (
          intro vproductI, 
          unfold Ball_def; 
          (intro allI impI)?;
          (intro vifunionI)?;
          (unfold in_Hom_iff)?
        )
        from f show "vsv f" by (auto simp: dg_prod_components(2))
        from f show "𝒟 f = J" by (auto simp: dg_prod_components(2))
        fix i assume i: "i  J"
        show "ai  ?UA"
          by 
            (
              intro vprojection_in_VUnionI, 
              rule that(2)[unfolded dg_prod_components(1)]; 
              intro a i
            )
        show "bi  ?UB"
          by 
            (
              intro vprojection_in_VUnionI, 
              rule that(3)[unfolded dg_prod_components(1)]; 
              intro b i
            )
        show "fi : ai 𝔄 ibi" by (rule J.dg_prod_is_arrD(7)[OF f i])
      qed
    qed
    ultimately show "(aA. bB. Hom (DGiJ. 𝔄 i) a b)  Vset α" 
      by blast
  qed
qed (intro pdigraph_base_axioms)



subsection‹Binary union and complement›


subsubsection‹Application-specific methods›

method vdiff_of_vunion uses rule assms subset = 
  (
    rule 
      rule
        [
          OF vintersection_complement assms, 
          unfolded vunion_complement[OF subset]
        ]
  )

method vdiff_of_vunion' uses rule assms subset = 
  (
    rule 
      rule
        [
          OF vintersection_complement complement_vsubset subset assms, 
          unfolded vunion_complement[OF subset]
        ]
  )


subsubsection‹Results›

lemma dg_prod_vunion_Obj_in_Obj:
  assumes "vdisjnt J K"
    and "b  (DGjJ. 𝔄 j)Obj" 
    and "c  (DGkK. 𝔄 k)Obj"
  shows "b  c  (DGiJ  K. 𝔄 i)Obj"
proof-

  interpret b: vsv b using assms(2) unfolding dg_prod_components by clarsimp
  interpret c: vsv c using assms(3) unfolding dg_prod_components by clarsimp

  from assms(2,3) have dom_b: "𝒟 b = J" and dom_c: "𝒟 c = K"
    unfolding dg_prod_components by auto
  from assms(1) have disjnt: "𝒟 b  𝒟 c = 0" unfolding dom_b dom_c by auto

  show ?thesis
    unfolding dg_prod_components
  proof(intro vproductI)
    show "𝒟 (b  c) = J  K" by (auto simp: vdomain_vunion dom_b dom_c)
    show "iJ  K. (b  c)i  𝔄 iObj"
    proof(intro ballI)
      fix i assume prems: "i  J  K" 
      then consider (ib) i  𝒟 b | (ic) i  𝒟 c 
        unfolding dom_b dom_c by auto
      then show "(b  c)i  𝔄 iObj"
      proof cases
        case ib
        with prems disjnt have bc_i: "(b  c)i = bi"
          by (auto intro!: vsv_vunion_app_left)
        from assms(2) ib show ?thesis unfolding bc_i dg_prod_components by auto
      next
        case ic 
        with prems disjnt have bc_i: "(b  c)i = ci"
          by (auto intro!: vsv_vunion_app_right)
        from assms(3) ic show ?thesis unfolding bc_i dg_prod_components by auto
      qed 
    qed
  qed (auto simp: disjnt)

qed

lemma dg_prod_vdiff_vunion_Obj_in_Obj:
  assumes "J  I"
    and "b  (DGkI - J. 𝔄 k)Obj" 
    and "c  (DGjJ. 𝔄 j)Obj"
  shows "b  c  (DGiI. 𝔄 i)Obj"
  by 
    (
      vdiff_of_vunion 
        rule: dg_prod_vunion_Obj_in_Obj assms: assms(2,3) subset: assms(1)
    )

lemma dg_prod_vunion_Arr_in_Arr:
  assumes "vdisjnt J K" 
    and "b  (DGjJ. 𝔄 j)Arr" 
    and "c  (DGkK. 𝔄 k)Arr"
  shows "b  c  (DGiJ  K. 𝔄 i)Arr"
  unfolding dg_prod_components
proof(intro vproductI)

  interpret b: vsv b using assms(2) unfolding dg_prod_components by clarsimp
  interpret c: vsv c using assms(3) unfolding dg_prod_components by clarsimp

  from assms have dom_b: "𝒟 b = J" and dom_c: "𝒟 c = K" 
    unfolding dg_prod_components by auto
  from assms have disjnt: "𝒟 b  𝒟 c = 0" unfolding dom_b dom_c by auto

  from disjnt show "vsv (b  c)" by auto
  show dom_bc: "𝒟 (b  c) = J  K" 
    unfolding vdomain_vunion dom_b dom_c by auto

  show "iJ  K. (b  c)i  𝔄 iArr"
  proof(intro ballI)
    fix i assume prems: "i  J  K" 
    then consider (ib) i  𝒟 b | (ic) i  𝒟 c 
      unfolding dom_b dom_c by auto
    then show "(b  c)i  𝔄 iArr"
    proof cases
      case ib
      with prems disjnt have bc_i: "(b  c)i = bi"
        by (auto intro!: vsv_vunion_app_left)
      from assms(2) ib show ?thesis unfolding bc_i dg_prod_components by auto
    next
      case ic 
      with prems disjnt have bc_i: "(b  c)i = ci"
        by (auto intro!: vsv_vunion_app_right)
      from assms(3) ic show ?thesis unfolding bc_i dg_prod_components by auto
    qed 
  qed

qed

lemma dg_prod_vdiff_vunion_Arr_in_Arr:
  assumes "J  I"
    and "b  (DGkI - J. 𝔄 k)Arr" 
    and "c  (DGjJ. 𝔄 j)Arr"
  shows "b  c  (DGiI. 𝔄 i)Arr"
  by 
    (
      vdiff_of_vunion 
        rule: dg_prod_vunion_Arr_in_Arr assms: assms(2,3) subset: assms(1)
    )

lemma (in pdigraph) pdg_dg_prod_vunion_is_arr:
  assumes "vdisjnt J K"
    and "J  I"
    and "K  I"
    and "g : a (DGjJ. 𝔄 j)b" 
    and "f : c (DGkK. 𝔄 k)d"
  shows "g  f : a  c (DGiJ  K. 𝔄 i)b  d"
proof-

  interpret J𝔄: pdigraph α J 𝔄 
    using assms(2) by (simp add: pdg_vsubset_index_pdigraph)
  interpret K𝔄: pdigraph α K 𝔄 
    using assms(3) by (simp add: pdg_vsubset_index_pdigraph)
  interpret JK𝔄: pdigraph α J  K 𝔄 
    using assms(2,3) by (simp add: pdg_vsubset_index_pdigraph)

  show ?thesis
  proof(intro JK𝔄.dg_prod_is_arrI)

    note gD = J𝔄.dg_prod_is_arrD[OF assms(4)]
      and fD = K𝔄.dg_prod_is_arrD[OF assms(5)]

    from assms(1) gD fD show
      "vsv (g  f)"
      "𝒟 (g  f) = J  K"
      "vsv (a  c)"
      "𝒟 (a  c) = J  K"
      "vsv (b  d)" 
      "𝒟 (b  d) = J  K"
      by (auto simp: vdomain_vunion)

    fix i assume "i  J  K"
    then consider (iJ) i  J | (iK) i  K by auto
    then show "(g  f)i : (a  c)i 𝔄 i(b  d)i" 
    proof cases
      case iJ
      have gf_i: "(g  f)i = gi" by (simp add: iJ assms(1) gD(1,2) fD(1,2))        
      have ac_i: "(a  c)i = ai" by (simp add: iJ assms(1) gD(3,4) fD(3,4))
      have bd_i: "(b  d)i = bi" by (simp add: iJ assms(1) gD(5,6) fD(5,6))
      show ?thesis unfolding gf_i ac_i bd_i by (rule gD(7)[OF iJ])
    next
      case iK
      have gf_i: "(g  f)i = fi" by (simp add: iK assms(1) gD(1,2) fD(1,2))        
      have ac_i: "(a  c)i = ci" by (simp add: iK assms(1) gD(3,4) fD(3,4))
      have bd_i: "(b  d)i = di" by (simp add: iK assms(1) gD(5,6) fD(5,6))
      show ?thesis unfolding gf_i ac_i bd_i by (rule fD(7)[OF iK])
    qed

  qed

qed

lemma (in pdigraph) pdg_dg_prod_vdiff_vunion_is_arr:
  assumes "J  I"  
    and "g : a (DGkI - J. 𝔄 k)b" 
    and "f : c (DGjJ. 𝔄 j)d"
  shows "g  f : a  c DGiI. 𝔄 ib  d"
  by 
    (
      vdiff_of_vunion' 
        rule: pdg_dg_prod_vunion_is_arr assms: assms(2,3) subset: assms(1)
    )



subsection‹Projection›


subsubsection‹Definition and elementary properties›


text‹See Chapter II-3 in cite"mac_lane_categories_2010".›

definition dghm_proj :: "V  (V  V)  V  V" (πDG)
  where "πDG I 𝔄 i =
    [
      (λa((DGiI. 𝔄 i)Obj). ai),
      (λf((DGiI. 𝔄 i)Arr). fi),
      (DGiI. 𝔄 i),
      𝔄 i
    ]"


text‹Components.›

lemma dghm_proj_components:
  shows "πDG I 𝔄 iObjMap = (λa((DGiI. 𝔄 i)Obj). ai)"
    and "πDG I 𝔄 iArrMap = (λf((DGiI. 𝔄 i)Arr). fi)"
    and "πDG I 𝔄 iHomDom = (DGiI. 𝔄 i)"
    and "πDG I 𝔄 iHomCod = 𝔄 i"
  unfolding dghm_proj_def dghm_field_simps by (simp_all add: nat_omega_simps)


text‹Object map.›

mk_VLambda dghm_proj_components(1)
  |vsv dghm_proj_ObjMap_vsv[dg_cs_intros]|
  |vdomain dghm_proj_ObjMap_vdomain[dg_cs_simps]|
  |app dghm_proj_ObjMap_app[dg_cs_simps]|

lemma (in pdigraph) dghm_proj_ObjMap_vrange: 
  assumes "i  I"
  shows " (πDG I 𝔄 iObjMap)  𝔄 iObj"
  using assms 
  unfolding dghm_proj_components
  by (intro vrange_VLambda_vsubset) (clarsimp simp: dg_prod_components)


text‹Arrow map.›

mk_VLambda dghm_proj_components(2)
  |vsv dghm_proj_ArrMap_vsv[dg_cs_intros]|
  |vdomain dghm_proj_ArrMap_vdomain[dg_cs_simps]|
  |app dghm_proj_ArrMap_app[dg_cs_simps]|

lemma (in pdigraph) dghm_proj_ArrMap_vrange: 
  assumes "i  I"
  shows " (πDG I 𝔄 iArrMap)  𝔄 iArr"
  using assms 
  unfolding dghm_proj_components
  by (intro vrange_VLambda_vsubset) (clarsimp simp: dg_prod_components)


subsubsection‹A projection digraph homomorphism is a digraph homomorphism›

lemma (in pdigraph) pdg_dghm_proj_is_dghm: 
  assumes "i  I" 
  shows "πDG I 𝔄 i : (DGiI. 𝔄 i) ↦↦DGα𝔄 i"
proof(intro is_dghmI)
  show "vfsequence (πDG I 𝔄 i)" unfolding dghm_proj_def by auto
  show "vcard (πDG I 𝔄 i) = 4"
    unfolding dghm_proj_def by (simp add: nat_omega_simps)
  show "πDG I 𝔄 iHomDom = (DGiI. 𝔄 i)"
    unfolding dghm_proj_components by simp
  show "πDG I 𝔄 iHomCod = 𝔄 i" 
    unfolding dghm_proj_components by simp
  fix f a b assume "f : a DGiI. 𝔄 ib"
  with assms pdg_digraph_dg_prod show 
    "πDG I 𝔄 iArrMapf : πDG I 𝔄 iObjMapa 𝔄 iπDG I 𝔄 iObjMapb"
    by (cs_concl cs_simp: dg_cs_simps cs_intro: dg_cs_intros dg_prod_is_arrD(7))
qed 
  (
    auto simp: 
      dg_cs_simps dg_cs_intros dg_prod_cs_intros
      assms pdg_digraph_dg_prod dghm_proj_ObjMap_vrange
  )

lemma (in pdigraph) pdg_dghm_proj_is_dghm':
  assumes "i  I" and " = (DGiI. 𝔄 i)" and "𝔇 = 𝔄 i"
  shows "πDG I 𝔄 i :  ↦↦DGα𝔇"
  using assms(1) unfolding assms(2,3) by (rule pdg_dghm_proj_is_dghm)

lemmas [dg_cs_intros] = pdigraph.pdg_dghm_proj_is_dghm'



subsection‹Digraph product universal property digraph homomorphism›


subsubsection‹Definition and elementary properties›


text‹
The following digraph homomorphism is used in the 
proof of the universal property of the product digraph 
later in this work.
›

definition dghm_up :: "V  (V  V)  V  (V  V)  V"
  where "dghm_up I 𝔄  φ =
    [
      (λaObj. (λiI. φ iObjMapa)),
      (λfArr. (λiI. φ iArrMapf)),
      ,
      (DGiI. 𝔄 i)
    ]"


text‹Components.›

lemma dghm_up_components: 
  shows "dghm_up I 𝔄  φObjMap = (λaObj. (λiI. φ iObjMapa))"
    and "dghm_up I 𝔄  φArrMap = (λfArr. (λiI. φ iArrMapf))"
    and "dghm_up I 𝔄  φHomDom = "
    and "dghm_up I 𝔄  φHomCod = (DGiI. 𝔄 i)"
  unfolding dghm_up_def dghm_field_simps by (simp_all add: nat_omega_simps)


subsubsection‹Object map›

mk_VLambda dghm_up_components(1)
  |vsv dghm_up_ObjMap_vsv[dg_cs_intros]|
  |vdomain dghm_up_ObjMap_vdomain[dg_cs_simps]|
  |app dghm_up_ObjMap_app|

lemma dghm_up_ObjMap_vrange: 
  assumes "i. i  I  φ i :  ↦↦DGα𝔄 i"
  shows " (dghm_up I 𝔄  φObjMap)  (DGiI. 𝔄 i)Obj"
  unfolding dghm_up_components dg_prod_components
proof(intro vrange_VLambda_vsubset vproductI)
  fix a assume prems: "a  Obj"
  show "iI. (λiI. φ iObjMapa)i  𝔄 iObj"
  proof(intro ballI)
    fix i assume prems': "i  I"
    interpret φ: is_dghm α  𝔄 i φ i by (rule assms[OF prems'])
    from prems prems' show "(λiI. φ iObjMapa)i  𝔄 iObj" 
      by (simp add: φ.dghm_ObjMap_app_in_HomCod_Obj)
  qed
qed auto

lemma dghm_up_ObjMap_app_vdomain[dg_cs_simps]: 
  assumes "a  Obj"
  shows "𝒟 (dghm_up I 𝔄  φObjMapa) = I"
  unfolding dghm_up_ObjMap_app[OF assms] by simp

lemma dghm_up_ObjMap_app_component[dg_cs_simps]: 
  assumes "a  Obj" and "i  I"
  shows "dghm_up I 𝔄  φObjMapai = φ iObjMapa"
  using assms unfolding dghm_up_components by simp

lemma dghm_up_ObjMap_app_vrange: 
  assumes "a  Obj" and "i. i  I  φ i :  ↦↦DGα𝔄 i"
  shows " (dghm_up I 𝔄  φObjMapa)  (iI. 𝔄 iObj)"
proof(intro vsubsetI)
  fix b assume prems: "b   (dghm_up I 𝔄  φObjMapa)"
  have "vsv (dghm_up I 𝔄  φObjMapa)"
    unfolding dghm_up_ObjMap_app[OF assms(1)] by auto
  with prems obtain i where b_def: "b = dghm_up I 𝔄  φObjMapai" 
    and i: "i  I"
    by (auto elim: vsv.vrange_atE simp: dghm_up_ObjMap_app[OF assms(1)])
  interpret φi: is_dghm α  𝔄 i φ i by (rule assms(2)[OF i])
  from dghm_up_ObjMap_app_component[OF assms(1) i] b_def have b_def':
    "b = φ iObjMapa"
    by simp
  from assms(1) have "b  𝔄 iObj" 
    unfolding b_def' by (auto intro: dg_cs_intros)
  with i show "b  (iI. 𝔄 iObj)" by force
qed


subsubsection‹Arrow map›

mk_VLambda dghm_up_components(2)
  |vsv dghm_up_ArrMap_vsv[dg_cs_intros]|
  |vdomain dghm_up_ArrMap_vdomain[dg_cs_simps]|
  |app dghm_up_ArrMap_app|

lemma (in pdigraph) dghm_up_ArrMap_vrange: 
  assumes "i. i  I  φ i :  ↦↦DGα𝔄 i"
  shows " (dghm_up I 𝔄  φArrMap)  (DGiI. 𝔄 i)Arr"
  unfolding dghm_up_components dg_prod_components
proof(intro vrange_VLambda_vsubset vproductI)
  fix a assume prems: "a  Arr"
  show "iI. (λiI. φ iArrMapa)i  𝔄 iArr"
  proof(intro ballI)
    fix i assume prems': "i  I"
    interpret φ: is_dghm α  𝔄 i φ i by (rule assms[OF prems'])
    from prems prems' show "(λiI. φ iArrMapa)i  𝔄 iArr" 
      by (auto intro: dg_cs_intros)
  qed
qed auto

lemma dghm_up_ArrMap_vrange: 
  assumes "i. i  I  φ i :  ↦↦DGα𝔄 i"
  shows " (dghm_up I 𝔄  φArrMap)  (DGiI. 𝔄 i)Arr"
proof(intro vsubsetI)
  fix A assume "A   (dghm_up I 𝔄  φArrMap)"
  then obtain a where A_def: "A = dghm_up I 𝔄  φArrMapa" 
    and a: "a  Arr"
    unfolding dghm_up_ArrMap_vdomain dghm_up_components by auto
  have "(λiI. φ iArrMapa)  (iI. 𝔄 iArr)"
  proof(intro vproductI)
    show "iI. (λiI. φ iArrMapa)i  𝔄 iArr"
    proof(intro ballI)
      fix i assume prems: "i  I"
      interpret φ: is_dghm α  𝔄 i φ i by (rule assms[OF prems])
      from prems a show "(λiI. φ iArrMapa)i  𝔄 iArr" 
        by (auto intro: dg_cs_intros)
    qed
  qed simp_all
  with a show "A  (DGiI. 𝔄 i)Arr"
    unfolding A_def dg_prod_components dghm_up_components by simp
qed

lemma dghm_up_ArrMap_app_vdomain[dg_cs_simps]: 
  assumes "a  Arr"
  shows "𝒟 (dghm_up I 𝔄  φArrMapa) = I"
  unfolding dghm_up_ArrMap_app[OF assms] by simp

lemma dghm_up_ArrMap_app_component[dg_cs_simps]: 
  assumes "a  Arr" and "i  I"
  shows "dghm_up I 𝔄  φArrMapai = φ iArrMapa"
  using assms unfolding dghm_up_components by simp

lemma dghm_up_ArrMap_app_vrange: 
  assumes "a  Arr" and "i. i  I  φ i :  ↦↦DGα𝔄 i"
  shows " (dghm_up I 𝔄  φArrMapa)  (iI. 𝔄 iArr)"
proof(intro vsubsetI)
  fix b assume prems: "b   (dghm_up I 𝔄  φArrMapa)"
  have "vsv (dghm_up I 𝔄  φArrMapa)"
    unfolding dghm_up_ArrMap_app[OF assms(1)] by auto
  with prems obtain i where b_def: "b = dghm_up I 𝔄  φArrMapai" 
    and i: "i  I"
    by (auto elim: vsv.vrange_atE simp: dghm_up_ArrMap_app[OF assms(1)])
  interpret φi: is_dghm α  𝔄 i φ i by (rule assms(2)[OF i])
  from dghm_up_ArrMap_app_component[OF assms(1) i] b_def have b_def':
    "b = φ iArrMapa"
    by simp
  from assms(1) have "b  𝔄 iArr" 
    unfolding b_def' by (auto intro: dg_cs_intros)
  with i show "b  (iI. 𝔄 iArr)" by force
qed


subsubsection‹
Digraph product universal property 
digraph homomorphism is a digraph homomorphism
›

lemma (in pdigraph) pdg_dghm_up_is_dghm:
  assumes "digraph α " and "i. i  I  φ i :  ↦↦DGα𝔄 i"
  shows "dghm_up I 𝔄  φ :  ↦↦DGα(DGiI. 𝔄 i)"
proof-
  interpret: digraph α  by (rule assms(1))
  show ?thesis
  proof(intro is_dghmI, unfold dghm_up_components(3,4))
    show "vfsequence (dghm_up I 𝔄  φ)" unfolding dghm_up_def by simp
    show "vcard (dghm_up I 𝔄  φ) = 4"
      unfolding dghm_up_def by (simp add: nat_omega_simps)
    from assms(2) show " (dghm_up I 𝔄  φObjMap)  (DGiI. 𝔄 i)Obj"
      by (intro dghm_up_ObjMap_vrange) blast
    fix f a b assume prems: "f : a b"
    then have f: "f  Arr" and a: "a  Obj" and b: "b  Obj" by auto
    show "dghm_up I 𝔄  φArrMapf :
      dghm_up I 𝔄  φObjMapa DGiI. 𝔄 idghm_up I 𝔄  φObjMapb"
    proof(rule dg_prod_is_arrI)
      fix i assume prems': "i  I"
      interpret φ: is_dghm α  𝔄 i φ i by (rule assms(2)[OF prems'])
      from φ.is_dghm_axioms ℭ.digraph_axioms prems pdigraph_axioms prems prems' 
      show "dghm_up I 𝔄  φArrMapfi : 
        dghm_up I 𝔄  φObjMapai 𝔄 idghm_up I 𝔄  φObjMapbi"
        by (cs_concl cs_simp: dg_cs_simps cs_intro: dg_cs_intros)
    qed (simp_all add: f a b dghm_up_ArrMap_app dghm_up_ObjMap_app)
  qed (auto simp: dghm_up_components pdg_digraph_dg_prod dg_cs_intros)
qed


subsubsection‹Further properties›

lemma (in pdigraph) pdg_dghm_comp_dghm_proj_dghm_up: 
  assumes "digraph α "
    and "i. i  I  φ i :  ↦↦DGα𝔄 i" 
    and "i  I" 
  shows "φ i = πDG I 𝔄 i DGHM dghm_up I 𝔄  φ"
proof(rule dghm_eqI[of α  𝔄 i _  𝔄 i])
  
  interpret φ: is_dghm α  𝔄 i φ i by (rule assms(2)[OF assms(3)])
  
  show "φ i :  ↦↦DGα𝔄 i" by (auto intro: dg_cs_intros)

  from assms(1,2) have dghm_up: "dghm_up I 𝔄  φ :  ↦↦DGα(DGiI. 𝔄 i)"
    by (simp add: pdg_dghm_up_is_dghm)
  note dghm_proj = pdg_dghm_proj_is_dghm[OF assms(3)]

  from assms(3) pdg_dghm_proj_is_dghm show
    "πDG I 𝔄 i DGHM dghm_up I 𝔄  φ :  ↦↦DGα𝔄 i"
    by (intro dghm_comp_is_dghm[of α (DGiI. 𝔄 i)]) 
      (auto simp: assms dghm_up)
  
  show "φ iObjMap = (πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ObjMap"
  proof(rule vsv_eqI)
    show "vsv ((πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ObjMap)"
      unfolding dghm_comp_components dghm_proj_components dghm_up_components 
      by (rule vsv_vcomp) simp_all
    from 
      dghm_up_ObjMap_vrange[
        OF assms(2), simplified, unfolded dg_prod_components
        ]
    have rd: " (dghm_up I 𝔄  φObjMap)  𝒟 (πDG I 𝔄 iObjMap)"
      by (simp add: dg_prod_components dg_cs_simps)
    show "𝒟 (φ iObjMap) = 𝒟 ((πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ObjMap)"
      unfolding dghm_comp_components vdomain_vcomp_vsubset[OF rd] 
      by (simp add: dg_cs_simps)
    fix a assume "a  𝒟 (φ iObjMap)"
    then have a: "a  Obj" by (simp add: dg_cs_simps) 
    with dghm_up dghm_proj assms(3) show 
      "φ iObjMapa = (πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ObjMapa"
      by (cs_concl cs_shallow cs_simp: dg_cs_simps cs_intro: dg_cs_intros)
  qed auto

  show "φ iArrMap = (πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ArrMap"
  proof(rule vsv_eqI)
    show "vsv ((πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ArrMap)"
      unfolding dghm_comp_components dghm_proj_components dghm_up_components 
      by (rule vsv_vcomp) simp_all
    from 
      dghm_up_ArrMap_vrange[
        OF assms(2), simplified, unfolded dg_prod_components
        ]
    have rd: " (dghm_up I 𝔄  φArrMap)  𝒟 (πDG I 𝔄 iArrMap)"
      by (simp add: dg_prod_components dg_cs_simps)
    show "𝒟 (φ iArrMap) = 𝒟 ((πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ArrMap)"
      unfolding dghm_comp_components vdomain_vcomp_vsubset[OF rd] 
      by (simp add: dg_cs_simps)
    fix a assume "a  𝒟 (φ iArrMap)"
    then have a: "a  Arr" by (simp add: dg_cs_simps)
    with dghm_up dghm_proj assms(3) show 
      "φ iArrMapa = (πDG I 𝔄 i DGHM dghm_up I 𝔄  φ)ArrMapa"
      by (cs_concl cs_shallow cs_simp: dg_cs_simps cs_intro: dg_cs_intros)
  qed auto

qed simp_all
      
lemma (in pdigraph) pdg_dghm_up_eq_dghm_proj:
  assumes "𝔉 :  ↦↦DGα(DGiI. 𝔄 i)"
    and "i. i  I  φ i = πDG I 𝔄 i DGHM 𝔉"
  shows "dghm_up I 𝔄  φ = 𝔉"
proof(rule dghm_eqI)

  interpret 𝔉: is_dghm α  (DGiI. 𝔄 i) 𝔉 by (rule assms(1))

  show "dghm_up I 𝔄  φ :  ↦↦DGα(DGiI. 𝔄 i)"
  proof(rule pdg_dghm_up_is_dghm)
    fix i assume prems: "i  I"
    interpret π: is_dghm α (DGiI. 𝔄 i) 𝔄 i πDG I 𝔄 i
      using prems by (rule pdg_dghm_proj_is_dghm)
    show "φ i :  ↦↦DGα𝔄 i" 
      unfolding assms(2)[OF prems] by (auto intro: dg_cs_intros)
  qed (auto intro: dg_cs_intros)

  show "dghm_up I 𝔄  φObjMap = 𝔉ObjMap"
  proof(rule vsv_eqI, unfold dghm_up_ObjMap_vdomain)
    fix a assume prems: "a  Obj"
    show "dghm_up I 𝔄  φObjMapa = 𝔉ObjMapa"
    proof(rule vsv_eqI, unfold dghm_up_ObjMap_app_vdomain[OF prems])
      fix i assume prems': "i  I"
      with pdg_dghm_proj_is_dghm[OF prems'] 𝔉.is_dghm_axioms prems show 
        "dghm_up I 𝔄  φObjMapai = 𝔉ObjMapai"
        by 
          (
            cs_concl cs_shallow 
              cs_simp: dg_cs_simps assms(2) cs_intro: dg_cs_intros
          )
    qed 
      (
        use 𝔉.dghm_ObjMap_app_in_HomCod_Obj prems in 
          auto simp: dg_prod_components dghm_up_ObjMap_app
      )
  qed (auto simp: dghm_up_components dg_cs_simps)

  show "dghm_up I 𝔄  φArrMap = 𝔉ArrMap"
  proof(rule vsv_eqI, unfold dghm_up_ArrMap_vdomain)
    fix a assume prems: "a  Arr"
    show "dghm_up I 𝔄  φArrMapa = 𝔉ArrMapa"
    proof(rule vsv_eqI, unfold dghm_up_ArrMap_app_vdomain[OF prems])
      fix i assume prems': "i  I"
      with pdg_dghm_proj_is_dghm[OF prems'] 𝔉.is_dghm_axioms prems show 
        "dghm_up I 𝔄  φArrMapai = 𝔉ArrMapai"
        by 
          (
            cs_concl cs_shallow 
              cs_simp: dg_cs_simps assms(2) cs_intro: dg_cs_intros
          )
    qed 
      (
        use 𝔉.dghm_ArrMap_app_in_HomCod_Arr prems in 
          auto simp: dg_prod_components dghm_up_ArrMap_app
      )+
  qed (auto simp: dghm_up_components dg_cs_simps)

qed (simp_all add: assms(1))



subsection‹Singleton digraph›


subsubsection‹Object›

lemma dg_singleton_ObjI: 
  assumes "A = set {j, a}" and "a  Obj"
  shows "A  (DGiset {j}. )Obj"
  using assms unfolding dg_prod_components by auto

lemma dg_singleton_ObjE: 
  assumes "A  (DGiset {j}. )Obj"
  obtains a where "A = set {j, a}" and "a  Obj"
proof-
  from vproductD[OF assms[unfolded dg_prod_components], rule_format] 
  have "vsv A" and [simp]: "𝒟 A = set {j}" and Aj: "Aj  Obj"
    by simp_all
  then interpret A: vsv A by simp
  from A.vsv_is_VLambda have "A = set {j, Aj}" 
    by (auto simp: VLambda_vsingleton)
  with Aj show ?thesis using that by simp
qed


subsubsection‹Arrow›

lemma dg_singleton_ArrI: 
  assumes "F = set {j, a}" and "a  Arr"
  shows "F  (DGjset {j}. )Arr"
  using assms unfolding dg_prod_components by auto

lemma dg_singleton_ArrE: 
  assumes "F  (DGjset {j}. )Arr"
  obtains a where "F = set {j, a}" and "a  Arr"
proof-
  from vproductD[OF assms[unfolded dg_prod_components], rule_format] 
  have "vsv F" and [simp]: "𝒟 F = set {j}" and Fj: "Fj  Arr"
    by simp_all
  then interpret F: vsv F by simp
  from F.vsv_is_VLambda have "F = set {j, Fj}" 
    by (auto simp: VLambda_vsingleton)
  with Fj show ?thesis using that by simp
qed


subsubsection‹Singleton digraph is a digraph›

lemma (in digraph) dg_finite_pdigraph_dg_singleton: 
  assumes "j  Vset α"
  shows "finite_pdigraph α (set {j}) (λi. )"
  by (intro finite_pdigraphI pdigraph_baseI)
    (auto simp: digraph_axioms Limit_vsingleton_in_VsetI assms)

lemma (in digraph) dg_digraph_dg_singleton:
  assumes "j  Vset α"
  shows "digraph α (DGjset {j}. )"
proof-
  interpret finite_pdigraph α set {j} λi. 
    using assms by (rule dg_finite_pdigraph_dg_singleton)
  show ?thesis by (rule pdg_digraph_dg_prod)
qed


subsubsection‹Arrow with a domain and a codomain›

lemma (in digraph) dg_singleton_is_arrI:
  assumes "j  Vset α" and "f : a b"
  shows "set {j, f} : set {j, a} (DGjset {j}. )set {j, b}"
proof-
  interpret finite_pdigraph α set {j} λi. 
    by (rule dg_finite_pdigraph_dg_singleton[OF assms(1)])
  from assms(2) show ?thesis by (intro dg_prod_is_arrI) auto
qed

lemma (in digraph) dg_singleton_is_arrD:
  assumes "set {j, f} : set {j, a} (DGjset {j}. )set {j, b}" 
    and "j  Vset α"
  shows "f : a b"
proof-
  interpret finite_pdigraph α set {j} λi. 
    by (rule dg_finite_pdigraph_dg_singleton[OF assms(2)])
  from dg_prod_is_arrD(7)[OF assms(1)] show ?thesis by simp
qed

lemma (in digraph) dg_singleton_is_arrE:
  assumes "set {j, f} : set {j, a} (DGjset {j}. )set {j, b}" 
    and "j  Vset α"
  obtains "f : a b"
  using assms dg_singleton_is_arrD by auto



subsection‹Singleton digraph homomorphism›

definition dghm_singleton :: "V  V  V"
  where "dghm_singleton j  = 
    [
      (λaObj. set {j, a}), 
      (λfArr. set {j, f}), 
      ,
      (DGjset {j}. )
    ]"


text‹Components.›

lemma dghm_singleton_components:
  shows "dghm_singleton j ObjMap = (λaObj. set {j, a})"
    and "dghm_singleton j ArrMap = (λfArr. set {j, f})"
    and "dghm_singleton j HomDom = "
    and "dghm_singleton j HomCod = (DGjset {j}. )"
  unfolding dghm_singleton_def dghm_field_simps 
  by (simp_all add: nat_omega_simps)


subsubsection‹Object map›

mk_VLambda dghm_singleton_components(1)
  |vsv dghm_singleton_ObjMap_vsv[dg_cs_intros]|
  |vdomain dghm_singleton_ObjMap_vdomain[dg_cs_simps]|
  |app dghm_singleton_ObjMap_app[dg_prod_cs_simps]|

lemma dghm_singleton_ObjMap_vrange[dg_cs_simps]: 
  " (dghm_singleton j ObjMap) = (DGjset {j}. )Obj"
proof(intro vsubset_antisym vsubsetI)
  fix A assume "A   (dghm_singleton j ObjMap)"
  then obtain a where A_def: "A = set {j, a}" and a: "a  Obj" 
    unfolding dghm_singleton_components by auto
  then show "A  (DGjset {j}. )Obj"
    unfolding dg_prod_components by auto
next
  fix A assume "A  (DGjset {j}. )Obj" 
  from vproductD[OF this[unfolded dg_prod_components], rule_format] 
  have "vsv A"
    and [simp]: "𝒟 A = set {j}" 
    and Ai: "i. i  set {j}  Ai  Obj"
    by auto
  then interpret A: vsv A by simp
  from Ai have "Aj  Obj" using Ai by auto
  moreover with A.vsv_is_VLambda have "A = (λfObj. set {j, f})Aj"
    by (simp add: VLambda_vsingleton)
  ultimately show "A   (dghm_singleton j ObjMap)"
    unfolding dghm_singleton_components
    by 
      (
        metis 
          dghm_singleton_ObjMap_vdomain 
          dghm_singleton_ObjMap_vsv 
          dghm_singleton_components(1) 
          vsv.vsv_vimageI2
      )
qed


subsubsection‹Arrow map›

mk_VLambda dghm_singleton_components(2)
  |vsv dghm_singleton_ArrMap_vsv[dg_cs_intros]|
  |vdomain dghm_singleton_ArrMap_vdomain[dg_cs_simps]|
  |app dghm_singleton_ArrMap_app[dg_prod_cs_simps]|

lemma dghm_singleton_ArrMap_vrange[dg_cs_simps]: 
  " (dghm_singleton j ArrMap) = (DGjset {j}. )Arr"
proof(intro vsubset_antisym vsubsetI)
  fix F assume "F   (dghm_singleton j ArrMap)"
  then obtain f where "F = set {j, f}" and "f  Arr" 
    unfolding dghm_singleton_components by auto
  then show "F  (DGjset {j}. )Arr"
    unfolding dg_prod_components by auto
next
  fix F assume "F  (DGjset {j}. )Arr" 
  from vproductD[OF this[unfolded dg_prod_components], rule_format] 
  have "vsv F"
    and [simp]: "𝒟 F = set {j}" 
    and Fi: "i. i  set {j}  Fi  Arr"
    by auto
  then interpret F: vsv F by simp
  from Fi have "Fj  Arr" using Fi by auto
  moreover with F.vsv_is_VLambda have "F = (λfArr. set {j, f})Fj"
    by (simp add: VLambda_vsingleton)
  ultimately show "F   (dghm_singleton j ArrMap)"
    unfolding dghm_singleton_components
    by 
      (
        metis 
          dghm_singleton_ArrMap_vdomain 
          dghm_singleton_ArrMap_vsv 
          dghm_singleton_components(2) 
          vsv.vsv_vimageI2
      )
qed


subsubsection‹Singleton digraph homomorphism is an isomorphism of digraphs›

lemma (in digraph) dg_dghm_singleton_is_dghm:
  assumes "j  Vset α"
  shows "dghm_singleton j  :  ↦↦DG.isoα(DGjset {j}. )"
proof-
  interpret finite_pdigraph α set {j} λi. 
    by (rule dg_finite_pdigraph_dg_singleton[OF assms])
  show ?thesis
  proof(intro is_iso_dghmI is_dghmI)
    show "vfsequence (dghm_singleton j )" unfolding dghm_singleton_def by simp
    show "vcard (dghm_singleton j ) = 4"
      unfolding dghm_singleton_def by (simp add: nat_omega_simps)
    show " (dghm_singleton j ObjMap)  (DGjset {j}. )Obj"
      by (simp add: dg_cs_simps)
    show "dghm_singleton j ArrMapf :
      dghm_singleton j ObjMapa DGjset {j}. dghm_singleton j ObjMapb"
      if "f : a b" for f a b
      using that
    proof(intro dg_prod_is_arrI)
      fix k assume "k  set {j}"
      then have k_def: "k = j" by simp
      from that show "dghm_singleton j ArrMapfk :
        dghm_singleton j ObjMapak dghm_singleton j ObjMapbk"
        by 
          (
            cs_concl 
              cs_simp: k_def V_cs_simps dg_cs_simps dg_prod_cs_simps
              cs_intro: dg_cs_intros
          )
    qed 
      (
        cs_concl  
          cs_simp: V_cs_simps dg_prod_cs_simps 
          cs_intro: V_cs_intros dg_cs_intros
      )+
    show " (dghm_singleton j ObjMap) = (DGjset {j}. )Obj" 
      by (simp add: dg_cs_simps)
    show " (dghm_singleton j ArrMap) = (DGjset {j}. )Arr" 
      by (simp add: dg_cs_simps)
  qed 
    (
      auto simp: 
        dg_cs_intros 
        dg_digraph_dg_singleton[OF assms] 
        dghm_singleton_components
    )
qed



subsection‹Product of two digraphs›


subsubsection‹Definition and elementary properties›


text‹See Chapter II-3 in cite"mac_lane_categories_2010".›

definition dg_prod_2 :: "V  V  V" (infixr ×DG 80)
  where "𝔄 ×DG 𝔅