Theory CZH_ECAT_Parallel

(* Copyright 2021 (C) Mihails Milehins *)

sectionβ€ΉCategories with parallel arrows between two objectsβ€Ί
theory CZH_ECAT_Parallel
  imports CZH_ECAT_Small_Functor
begin



subsectionβ€ΉBackground: category with parallel arrows between two objectsβ€Ί

named_theorems cat_parallel_cs_simps
named_theorems cat_parallel_cs_intros

definition π”žPL :: "V β‡’ V" where "π”žPL F = set {F, 0}"
definition π”ŸPL :: "V β‡’ V" where "π”ŸPL F = set {F, 1β„•}"

lemma cat_PL_π”ž_nin_F[cat_parallel_cs_intros]: "π”žPL F βˆ‰βˆ˜ F" 
  unfolding π”žPL_def using mem_not_sym by auto

lemma cat_PL_π”Ÿ_nin_F[cat_parallel_cs_intros]: "π”ŸPL F βˆ‰βˆ˜ F"
  unfolding π”ŸPL_def using mem_not_sym by auto

lemma cat_PL_π”žπ”Ÿ[cat_parallel_cs_intros]: "π”žPL F β‰  π”ŸPL F"
  unfolding π”žPL_def π”ŸPL_def by (simp add: Set.doubleton_eq_iff)

lemmas cat_PL_π”Ÿπ”ž[cat_parallel_cs_intros] = cat_PL_π”žπ”Ÿ[symmetric]



subsectionβ€Ή
Composable arrows for a category with parallel arrows between two objects
β€Ί

definition cat_parallel_composable :: "V β‡’ V β‡’ V β‡’ V"
  where "cat_parallel_composable π”ž π”Ÿ F ≑
    set {[π”ž, π”ž]∘, [π”Ÿ, π”Ÿ]∘} βˆͺ∘
    (F Γ—βˆ™ set {π”ž}) βˆͺ∘
    (set {π”Ÿ} Γ—βˆ™ F)"


textβ€ΉRules.β€Ί

lemma cat_parallel_composable_π”žπ”ž[cat_parallel_cs_intros]:
  assumes "g = π”ž" and "f = π”ž"
  shows "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
  unfolding assms cat_parallel_composable_def by auto

lemma cat_parallel_composable_π”Ÿπ”£[cat_parallel_cs_intros]:
  assumes "g = π”Ÿ" and "f ∈∘ F"
  shows "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
  using assms(2) unfolding assms(1) cat_parallel_composable_def by auto

lemma cat_parallel_composable_π”£π”ž[cat_parallel_cs_intros]:
  assumes "g ∈∘ F" and "f = π”ž" 
  shows "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
  using assms(1) unfolding assms(2) cat_parallel_composable_def by auto

lemma cat_parallel_composable_π”Ÿπ”Ÿ[cat_parallel_cs_intros]:
  assumes "g = π”Ÿ" and "f = π”Ÿ"
  shows "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
  unfolding assms cat_parallel_composable_def by auto

lemma cat_parallel_composableE:
  assumes "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
  obtains "g = π”Ÿ" and "f = π”Ÿ"
        | "g = π”Ÿ" and "f ∈∘ F" 
        | "g ∈∘ F" and "f = π”ž"
        | "g = π”ž" and "f = π”ž"
  using assms that unfolding cat_parallel_composable_def by auto


textβ€ΉElementary properties.β€Ί

lemma cat_parallel_composable_fconverse: 
  "(cat_parallel_composable π”ž π”Ÿ F)Β―βˆ™ = cat_parallel_composable π”Ÿ π”ž F"
  unfolding cat_parallel_composable_def by auto



subsectionβ€Ή
Local assumptions for a category with parallel arrows between two objects
β€Ί

locale cat_parallel = 𝒡 Ξ± for Ξ± +  
  fixes π”ž π”Ÿ F
  assumes cat_parallel_π”žπ”Ÿ[cat_parallel_cs_intros]: "π”ž β‰  π”Ÿ"
    and cat_parallel_π”žF[cat_parallel_cs_intros]: "π”ž βˆ‰βˆ˜ F"
    and cat_parallel_π”ŸF[cat_parallel_cs_intros]: "π”Ÿ βˆ‰βˆ˜ F"
    and cat_parallel_π”ž_in_Vset[cat_parallel_cs_intros]: "π”ž ∈∘ Vset Ξ±"
    and cat_parallel_π”Ÿ_in_Vset[cat_parallel_cs_intros]: "π”Ÿ ∈∘ Vset Ξ±"
    and cat_parallel_F_in_Vset[cat_parallel_cs_intros]: "F ∈∘ Vset α"

lemmas (in cat_parallel) cat_parallel_ineq =
  cat_parallel_π”žπ”Ÿ
  cat_parallel_π”žF
  cat_parallel_π”ŸF


textβ€ΉRules.β€Ί

lemmas (in cat_parallel) [cat_parallel_cs_intros] = cat_parallel_axioms

mk_ide rf cat_parallel_def[unfolded cat_parallel_axioms_def]
  |intro cat_parallelI|
  |dest cat_parallelD[dest]|
  |elim cat_parallelE[elim]|


textβ€ΉDuality.β€Ί

lemma (in cat_parallel) cat_parallel_op[cat_op_intros]: 
  "cat_parallel Ξ± π”Ÿ π”ž F"
  by (intro cat_parallelI) 
    (auto intro!: cat_parallel_cs_intros cat_parallel_π”žπ”Ÿ[symmetric])


textβ€ΉElementary properties.β€Ί

lemma (in 𝒡) cat_parallel_PL: 
  assumes "F ∈∘ Vset α"
  shows "cat_parallel Ξ± (π”žPL F) (π”ŸPL F) F"
proof (rule cat_parallelI)
  show "π”žPL F ∈∘ Vset Ξ±"
    unfolding π”žPL_def by (intro Limit_vdoubleton_in_VsetI assms) auto
  show "π”ŸPL F ∈∘ Vset Ξ±"
    unfolding π”ŸPL_def
    by (intro Limit_vdoubleton_in_VsetI ord_of_nat_in_Vset assms) simp
qed (auto simp: assms cat_PL_π”žπ”Ÿ cat_PL_π”ž_nin_F cat_PL_π”Ÿ_nin_F)



subsection‹‹⇑›: category with parallel arrows between two objectsβ€Ί


subsubsectionβ€ΉDefinition and elementary propertiesβ€Ί


textβ€ΉSee Chapter I-2 and Chapter III-3 in citeβ€Ή"mac_lane_categories_2010"β€Ί.β€Ί

definition the_cat_parallel :: "V β‡’ V β‡’ V β‡’ V" (‹⇑Cβ€Ί)
  where "⇑C π”ž π”Ÿ F =
    [
      set {π”ž, π”Ÿ},
      set {π”ž, π”Ÿ} βˆͺ∘ F,
      (Ξ»x∈∘set {π”ž, π”Ÿ} βˆͺ∘ F. (x = π”Ÿ ? π”Ÿ : π”ž)),
      (Ξ»x∈∘set {π”ž, π”Ÿ} βˆͺ∘ F. (x = π”ž ? π”ž : π”Ÿ)),
      (
        Ξ»gf∈∘cat_parallel_composable π”ž π”Ÿ F.
         if gf = [π”Ÿ, π”Ÿ]∘ β‡’ π”Ÿ
          | βˆƒf. gf = [π”Ÿ, f]∘ β‡’ gf⦇1β„•β¦ˆ
          | βˆƒf. gf = [f, π”ž]∘ β‡’ gf⦇0⦈
          | otherwise β‡’ π”ž
      ),
      vid_on (set {π”ž, π”Ÿ})
    ]∘"


textβ€ΉComponents.β€Ί

lemma the_cat_parallel_components: 
  shows "⇑C π”ž π”Ÿ F⦇Obj⦈ = set {π”ž, π”Ÿ}"
    and "⇑C π”ž π”Ÿ F⦇Arr⦈ = set {π”ž, π”Ÿ} βˆͺ∘ F"
    and "⇑C π”ž π”Ÿ F⦇Dom⦈ = (Ξ»x∈∘set {π”ž, π”Ÿ} βˆͺ∘ F. (x = π”Ÿ ? π”Ÿ : π”ž))"
    and "⇑C π”ž π”Ÿ F⦇Cod⦈ = (Ξ»x∈∘set {π”ž, π”Ÿ} βˆͺ∘ F. (x = π”ž ? π”ž : π”Ÿ))"
    and "⇑C π”ž π”Ÿ F⦇Comp⦈ =
      (
        Ξ»gf∈∘cat_parallel_composable π”ž π”Ÿ F.
         if gf = [π”Ÿ, π”Ÿ]∘ β‡’ π”Ÿ
          | βˆƒf. gf = [π”Ÿ, f]∘ β‡’ gf⦇1β„•β¦ˆ
          | βˆƒf. gf = [f, π”ž]∘ β‡’ gf⦇0⦈
          | otherwise β‡’ π”ž
      )"
    and "⇑C π”ž π”Ÿ F⦇CId⦈ = vid_on (set {π”ž, π”Ÿ})"
  unfolding the_cat_parallel_def dg_field_simps 
  by (simp_all add: nat_omega_simps)


subsubsectionβ€ΉObjectsβ€Ί

lemma the_cat_parallel_Obj_π”žI[cat_parallel_cs_intros]:
  assumes "a = π”ž"
  shows "a ∈∘ ⇑C π”ž π”Ÿ F⦇Obj⦈"
  using assms unfolding the_cat_parallel_components by simp

lemma the_cat_parallel_Obj_π”ŸI[cat_parallel_cs_intros]:
  assumes "a = π”Ÿ"
  shows "a ∈∘ ⇑C π”ž π”Ÿ F⦇Obj⦈"
  using assms unfolding the_cat_parallel_components by simp

lemma the_cat_parallel_ObjE:
  assumes "a ∈∘ ⇑C π”ž π”Ÿ F⦇Obj⦈"
  obtains "a = π”ž" | "a = π”Ÿ" 
  using assms unfolding the_cat_parallel_components(1) by fastforce


subsubsectionβ€ΉArrowsβ€Ί

lemma the_cat_parallel_Arr_π”žI[cat_parallel_cs_intros]:
  assumes "f = π”ž"  
  shows "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
  using assms unfolding the_cat_parallel_components by simp

lemma the_cat_parallel_Arr_π”ŸI[cat_parallel_cs_intros]:
  assumes "f = π”Ÿ"  
  shows "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
  using assms unfolding the_cat_parallel_components by simp

lemma the_cat_parallel_Arr_FI[cat_parallel_cs_intros]:
  assumes "f ∈∘ F"
  shows "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
  using assms unfolding the_cat_parallel_components by simp

lemma the_cat_parallel_ArrE:
  assumes "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
  obtains "f = π”ž" | "f = π”Ÿ" | "f ∈∘ F"  
  using assms that unfolding the_cat_parallel_components by auto


subsubsectionβ€ΉDomainβ€Ί

mk_VLambda the_cat_parallel_components(3)
  |vsv the_cat_parallel_Dom_vsv[cat_parallel_cs_intros]|
  |vdomain the_cat_parallel_Dom_vdomain[cat_parallel_cs_simps]|

lemma (in cat_parallel) the_cat_parallel_Dom_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "f = π”Ÿ"
  shows "⇑C π”ž π”Ÿ F⦇Domβ¦ˆβ¦‡f⦈ = π”Ÿ"
  unfolding the_cat_parallel_components assms by simp

lemmas [cat_parallel_cs_simps] = cat_parallel.the_cat_parallel_Dom_app_π”Ÿ

lemma (in cat_parallel) the_cat_parallel_Dom_app_F[cat_parallel_cs_simps]:
  assumes "f ∈∘ F"
  shows "⇑C π”ž π”Ÿ F⦇Domβ¦ˆβ¦‡f⦈ = π”ž"
  unfolding the_cat_parallel_components using assms cat_parallel_ineq by auto

lemmas [cat_parallel_cs_simps] = cat_parallel.the_cat_parallel_Dom_app_F

lemma (in cat_parallel) the_cat_parallel_Dom_app_π”ž[cat_parallel_cs_simps]:
  assumes "f = π”ž"
  shows "⇑C π”ž π”Ÿ F⦇Domβ¦ˆβ¦‡f⦈ = π”ž"
  unfolding the_cat_parallel_components assms by auto

lemmas [cat_parallel_cs_simps] = cat_parallel.the_cat_parallel_Dom_app_π”ž


subsubsectionβ€ΉCodomainβ€Ί

mk_VLambda the_cat_parallel_components(4)
  |vsv the_cat_parallel_Cod_vsv[cat_parallel_cs_intros]|
  |vdomain the_cat_parallel_Cod_vdomain[cat_parallel_cs_simps]|

lemma (in cat_parallel) the_cat_parallel_Cod_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "f = π”Ÿ"
  shows "⇑C π”ž π”Ÿ F⦇Codβ¦ˆβ¦‡f⦈ = π”Ÿ"
  unfolding the_cat_parallel_components assms by simp

lemmas [cat_parallel_cs_simps] = cat_parallel.the_cat_parallel_Cod_app_π”Ÿ

lemma (in cat_parallel) the_cat_parallel_Cod_app_F[cat_parallel_cs_simps]:
  assumes "f ∈∘ F"
  shows "⇑C π”ž π”Ÿ F⦇Codβ¦ˆβ¦‡f⦈ = π”Ÿ"
  unfolding the_cat_parallel_components using assms cat_parallel_ineq by auto

lemmas [cat_parallel_cs_simps] = cat_parallel.the_cat_parallel_Cod_app_F

lemma (in cat_parallel) the_cat_parallel_Cod_app_π”ž[cat_parallel_cs_simps]:
  assumes "f = π”ž"
  shows "⇑C π”ž π”Ÿ F⦇Codβ¦ˆβ¦‡f⦈ = π”ž"
  unfolding the_cat_parallel_components assms by auto

lemmas [cat_parallel_cs_simps] = cat_parallel.the_cat_parallel_Cod_app_π”ž


subsubsectionβ€ΉCompositionβ€Ί

mk_VLambda the_cat_parallel_components(5)
  |vsv the_cat_parallel_Comp_vsv[cat_parallel_cs_intros]|
  |vdomain the_cat_parallel_Comp_vdomain[cat_parallel_cs_simps]|
  |app the_cat_parallel_Comp_app[cat_parallel_cs_simps]|

lemma the_cat_parallel_Comp_app_π”Ÿπ”Ÿ[cat_parallel_cs_simps]:
  assumes "g = π”Ÿ" and "f = π”Ÿ"
  shows "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = g" "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = f"
proof-
  from assms have "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
    by (cs_concl cs_shallow cs_intro: cat_parallel_cs_intros)
  then show "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = g" "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = f"
    unfolding the_cat_parallel_components(5) assms 
    by (auto simp: nat_omega_simps)
qed

lemma the_cat_parallel_Comp_app_π”žπ”ž[cat_parallel_cs_simps]:
  assumes "g = π”ž" and "f = π”ž"
  shows "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = g" "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = f"
proof-
  from assms have "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
    by (cs_concl cs_intro: cat_parallel_cs_intros)
  then show "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = g" "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = f"
    unfolding the_cat_parallel_components(5) assms 
    by (auto simp: nat_omega_simps)
qed

lemma the_cat_parallel_Comp_app_π”ŸF[cat_parallel_cs_simps]:
  assumes "g = π”Ÿ" and "f ∈∘ F"
  shows "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = f" 
proof-
  from assms have "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
    by (cs_concl cs_intro: cat_parallel_cs_intros)
  then show "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = f"
    unfolding the_cat_parallel_components(5) assms 
    by (auto simp: nat_omega_simps)
qed

lemma (in cat_parallel) the_cat_parallel_Comp_app_Fπ”ž[cat_parallel_cs_simps]:
  assumes "g ∈∘ F" and "f = π”ž"
  shows "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = g" 
proof-
  from assms have "[g, f]∘ ∈∘ cat_parallel_composable π”ž π”Ÿ F"
    by (cs_concl cs_intro: cat_parallel_cs_intros)
  then show "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = g"
    unfolding the_cat_parallel_components(5)  
    using assms cat_parallel_ineq
    by (auto simp: nat_omega_simps)
qed


subsubsectionβ€ΉIdentityβ€Ί

mk_VLambda the_cat_parallel_components(6)[unfolded VLambda_vid_on[symmetric]]
  |vsv the_cat_parallel_CId_vsv[cat_parallel_cs_intros]|
  |vdomain the_cat_parallel_CId_vdomain[cat_parallel_cs_simps]|
  |app the_cat_parallel_CId_app|

lemma the_cat_parallel_CId_app_π”ž[cat_parallel_cs_simps]: 
  assumes "a = π”ž"
  shows "⇑C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡a⦈ = π”ž"
  unfolding assms by (auto simp: the_cat_parallel_CId_app)

lemma the_cat_parallel_CId_app_π”Ÿ[cat_parallel_cs_simps]: 
  assumes "a = π”Ÿ"
  shows "⇑C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡a⦈ = π”Ÿ"
  unfolding assms by (auto simp: the_cat_parallel_CId_app)


subsubsectionβ€ΉArrow with a domain and a codomainβ€Ί

lemma (in cat_parallel) the_cat_parallel_is_arr_π”žπ”žπ”ž[cat_parallel_cs_intros]:
  assumes "a' = π”ž" and "b' = π”ž" and "f = π”ž"
  shows "f : a' β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b'"
proof(intro is_arrI, unfold assms)
  show "⇑C π”ž π”Ÿ F⦇Domβ¦ˆβ¦‡π”žβ¦ˆ = π”ž" "⇑C π”ž π”Ÿ F⦇Codβ¦ˆβ¦‡π”žβ¦ˆ = π”ž"
    by (cs_concl cs_shallow cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros)+
qed (auto simp: the_cat_parallel_components)

lemma (in cat_parallel) the_cat_parallel_is_arr_π”Ÿπ”Ÿπ”Ÿ[cat_parallel_cs_intros]:
  assumes "a' = π”Ÿ" and "b' = π”Ÿ" and "f = π”Ÿ"
  shows "f : a' β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b'"
proof(intro is_arrI, unfold assms)
  show "⇑C π”ž π”Ÿ F⦇Domβ¦ˆβ¦‡π”Ÿβ¦ˆ = π”Ÿ" "⇑C π”ž π”Ÿ F⦇Codβ¦ˆβ¦‡π”Ÿβ¦ˆ = π”Ÿ"
    by (cs_concl cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros)+
qed (auto simp: the_cat_parallel_components)

lemma (in cat_parallel) the_cat_parallel_is_arr_π”žπ”ŸF[cat_parallel_cs_intros]:
  assumes "a' = π”ž" and "b' = π”Ÿ" and "f ∈∘ F"
  shows "f : a' β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b'"
proof(intro is_arrI, unfold assms(1,2))
  from assms(3) show "⇑C π”ž π”Ÿ F⦇Domβ¦ˆβ¦‡f⦈ = π”ž" "⇑C π”ž π”Ÿ F⦇Codβ¦ˆβ¦‡f⦈ = π”Ÿ"
    by (cs_concl cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros)+
qed (auto simp: the_cat_parallel_components assms(3))

lemma (in cat_parallel) the_cat_parallel_is_arrE:
  assumes "f' : a' β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b'"
  obtains "a' = π”ž" and "b' = π”ž" and "f' = π”ž"
        | "a' = π”Ÿ" and "b' = π”Ÿ" and "f' = π”Ÿ"
        | "a' = π”ž" and "b' = π”Ÿ" and "f' ∈∘ F"
proof-
  note f = is_arrD[OF assms]
  from f(1) consider (π”ž) β€Ήf' = π”žβ€Ί | (π”Ÿ) β€Ήf' = π”Ÿβ€Ί | (F) β€Ήf' ∈∘ Fβ€Ί 
    unfolding the_cat_parallel_components(2) by auto
  then show ?thesis
  proof cases
    case π”ž
    moreover from f(2)[unfolded π”ž, symmetric] have "a' = π”ž"
      by 
        (
          cs_prems cs_shallow 
            cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros
        )
    moreover from f(3)[unfolded π”ž, symmetric] have "b' = π”ž"
      by 
        (
          cs_prems cs_shallow
            cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros
        )
    ultimately show ?thesis using that by auto
  next
    case π”Ÿ
    moreover from f(2)[unfolded π”Ÿ, symmetric] have "a' = π”Ÿ"
      by 
        (
          cs_prems cs_shallow 
            cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros
        )
    moreover from f(3)[unfolded π”Ÿ, symmetric] have "b' = π”Ÿ"
      by 
        (
          cs_prems cs_shallow 
            cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros
        )
    ultimately show ?thesis using that by auto
  next
    case F
    moreover from f(2)[symmetric] F have "a' = π”ž"
      by 
        (
          cs_prems cs_shallow 
            cs_simp: cat_parallel_cs_simps cs_intro: V_cs_intros
        )
    moreover from f(3)[symmetric] F have "b' = π”Ÿ"
      by (cs_prems cs_shallow cs_simp: cat_parallel_cs_simps)
    ultimately show ?thesis using that by auto
  qed
qed


subsubsection‹‹⇑› is a categoryβ€Ί

lemma (in cat_parallel) tiny_category_the_cat_parallel[cat_parallel_cs_intros]:
  "tiny_category Ξ± (⇑C π”ž π”Ÿ F)"
proof(intro tiny_categoryI'')
  show "vfsequence (⇑C π”ž π”Ÿ F)" unfolding the_cat_parallel_def by simp
  show "vcard (⇑C π”ž π”Ÿ F) = 6β„•"
    unfolding the_cat_parallel_def by (simp_all add: nat_omega_simps)
  show "β„›βˆ˜ (⇑C π”ž π”Ÿ F⦇Dom⦈) βŠ†βˆ˜ ⇑C π”ž π”Ÿ F⦇Obj⦈" 
    by (auto simp: the_cat_parallel_components)
  show "β„›βˆ˜ (⇑C π”ž π”Ÿ F⦇Cod⦈) βŠ†βˆ˜ ⇑C π”ž π”Ÿ F⦇Obj⦈" 
    by (auto simp: the_cat_parallel_components)
  show "(gf ∈∘ π’Ÿβˆ˜ (⇑C π”ž π”Ÿ F⦇Comp⦈)) =
    (βˆƒg f b c a. gf = [g, f]∘ ∧ g : b β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c ∧ f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b)"
    for gf
    unfolding the_cat_parallel_Comp_vdomain
  proof
    assume prems: "gf ∈∘ cat_parallel_composable π”ž π”Ÿ F"
    then obtain g f where gf_def: "gf = [g, f]∘" 
      unfolding cat_parallel_composable_def by auto
    from prems show 
      "βˆƒg f b c a. gf = [g, f]∘ ∧ g : b β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c ∧ f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b"
      unfolding gf_def
      by (*slow*)
        (
          cases rule: cat_parallel_composableE; 
          (intro exI conjI)?; 
          cs_concl_step?;
          (simp only:)?,
          allβ€Ήintro is_arrI, unfold the_cat_parallel_components(2)β€Ί
        )
        (
          cs_concl 
            cs_simp: cat_parallel_cs_simps V_cs_simps cs_intro: V_cs_intros
        )+
  next
    assume 
      "βˆƒg f b' c' a'. 
        gf = [g, f]∘ ∧ g : b' β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c' ∧ f : a' β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b'"
    then obtain g f b c a 
      where gf_def: "gf = [g, f]∘" 
        and g: "g : b β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c"
        and f: "f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b" 
      by clarsimp
    from g f show "gf ∈∘ cat_parallel_composable π”ž π”Ÿ F"
      unfolding gf_def 
      by (elim the_cat_parallel_is_arrE) (auto simp: cat_parallel_cs_intros)
  qed
  show "π’Ÿβˆ˜ (⇑C π”ž π”Ÿ F⦇CId⦈) = ⇑C π”ž π”Ÿ F⦇Obj⦈"
    by (simp add: cat_parallel_cs_simps the_cat_parallel_components)
  show "g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c"
    if "g : b β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c" and "f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b" for b c g a f
    using that
    by (elim the_cat_parallel_is_arrE; simp only:)
      (
        allβ€Ή
          solvesβ€Ήsimp add: cat_parallel_π”žπ”Ÿ[symmetric]β€Ί |
          cs_concl cs_simp: cat_parallel_cs_simps 
        β€Ί
      )
  show 
    "h ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = 
      h ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ (g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f)"
    if "h : c β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ d" 
      and "g : b β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c" 
      and "f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b"
    for c d h b g a f
    using that 
    by (elim the_cat_parallel_is_arrE; simp only:) (*slow*)
      (
        allβ€Ή
          solvesβ€Ήsimp only: cat_parallel_ineq cat_parallel_π”žπ”Ÿ[symmetric]β€Ί |
          cs_concl 
            cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros
          β€Ί
      )
  show "⇑C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡a⦈ : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ a" if "a ∈∘ ⇑C π”ž π”Ÿ F⦇Obj⦈" 
    for a
  proof-
    from that consider β€Ήa = π”žβ€Ί | β€Ήa = π”Ÿβ€Ί
      unfolding the_cat_parallel_components(1) by auto
    then show "⇑C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡a⦈ : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ a"
      by cases
        (
          cs_concl 
            cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros
        )+
  qed
  show "⇑C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡b⦈ ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f = f" 
    if "f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b" for a b f
    using that
    by (elim the_cat_parallel_is_arrE)
      (cs_concl cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros)
  show "f ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ ⇑C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡b⦈ = f" 
    if "f : b β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c" for b c f
    using that
    by (elim the_cat_parallel_is_arrE)
      (cs_concl cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros)
  show "⇑C π”ž π”Ÿ F⦇Obj⦈ ∈∘ Vset Ξ±"
    by 
      (
        cs_concl cs_shallow
          cs_simp: the_cat_parallel_components nat_omega_simps 
          cs_intro: V_cs_intros cat_parallel_cs_intros
      )
qed 
  (
    cs_concl  
      cs_simp: 
        nat_omega_simps cat_parallel_cs_simps the_cat_parallel_components(2) 
      cs_intro: 
        cat_cs_intros 
        cat_parallel_cs_intros 
        V_cs_intros 
        Limit_succ_in_VsetI
  )+

lemmas [cat_parallel_cs_intros] = cat_parallel.tiny_category_the_cat_parallel


subsubsectionβ€ΉOpposite parallel categoryβ€Ί

lemma (in cat_parallel) op_cat_the_cat_parallel[cat_op_simps]: 
  "op_cat (⇑C π”ž π”Ÿ F) = ⇑C π”Ÿ π”ž F"
proof(rule cat_eqI)
  interpret par: cat_parallel Ξ± π”Ÿ π”ž F by (rule cat_parallel_op) 
  show π”Ÿπ”ž: "category Ξ± (⇑C π”Ÿ π”ž F)"
    by (cs_concl cs_shallow cs_intro: cat_small_cs_intros cat_parallel_cs_intros)
  show π”žπ”Ÿ: "category Ξ± (op_cat (⇑C π”ž π”Ÿ F))" 
    by 
      (
        cs_concl cs_shallow 
          cs_intro: cat_small_cs_intros cat_op_intros cat_parallel_cs_intros
      )
  interpret π”Ÿπ”ž: category Ξ± ‹⇑C π”Ÿ π”ž Fβ€Ί by (rule π”Ÿπ”ž)
  interpret π”žπ”Ÿ: category Ξ± ‹⇑C π”ž π”Ÿ Fβ€Ί
    by (cs_concl cs_shallow cs_intro: cat_small_cs_intros cat_parallel_cs_intros)
  show "op_cat (⇑C π”ž π”Ÿ F)⦇Comp⦈ = ⇑C π”Ÿ π”ž F⦇Comp⦈"
  proof(rule vsv_eqI)
    show "vsv (op_cat (⇑C π”ž π”Ÿ F)⦇Comp⦈)"
      unfolding op_cat_components by (rule fflip_vsv)
    show "vsv (⇑C π”Ÿ π”ž F⦇Comp⦈)"
      by (cs_concl cs_shallow cs_intro: cat_parallel_cs_intros)
    show [cat_op_simps]: "π’Ÿβˆ˜ (op_cat (⇑C π”ž π”Ÿ F)⦇Comp⦈) = π’Ÿβˆ˜ (⇑C π”Ÿ π”ž F⦇Comp⦈)"
      by 
        (
          cs_concl cs_shallow
            cs_simp: 
              cat_parallel_composable_fconverse
              op_cat_components(5) 
              vdomain_fflip 
              cat_parallel_cs_simps 
            cs_intro: cat_cs_intros
        )
    fix gf assume "gf ∈∘ π’Ÿβˆ˜ (op_cat (⇑C π”ž π”Ÿ F)⦇Comp⦈)"
    then have "gf ∈∘ π’Ÿβˆ˜ (⇑C π”Ÿ π”ž F⦇Comp⦈)" unfolding cat_op_simps by simp
    then obtain g f a b c 
      where gf_def: "gf = [g, f]∘" 
        and g: "g : b β†¦β‡˜β‡‘C π”Ÿ π”ž F⇙ c"
        and f: "f : a β†¦β‡˜β‡‘C π”Ÿ π”ž F⇙ b"
      by auto
    from g f show "op_cat (⇑C π”ž π”Ÿ F)⦇Compβ¦ˆβ¦‡gf⦈ = ⇑C π”Ÿ π”ž F⦇Compβ¦ˆβ¦‡gf⦈"
      unfolding gf_def
      by (elim par.the_cat_parallel_is_arrE)
        (
          simp add: cat_parallel_cs_intros | 
          cs_concl 
            cs_simp: cat_op_simps cat_parallel_cs_simps 
            cs_intro: cat_cs_intros cat_parallel_cs_intros
        )+
  qed
  show "op_cat (⇑C π”ž π”Ÿ F)⦇CId⦈ = ⇑C π”Ÿ π”ž F⦇CId⦈"
  proof(unfold cat_op_simps, rule vsv_eqI, unfold cat_parallel_cs_simps)  
    fix a assume "a ∈∘ set {π”ž, π”Ÿ}"
    then consider β€Ήa = π”žβ€Ί | β€Ήa = π”Ÿβ€Ί by auto
    then show "⇑C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡a⦈ = ⇑C π”Ÿ π”ž F⦇CIdβ¦ˆβ¦‡a⦈"
      by cases (cs_concl cs_simp: cat_parallel_cs_simps)+
  qed auto
qed (auto simp: the_cat_parallel_components op_cat_components)

lemmas [cat_op_simps] = cat_parallel.op_cat_the_cat_parallel



subsectionβ€ΉParallel functorβ€Ί


subsubsectionβ€ΉBackgroundβ€Ί


textβ€Ή
See Chapter III-3 and Chapter III-4 in citeβ€Ή"mac_lane_categories_2010"β€Ί).
β€Ί


subsubsectionβ€ΉLocal assumptions for the parallel functorβ€Ί

locale cf_parallel = cat_parallel Ξ± π”ž π”Ÿ F + category Ξ± β„­ + F': vsv F'
  for Ξ± π”ž π”Ÿ F π”ž' π”Ÿ' F' β„­ :: V +
  assumes cf_parallel_F'_vdomain[cat_parallel_cs_simps]: "π’Ÿβˆ˜ F' = F"
    and cf_parallel_F'[cat_parallel_cs_intros]: "𝔣 ∈∘ F ⟹ F'β¦‡π”£β¦ˆ : π”ž' β†¦β‡˜β„­β‡™ π”Ÿ'"
    and cf_parallel_π”ž'[cat_parallel_cs_intros]: "π”ž' ∈∘ ℭ⦇Obj⦈"
    and cf_parallel_π”Ÿ'[cat_parallel_cs_intros]: "π”Ÿ' ∈∘ ℭ⦇Obj⦈"

lemmas (in cf_parallel) [cat_parallel_cs_intros] = F'.vsv_axioms 

lemma (in cf_parallel) cf_parallel_F''[cat_parallel_cs_intros]:
  assumes "𝔣 ∈∘ F" and "a = π”ž'" and "b = π”Ÿ'"
  shows "F'β¦‡π”£β¦ˆ : a β†¦β‡˜β„­β‡™ b"
  using assms(1) unfolding assms(2-3) by (rule cf_parallel_F')

lemma (in cf_parallel) cf_parallel_F'''[cat_parallel_cs_intros]:
  assumes "𝔣 ∈∘ F" and "f = F'β¦‡π”£β¦ˆ" and "b = π”Ÿ'"
  shows "f : π”ž' β†¦β‡˜β„­β‡™ b"
  using assms(1) unfolding assms(2-3) by (rule cf_parallel_F')

lemma (in cf_parallel) cf_parallel_F''''[cat_parallel_cs_intros]:
  assumes "𝔣 ∈∘ F" and "f = F'β¦‡π”£β¦ˆ" and "a = π”ž'"
  shows "f : a β†¦β‡˜β„­β‡™ π”Ÿ'"
  using assms(1) unfolding assms(2,3) by (rule cf_parallel_F')


textβ€ΉRules.β€Ί

lemma (in cf_parallel) cf_parallel_axioms'[cat_parallel_cs_intros]:
  assumes "Ξ±' = Ξ±" 
    and "a'' = π”ž" 
    and "b'' = π”Ÿ" 
    and "F'' = F" 
    and "a''' = π”ž'" 
    and "b''' = π”Ÿ'" 
    and "F''' = F'" 
  shows "cf_parallel Ξ±' a'' b'' F'' a''' b''' F''' β„­"
  unfolding assms by (rule cf_parallel_axioms)

mk_ide rf cf_parallel_def[unfolded cf_parallel_axioms_def]
  |intro cf_parallelI|
  |dest cf_parallelD[dest]|
  |elim cf_parallelE[elim]|

lemmas [cat_parallel_cs_intros] = cf_parallelD(1,2)


textβ€ΉDuality.β€Ί

lemma (in cf_parallel) cf_parallel_op[cat_op_intros]: 
  "cf_parallel Ξ± π”Ÿ π”ž F π”Ÿ' π”ž' F' (op_cat β„­)"
  by (intro cf_parallelI, unfold cat_op_simps insert_commute) 
    (
      cs_concl 
        cs_simp: cat_parallel_cs_simps  
        cs_intro: cat_parallel_cs_intros cat_cs_intros cat_op_intros
    )+

lemmas [cat_op_intros] = cf_parallel.cf_parallel_op


subsubsectionβ€ΉDefinition and elementary propertiesβ€Ί

definition the_cf_parallel :: "V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V" 
  (‹⇑→⇑CFβ€Ί)
  where "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F' =
    [
      (Ξ»aβˆˆβˆ˜β‡‘C π”ž π”Ÿ F⦇Obj⦈. (a = π”ž ? π”ž' : π”Ÿ')),
      (
        Ξ»fβˆˆβˆ˜β‡‘C π”ž π”Ÿ F⦇Arr⦈.
          (
           if f = π”ž β‡’ ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈
            | f = π”Ÿ β‡’ ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈
            | otherwise β‡’ F'⦇f⦈ 
          )
      ),
      ⇑C π”ž π”Ÿ F,
      β„­
    ]∘"


textβ€ΉComponents.β€Ί

lemma the_cf_parallel_components:
  shows "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈ =
      (Ξ»aβˆˆβˆ˜β‡‘C π”ž π”Ÿ F⦇Obj⦈. (a = π”ž ? π”ž' : π”Ÿ'))"
    and "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈ =
      (
        Ξ»fβˆˆβˆ˜β‡‘C π”ž π”Ÿ F⦇Arr⦈.
          (
           if f = π”ž β‡’ ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈
            | f = π”Ÿ β‡’ ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈
            | otherwise β‡’ F'⦇f⦈ 
          )
      )"
    and [cat_parallel_cs_simps]: "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇HomDom⦈ = ⇑C π”ž π”Ÿ F"
    and [cat_parallel_cs_simps]: "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇HomCod⦈ = β„­"
  unfolding the_cf_parallel_def dghm_field_simps 
  by (simp_all add: nat_omega_simps)


subsubsectionβ€ΉObject mapβ€Ί

mk_VLambda the_cf_parallel_components(1)
  |vsv the_cf_parallel_ObjMap_vsv[cat_parallel_cs_intros]|
  |vdomain the_cf_parallel_ObjMap_vdomain[cat_parallel_cs_simps]|
  |app the_cf_parallel_ObjMap_app|

lemma (in cf_parallel) the_cf_parallel_ObjMap_app_π”ž[cat_parallel_cs_simps]:
  assumes "x = π”ž"
  shows "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMapβ¦ˆβ¦‡x⦈ = π”ž'"
  by 
    (
      cs_concl 
        cs_simp: 
          assms the_cf_parallel_ObjMap_app cat_parallel_cs_simps V_cs_simps 
        cs_intro: cat_parallel_cs_intros
    )

lemmas [cat_parallel_cs_simps] = cf_parallel.the_cf_parallel_ObjMap_app_π”ž

lemma (in cf_parallel) the_cf_parallel_ObjMap_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "x = π”Ÿ"
  shows "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMapβ¦ˆβ¦‡x⦈ = π”Ÿ'"
  using cat_parallel_ineq
  by 
    (
      cs_concl 
        cs_simp: 
          assms the_cf_parallel_ObjMap_app cat_parallel_cs_simps V_cs_simps 
        cs_intro: cat_parallel_cs_intros
    )

lemmas [cat_parallel_cs_simps] = cf_parallel.the_cf_parallel_ObjMap_app_π”Ÿ

lemma (in cf_parallel) the_cf_parallel_ObjMap_vrange:
  "β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈) = set {π”ž', π”Ÿ'}"
proof(intro vsubset_antisym)
  show "β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈) βŠ†βˆ˜ set {π”ž', π”Ÿ'}"
    unfolding the_cf_parallel_components
    by (intro vrange_VLambda_vsubset)
      (simp_all add: cat_parallel_π”žπ”Ÿ cf_parallel_π”ž' cf_parallel_π”Ÿ')
  show "set {π”ž', π”Ÿ'} βŠ†βˆ˜ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈)"
  proof(rule vsubsetI)
    fix x assume prems: "x ∈∘ set {π”ž', π”Ÿ'}"
    from prems consider β€Ήx = π”ž'β€Ί | β€Ήx = π”Ÿ'β€Ί by auto
    moreover have "π”ž' ∈∘ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈)"
      by (rule vsv.vsv_vimageI2'[of _ _ π”ž])
        (
          cs_concl 
            cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros 
        )
    moreover have "π”Ÿ' ∈∘ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈)"
      by (rule vsv.vsv_vimageI2'[of _ _ π”Ÿ])
        (
          cs_concl 
            cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros 
        )
    ultimately show "x ∈∘ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈)" by auto
  qed
qed

lemma (in cf_parallel) the_cf_parallel_ObjMap_vrange_vsubset_Obj:
  "β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈) βŠ†βˆ˜ ℭ⦇Obj⦈"
  unfolding the_cf_parallel_components
  by (intro vrange_VLambda_vsubset)
    (simp_all add: cat_parallel_π”žπ”Ÿ cf_parallel_π”ž' cf_parallel_π”Ÿ')


subsubsectionβ€ΉArrow mapβ€Ί

mk_VLambda the_cf_parallel_components(2)
  |vsv the_cf_parallel_ArrMap_vsv[cat_parallel_cs_intros]|
  |vdomain the_cf_parallel_ArrMap_vdomain[cat_parallel_cs_simps]|
  |app the_cf_parallel_ArrMap_app|

lemma (in cf_parallel) the_cf_parallel_ArrMap_app_F[cat_parallel_cs_simps]:
  assumes "f ∈∘ F"
  shows "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈ = F'⦇f⦈"
proof-
  from assms have "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
    by (cs_concl cs_shallow cs_intro: cat_parallel_cs_intros a_in_succ_xI)
  from assms this show ?thesis
    using cat_parallel_ineq 
    by (auto simp: the_cf_parallel_ArrMap_app cat_parallel_cs_simps)
qed

lemmas [cat_parallel_cs_simps] = cf_parallel.the_cf_parallel_ArrMap_app_F

lemma (in cf_parallel) the_cf_parallel_ArrMap_app_π”ž[cat_parallel_cs_simps]:
  assumes "f = π”ž"
  shows "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈ = ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈"
proof-
  from assms have "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
    by (cs_concl cs_intro: cat_parallel_cs_intros a_in_succ_xI)
  from this show ?thesis
    using cat_parallel_ineq
    by (elim the_cat_parallel_ArrE; simp only: assms) 
      (auto simp: the_cf_parallel_ArrMap_app)
qed

lemmas [cat_parallel_cs_simps] = cf_parallel.the_cf_parallel_ArrMap_app_π”ž

lemma (in cf_parallel) the_cf_parallel_ArrMap_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "f = π”Ÿ"
  shows "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈ = ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈"
proof-
  from assms have "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
    by (cs_concl cs_intro: cat_parallel_cs_intros a_in_succ_xI)
  from this show ?thesis
    using cat_parallel_ineq
    by (elim the_cat_parallel_ArrE; simp only: assms) 
      (auto simp: the_cf_parallel_ArrMap_app)
qed

lemmas [cat_parallel_cs_simps] = cf_parallel.the_cf_parallel_ArrMap_app_π”Ÿ

lemma (in cf_parallel) the_cf_parallel_ArrMap_vrange:
  "β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈) = (F' `∘ F) βˆͺ∘ set {ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈, ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈}"
  (is β€Ήβ„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈) = ?FF βˆͺ∘ ?CIDβ€Ί)
proof(intro vsubset_antisym)

  show "β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈) βŠ†βˆ˜ ?FF βˆͺ∘ ?CID"
  proof
    (
      intro vsv.vsv_vrange_vsubset the_cf_parallel_ArrMap_vsv, 
      unfold the_cf_parallel_ArrMap_vdomain
    )
    fix f assume prems: "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
    from prems show "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈ ∈∘ ?FF βˆͺ∘ ?CID"
      by (elim the_cat_parallel_ArrE; (simp only:)?)
        (
          cs_concl  
            cs_simp: vinsert_set_insert_eq cat_parallel_cs_simps 
            cs_intro: vsv.vsv_vimageI1 V_cs_intros
        )
  qed

  show "?FF βˆͺ∘ ?CID βŠ†βˆ˜ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
  proof(rule vsubsetI)
    fix f assume prems: "f ∈∘ F' `∘ F βˆͺ∘ set {ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈, ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈}"
    then consider β€Ήf ∈∘ F' `∘ Fβ€Ί | β€Ήf = ℭ⦇CIdβ¦ˆβ¦‡π”ž'β¦ˆβ€Ί | β€Ήf = ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'β¦ˆβ€Ί by auto
    then show "f ∈∘ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
    proof cases
      assume "f ∈∘ F' `∘ F"
      then obtain 𝔣 where 𝔣: "𝔣 ∈∘ F" and f_def: "f = F'β¦‡π”£β¦ˆ" by auto
      from 𝔣 have f_def': "f = ⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡π”£β¦ˆ"
        unfolding f_def by (cs_concl cs_simp: cat_parallel_cs_simps)
      from 𝔣 have "𝔣 ∈∘ π’Ÿβˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
        by 
          (
            cs_concl cs_shallow
              cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros
          )
      then show "f ∈∘ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
        unfolding f_def' 
        by (auto simp: cat_parallel_cs_intros intro: vsv.vsv_vimageI2)
    next
      assume prems: "f = ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈"
      have f_def': "f = ⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡π”žβ¦ˆ"
        by (cs_concl cs_simp: cat_parallel_cs_simps prems)
      have "π”ž ∈∘ π’Ÿβˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
        by 
          (
            cs_concl 
              cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros
          )
      then show "f ∈∘ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
        unfolding f_def'
        by (auto simp: cat_parallel_cs_intros intro: vsv.vsv_vimageI2)
    next
      assume prems: "f = ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈"
      have f_def': "f = ⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡π”Ÿβ¦ˆ"
        by (cs_concl cs_shallow cs_simp: V_cs_simps cat_parallel_cs_simps prems)
      have "π”Ÿ ∈∘ π’Ÿβˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
        by 
          (
            cs_concl 
              cs_simp: cat_parallel_cs_simps cs_intro: cat_parallel_cs_intros
          )
      then show "f ∈∘ β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)"
        unfolding f_def'
        by (auto simp: cat_parallel_cs_intros intro: vsv.vsv_vimageI2)
    qed
  qed

qed

lemma (in cf_parallel) the_cf_parallel_ArrMap_vrange_vsubset_Arr:
  "β„›βˆ˜ (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈) βŠ†βˆ˜ ℭ⦇Arr⦈"
proof(intro vsv.vsv_vrange_vsubset, unfold cat_parallel_cs_simps)
  show "vsv (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈)" 
    by (cs_intro_step cat_parallel_cs_intros)
  fix f assume "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
  then show "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈ ∈∘ ℭ⦇Arr⦈"
    by (elim the_cat_parallel_ArrE)
      (
        cs_concl 
          cs_simp: cat_parallel_cs_simps  
          cs_intro: cat_cs_intros cat_parallel_cs_intros 
      )+
qed


subsubsectionβ€ΉParallel functor is a functorβ€Ί

lemma (in cf_parallel) cf_parallel_the_cf_parallel_is_tm_functor:
  "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F' : ⇑C π”ž π”Ÿ F ↦↦C.tmβ‡˜Ξ±β‡™ β„­"
proof(intro is_tm_functorI' is_functorI')

  interpret tcp: tiny_category Ξ± ‹⇑C π”ž π”Ÿ Fβ€Ί 
    by (rule tiny_category_the_cat_parallel)

  show "vfsequence (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F')" 
    unfolding the_cf_parallel_def by auto
  show "vcard (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F') = 4β„•"
    unfolding the_cf_parallel_def by (simp add: nat_omega_simps)
  show "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈ :
    ⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMapβ¦ˆβ¦‡a⦈ β†¦β‡˜β„­β‡™
    ⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMapβ¦ˆβ¦‡b⦈"
    if "f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b" for a b f
    using that
    by (cases rule: the_cat_parallel_is_arrE; simp only:)
      (
        cs_concl 
          cs_simp: cat_parallel_cs_simps
          cs_intro: cat_cs_intros cat_parallel_cs_intros
      )+

  show
    "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡g ∘Aβ‡˜β‡‘C π”ž π”Ÿ F⇙ f⦈ =
      ⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡g⦈ ∘Aβ‡˜β„­β‡™
      ⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈"
    if "g : b β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ c" and "f : a β†¦β‡˜β‡‘C π”ž π”Ÿ F⇙ b" for b c g a f
    using that
    by (elim the_cat_parallel_is_arrE) (*very slow*)
      (
        allβ€Ήsimp only:β€Ί, 
        allβ€Ή
          solvesβ€Ήsimp add: cat_parallel_ineq cat_parallel_π”žπ”Ÿ[symmetric]β€Ί | 
          cs_concl 
            cs_simp: cat_cs_simps cat_parallel_cs_simps 
            cs_intro: cat_cs_intros cat_parallel_cs_intros
          β€Ί
      )

  show 
    "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡β‡‘C π”ž π”Ÿ F⦇CIdβ¦ˆβ¦‡c⦈⦈ =
      ℭ⦇CIdβ¦ˆβ¦‡β‡‘β†’β‡‘CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMapβ¦ˆβ¦‡c⦈⦈"
    if "c ∈∘ ⇑C π”ž π”Ÿ F⦇Obj⦈" for c
    using that
    by (elim the_cat_parallel_ObjE; simp only:)
      (cs_concl cs_simp: cat_parallel_cs_simps)+

  show "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈ ∈∘ Vset Ξ±"
  proof
    (
      rule vbrelation.vbrelation_Limit_in_VsetI,
      unfold 
        the_cf_parallel_ObjMap_vdomain 
        the_cf_parallel_ObjMap_vrange 
        the_cat_parallel_components(1);
      (intro Limit_vdoubleton_in_VsetI)?
    )
    show "π”ž ∈∘ Vset Ξ±" "π”Ÿ ∈∘ Vset Ξ±" "π”ž' ∈∘ Vset Ξ±" "π”Ÿ' ∈∘ Vset Ξ±"
      by (cs_concl cs_intro: cat_cs_intros cat_parallel_cs_intros)+
  qed (use the_cf_parallel_ObjMap_vsv in blast)+

  show "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈ ∈∘ Vset Ξ±"
  proof
    (
      rule vbrelation.vbrelation_Limit_in_VsetI,
      unfold 
        the_cf_parallel_ArrMap_vdomain 
        the_cf_parallel_ArrMap_vrange 
        the_cat_parallel_components(1);
      (intro tcp.tiny_cat_Arr_in_Vset vunion_in_VsetI Limit_vdoubleton_in_VsetI)?
    )
    show "ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈ ∈∘ Vset Ξ±" "ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈ ∈∘ Vset Ξ±"
      by (cs_concl cs_intro: cat_cs_intros cat_parallel_cs_intros)+
    from cf_parallel_F' have "F' `∘ F βŠ†βˆ˜ Hom β„­ π”ž' π”Ÿ'"
      by (simp add: F'.vsv_vimage_vsubsetI)
    moreover have "Hom β„­ π”ž' π”Ÿ' ∈∘ Vset Ξ±"
      by (auto simp: cat_Hom_in_Vset cf_parallel_π”ž' cf_parallel_π”Ÿ')
    ultimately show "F' `∘ F ∈∘ Vset α" by auto
  qed (use the_cf_parallel_ArrMap_vsv in blast)+

qed
  (
    cs_concl 
      cs_simp: cat_parallel_cs_simps 
      cs_intro: 
        the_cf_parallel_ObjMap_vrange_vsubset_Obj 
        cat_parallel_cs_intros cat_cs_intros cat_small_cs_intros
  )+

lemma (in cf_parallel) cf_parallel_the_cf_parallel_is_tm_functor':
  assumes "𝔄' = ⇑C π”ž π”Ÿ F" and "β„­' = β„­"
  shows "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F' : 𝔄' ↦↦C.tmβ‡˜Ξ±β‡™ β„­'"
  unfolding assms by (rule cf_parallel_the_cf_parallel_is_tm_functor)

lemmas [cat_parallel_cs_intros] =
  cf_parallel.cf_parallel_the_cf_parallel_is_tm_functor'


subsubsectionβ€ΉOpposite parallel functorβ€Ί

lemma (in cf_parallel) cf_parallel_the_cf_parallel_op[cat_op_simps]:
  "op_cf (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F') = ⇑→⇑CF (op_cat β„­) π”Ÿ π”ž F π”Ÿ' π”ž' F'"
proof-
  interpret ↑: is_tm_functor Ξ± ‹⇑C π”ž π”Ÿ Fβ€Ί β„­ ‹⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'β€Ί
    by (rule cf_parallel_the_cf_parallel_is_tm_functor)
  show ?thesis
  proof
    (
      rule cf_eqI[of Ξ± ‹⇑C π”Ÿ π”ž Fβ€Ί β€Ήop_cat β„­β€Ί _ ‹⇑C π”Ÿ π”ž Fβ€Ί β€Ήop_cat β„­β€Ί], 
      unfold cat_op_simps
    )
    show "op_cf (⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F') : ⇑C π”Ÿ π”ž F ↦↦Cβ‡˜Ξ±β‡™ op_cat β„­"
      by (cs_concl cs_shallow cs_simp: cat_op_simps cs_intro: cat_op_intros)
    show "⇑→⇑CF (op_cat β„­) π”Ÿ π”ž F π”Ÿ' π”ž' F' : ⇑C π”Ÿ π”ž F ↦↦Cβ‡˜Ξ±β‡™ op_cat β„­"
      by 
        (
          cs_concl 
            cs_intro: cat_op_intros cat_small_cs_intros cat_parallel_cs_intros
        )
    show
      "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMap⦈ =
        ⇑→⇑CF (op_cat β„­) π”Ÿ π”ž F π”Ÿ' π”ž' F'⦇ObjMap⦈"
    proof
      (
        rule vsv_eqI;
        (intro cat_parallel_cs_intros)?;
        unfold cat_parallel_cs_simps
      )
      fix a assume "a ∈∘ ⇑C π”ž π”Ÿ F⦇Obj⦈"
      then consider β€Ήa = π”žβ€Ί | β€Ήa = π”Ÿβ€Ί by (elim the_cat_parallel_ObjE) simp
      then show
        "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ObjMapβ¦ˆβ¦‡a⦈ =
          ⇑→⇑CF (op_cat β„­) π”Ÿ π”ž F π”Ÿ' π”ž' F'⦇ObjMapβ¦ˆβ¦‡a⦈"
        by cases
          (
            cs_concl 
              cs_simp: cat_parallel_cs_simps
              cs_intro: cat_parallel_cs_intros cat_op_intros
          )
    qed (auto simp: the_cat_parallel_components)
    show 
      "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMap⦈ =
        ⇑→⇑CF (op_cat β„­) π”Ÿ π”ž F π”Ÿ' π”ž' F'⦇ArrMap⦈"
    proof
      (
        rule vsv_eqI;
        (intro cat_parallel_cs_intros)?; 
        unfold cat_parallel_cs_simps
      )
      fix f assume "f ∈∘ ⇑C π”ž π”Ÿ F⦇Arr⦈"
      then consider β€Ήf = π”žβ€Ί | β€Ήf = π”Ÿβ€Ί | β€Ήf ∈∘ Fβ€Ί
        by (elim the_cat_parallel_ArrE) simp
      then show
        "⇑→⇑CF β„­ π”ž π”Ÿ F π”ž' π”Ÿ' F'⦇ArrMapβ¦ˆβ¦‡f⦈ =
          ⇑→⇑CF (op_cat β„­) π”Ÿ π”ž F π”Ÿ' π”ž' F'⦇ArrMapβ¦ˆβ¦‡f⦈"
        by cases
          (
            cs_concl 
              cs_simp: cat_parallel_cs_simps cat_op_simps 
              cs_intro: cat_parallel_cs_intros cat_op_intros
          )+
    qed (auto simp: the_cat_parallel_components)
  qed simp_all
qed

lemmas [cat_op_simps] = cf_parallel.cf_parallel_the_cf_parallel_op



subsectionβ€Ή
Background for the definition of a category with two parallel arrows 
between two objects
β€Ί


textβ€Ή
The case of two parallel arrows between two objects is treated explicitly 
because it is prevalent in applications.
β€Ί

definition 𝔀PL :: V where "𝔀PL = 0"
definition 𝔣PL :: V where "𝔣PL = 1β„•"

definition π”žPL2 :: V where "π”žPL2 = π”žPL (set {𝔀PL, 𝔣PL})"
definition π”ŸPL2 :: V where "π”ŸPL2 = π”ŸPL (set {𝔀PL, 𝔣PL})"

lemma cat_PL2_ineq:
  shows cat_PL2_π”žπ”Ÿ[cat_parallel_cs_intros]: "π”žPL2 β‰  π”ŸPL2"
    and cat_PL2_π”žπ”€[cat_parallel_cs_intros]: "π”žPL2 β‰  𝔀PL"
    and cat_PL2_π”žπ”£[cat_parallel_cs_intros]: "π”žPL2 β‰  𝔣PL"
    and cat_PL2_π”Ÿπ”€[cat_parallel_cs_intros]: "π”ŸPL2 β‰  𝔀PL"
    and cat_PL2_π”Ÿπ”£[cat_parallel_cs_intros]: "π”ŸPL2 β‰  𝔣PL"
    and cat_PL2_𝔀𝔣[cat_parallel_cs_intros]: "𝔀PL β‰  𝔣PL"
  unfolding π”žPL2_def π”ŸPL2_def 𝔀PL_def 𝔣PL_def π”žPL_def π”ŸPL_def 
  by (simp_all add: Set.doubleton_eq_iff one)
  
lemma (in 𝒡) 
  shows cat_PL2_π”ž[cat_parallel_cs_intros]: "π”žPL2 ∈∘ Vset Ξ±"
    and cat_PL2_π”Ÿ[cat_parallel_cs_intros]: "π”ŸPL2 ∈∘ Vset Ξ±"
    and cat_PL2_𝔀[cat_parallel_cs_intros]: "𝔀PL ∈∘ Vset Ξ±"
    and cat_PL2_𝔣[cat_parallel_cs_intros]: "𝔣PL ∈∘ Vset Ξ±"
  unfolding π”žPL_def π”ŸPL_def π”žPL2_def π”ŸPL2_def 𝔀PL_def 𝔣PL_def 
  by (simp_all add: Limit_vdoubleton_in_VsetI)



subsectionβ€Ή
Local assumptions for a category with two parallel arrows between two objects
β€Ί

locale cat_parallel_2 = 𝒡 Ξ± for Ξ± +  
  fixes π”ž π”Ÿ 𝔀 𝔣
  assumes cat_parallel_2_π”žπ”Ÿ[cat_parallel_cs_intros]: "π”ž β‰  π”Ÿ"
    and cat_parallel_2_π”žπ”€[cat_parallel_cs_intros]: "π”ž β‰  𝔀"
    and cat_parallel_2_π”žπ”£[cat_parallel_cs_intros]: "π”ž β‰  𝔣"
    and cat_parallel_2_π”Ÿπ”€[cat_parallel_cs_intros]: "π”Ÿ β‰  𝔀"
    and cat_parallel_2_π”Ÿπ”£[cat_parallel_cs_intros]: "π”Ÿ β‰  𝔣"
    and cat_parallel_2_𝔀𝔣[cat_parallel_cs_intros]: "𝔀 β‰  𝔣"
    and cat_parallel_2_π”ž_in_Vset[cat_parallel_cs_intros]: "π”ž ∈∘ Vset Ξ±"
    and cat_parallel_2_π”Ÿ_in_Vset[cat_parallel_cs_intros]: "π”Ÿ ∈∘ Vset Ξ±"
    and cat_parallel_2_𝔀_in_Vset[cat_parallel_cs_intros]: "𝔀 ∈∘ Vset Ξ±"
    and cat_parallel_2_𝔣_in_Vset[cat_parallel_cs_intros]: "𝔣 ∈∘ Vset Ξ±"

lemmas (in cat_parallel_2) cat_parallel_ineq =
  cat_parallel_2_π”žπ”Ÿ
  cat_parallel_2_π”žπ”€
  cat_parallel_2_π”žπ”£
  cat_parallel_2_π”Ÿπ”€
  cat_parallel_2_π”Ÿπ”£
  cat_parallel_2_𝔀𝔣


textβ€ΉRules.β€Ί

lemmas (in cat_parallel_2) [cat_parallel_cs_intros] = cat_parallel_2_axioms

mk_ide rf cat_parallel_2_def[unfolded cat_parallel_2_axioms_def]
  |intro cat_parallel_2I|
  |dest cat_parallel_2D[dest]|
  |elim cat_parallel_2E[elim]|

sublocale cat_parallel_2 βŠ† cat_parallel Ξ± π”ž π”Ÿ β€Ήset {𝔀, 𝔣}β€Ί
  by unfold_locales 
    (simp_all add: cat_parallel_cs_intros Limit_vdoubleton_in_VsetI)


textβ€ΉDuality.β€Ί

lemma (in cat_parallel_2) cat_parallel_op[cat_op_intros]: 
  "cat_parallel_2 Ξ± π”Ÿ π”ž 𝔣 𝔀"
  by (intro cat_parallel_2I) 
    (auto intro!: cat_parallel_cs_intros cat_parallel_ineq[symmetric])



subsection‹‹↑↑›: category with two parallel arrows between two objectsβ€Ί


subsubsectionβ€ΉDefinition and elementary propertiesβ€Ί


textβ€ΉSee Chapter I-2 and Chapter III-3 in citeβ€Ή"mac_lane_categories_2010"β€Ί.β€Ί

definition the_cat_parallel_2 :: "V β‡’ V β‡’ V β‡’ V β‡’ V" (‹↑↑Cβ€Ί)
  where "↑↑C π”ž π”Ÿ 𝔀 𝔣 = ⇑C π”ž π”Ÿ (set {𝔀, 𝔣})"


textβ€ΉComponents.β€Ί

lemma the_cat_parallel_2_components:
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Obj⦈ = set {π”ž, π”Ÿ}"
    and "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Arr⦈ = set {π”ž, π”Ÿ, 𝔀, 𝔣}"
  unfolding the_cat_parallel_2_def the_cat_parallel_components by auto


textβ€ΉElementary properties.β€Ί

lemma the_cat_parallel_2_commute: "↑↑C π”ž π”Ÿ 𝔀 𝔣 = ↑↑C π”ž π”Ÿ 𝔣 𝔀"
  unfolding the_cat_parallel_2_def by (simp add: insert_commute)

lemma cat_parallel_is_cat_parallel_2:
  assumes "cat_parallel Ξ± π”ž π”Ÿ (set {𝔀, 𝔣})" and "𝔀 β‰  𝔣"
  shows "cat_parallel_2 Ξ± π”ž π”Ÿ 𝔀 𝔣"
proof-
  interpret cat_parallel Ξ± π”ž π”Ÿ β€Ήset {𝔀, 𝔣}β€Ί by (rule assms(1))
  show ?thesis
    using cat_parallel_π”žF cat_parallel_π”ŸF cat_parallel_F_in_Vset assms
    by (intro cat_parallel_2I)
      (
        auto 
          dest: vdoubleton_in_VsetD 
          simp: cat_parallel_π”ž_in_Vset cat_parallel_π”Ÿ_in_Vset
     )
qed


subsubsectionβ€ΉObjectsβ€Ί

lemma the_cat_parallel_2_Obj_π”žI[cat_parallel_cs_intros]:
  assumes "a = π”ž"
  shows "a ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Obj⦈"
  unfolding the_cat_parallel_2_def
  by (cs_concl cs_simp: assms cs_intro: cat_parallel_cs_intros)

lemma the_cat_parallel_2_Obj_π”ŸI[cat_parallel_cs_intros]:
  assumes "a = π”Ÿ"
  shows "a ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Obj⦈"
  unfolding the_cat_parallel_2_def
  by (cs_concl cs_shallow cs_simp: assms cs_intro: cat_parallel_cs_intros)

lemma the_cat_parallel_2_ObjE:
  assumes "a ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Obj⦈"
  obtains "a = π”ž" | "a = π”Ÿ" 
  using assms unfolding the_cat_parallel_2_def by (elim the_cat_parallel_ObjE)


subsubsectionβ€ΉArrowsβ€Ί

lemma the_cat_parallel_2_Arr_π”žI[cat_parallel_cs_intros]:
  assumes "f = π”ž"  
  shows "f ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Arr⦈"
  using assms unfolding the_cat_parallel_2_def by (intro the_cat_parallel_Arr_π”žI)

lemma the_cat_parallel_2_Arr_π”ŸI[cat_parallel_cs_intros]:
  assumes "f = π”Ÿ"  
  shows "f ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Arr⦈"
  using assms unfolding the_cat_parallel_2_def by (intro the_cat_parallel_Arr_π”ŸI)

lemma the_cat_parallel_2_Arr_𝔀I[cat_parallel_cs_intros]:
  assumes "f = 𝔀"
  shows "f ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Arr⦈"
  unfolding assms(1) the_cat_parallel_2_def
  by (cs_concl cs_simp: V_cs_simps cs_intro: V_cs_intros cat_parallel_cs_intros)

lemma the_cat_parallel_2_Arr_𝔣I[cat_parallel_cs_intros]:
  assumes "f = 𝔣"
  shows "f ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Arr⦈"
  unfolding assms(1) the_cat_parallel_2_def
  by 
    (
      cs_concl cs_shallow 
        cs_simp: V_cs_simps cs_intro: V_cs_intros cat_parallel_cs_intros
    )

lemma the_cat_parallel_2_ArrE:
  assumes "f ∈∘ ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Arr⦈"
  obtains "f = π”ž" | "f = π”Ÿ" | "f = 𝔀" | "f = 𝔣"
  using assms that 
  unfolding the_cat_parallel_2_def
  by (auto elim!: the_cat_parallel_ArrE)


subsubsectionβ€ΉDomainβ€Ί

lemma the_cat_parallel_2_Dom_vsv[cat_parallel_cs_intros]: "vsv (↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Dom⦈)"
  unfolding the_cat_parallel_2_def by (rule the_cat_parallel_Dom_vsv)

lemma the_cat_parallel_2_Dom_vdomain[cat_parallel_cs_simps]: 
  "π’Ÿβˆ˜ (↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Dom⦈) = set {π”ž, π”Ÿ, 𝔀, 𝔣}"
  unfolding the_cat_parallel_2_def the_cat_parallel_Dom_vdomain by auto

lemma (in cat_parallel_2) the_cat_parallel_2_Dom_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "f = π”Ÿ"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Domβ¦ˆβ¦‡f⦈ = π”Ÿ"
  using assms 
  unfolding the_cat_parallel_2_def 
  by (simp add: the_cat_parallel_Dom_app_π”Ÿ)

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Dom_app_π”Ÿ

lemma (in cat_parallel_2) the_cat_parallel_2_Dom_app_𝔀[cat_parallel_cs_simps]:
  assumes "f = 𝔀"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Domβ¦ˆβ¦‡f⦈ = π”ž"
  using assms
  unfolding the_cat_parallel_2_def
  by (intro the_cat_parallel_Dom_app_F) simp

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Dom_app_𝔀

lemma (in cat_parallel_2) the_cat_parallel_2_Dom_app_𝔣[cat_parallel_cs_simps]:
  assumes "f = 𝔣"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Domβ¦ˆβ¦‡f⦈ = π”ž"
  using assms
  unfolding the_cat_parallel_2_def
  by (intro the_cat_parallel_Dom_app_F) simp

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Dom_app_𝔣

lemma (in cat_parallel_2) the_cat_parallel_2_Dom_app_π”ž[cat_parallel_cs_simps]:
  assumes "f = π”ž"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Domβ¦ˆβ¦‡f⦈ = π”ž"
  using assms 
  unfolding the_cat_parallel_2_def 
  by (simp add: the_cat_parallel_Dom_app_π”ž)

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Dom_app_π”ž


subsubsectionβ€ΉCodomainβ€Ί

lemma the_cat_parallel_2_Cod_vsv[cat_parallel_cs_intros]: "vsv (↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Cod⦈)"
  unfolding the_cat_parallel_2_def by (rule the_cat_parallel_Cod_vsv)

lemma the_cat_parallel_2_Cod_vdomain[cat_parallel_cs_simps]: 
  "π’Ÿβˆ˜ (↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Cod⦈) = set {π”ž, π”Ÿ, 𝔀, 𝔣}"
  unfolding the_cat_parallel_2_def the_cat_parallel_Cod_vdomain by auto

lemma (in cat_parallel_2) the_cat_parallel_2_Cod_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "f = π”Ÿ"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Codβ¦ˆβ¦‡f⦈ = π”Ÿ"
  using assms 
  unfolding the_cat_parallel_2_def 
  by (simp add: the_cat_parallel_Cod_app_π”Ÿ)

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Cod_app_π”Ÿ

lemma (in cat_parallel_2) the_cat_parallel_2_Cod_app_𝔀[cat_parallel_cs_simps]:
  assumes "f = 𝔀"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Codβ¦ˆβ¦‡f⦈ = π”Ÿ"
  using assms
  unfolding the_cat_parallel_2_def
  by (intro the_cat_parallel_Cod_app_F) simp

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Cod_app_𝔀

lemma (in cat_parallel_2) the_cat_parallel_2_Cod_app_𝔣[cat_parallel_cs_simps]:
  assumes "f = 𝔣"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Codβ¦ˆβ¦‡f⦈ = π”Ÿ"
  using assms
  unfolding the_cat_parallel_2_def
  by (intro the_cat_parallel_Cod_app_F) simp

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Cod_app_𝔣

lemma (in cat_parallel_2) the_cat_parallel_2_Cod_app_π”ž[cat_parallel_cs_simps]:
  assumes "f = π”ž"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Codβ¦ˆβ¦‡f⦈ = π”ž"
  using assms 
  unfolding the_cat_parallel_2_def 
  by (simp add: the_cat_parallel_Cod_app_π”ž)

lemmas [cat_parallel_cs_simps] = cat_parallel_2.the_cat_parallel_2_Cod_app_π”ž


subsubsectionβ€ΉCompositionβ€Ί

lemma the_cat_parallel_2_Comp_vsv[cat_parallel_cs_intros]:
  "vsv (↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Comp⦈)"
  unfolding the_cat_parallel_2_def by (rule the_cat_parallel_Comp_vsv)

lemma the_cat_parallel_2_Comp_app_π”Ÿπ”Ÿ[cat_parallel_cs_simps]:
  assumes "g = π”Ÿ" and "f = π”Ÿ"
  shows "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = g" "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = f"
proof-
  note gf = the_cat_parallel_Comp_app_π”Ÿπ”Ÿ[OF assms, where F=β€Ήset {𝔀, 𝔣}β€Ί]
  show "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = g" "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = f"
    unfolding the_cat_parallel_2_def 
    subgoal unfolding gf(1) by simp
    subgoal unfolding gf(2) by simp
    done
qed

lemma the_cat_parallel_2_Comp_app_π”žπ”ž[cat_parallel_cs_simps]:
  assumes "g = π”ž" and "f = π”ž"
  shows "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = g" "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = f"
proof-
  note gf = the_cat_parallel_Comp_app_π”žπ”ž[OF assms, where F=β€Ήset {𝔀, 𝔣}β€Ί]
  show "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = g" "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = f"
    unfolding the_cat_parallel_2_def 
    subgoal unfolding gf(1) by simp
    subgoal unfolding gf(2) by simp
    done
qed

lemma the_cat_parallel_2_Comp_app_π”Ÿπ”€[cat_parallel_cs_simps]:
  assumes "g = π”Ÿ" and "f = 𝔀"
  shows "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = f"
  unfolding 
    the_cat_parallel_2_def assms
    the_cat_parallel_Comp_app_π”ŸF[
      where F=β€Ήset {𝔀, 𝔣}β€Ί, OF assms(1), of 𝔀, unfolded assms, simplified
      ]
  by simp

lemma the_cat_parallel_2_Comp_app_π”Ÿπ”£[cat_parallel_cs_simps]:
  assumes "g = π”Ÿ" and "f = 𝔣"
  shows "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = f" 
  unfolding 
    the_cat_parallel_2_def assms
    the_cat_parallel_Comp_app_π”ŸF[
      where F=β€Ήset {𝔀, 𝔣}β€Ί, OF assms(1), of 𝔣, unfolded assms, simplified
      ]
  by simp

lemma (in cat_parallel_2) the_cat_parallel_2_Comp_app_π”€π”ž[cat_parallel_cs_simps]:
  assumes "g = 𝔀" and "f = π”ž"
  shows "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = g" 
  unfolding 
    the_cat_parallel_2_def assms
    the_cat_parallel_Comp_app_Fπ”ž[
      of 𝔀, OF _ assms(2), unfolded assms, simplified
      ]
  by simp

lemma (in cat_parallel_2) the_cat_parallel_2_Comp_app_π”£π”ž[cat_parallel_cs_simps]:
  assumes "g = 𝔣" and "f = π”ž"
  shows "g ∘Aβ‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ f = g" 
  unfolding 
    the_cat_parallel_2_def assms
    the_cat_parallel_Comp_app_Fπ”ž[
      of 𝔣, OF _ assms(2), unfolded assms, simplified
      ]
  by simp


subsubsectionβ€ΉIdentityβ€Ί

lemma the_cat_parallel_2_CId_vsv[cat_parallel_cs_intros]: "vsv (↑↑C π”ž π”Ÿ 𝔀 𝔣⦇CId⦈)"
  unfolding the_cat_parallel_2_def by (rule the_cat_parallel_CId_vsv)

lemma the_cat_parallel_2_CId_vdomain[cat_parallel_cs_simps]:
  "π’Ÿβˆ˜ (↑↑C π”ž π”Ÿ 𝔀 𝔣⦇CId⦈) = set {π”ž, π”Ÿ}"
  unfolding the_cat_parallel_2_def by (rule the_cat_parallel_CId_vdomain)
  
lemma the_cat_parallel_2_CId_app_π”ž[cat_parallel_cs_simps]: 
  assumes "a = π”ž"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇CIdβ¦ˆβ¦‡a⦈ = π”ž"
  unfolding assms the_cat_parallel_2_def
  by (simp add: the_cat_parallel_CId_app_π”ž)

lemma the_cat_parallel_2_CId_app_π”Ÿ[cat_parallel_cs_simps]: 
  assumes "a = π”Ÿ"
  shows "↑↑C π”ž π”Ÿ 𝔀 𝔣⦇CIdβ¦ˆβ¦‡a⦈ = π”Ÿ"
  unfolding assms the_cat_parallel_2_def
  by (simp add: the_cat_parallel_CId_app_π”Ÿ)


subsubsectionβ€ΉArrow with a domain and a codomainβ€Ί

lemma (in cat_parallel_2) the_cat_parallel_2_is_arr_π”žπ”žπ”ž[cat_parallel_cs_intros]:
  assumes "a' = π”ž" and "b' = π”ž" and "f = π”ž"
  shows "f : a' β†¦β‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ b'"
  unfolding assms the_cat_parallel_2_def
  by (simp add: the_cat_parallel_is_arr_π”žπ”žπ”ž)

lemma (in cat_parallel_2) the_cat_parallel_2_is_arr_π”Ÿπ”Ÿπ”Ÿ[cat_parallel_cs_intros]:
  assumes "a' = π”Ÿ" and "b' = π”Ÿ" and "f = π”Ÿ"
  shows "f : a' β†¦β‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ b'"
  unfolding assms the_cat_parallel_2_def
  by (simp add: the_cat_parallel_is_arr_π”Ÿπ”Ÿπ”Ÿ)

lemma (in cat_parallel_2) the_cat_parallel_2_is_arr_π”žπ”Ÿπ”€[cat_parallel_cs_intros]:
  assumes "a' = π”ž" and "b' = π”Ÿ" and "f = 𝔀"
  shows "f : a' β†¦β‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ b'"
  unfolding assms the_cat_parallel_2_def
  by 
    (
      rule the_cat_parallel_is_arr_π”žπ”ŸF[
        OF assms(1,2), of 𝔀, unfolded assms, simplified
        ]
    )

lemma (in cat_parallel_2) the_cat_parallel_2_is_arr_π”žπ”Ÿπ”£[cat_parallel_cs_intros]:
  assumes "a' = π”ž" and "b' = π”Ÿ" and "f = 𝔣"
  shows "f : a' β†¦β‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ b'"
  unfolding assms the_cat_parallel_2_def
  by 
    (
      rule the_cat_parallel_is_arr_π”žπ”ŸF[
        OF assms(1,2), of 𝔣, unfolded assms, simplified
        ]
    )

lemma (in cat_parallel_2) the_cat_parallel_2_is_arrE:
  assumes "f' : a' β†¦β‡˜β†‘β†‘C π”ž π”Ÿ 𝔀 𝔣⇙ b'"
  obtains "a' = π”ž" and "b' = π”ž" and "f' = π”ž"
        | "a' = π”Ÿ" and "b' = π”Ÿ" and "f' = π”Ÿ"
        | "a' = π”ž" and "b' = π”Ÿ" and "f' = 𝔀"
        | "a' = π”ž" and "b' = π”Ÿ" and "f' = 𝔣"
  using assms 
  unfolding the_cat_parallel_2_def
  by (elim the_cat_parallel_is_arrE) auto


subsubsection‹‹↑↑› is a categoryβ€Ί

lemma (in cat_parallel_2) 
  finite_category_the_cat_parallel_2[cat_parallel_cs_intros]:
  "finite_category Ξ± (↑↑C π”ž π”Ÿ 𝔀 𝔣)"
proof(intro finite_categoryI'' )
  show "tiny_category Ξ± (↑↑C π”ž π”Ÿ 𝔀 𝔣)"
    unfolding the_cat_parallel_2_def by (rule tiny_category_the_cat_parallel)
qed (auto simp: the_cat_parallel_2_components)

lemmas [cat_parallel_cs_intros] = 
  cat_parallel_2.finite_category_the_cat_parallel_2


subsubsectionβ€ΉOpposite parallel categoryβ€Ί

lemma (in cat_parallel_2) op_cat_the_cat_parallel_2[cat_op_simps]: 
  "op_cat (↑↑C π”ž π”Ÿ 𝔀 𝔣) = ↑↑C π”Ÿ π”ž 𝔣 𝔀"
  unfolding the_cat_parallel_2_def cat_op_simps by (metis doubleton_eq_iff)

lemmas [cat_op_simps] = cat_parallel_2.op_cat_the_cat_parallel_2



subsectionβ€Ή
Parallel functor for a category with two parallel arrows between two objects
β€Ί

locale cf_parallel_2 = cat_parallel_2 Ξ± π”ž π”Ÿ 𝔀 𝔣 + category Ξ± β„­ 
  for Ξ± π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣' β„­ :: V +
  assumes cf_parallel_𝔀'[cat_parallel_cs_intros]: "𝔀' : π”ž' β†¦β‡˜β„­β‡™ π”Ÿ'"
    and cf_parallel_𝔣'[cat_parallel_cs_intros]: "𝔣' : π”ž' β†¦β‡˜β„­β‡™ π”Ÿ'"

sublocale cf_parallel_2 βŠ† 
  cf_parallel Ξ± π”ž π”Ÿ β€Ήset {𝔀, 𝔣}β€Ί π”ž' π”Ÿ' β€ΉΞ»f∈∘set {𝔀, 𝔣}. (f = 𝔣 ? 𝔣' : 𝔀')β€Ί β„­
  by unfold_locales (auto intro: cat_parallel_cs_intros cat_cs_intros)

lemma (in cf_parallel_2) cf_parallel_2_𝔀''[cat_parallel_cs_intros]:
  assumes "a = π”ž'" and "b = π”Ÿ'"
  shows "𝔀' : a β†¦β‡˜β„­β‡™ b"
  unfolding assms by (rule cf_parallel_𝔀')

lemma (in cf_parallel_2) cf_parallel_2_𝔀'''[cat_parallel_cs_intros]:
  assumes "g = 𝔀'" and "b = π”Ÿ'"
  shows "g : π”ž' β†¦β‡˜β„­β‡™ b"
  unfolding assms by (rule cf_parallel_𝔀')

lemma (in cf_parallel_2) cf_parallel_2_𝔀''''[cat_parallel_cs_intros]:
  assumes "g = 𝔀'" and "a = π”ž'"
  shows "g : a β†¦β‡˜β„­β‡™ π”Ÿ'"
  unfolding assms by (rule cf_parallel_𝔀')

lemma (in cf_parallel_2) cf_parallel_2_𝔣''[cat_parallel_cs_intros]:
  assumes "a = π”ž'" and "b = π”Ÿ'"
  shows "𝔣' : a β†¦β‡˜β„­β‡™ b"
  unfolding assms by (rule cf_parallel_𝔣') 

lemma (in cf_parallel_2) cf_parallel_2_𝔣'''[cat_parallel_cs_intros]:
  assumes "f = 𝔣'" and "b = π”Ÿ'"
  shows "f : π”ž' β†¦β‡˜β„­β‡™ b"
  unfolding assms by (rule cf_parallel_𝔣')

lemma (in cf_parallel_2) cf_parallel_2_𝔣''''[cat_parallel_cs_intros]:
  assumes "f = 𝔣'" and "a = π”ž'"
  shows "f : a β†¦β‡˜β„­β‡™ π”Ÿ'"
  unfolding assms by (rule cf_parallel_𝔣') 


textβ€ΉRules.β€Ί

lemma (in cf_parallel_2) cf_parallel_axioms'[cat_parallel_cs_intros]:
  assumes "Ξ±' = Ξ±" 
    and "a = π”ž" 
    and "b = π”Ÿ" 
    and "g = 𝔀" 
    and "f = 𝔣" 
    and "a' = π”ž'" 
    and "b' = π”Ÿ'" 
    and "g' = 𝔀'" 
    and "f' = 𝔣'" 
  shows "cf_parallel_2 Ξ±' a b g f a' b' g' f' β„­"
  unfolding assms by (rule cf_parallel_2_axioms)

mk_ide rf cf_parallel_2_def[unfolded cf_parallel_2_axioms_def]
  |intro cf_parallel_2I|
  |dest cf_parallel_2D[dest]|
  |elim cf_parallel_2E[elim]|

lemmas [cat_parallel_cs_intros] = cf_parallelD(1,2)


textβ€ΉDuality.β€Ί

lemma (in cf_parallel_2) cf_parallel_2_op[cat_op_intros]: 
  "cf_parallel_2 Ξ± π”Ÿ π”ž 𝔣 𝔀 π”Ÿ' π”ž' 𝔣' 𝔀' (op_cat β„­)"
  by (intro cf_parallel_2I, unfold cat_op_simps)
    (cs_concl cs_intro: cat_parallel_cs_intros cat_cs_intros cat_op_intros)

lemmas [cat_op_intros] = cf_parallel.cf_parallel_op


subsubsectionβ€ΉDefinition and elementary propertiesβ€Ί

definition the_cf_parallel_2 :: "V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V β‡’ V" 
  (‹↑↑→↑↑CFβ€Ί)
  where "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣' =
    ⇑→⇑CF β„­ π”ž π”Ÿ (set {𝔀, 𝔣}) π”ž' π”Ÿ' (Ξ»f∈∘set {𝔀, 𝔣}. (f = 𝔣 ? 𝔣' : 𝔀'))"


textβ€ΉComponents.β€Ί

lemma the_cf_parallel_2_components:
  shows [cat_parallel_cs_simps]: 
      "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇HomDom⦈ = ↑↑C π”ž π”Ÿ 𝔀 𝔣"
    and [cat_parallel_cs_simps]: 
      "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇HomCod⦈ = β„­"
  unfolding 
    the_cf_parallel_2_def the_cat_parallel_2_def the_cf_parallel_components
  by simp_all


textβ€ΉElementary properties.β€Ί

lemma (in cf_parallel_2) cf_parallel_2_the_cf_parallel_2_commute:
  "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣' = ↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔣 𝔀 π”ž' π”Ÿ' 𝔣' 𝔀'"
  using cat_parallel_2_𝔀𝔣 
  unfolding the_cf_parallel_2_def insert_commute
  by (force simp: VLambda_vdoubleton)

lemma cf_parallel_is_cf_parallel_2:
  assumes 
    "cf_parallel Ξ± π”ž π”Ÿ (set {𝔀, 𝔣}) π”ž' π”Ÿ' (Ξ»f∈∘set {𝔀, 𝔣}. (f = 𝔣 ? 𝔣' : 𝔀')) β„­" 
    and "𝔀 β‰  𝔣"
  shows "cf_parallel_2 Ξ± π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣' β„­"
proof-
  interpret
    cf_parallel Ξ± π”ž π”Ÿ β€Ήset {𝔀, 𝔣}β€Ί π”ž' π”Ÿ' β€ΉΞ»f∈∘set {𝔀, 𝔣}. (f = 𝔣 ? 𝔣' : 𝔀')β€Ί β„­  
    by (rule assms(1))
  have 𝔀𝔣: "𝔀 ∈∘ set {𝔀, 𝔣}" "𝔣 ∈∘ set {𝔀, 𝔣}" by auto
  show ?thesis
    using cat_parallel_axioms assms(2) category_axioms 𝔀𝔣[THEN cf_parallel_F']
    by (intro cf_parallel_2I cat_parallel_is_cat_parallel_2) 
      (auto simp: assms(2))
qed


subsubsectionβ€ΉObject mapβ€Ί

lemma the_cf_parallel_2_ObjMap_vsv[cat_parallel_cs_intros]: 
  "vsv (↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ObjMap⦈)"
  unfolding the_cf_parallel_2_def by (intro cat_parallel_cs_intros)

lemma the_cf_parallel_2_ObjMap_vdomain[cat_parallel_cs_simps]: 
  "π’Ÿβˆ˜ (↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ObjMap⦈) = ↑↑C π”ž π”Ÿ 𝔀 𝔣⦇Obj⦈"
  unfolding the_cf_parallel_2_def
  by (cs_concl cs_shallow cs_simp: cat_parallel_cs_simps the_cat_parallel_2_def) 

lemma (in cf_parallel_2) the_cf_parallel_2_ObjMap_app_π”ž[cat_parallel_cs_simps]:
  assumes "x = π”ž"
  shows "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ObjMapβ¦ˆβ¦‡x⦈ = π”ž'"
  unfolding the_cf_parallel_2_def 
  by (cs_concl cs_simp: assms cat_parallel_cs_simps)

lemmas [cat_parallel_cs_simps] = cf_parallel_2.the_cf_parallel_2_ObjMap_app_π”ž

lemma (in cf_parallel_2) the_cf_parallel_2_ObjMap_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "x = π”Ÿ"
  shows "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ObjMapβ¦ˆβ¦‡x⦈ = π”Ÿ'"
  unfolding the_cf_parallel_2_def 
  by (cs_concl cs_shallow cs_simp: assms cat_parallel_cs_simps)

lemmas [cat_parallel_cs_simps] = cf_parallel_2.the_cf_parallel_2_ObjMap_app_π”Ÿ

lemma (in cf_parallel_2) the_cf_parallel_2_ObjMap_vrange:
  "β„›βˆ˜ (↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ObjMap⦈) = set {π”ž', π”Ÿ'}"
  unfolding the_cf_parallel_2_def by (rule the_cf_parallel_ObjMap_vrange)

lemma (in cf_parallel_2) the_cf_parallel_2_ObjMap_vrange_vsubset_Obj:
  "β„›βˆ˜ (↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ObjMap⦈) βŠ†βˆ˜ ℭ⦇Obj⦈"
  unfolding the_cf_parallel_2_def 
  by (rule the_cf_parallel_ObjMap_vrange_vsubset_Obj)


subsubsectionβ€ΉArrow mapβ€Ί

lemma (in cf_parallel_2) the_cf_parallel_2_ArrMap_app_𝔀[cat_parallel_cs_simps]:
  assumes "f = 𝔀"
  shows "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ArrMapβ¦ˆβ¦‡f⦈ = 𝔀'"
  unfolding the_cf_parallel_2_def assms
  by
    (
      cs_concl 
        cs_simp: V_cs_simps cat_parallel_cs_simps 
        cs_intro: V_cs_intros cat_parallel_cs_intros
    )

lemmas [cat_parallel_cs_simps] = cf_parallel_2.the_cf_parallel_2_ArrMap_app_𝔀

lemma (in cf_parallel_2) the_cf_parallel_2_ArrMap_app_𝔣[cat_parallel_cs_simps]:
  assumes "f = 𝔣"
  shows "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ArrMapβ¦ˆβ¦‡f⦈ = 𝔣'"
  unfolding the_cf_parallel_2_def assms
  by
    (
      cs_concl 
        cs_simp: V_cs_simps cat_parallel_cs_simps 
        cs_intro: V_cs_intros cat_parallel_cs_intros
    )

lemmas [cat_parallel_cs_simps] = cf_parallel_2.the_cf_parallel_2_ArrMap_app_𝔣

lemma (in cf_parallel_2) the_cf_parallel_2_ArrMap_app_π”ž[cat_parallel_cs_simps]:
  assumes "f = π”ž"
  shows "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ArrMapβ¦ˆβ¦‡f⦈ = ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈"
  unfolding the_cf_parallel_2_def assms
  by (cs_concl cs_simp: cat_parallel_cs_simps)

lemmas [cat_parallel_cs_simps] = cf_parallel_2.the_cf_parallel_2_ArrMap_app_π”ž

lemma (in cf_parallel_2) the_cf_parallel_2_ArrMap_app_π”Ÿ[cat_parallel_cs_simps]:
  assumes "f = π”Ÿ"
  shows "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ArrMapβ¦ˆβ¦‡f⦈ = ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈"
  unfolding the_cf_parallel_2_def assms
  by (cs_concl cs_shallow cs_simp: cat_parallel_cs_simps)

lemmas [cat_parallel_cs_simps] = cf_parallel_2.the_cf_parallel_2_ArrMap_app_π”Ÿ

lemma (in cf_parallel_2) the_cf_parallel_2_ArrMap_vrange:
  "β„›βˆ˜ (↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ArrMap⦈) = set {ℭ⦇CIdβ¦ˆβ¦‡π”ž'⦈, ℭ⦇CIdβ¦ˆβ¦‡π”Ÿ'⦈, 𝔣', 𝔀'}"
  unfolding the_cf_parallel_2_def the_cf_parallel_ArrMap_vrange
  using cat_parallel_2_𝔀𝔣 
  by (auto simp: app_vimage_iff VLambda_vdoubleton)

lemma (in cf_parallel_2) the_cf_parallel_2_ArrMap_vrange_vsubset_Arr:
  "β„›βˆ˜ (↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣'⦇ArrMap⦈) βŠ†βˆ˜ ℭ⦇Arr⦈"
  unfolding the_cf_parallel_2_def 
  by (rule the_cf_parallel_ArrMap_vrange_vsubset_Arr)


subsubsectionβ€Ή
Parallel functor for a category with two parallel arrows between 
two objects is a functor
β€Ί

lemma (in cf_parallel_2) cf_parallel_2_the_cf_parallel_2_is_tm_functor:
  "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣' : ↑↑C π”ž π”Ÿ 𝔀 𝔣 ↦↦C.tmβ‡˜Ξ±β‡™ β„­"
  unfolding the_cf_parallel_2_def the_cat_parallel_2_def
  by (rule cf_parallel_the_cf_parallel_is_tm_functor)

lemma (in cf_parallel_2) cf_parallel_2_the_cf_parallel_2_is_tm_functor':
  assumes "𝔄' = ↑↑C π”ž π”Ÿ 𝔀 𝔣" and "β„­' = β„­"
  shows "↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣' : 𝔄' ↦↦C.tmβ‡˜Ξ±β‡™ β„­'"
  unfolding assms by (rule cf_parallel_2_the_cf_parallel_2_is_tm_functor)

lemmas [cat_parallel_cs_intros] = 
  cf_parallel_2.cf_parallel_2_the_cf_parallel_2_is_tm_functor'


subsubsectionβ€Ή
Opposite parallel functor for a category with two parallel arrows between 
two objects
β€Ί

lemma (in cf_parallel_2) cf_parallel_2_the_cf_parallel_2_op[cat_op_simps]:
  "op_cf (↑↑→↑↑CF β„­ π”ž π”Ÿ 𝔀 𝔣 π”ž' π”Ÿ' 𝔀' 𝔣') = 
    ↑↑→↑↑CF (op_cat β„­) π”Ÿ π”ž 𝔣 𝔀 π”Ÿ' π”ž' 𝔣' 𝔀'"
  using cat_parallel_2_𝔀𝔣
  unfolding the_cf_parallel_2_def cf_parallel_the_cf_parallel_op
  by (auto simp: VLambda_vdoubleton insert_commute)

lemmas [cat_op_simps] = cf_parallel_2.cf_parallel_2_the_cf_parallel_2_op

textβ€Ή\newpageβ€Ί

end