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 𝔅  dg_prod (2) (if2 𝔄 𝔅)"


subsubsection‹Product of two digraphs is a digraph›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

interpretation 𝒵 α by (rule digraphD[OF 𝔄(1)])
interpretation 𝔄: digraph α 𝔄 by (rule 𝔄)
interpretation 𝔅: digraph α 𝔅 by (rule 𝔅)

lemma finite_pdigraph_dg_prod_2: "finite_pdigraph α (2) (if2 𝔄 𝔅)"
proof(intro finite_pdigraphI pdigraph_baseI)
  from Axiom_of_Infinity show z1_in_Vset: "2  Vset α" by blast
  show "digraph α (i = 0 ? 𝔄 : 𝔅)" if "i  2" for i
    by (auto intro: dg_cs_intros)
qed auto

interpretation finite_pdigraph α 2 if2 𝔄 𝔅
  by (intro finite_pdigraph_dg_prod_2 𝔄 𝔅)

lemma digraph_dg_prod_2[dg_cs_intros]: "digraph α (𝔄 ×DG 𝔅)"
proof-
  show ?thesis unfolding dg_prod_2_def by (rule pdg_digraph_dg_prod)
qed

end


subsubsection‹Object›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

lemma dg_prod_2_ObjI:
  assumes "a  𝔄Obj" and "b  𝔅Obj"
  shows "[a, b]  (𝔄 ×DG 𝔅)Obj"
  unfolding dg_prod_2_def dg_prod_components
proof(intro vproductI ballI)
  show "𝒟 [a, b] = 2" by (simp add: nat_omega_simps two)
  fix i assume "i  2"
  then consider i = 0 | i = 1 unfolding two by auto 
  then show "[a, b]i  (if i = 0 then 𝔄 else 𝔅)Obj"
    by cases (simp_all add: nat_omega_simps assms(1,2))
qed auto

lemma dg_prod_2_ObjI'[dg_prod_cs_intros]:
  assumes "ab = [a, b]" and "a  𝔄Obj" and "b  𝔅Obj"
  shows "ab  (𝔄 ×DG 𝔅)Obj"
  using assms(2,3) unfolding assms(1) by (rule dg_prod_2_ObjI)

lemma dg_prod_2_ObjE:
  assumes "ab  (𝔄 ×DG 𝔅)Obj"
  obtains a b where "ab = [a, b]" and "a  𝔄Obj" and "b  𝔅Obj"
proof-
  from vproductD[OF assms[unfolded dg_prod_2_def dg_prod_components]]
  have vsv_ab: "vsv ab"
    and dom_ab: "𝒟 ab = 2"
    and ab_app: "i. i  2  abi  (if i = 0 then 𝔄 else 𝔅)Obj"
    by auto
  have dom_ab[simp]: "𝒟 ab = 2"
    unfolding dom_ab by (simp add: nat_omega_simps two)
  interpret vsv ab by (rule vsv_ab)
  have "ab = [vpfst ab, vpsnd ab]"
    by (rule vsv_vfsequence_two[symmetric]) auto
  moreover from ab_app[of 0] have "vpfst ab  𝔄Obj" by simp
  moreover from ab_app[of 1] have "vpsnd ab  𝔅Obj" by simp
  ultimately show ?thesis using that by auto
qed

end


subsubsection‹Arrow›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

lemma dg_prod_2_ArrI:
  assumes "g  𝔄Arr" and "f  𝔅Arr"
  shows "[g, f]  (𝔄 ×DG 𝔅)Arr"
  unfolding dg_prod_2_def dg_prod_components
proof(intro vproductI ballI)
  show "𝒟 [g, f] = 2" by (simp add: nat_omega_simps two)
  fix i assume "i  2"
  then consider i = 0 | i = 1 unfolding two by auto 
  then show "[g, f]i  (if i = 0 then 𝔄 else 𝔅)Arr"
    by cases (simp_all add: nat_omega_simps assms(1,2))
qed auto

lemma dg_prod_2_ArrI'[dg_prod_cs_intros]:
  assumes "gf = [g, f]" and "g  𝔄Arr" and "f  𝔅Arr"
  shows "[g, f]  (𝔄 ×DG 𝔅)Arr"
  using assms(2,3) unfolding assms(1) by (rule dg_prod_2_ArrI)

lemma dg_prod_2_ArrE:
  assumes "gf  (𝔄 ×DG 𝔅)Arr"
  obtains g f where "gf = [g, f]" and "g  𝔄Arr" and "f  𝔅Arr"
proof-
  from vproductD[OF assms[unfolded dg_prod_2_def dg_prod_components]]
  have vsv_gf: "vsv gf"
    and dom_gf: "𝒟 gf = 2"
    and gf_app: "i. i  2  gfi  (if i = 0 then 𝔄 else 𝔅)Arr"
    by auto
  have dom_gf[simp]: "𝒟 gf = 2" unfolding dom_gf by (simp add: two)
  interpret vsv gf by (rule vsv_gf)
  have "gf = [vpfst gf, vpsnd gf]"
    by (rule vsv_vfsequence_two[symmetric]) auto
  moreover from gf_app[of 0] have "vpfst gf  𝔄Arr" by simp
  moreover from gf_app[of 1] have "vpsnd gf  𝔅Arr" by simp
  ultimately show ?thesis using that by auto
qed

end


subsubsection‹Arrow with a domain and a codomain›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

interpretation 𝒵 α by (rule digraphD[OF 𝔄(1)])
interpretation 𝔄: digraph α 𝔄 by (rule 𝔄)
interpretation 𝔅: digraph α 𝔅 by (rule 𝔅)
interpretation finite_pdigraph α 2 if2 𝔄 𝔅
  by (intro finite_pdigraph_dg_prod_2 𝔄 𝔅)

lemma dg_prod_2_is_arrI:
  assumes "g : a 𝔄c" and "f : b 𝔅d"
  shows "[g, f] : [a, b] 𝔄 ×DG 𝔅[c, d]"
  unfolding dg_prod_2_def
proof(rule dg_prod_is_arrI)
  show "[g, f]i : [a, b]i if i = 0 then 𝔄 else 𝔅[c, d]i"
    if "i  2" for i
  proof-
    from that consider i = 0 | i = 1 unfolding two by auto 
    then show "[g, f]i : [a, b]i if i = 0 then 𝔄 else 𝔅[c, d]i"
      by cases (simp_all add: nat_omega_simps assms)
  qed
qed (auto simp: nat_omega_simps two)

lemma dg_prod_2_is_arrI'[dg_prod_cs_intros]:
  assumes "gf = [g, f]"
    and "ab = [a, b]"
    and "cd = [c, d]"
    and "g : a 𝔄c" 
    and "f : b 𝔅d"
  shows "gf : ab 𝔄 ×DG 𝔅cd"
  using assms(4,5) unfolding assms(1,2,3) by (rule dg_prod_2_is_arrI)

lemma dg_prod_2_is_arrE:
  assumes "gf : ab 𝔄 ×DG 𝔅cd"
  obtains g f a b c d 
    where "gf = [g, f]"
      and "ab = [a, b]"
      and "cd = [c, d]"
      and "g : a 𝔄c"
      and "f : b 𝔅d"
proof-
  from dg_prod_is_arrD[OF assms[unfolded dg_prod_2_def]] 
  have [simp]: "vsv gf" "𝒟 gf = 2" "vsv ab" "𝒟 ab = 2" "vsv cd" "𝒟 cd = 2"
    and gf_app: 
      "i. i  2  gfi : abi if i = 0 then 𝔄 else 𝔅cdi"
    by (auto simp: two)
  have "gf = [vpfst gf, vpsnd gf]" by (simp add: vsv_vfsequence_two)
  moreover have "ab = [vpfst ab, vpsnd ab]" by (simp add: vsv_vfsequence_two)
  moreover have "cd = [vpfst cd, vpsnd cd]" by (simp add: vsv_vfsequence_two)
  moreover from gf_app[of 0] have "vpfst gf : vpfst ab 𝔄vpfst cd" by simp
  moreover from gf_app[of 1] have "vpsnd gf : vpsnd ab 𝔅vpsnd cd" 
    by (simp add: nat_omega_simps)
  ultimately show ?thesis using that by auto
qed

end


subsubsection‹Domain›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

lemma dg_prod_2_Dom_vsv: "vsv ((𝔄 ×DG 𝔅)Dom)"
  unfolding dg_prod_2_def dg_prod_components by simp

lemma dg_prod_2_Dom_vdomain[dg_cs_simps]: 
  "𝒟 ((𝔄 ×DG 𝔅)Dom) = (𝔄 ×DG 𝔅)Arr"
  unfolding dg_prod_2_def dg_prod_components by simp

lemma dg_prod_2_Dom_app[dg_prod_cs_simps]:
  assumes "[g, f]  (𝔄 ×DG 𝔅)Arr"
  shows "(𝔄 ×DG 𝔅)Domg, f = [𝔄Domg, 𝔅Domf]"
proof-
  from assms obtain ab cd where gf: "[g, f] : ab 𝔄 ×DG 𝔅cd" 
    by (auto intro: is_arrI)
  then have Dom_gf: "(𝔄 ×DG 𝔅)Domg, f = ab" 
    by (simp add: dg_cs_simps)
  from gf obtain a b c d 
    where ab_def: "ab = [a, b]" 
      and "cd = [c, d]" 
      and "g : a 𝔄c"
      and "f : b 𝔅d"
    by (elim dg_prod_2_is_arrE[OF 𝔄 𝔅]) simp
  then have Dom_g: "𝔄Domg = a" and Dom_f: "𝔅Domf = b" 
    by (simp_all add: dg_cs_simps)
  show ?thesis unfolding Dom_gf ab_def Dom_g Dom_f ..
qed

lemma dg_prod_2_Dom_vrange: " ((𝔄 ×DG 𝔅)Dom)  (𝔄 ×DG 𝔅)Obj"
proof(rule vsv.vsv_vrange_vsubset, unfold dg_cs_simps)
  show "vsv ((𝔄 ×DG 𝔅)Dom)" by (rule dg_prod_2_Dom_vsv)
  fix gf assume prems: "gf  (𝔄 ×DG 𝔅)Arr"
  then obtain g f where gf_def: "gf = [g, f]" 
    and g: "g  𝔄Arr" 
    and f: "f  𝔅Arr"
    by (elim dg_prod_2_ArrE[OF 𝔄 𝔅]) simp
  from g f obtain a b c d where g: "g : a 𝔄c" and f: "f : b 𝔅d"
    by (auto intro!: is_arrI)
  from 𝔄 𝔅 g f show "(𝔄 ×DG 𝔅)Domgf  (𝔄 ×DG 𝔅)Obj"
    unfolding gf_def dg_prod_2_Dom_app[OF prems[unfolded gf_def]]
    by (cs_concl cs_simp: dg_cs_simps cs_intro: dg_cs_intros dg_prod_cs_intros)
qed

end


subsubsection‹Codomain›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

lemma dg_prod_2_Cod_vsv: "vsv ((𝔄 ×DG 𝔅)Cod)"
  unfolding dg_prod_2_def dg_prod_components by simp

lemma dg_prod_2_Cod_vdomain[dg_cs_simps]: 
  "𝒟 ((𝔄 ×DG 𝔅)Cod) = (𝔄 ×DG 𝔅)Arr"
  unfolding dg_prod_2_def dg_prod_components by simp

lemma dg_prod_2_Cod_app[dg_prod_cs_simps]:
  assumes "[g, f]  (𝔄 ×DG 𝔅)Arr"
  shows "(𝔄 ×DG 𝔅)Codg, f = [𝔄Codg, 𝔅Codf]"
proof-
  from assms obtain ab cd where gf: "[g, f] : ab 𝔄 ×DG 𝔅cd" 
    by (auto intro: is_arrI)
  then have Cod_gf: "(𝔄 ×DG 𝔅)Codg, f = cd"
    by (simp add: dg_cs_simps)
  from gf obtain a b c d 
    where "ab = [a, b]" 
      and cd_def: "cd = [c, d]" 
      and "g : a 𝔄c"
      and "f : b 𝔅d"
    by (elim dg_prod_2_is_arrE[OF 𝔄 𝔅]) simp
  then have Cod_g: "𝔄Codg = c" and Cod_f: "𝔅Codf = d"
    by (simp_all add: dg_cs_simps)
  show ?thesis unfolding Cod_gf cd_def Cod_g Cod_f ..
qed

lemma dg_prod_2_Cod_vrange: " ((𝔄 ×DG 𝔅)Cod)  (𝔄 ×DG 𝔅)Obj"
proof(rule vsv.vsv_vrange_vsubset, unfold dg_cs_simps)
  show "vsv ((𝔄 ×DG 𝔅)Cod)" by (rule dg_prod_2_Cod_vsv)
  fix gf assume prems: "gf  (𝔄 ×DG 𝔅)Arr"
  then obtain g f where gf_def: "gf = [g, f]" 
    and g: "g  𝔄Arr" 
    and f: "f  𝔅Arr"
    by (elim dg_prod_2_ArrE[OF 𝔄 𝔅]) simp
  from g f obtain a b c d where g: "g : a 𝔄c" and f: "f : b 𝔅d"
    by (auto intro!: is_arrI)
  from 𝔄 𝔅 g f show "(𝔄 ×DG 𝔅)Codgf  (𝔄 ×DG 𝔅)Obj"
    unfolding gf_def dg_prod_2_Cod_app[OF prems[unfolded gf_def]]
    by 
      (
        cs_concl cs_shallow 
          cs_simp: dg_cs_simps cs_intro: dg_cs_intros dg_prod_cs_intros
      )
qed

end


subsubsection‹Opposite product digraph›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

interpretation 𝔄: digraph α 𝔄 by (rule 𝔄)
interpretation 𝔅: digraph α 𝔅 by (rule 𝔅)

lemma dg_prod_2_op_dg_dg_Obj[dg_op_simps]: 
  "(op_dg 𝔄 ×DG 𝔅)Obj = (𝔄 ×DG 𝔅)Obj"
proof
  (
    intro vsubset_antisym vsubsetI; 
    elim dg_prod_2_ObjE[OF 𝔄.digraph_op 𝔅] dg_prod_2_ObjE[OF 𝔄 𝔅],
    (unfold dg_op_simps)?
  )
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Obj" "b  𝔅Obj"
  from 𝔄 𝔅 prems(2,3) show "ab  (𝔄 ×DG 𝔅)Obj"
    unfolding prems(1) dg_op_simps
    by (cs_concl cs_shallow cs_simp: dg_cs_simps cs_intro: dg_prod_cs_intros)
next
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Obj" "b  𝔅Obj"
  from 𝔄 𝔅 prems(2,3) show "ab  (op_dg 𝔄 ×DG 𝔅)Obj"
    unfolding prems(1) dg_op_simps
    by 
      (
        cs_concl cs_shallow 
          cs_simp: dg_cs_simps cs_intro: dg_op_intros dg_prod_cs_intros
      )
qed

lemma dg_prod_2_dg_op_dg_Obj[dg_op_simps]: 
  "(𝔄 ×DG op_dg 𝔅)Obj = (𝔄 ×DG 𝔅)Obj"
proof
  (
    intro vsubset_antisym vsubsetI; 
    elim dg_prod_2_ObjE[OF 𝔄 𝔅.digraph_op] dg_prod_2_ObjE[OF 𝔄 𝔅],
    (unfold dg_op_simps)?
  )
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Obj" "b  𝔅Obj"
  from 𝔄 𝔅 prems(2,3) show "ab  (𝔄 ×DG 𝔅)Obj"
    unfolding prems(1) dg_op_simps
    by (cs_concl cs_shallow cs_simp: dg_cs_simps cs_intro: dg_prod_cs_intros)
next
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Obj" "b  𝔅Obj"
  from 𝔄 𝔅 prems(2,3) show "ab  (𝔄 ×DG op_dg 𝔅)Obj"
    unfolding prems(1) dg_op_simps
    by 
      (
        cs_concl cs_shallow 
          cs_simp: dg_cs_simps cs_intro: dg_prod_cs_intros dg_op_intros
      ) 
qed

lemma dg_prod_2_op_dg_dg_Arr[dg_op_simps]: 
  "(op_dg 𝔄 ×DG 𝔅)Arr = (𝔄 ×DG 𝔅)Arr"
proof
  (
    intro vsubset_antisym vsubsetI; 
    elim dg_prod_2_ArrE[OF 𝔄.digraph_op 𝔅] dg_prod_2_ArrE[OF 𝔄 𝔅],
    (unfold dg_op_simps)?
  )
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Arr" "b  𝔅Arr"
  from 𝔄 𝔅 prems(2,3) show "ab  (𝔄 ×DG 𝔅)Arr"
    unfolding prems(1) dg_op_simps
    by (cs_concl cs_shallow cs_simp: dg_cs_simps cs_intro: dg_prod_cs_intros)
next
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Arr" "b  𝔅Arr"
  from 𝔄 𝔅 prems(2,3) show "ab  (op_dg 𝔄 ×DG 𝔅)Arr"
    unfolding prems(1) dg_op_simps
    by 
      (
        cs_concl cs_shallow 
          cs_simp: dg_cs_simps cs_intro: dg_prod_cs_intros dg_op_intros
      ) 
qed

lemma dg_prod_2_dg_op_dg_Arr[dg_op_simps]: 
  "(𝔄 ×DG op_dg 𝔅)Arr = (𝔄 ×DG 𝔅)Arr"
proof
  (
    intro vsubset_antisym vsubsetI; 
    elim dg_prod_2_ArrE[OF 𝔄 𝔅.digraph_op] dg_prod_2_ArrE[OF 𝔄 𝔅],
    (unfold dg_op_simps)?
  )
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Arr" "b  𝔅Arr"
  from 𝔄 𝔅 prems(2,3) show "ab  (𝔄 ×DG 𝔅)Arr"
    unfolding prems(1) dg_op_simps
    by (cs_concl cs_shallow cs_simp: dg_cs_simps cs_intro: dg_prod_cs_intros)
next
  fix ab a b assume prems: "ab = [a, b]" "a  𝔄Arr" "b  𝔅Arr"
  from 𝔄 𝔅 prems(2,3) show "ab  (𝔄 ×DG op_dg 𝔅)Arr"
    unfolding prems(1) dg_op_simps
    by 
      (
        cs_concl cs_shallow 
          cs_simp: dg_cs_simps cs_intro: dg_prod_cs_intros dg_op_intros
      ) 
qed

end

context
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

lemma op_dg_dg_prod_2[dg_op_simps]: "op_dg (𝔄 ×DG 𝔅) = op_dg 𝔄 ×DG op_dg 𝔅"
proof(rule vsv_eqI)

  show "vsv (op_dg (𝔄 ×DG 𝔅))" unfolding op_dg_def by auto
  show "vsv (op_dg 𝔄 ×DG op_dg 𝔅)" unfolding dg_prod_2_def dg_prod_def by auto
  have dom_lhs: "𝒟 (op_dg (𝔄 ×DG 𝔅)) = 4" 
    by (simp add: op_dg_def nat_omega_simps)
  show "𝒟 (op_dg (𝔄 ×DG 𝔅)) = 𝒟 (op_dg 𝔄 ×DG op_dg 𝔅)"
    unfolding dom_lhs by (simp add: dg_prod_2_def dg_prod_def nat_omega_simps)

  have Cod_Dom: "(𝔄 ×DG 𝔅)Cod = (op_dg 𝔄 ×DG op_dg 𝔅)Dom"
  proof(rule vsv_eqI)
    from 𝔄 𝔅 show "vsv ((𝔄 ×DG 𝔅)Cod)" by (rule dg_prod_2_Cod_vsv)
    from 𝔄 𝔅 show "vsv ((op_dg 𝔄 ×DG op_dg 𝔅)Dom)"
      by (cs_concl cs_shallow cs_intro: dg_prod_2_Dom_vsv dg_op_intros)+
    from 𝔄 𝔅 have dom_lhs: "𝒟 ((𝔄 ×DG 𝔅)Cod) = (𝔄 ×DG 𝔅)Arr"
      by (cs_concl cs_shallow cs_simp: dg_cs_simps)
    from 𝔄 𝔅 show "𝒟 ((𝔄 ×DG 𝔅)Cod) = 𝒟 ((op_dg 𝔄 ×DG op_dg 𝔅)Dom)"
      unfolding dom_lhs
      by 
        (
          cs_concl cs_shallow 
            cs_simp: dg_cs_simps dg_op_simps cs_intro: dg_op_intros
        )
    show "(𝔄 ×DG 𝔅)Codgf = (op_dg 𝔄 ×DG op_dg 𝔅)Domgf"
      if "gf  𝒟 ((𝔄 ×DG 𝔅)Cod)" for gf
      using that unfolding dom_lhs
    proof-
      assume "gf  (𝔄 ×DG 𝔅)Arr"
      then obtain g f 
        where gf_def: "gf = [g, f]" 
          and g: "g  𝔄Arr" 
          and f: "f  𝔅Arr"
        by (rule dg_prod_2_ArrE[OF 𝔄 𝔅]) simp
      from 𝔄 𝔅 g f show "(𝔄 ×DG 𝔅)Codgf = (op_dg 𝔄 ×DG op_dg 𝔅)Domgf"
        unfolding gf_def
        by 
          (
            cs_concl cs_shallow
              cs_simp: dg_prod_cs_simps dg_op_simps 
              cs_intro: dg_prod_cs_intros dg_op_intros
          )
    qed
  qed

  have Dom_Cod: "(𝔄 ×DG 𝔅)Dom = (op_dg 𝔄 ×DG op_dg 𝔅)Cod"
  proof(rule vsv_eqI)
    from 𝔄 𝔅 show "vsv ((op_dg 𝔄 ×DG op_dg 𝔅)Cod)"
      by (cs_concl cs_shallow cs_intro: dg_prod_2_Cod_vsv dg_op_intros)+
    from 𝔄 𝔅 have dom_lhs: "𝒟 ((𝔄 ×DG 𝔅)Dom) = (𝔄 ×DG 𝔅)Arr"
      by (cs_concl cs_shallow cs_simp: dg_cs_simps)
    from 𝔄 𝔅 show "𝒟 ((𝔄 ×DG 𝔅)Dom) = 𝒟 ((op_dg 𝔄 ×DG op_dg 𝔅)Cod)"
      unfolding dom_lhs
      by 
        (
          cs_concl cs_shallow 
            cs_simp: dg_cs_simps dg_op_simps cs_intro: dg_op_intros
        )
    show "(𝔄 ×DG 𝔅)Domgf = (op_dg 𝔄 ×DG op_dg 𝔅)Codgf"
      if "gf  𝒟 ((𝔄 ×DG 𝔅)Dom)" for gf
      using that unfolding dom_lhs
    proof-
      assume "gf  (𝔄 ×DG 𝔅)Arr"
      then obtain g f 
        where gf_def: "gf = [g, f]" 
          and g: "g  𝔄Arr" 
          and f: "f  𝔅Arr"
        by (rule dg_prod_2_ArrE[OF 𝔄 𝔅]) simp
      from 𝔄 𝔅 g f show "(𝔄 ×DG 𝔅)Domgf = (op_dg 𝔄 ×DG op_dg 𝔅)Codgf"
        unfolding gf_def
        by 
          (
            cs_concl cs_shallow 
              cs_simp: dg_cs_simps dg_prod_cs_simps dg_op_simps 
              cs_intro: dg_op_intros dg_prod_cs_intros
          )
    qed
  qed (auto intro: 𝔄 𝔅 dg_prod_2_Dom_vsv)

  show "a  𝒟 (op_dg (𝔄 ×DG 𝔅)) 
    op_dg (𝔄 ×DG 𝔅)a = (op_dg 𝔄 ×DG op_dg 𝔅)a" 
    for a
  proof
    (
      unfold dom_lhs, 
      elim_in_numeral, 
      fold dg_field_simps, 
      unfold op_dg_components
    )
    from 𝔄 𝔅 show "(𝔄 ×DG 𝔅)Obj = (op_dg 𝔄 ×DG op_dg 𝔅)Obj"
      by (cs_concl cs_shallow cs_simp: dg_op_simps cs_intro: dg_op_intros) 
    from 𝔄 𝔅 show "(𝔄 ×DG 𝔅)Arr = (op_dg 𝔄 ×DG op_dg 𝔅)Arr"
      by (cs_concl cs_shallow cs_simp: dg_op_simps cs_intro: dg_op_intros) 
  qed (auto simp: 𝔄 𝔅 Cod_Dom Dom_Cod)

qed

end



subsection‹Projections for the product of two digraphs›


subsubsection‹Definition and elementary properties›

definition dghm_proj_fst :: "V  V  V" (πDG.1)
  where "πDG.1 𝔄 𝔅 = dghm_proj (2) (if2 𝔄 𝔅) 0"
definition dghm_proj_snd :: "V  V  V" (πDG.2)
  where "πDG.2 𝔄 𝔅 = dghm_proj (2) (if2 𝔄 𝔅) (1)"


subsubsection‹Object map for a projection of a product of two digraphs›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

lemma dghm_proj_fst_ObjMap_app[dg_cs_simps]:
  assumes "[a, b]  (𝔄 ×DG 𝔅)Obj"
  shows "πDG.1 𝔄 𝔅ObjMapa, b = a"
proof-
  from assms have "[a, b]  (i2. (if i = 0 then 𝔄 else 𝔅)Obj)"
    unfolding dg_prod_2_def dg_prod_components by simp
  then show "πDG.1 𝔄 𝔅ObjMapa, b = a"
    unfolding dghm_proj_fst_def dghm_proj_components dg_prod_components by simp
qed

lemma dghm_proj_snd_ObjMap_app[dg_cs_simps]:
  assumes "[a, b]  (𝔄 ×DG 𝔅)Obj"
  shows "πDG.2 𝔄 𝔅ObjMapa, b = b"
proof-
  from assms have "[a, b]  (i2. (if i = 0 then 𝔄 else 𝔅)Obj)"
    unfolding dg_prod_2_def dg_prod_components by simp
  then show "πDG.2 𝔄 𝔅ObjMapa, b = b"
    unfolding dghm_proj_snd_def dghm_proj_components dg_prod_components
    by (simp add: nat_omega_simps)
qed

end


subsubsection‹Arrow map for a projection of a product of two digraphs›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

lemma dghm_proj_fst_ArrMap_app[dg_cs_simps]:
  assumes "[g, f]  (𝔄 ×DG 𝔅)Arr"
  shows "πDG.1 𝔄 𝔅ArrMapg, f = g"
proof-
  from assms have "[g, f]  (i2. (if i = 0 then 𝔄 else 𝔅)Arr)"
    unfolding dg_prod_2_def dg_prod_components by simp
  then show "πDG.1 𝔄 𝔅ArrMapg, f = g"
    unfolding dghm_proj_fst_def dghm_proj_components dg_prod_components by simp
qed

lemma dghm_proj_snd_ArrMap_app[dg_cs_simps]:
  assumes "[g, f]  (𝔄 ×DG 𝔅)Arr"
  shows "πDG.2 𝔄 𝔅ArrMapg, f = f"
proof-
  from assms have "[g, f]  (i2. (if i = 0 then 𝔄 else 𝔅)Arr)"
    unfolding dg_prod_2_def dg_prod_components by simp
  then show "πDG.2 𝔄 𝔅ArrMapg, f = f"
    unfolding dghm_proj_snd_def dghm_proj_components dg_prod_components
    by (simp add: nat_omega_simps)
qed

end


subsubsection‹Domain and codomain of a projection of a product of two digraphs›

lemma dghm_proj_fst_HomDom: "πDG.1 𝔄 𝔅HomDom = 𝔄 ×DG 𝔅"
  unfolding dghm_proj_fst_def dghm_proj_components dg_prod_2_def ..

lemma dghm_proj_fst_HomCod: "πDG.1 𝔄 𝔅HomCod = 𝔄"
  unfolding dghm_proj_fst_def dghm_proj_components dg_prod_2_def by simp
  
lemma dghm_proj_snd_HomDom: "πDG.2 𝔄 𝔅HomDom = 𝔄 ×DG 𝔅"
  unfolding dghm_proj_snd_def dghm_proj_components dg_prod_2_def ..

lemma dghm_proj_snd_HomCod: "πDG.2 𝔄 𝔅HomCod = 𝔅"
  unfolding dghm_proj_snd_def dghm_proj_components dg_prod_2_def by simp


subsubsection‹Projection of a product of two digraphs is a digraph homomorphism›

context 
  fixes α 𝔄 𝔅
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅"
begin

interpretation finite_pdigraph α 2 if2 𝔄 𝔅
  by (intro finite_pdigraph_dg_prod_2 𝔄 𝔅)

lemma dghm_proj_fst_is_dghm: 
  assumes "i  I" 
  shows "πDG.1 𝔄 𝔅 : 𝔄 ×DG 𝔅 ↦↦DGα𝔄"
  by 
    (
      rule pdg_dghm_proj_is_dghm[
        where i=0, simplified, folded dghm_proj_fst_def dg_prod_2_def
        ]
    )

lemma dghm_proj_fst_is_dghm'[dg_cs_intros]:
  assumes "i  I" and " = 𝔄 ×DG 𝔅" and "𝔇 = 𝔄"
  shows "πDG.1 𝔄 𝔅 :  ↦↦DGα𝔇"
  using assms(1) unfolding assms(2,3) by (rule dghm_proj_fst_is_dghm)

lemma dghm_proj_snd_is_dghm:
  assumes "i  I"
  shows "πDG.2 𝔄 𝔅 : 𝔄 ×DG 𝔅 ↦↦DGα𝔅"
  by
    (
      rule pdg_dghm_proj_is_dghm[
        where i=1, simplified, folded dghm_proj_snd_def dg_prod_2_def
        ]
    )

lemma dghm_proj_snd_is_dghm'[dg_cs_intros]:  
  assumes "i  I" and " = 𝔄 ×DG 𝔅" and "𝔇 = 𝔅"
  shows "πDG.2 𝔄 𝔅 :  ↦↦DGα𝔇"
  using assms(1) unfolding assms(2,3) by (rule dghm_proj_snd_is_dghm)

end



subsection‹Product of three digraphs›
(*TODO: find a way to generalize to the product of n digraphs*)

definition dg_prod_3 :: "V  V  V  V" ("(_ ×DG3 _ ×DG3 _)" [81, 81, 81] 80)
  where "𝔄 ×DG3 𝔅 ×DG3  = (DGi3. if3 𝔄 𝔅  i)"


subsubsection‹Product of three digraphs is a digraph›

context 
  fixes α 𝔄 𝔅 
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅" and : "digraph α "
begin

interpretation 𝒵 α by (rule digraphD[OF 𝔄(1)])
interpretation 𝔄: digraph α 𝔄 by (rule 𝔄)
interpretation 𝔅: digraph α 𝔅 by (rule 𝔅)
interpretation 𝔅: digraph α  by (rule )

lemma finite_pdigraph_dg_prod_3: 
  "finite_pdigraph α (3) (if3 𝔄 𝔅 )"
proof(intro finite_pdigraphI pdigraph_baseI)
  from Axiom_of_Infinity show z1_in_Vset: "3  Vset α" by blast
  show "digraph α (if3 𝔄 𝔅  i)" if "i  3" for i
    by (auto intro: dg_cs_intros)
qed auto

interpretation finite_pdigraph α 3 if3 𝔄 𝔅 
  by (intro finite_pdigraph_dg_prod_3 𝔄 𝔅)

lemma digraph_dg_prod_3[dg_cs_intros]: "digraph α (𝔄 ×DG3 𝔅 ×DG3 )"
proof-
  show ?thesis unfolding dg_prod_3_def by (rule pdg_digraph_dg_prod)
qed

end


subsubsection‹Object›

context 
  fixes α 𝔄 𝔅 
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅" and : "digraph α "
begin

lemma dg_prod_3_ObjI:
  assumes "a  𝔄Obj" and "b  𝔅Obj" and "c  Obj"
  shows "[a, b, c]  (𝔄 ×DG3 𝔅 ×DG3 )Obj"
  unfolding dg_prod_3_def dg_prod_components
proof(intro vproductI ballI)
  show "𝒟 [a, b, c] = 3" by (simp add: nat_omega_simps)
  fix i assume "i  3"
  then consider i = 0 | i = 1 | i = 2 unfolding three by auto 
  then show "[a, b, c]i  (if3 𝔄 𝔅  i)Obj"
    by cases (simp_all add: nat_omega_simps assms)
qed auto

lemma dg_prod_3_ObjI'[dg_prod_cs_intros]:
  assumes "abc = [a, b, c]" and "a  𝔄Obj" and "b  𝔅Obj" and "c  Obj"
  shows "abc  (𝔄 ×DG3 𝔅 ×DG3 )Obj"
  using assms(2-4) unfolding assms(1) by (rule dg_prod_3_ObjI)

lemma dg_prod_3_ObjE:
  assumes "abc  (𝔄 ×DG3 𝔅 ×DG3 )Obj"
  obtains a b c
    where "abc = [a, b, c]" 
      and "a  𝔄Obj" 
      and "b  𝔅Obj"
      and "c  Obj"
proof-
  from vproductD[OF assms[unfolded dg_prod_3_def dg_prod_components]]
  have vsv_abc: "vsv abc"
    and dom_abc: "𝒟 abc = 3"
    and abc_app: "i. i  3  abci  (if3 𝔄 𝔅  i)Obj"
    by auto
  have dom_abc[simp]: "𝒟 abc = 3"
    unfolding dom_abc by (simp add: nat_omega_simps two)
  interpret vsv abc by (rule vsv_abc)
  have "abc = [vpfst abc, vpsnd abc, vpthrd abc]"
    by (rule vsv_vfsequence_three[symmetric]) auto
  moreover from abc_app[of 0] have "vpfst abc  𝔄Obj" by simp
  moreover from abc_app[of 1] have "vpsnd abc  𝔅Obj" by simp
  moreover from abc_app[of 2] have "vpthrd abc  Obj" by simp
  ultimately show ?thesis using that by auto
qed

end


subsubsection‹Arrow›

context 
  fixes α 𝔄 𝔅 
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅" and : "digraph α "
begin

lemma dg_prod_3_ArrI:
  assumes "h  𝔄Arr" and "g  𝔅Arr" and "f  Arr"
  shows "[h, g, f]  (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  unfolding dg_prod_3_def dg_prod_components
proof(intro vproductI ballI)
  show "𝒟 [h, g, f] = 3" by (simp add: nat_omega_simps three)
  fix i assume "i  3"
  then consider i = 0 | i = 1 | i = 2 unfolding three by auto 
  then show "[h, g, f]i  (if3 𝔄 𝔅  i)Arr"
    by cases (simp_all add: nat_omega_simps assms)
qed auto

lemma dg_prod_3_ArrI'[dg_prod_cs_intros]:
  assumes "hgf = [h, g, f]" 
    and "h  𝔄Arr" 
    and "g  𝔅Arr"
    and "f  Arr"
  shows "[h, g, f]  (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  using assms(2-4) unfolding assms(1) by (rule dg_prod_3_ArrI)

lemma dg_prod_3_ArrE:
  assumes "hgf  (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  obtains h g f 
    where "hgf = [h, g, f]" 
      and "h  𝔄Arr" 
      and "g  𝔅Arr" 
      and "f  Arr"
proof-
  from vproductD[OF assms[unfolded dg_prod_3_def dg_prod_components]]
  have vsv_hgf: "vsv hgf"
    and dom_hgf: "𝒟 hgf = 3"
    and hgf_app: "i. i  3  hgfi  (if3 𝔄 𝔅  i)Arr"
    by auto
  have dom_hgf[simp]: "𝒟 hgf = 3" unfolding dom_hgf by (simp add: three)
  interpret vsv hgf by (rule vsv_hgf)
  have "hgf = [vpfst hgf, vpsnd hgf, vpthrd hgf]"
    by (rule vsv_vfsequence_three[symmetric]) auto
  moreover from hgf_app[of 0] have "vpfst hgf  𝔄Arr" by simp
  moreover from hgf_app[of 1] have "vpsnd hgf  𝔅Arr" by simp
  moreover from hgf_app[of 2] have "vpthrd hgf  Arr" by simp
  ultimately show ?thesis using that by auto
qed

end


subsubsection‹Arrow with a domain and a codomain›

context 
  fixes α 𝔄 𝔅 
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅" and : "digraph α "
begin

interpretation 𝒵 α by (rule digraphD[OF 𝔄(1)])
interpretation 𝔄: digraph α 𝔄 by (rule 𝔄)
interpretation 𝔅: digraph α 𝔅 by (rule 𝔅)
interpretation: digraph α  by (rule )
interpretation finite_pdigraph α 3 if3 𝔄 𝔅 
  by (intro finite_pdigraph_dg_prod_3 𝔄 𝔅 )

lemma dg_prod_3_is_arrI:
  assumes "f : a 𝔄b" and "f' : a' 𝔅b'" and "f'' : a'' b''"
  shows "[f, f', f''] : [a, a', a''] 𝔄 ×DG3 𝔅 ×DG3 [b, b', b'']"
  unfolding dg_prod_3_def
proof(rule dg_prod_is_arrI)
  show "[f, f', f'']i : [a, a', a'']i if3 𝔄 𝔅  i[b, b', b'']i"
    if "i  3" for i
  proof-
    from that consider i = 0 | i = 1 | i = 2 unfolding three by auto 
    then show 
      "[f, f', f'']i : [a, a', a'']i if3 𝔄 𝔅  i[b, b', b'']i"
      by cases (simp_all add: nat_omega_simps assms)
  qed
qed (auto simp: nat_omega_simps three)

lemma dg_prod_3_is_arrI'[dg_prod_cs_intros]:
  assumes "F = [f, f', f'']"
    and "A = [a, a', a'']"
    and "B = [b, b', b'']"
    and "f : a 𝔄b"
    and "f' : a' 𝔅b'"  
    and "f'' : a'' b''"
  shows "F : A 𝔄 ×DG3 𝔅 ×DG3 B"
  using assms(4,5,6) unfolding assms(1,2,3) by (rule dg_prod_3_is_arrI)

lemma dg_prod_3_is_arrE:
  assumes "F : A 𝔄 ×DG3 𝔅 ×DG3 B"
  obtains f f' f'' a a' a'' b b' b'' 
    where "F = [f, f', f'']"
      and "A = [a, a', a'']"
      and "B = [b, b', b'']"
      and "f : a 𝔄b"
      and "f' : a' 𝔅b'"
      and "f'' : a'' b''"
proof-
  from dg_prod_is_arrD[OF assms[unfolded dg_prod_3_def]] 
  have [simp]: "vsv F" "𝒟 F = 3" "vsv A" "𝒟 A = 3" "vsv B" "𝒟 B = 3"
    and F_app: "i. i  3  Fi : Ai if3 𝔄 𝔅  iBi"
    by (auto simp: three)
  have "F = [vpfst F, vpsnd F, vpthrd F]" 
    by (simp add: vsv_vfsequence_three)
  moreover have "A = [vpfst A, vpsnd A, vpthrd A]" 
    by (simp add: vsv_vfsequence_three)
  moreover have "B = [vpfst B, vpsnd B, vpthrd B]" 
    by (simp add: vsv_vfsequence_three)
  moreover from F_app[of 0] have "vpfst F : vpfst A 𝔄vpfst B" by simp
  moreover from F_app[of 1] have "vpsnd F : vpsnd A 𝔅vpsnd B" 
    by (simp add: nat_omega_simps)
  moreover from F_app[of 2] have "vpthrd F : vpthrd A vpthrd B" 
    by (simp add: nat_omega_simps)
  ultimately show ?thesis using that by auto
qed

end


subsubsection‹Domain›

context 
  fixes α 𝔄 𝔅 
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅" and : "digraph α "
begin

interpretation 𝒵 α by (rule digraphD[OF 𝔄(1)])
interpretation 𝔄: digraph α 𝔄 by (rule 𝔄)
interpretation 𝔅: digraph α 𝔅 by (rule 𝔅)
interpretation: digraph α  by (rule )

lemma dg_prod_3_Dom_vsv: "vsv ((𝔄 ×DG3 𝔅 ×DG3 )Dom)"
  unfolding dg_prod_3_def dg_prod_components by simp

lemma dg_prod_3_Dom_vdomain[dg_cs_simps]: 
  "𝒟 ((𝔄 ×DG3 𝔅 ×DG3 )Dom) = (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  unfolding dg_prod_3_def dg_prod_components by simp

lemma dg_prod_3_Dom_app[dg_prod_cs_simps]:
  assumes "[f, f', f'']  (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  shows "(𝔄 ×DG3 𝔅 ×DG3 )Domf, f', f'' =
    [𝔄Domf, 𝔅Domf', Domf'']"
proof-
  from assms obtain A B where F: "[f, f', f''] : A 𝔄 ×DG3 𝔅 ×DG3 B" 
    by (auto intro: is_arrI)
  then have Dom_F: "(𝔄 ×DG3 𝔅 ×DG3 )Domf, f', f'' = A" 
    by (simp add: dg_cs_simps)
  from F obtain a a' a'' b b' b'' 
    where A_def: "A = [a, a', a'']" 
      and "B = [b, b', b'']" 
      and "f : a 𝔄b"
      and "f' : a' 𝔅b'"
      and "f'' : a'' b''"
    by (elim dg_prod_3_is_arrE[OF 𝔄 𝔅 ]) simp
  then have Dom_f: "𝔄Domf = a"   
    and Dom_f': "𝔅Domf' = a'" 
    and Dom_f'': "Domf'' = a''" 
    by (simp_all add: dg_cs_simps)
  show ?thesis unfolding Dom_F A_def Dom_f Dom_f' Dom_f'' ..
qed

lemma dg_prod_3_Dom_vrange: 
  " ((𝔄 ×DG3 𝔅 ×DG3 )Dom)  (𝔄 ×DG3 𝔅 ×DG3 )Obj"
proof(rule vsv.vsv_vrange_vsubset, unfold dg_cs_simps)
  show "vsv ((𝔄 ×DG3 𝔅 ×DG3 )Dom)" by (rule dg_prod_3_Dom_vsv)
  fix F assume prems: "F  (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  then obtain f f' f'' where F_def: "F = [f, f', f'']" 
    and f: "f  𝔄Arr" 
    and f': "f'  𝔅Arr"
    and f'': "f''  Arr"
    by (elim dg_prod_3_ArrE[OF 𝔄 𝔅 ]) simp
  from f f' f'' obtain a a' a'' b b' b''
    where f: "f : a 𝔄b" 
      and f': "f' : a' 𝔅b'" 
      and f'': "f'' : a'' b''" 
    by (meson is_arrI)
  from 𝔄 𝔅 f f' f'' show "(𝔄 ×DG3 𝔅 ×DG3 )DomF  (𝔄 ×DG3 𝔅 ×DG3 )Obj"
    unfolding F_def dg_prod_3_Dom_app[OF prems[unfolded F_def]]
    by (cs_concl cs_simp: dg_cs_simps cs_intro: dg_cs_intros dg_prod_cs_intros)
qed

end


subsubsection‹Codomain›

context 
  fixes α 𝔄 𝔅 
  assumes 𝔄: "digraph α 𝔄" and 𝔅: "digraph α 𝔅" and : "digraph α "
begin

interpretation 𝒵 α by (rule digraphD[OF 𝔄(1)])
interpretation 𝔄: digraph α 𝔄 by (rule 𝔄)
interpretation 𝔅: digraph α 𝔅 by (rule 𝔅)
interpretation: digraph α  by (rule )

lemma dg_prod_3_Cod_vsv: "vsv ((𝔄 ×DG3 𝔅 ×DG3 )Cod)"
  unfolding dg_prod_3_def dg_prod_components by simp

lemma dg_prod_3_Cod_vdomain[dg_cs_simps]: 
  "𝒟 ((𝔄 ×DG3 𝔅 ×DG3 )Cod) = (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  unfolding dg_prod_3_def dg_prod_components by simp

lemma dg_prod_3_Cod_app[dg_prod_cs_simps]:
  assumes "[f, f', f'']  (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  shows 
    "(𝔄 ×DG3 𝔅 ×DG3 )Codf, f', f'' =
      [𝔄Codf, 𝔅Codf', Codf'']"
proof-
  from assms obtain A B where F: "[f, f', f''] : A 𝔄 ×DG3 𝔅 ×DG3 B" 
    by (auto intro: is_arrI)
  then have Cod_F: "(𝔄 ×DG3 𝔅 ×DG3 )Codf, f', f'' = B"
    by (simp add: dg_cs_simps)
  from F obtain a a' a'' b b' b'' 
    where "A = [a, a', a'']" 
      and B_def: "B = [b, b', b'']" 
      and "f : a 𝔄b"
      and "f' : a' 𝔅b'"
      and "f'' : a'' b''"
    by (elim dg_prod_3_is_arrE[OF 𝔄 𝔅 ]) simp
  then have Cod_f: "𝔄Codf = b"
    and Cod_f': "𝔅Codf' = b'"
    and Cod_f'': "Codf'' = b''"
    by (simp_all add: dg_cs_simps)
  show ?thesis unfolding Cod_F B_def Cod_f Cod_f' Cod_f'' ..
qed

lemma dg_prod_3_Cod_vrange: 
  " ((𝔄 ×DG3 𝔅 ×DG3 )Cod)  (𝔄 ×DG3 𝔅 ×DG3 )Obj"
proof(rule vsv.vsv_vrange_vsubset, unfold dg_cs_simps)
  show "vsv ((𝔄 ×DG3 𝔅 ×DG3 )Cod)" by (rule dg_prod_3_Cod_vsv)
  fix F assume prems: "F  (𝔄 ×DG3 𝔅 ×DG3 )Arr"
  then obtain f f' f'' where F_def: "F = [f, f', f'']" 
    and f: "f  𝔄Arr" 
    and f': "f'  𝔅Arr" 
    and f'': "f''  Arr"
    by (elim dg_prod_3_ArrE[OF 𝔄 𝔅 ]) simp
  from f f' f'' obtain a a' a'' b b' b'' 
    where f: "f : a 𝔄b" 
      and f': "f' : a' 𝔅b'"
      and f'': "f'' : a'' b''"
    by (metis is_arrI)
  from 𝔄 𝔅  f f' f'' show 
    "(𝔄 ×DG3 𝔅 ×DG3 )CodF  (𝔄 ×DG3 𝔅 ×DG3 )Obj"
    unfolding F_def dg_prod_3_Cod_app[OF prems[unfolded F_def]]
    by 
      (
        cs_concl cs_shallow 
          cs_simp: dg_cs_simps cs_intro: dg_cs_intros dg_prod_cs_intros
      )
qed

end

text‹\newpage›

end