Theory CZH_SMC_Semicategory

(* Copyright 2021 (C) Mihails Milehins *)

section‹Semicategory›
theory CZH_SMC_Semicategory
  imports 
    CZH_DG_Digraph
    CZH_SMC_Introduction
begin              



subsection‹Background›

lemmas [smc_cs_simps] = dg_shared_cs_simps
lemmas [smc_cs_intros] = dg_shared_cs_intros


subsubsection‹Slicing›


textSlicing› is a term that is introduced in this work for the description
of the process of the conversion of more specialized mathematical objects to 
their generalizations. 

The terminology was adapted from the informal imperative
object oriented programming, where the term slicing often refers to the
process of copying an object of a subclass type to an object of a 
superclass type cite"noauthor_wikipedia_2001"\footnote{
\url{https://en.wikipedia.org/wiki/Object_slicing}
}.
However, it is important to note that the term has other meanings in 
programming and computer science.
›

definition smc_dg :: "V  V"
  where "smc_dg  = [Obj, Arr, Dom, Cod]"


text‹Components.›

lemma smc_dg_components[slicing_simps]:
  shows "smc_dg Obj = Obj"
    and "smc_dg Arr = Arr"
    and "smc_dg Dom = Dom"
    and "smc_dg Cod = Cod"
  unfolding smc_dg_def dg_field_simps by (auto simp: nat_omega_simps)


text‹Regular definitions.›

lemma smc_dg_is_arr[slicing_simps]: "f : a smc_dg b  f : a b"
  unfolding is_arr_def slicing_simps ..

lemmas [slicing_intros] = smc_dg_is_arr[THEN iffD2]


subsubsection‹Composition and composable arrows›


text‹
The definition of a set of composable_arrs› is equivalent to the definition
of composable pairs› presented on page 10 in cite"mac_lane_categories_2010"
(see theorem dg_composable_arrs'› below). 
Nonetheless, the definition is meant to be used sparingly. Normally,
the arrows are meant to be specified explicitly using the predicate 
constis_arr.
›

definition Comp :: V
  where [dg_field_simps]: "Comp = 4"

abbreviation Comp_app :: "V  V  V  V" (infixl Aı› 55)
  where "Comp_app  a b  Compa, b"

definition composable_arrs :: "V  V"
  where "composable_arrs  = set 
    {[g, f] | g f. a b c. g : b c  f : a b}"

lemma small_composable_arrs[simp]:
  "small {[g, f] | g f. a b c. g : b c  f : a b}"
proof(intro down[of _ Arr ^× 2] subsetI)
  fix x assume "x  {[g, f] | g f. a b c. g : b c  f : a b}"
  then obtain g f a b c 
    where x_def: "x = [g, f]" and "g : b c"  and "f : a b"
    by clarsimp
  with vfsequence_vcpower_two_vpair show "x  Arr ^× 2"
    unfolding x_def by auto
qed


text‹Rules.›

lemma composable_arrsI[smc_cs_intros]:
  assumes "gf = [g, f]" and "g : b c" and "f : a b"
  shows "gf  composable_arrs "
  using assms(2,3) small_composable_arrs 
  unfolding assms(1) composable_arrs_def 
  by auto

lemma composable_arrsE[elim!]:
  assumes "gf  composable_arrs "
  obtains g f a b c where "gf = [g, f]" and "g : b c" and "f : a b"
  using assms small_composable_arrs unfolding composable_arrs_def by clarsimp

lemma small_composable_arrs'[simp]:
  "small {[g, f] | g f. g  Arr  f  Arr  Domg = Codf}"
proof(intro down[of _ Arr ^× 2] subsetI)
  fix gf assume 
    "gf {[g, f] | g f. g  Arr  f  Arr  Domg = Codf}"
  then obtain g f 
    where gf_def: "gf = [g, f]" 
      and "g  Arr" 
      and "f  Arr" 
      and "Domg = Codf"
    by clarsimp
  with vfsequence_vcpower_two_vpair show "gf  Arr ^× 2"
    unfolding gf_def by auto
qed

lemma dg_composable_arrs':
  "set {[g, f] | g f. g  Arr  f  Arr  Domg = Codf} = 
    composable_arrs "
proof-
  have "{[g, f] | g f. g  Arr  f  Arr  Domg = Codf} = 
    {[g, f] | g f. a b c. g : b c  f : a b}"
  proof(intro subset_antisym subsetI, unfold mem_Collect_eq; elim exE conjE)
    fix gf g f 
    assume gf_def: "gf = [g, f]" 
      and "g  Arr"
      and "f  Arr" 
      and gf: "Domg = Codf"
    then obtain a b b' c where g: "g : b' c" and f: "f : a b" 
      by (auto intro!: is_arrI)
    moreover have "b' = b"
      unfolding is_arrD(2,3)[OF g, symmetric] is_arrD(2,3)[OF f, symmetric]
      by (rule gf)
    ultimately have "a b c. g : b c  f : a b" by auto
    then show "g f. gf = [g, f]  (a b c. g : b c  f : a b)"
      unfolding gf_def by auto
  next
    fix gf g f a b c 
    assume gf_def: "gf = [g, f]" and "g : b c" and "f : a b"
    then have "g  Arr" "f  Arr" "Domg = Codf" by auto
    then show 
      "g f. gf = [g, f]  g  Arr  f  Arr  Domg = Codf"
      unfolding gf_def by auto
  qed
  then show ?thesis unfolding composable_arrs_def by auto
qed



subsection‹Definition and elementary properties›


text‹
The definition of a semicategory that is used in this work is
similar to the definition that was used in cite"mitchell_dominion_1972".
It is also a natural generalization of the definition of a category that is
presented in Chapter I-2 in cite"mac_lane_categories_2010". The generalization
is performed by omitting the identity and the axioms associated
with it. The amendments to the definitions that are associated with size 
have already been explained in the previous chapter.
›

locale semicategory = 𝒵 α + vfsequence  + Comp: vsv Comp for α  +
  assumes smc_length[smc_cs_simps]: "vcard  = 5"
    and smc_digraph[slicing_intros]: "digraph α (smc_dg )"
    and smc_Comp_vdomain: "gf  𝒟 (Comp) 
      (g f b c a. gf = [g, f]  g : b c  f : a b)"
    and smc_Comp_is_arr: 
      " g : b c; f : a b   g Af : a c"
    and smc_Comp_assoc[smc_cs_simps]:
      " h : c d; g : b c; f : a b  
        (h Ag) Af = h A(g Af)"

lemmas [smc_cs_simps] =
  semicategory.smc_length
  semicategory.smc_Comp_assoc

lemma (in semicategory) smc_Comp_is_arr'[smc_cs_intros]:
  assumes "g : b c"
    and "f : a b"
    and "ℭ' = "
  shows "g Af : a ℭ'c"
  using assms(1,2) unfolding assms(3) by (rule smc_Comp_is_arr)

lemmas [smc_cs_intros] = 
  semicategory.smc_Comp_is_arr'
  semicategory.smc_Comp_is_arr

lemmas [slicing_intros] = semicategory.smc_digraph


text‹Rules.›

lemma (in semicategory) semicategory_axioms'[smc_cs_intros]:
  assumes "α' = α"
  shows "semicategory α' "
  unfolding assms by (rule semicategory_axioms)

mk_ide rf semicategory_def[unfolded semicategory_axioms_def]
  |intro semicategoryI|
  |dest semicategoryD[dest]|
  |elim semicategoryE[elim]|

lemma semicategoryI':
  assumes "𝒵 α"
    and "vfsequence "
    and "vsv (Comp)"
    and "vcard  = 5"
    and "vsv (Dom)"
    and "vsv (Cod)"
    and "𝒟 (Dom) = Arr"
    and " (Dom)  Obj"
    and "𝒟 (Cod) = Arr"
    and " (Cod)  Obj"
    and "gf. gf  𝒟 (Comp) 
      (g f b c a. gf = [g, f]  g : b c  f : a b)"
    and "b c g a f.  g : b c; f : a b   g Af : a c"
    and "c d h b g a f.  h : c d; g : b c; f : a b  
        (h Ag) Af = h A(g Af)"
    and "Obj  Vset α"
    and "A B.  A  Obj; B  Obj; A  Vset α; B  Vset α  
      (aA. bB. Hom  a b)  Vset α"
  shows "semicategory α "
  by (intro semicategoryI digraphI, unfold slicing_simps)
    (simp_all add: assms  nat_omega_simps smc_dg_def)

lemma semicategoryD':
  assumes "semicategory α "
  shows "𝒵 α"
    and "vfsequence "
    and "vsv (Comp)"
    and "vcard  = 5"
    and "vsv (Dom)"
    and "vsv (Cod)"
    and "𝒟 (Dom) = Arr"
    and " (Dom)  Obj"
    and "𝒟 (Cod) = Arr"
    and " (Cod)  Obj"
    and "gf. gf  𝒟 (Comp) 
      (g f b c a. gf = [g, f]  g : b c  f : a b)"
    and "b c g a f.  g : b c; f : a b   g Af : a c"
    and "c d h b g a f.  h : c d; g : b c; f : a b  
        (h Ag) Af = h A(g Af)"
    and "Obj  Vset α"
    and "A B.  A  Obj; B  Obj; A  Vset α; B  Vset α  
      (aA. bB. Hom  a b)  Vset α"
  by 
    (
      simp_all add: 
        semicategoryD(2-8)[OF assms] 
        digraphD[OF semicategoryD(5)[OF assms], unfolded slicing_simps]
    )

lemma semicategoryE':
  assumes "semicategory α "
  obtains "𝒵 α"
    and "vfsequence "
    and "vsv (Comp)"
    and "vcard  = 5"
    and "vsv (Dom)"
    and "vsv (Cod)"
    and "𝒟 (Dom) = Arr"
    and " (Dom)  Obj"
    and "𝒟 (Cod) = Arr"
    and " (Cod)  Obj"
    and "gf. gf  𝒟 (Comp) 
      (g f b c a. gf = [g, f]  g : b c  f : a b)"
    and "b c g a f.  g : b c; f : a b   g Af : a c"
    and "c d h b g a f.  h : c d; g : b c; f : a b  
        (h Ag) Af = h A(g Af)"
    and "Obj  Vset α"
    and "A B.  A  Obj; B  Obj; A  Vset α; B  Vset α  
      (aA. bB. Hom  a b)  Vset α"
  using assms by (simp add: semicategoryD')


text‹
While using the sublocale infrastructure in conjunction with the rewrite 
morphisms is plausible for achieving automation of slicing, this approach
has certain limitations. For example, the rewrite morphisms cannot be added to a 
given interpretation that was achieved using the
command @{command sublocale}\footnote{
\url{
https://lists.cam.ac.uk/pipermail/cl-isabelle-users/2019-September/msg00074.html
}
}.
Thus, instead of using a partial solution based on the command 
@{command sublocale}, the rewriting is performed manually for 
selected theorems. However, it is hoped that better automation will be provided
in the future.
›

context semicategory
begin

interpretation dg: digraph α smc_dg  by (rule smc_digraph)

sublocale Dom: vsv Dom by (rule dg.Dom.vsv_axioms[unfolded slicing_simps])
sublocale Cod: vsv Cod by (rule dg.Cod.vsv_axioms[unfolded slicing_simps])

lemmas_with [unfolded slicing_simps]:
  smc_Dom_vdomain[smc_cs_simps] = dg.dg_Dom_vdomain
  and smc_Dom_vrange = dg.dg_Dom_vrange
  and smc_Cod_vdomain[smc_cs_simps] = dg.dg_Cod_vdomain
  and smc_Cod_vrange = dg.dg_Cod_vrange
  and smc_Obj_vsubset_Vset = dg.dg_Obj_vsubset_Vset
  and smc_Hom_vifunion_in_Vset[smc_cs_intros] = dg.dg_Hom_vifunion_in_Vset
  and smc_Obj_if_Dom_vrange = dg.dg_Obj_if_Dom_vrange
  and smc_Obj_if_Cod_vrange = dg.dg_Obj_if_Cod_vrange
  and smc_is_arrD = dg.dg_is_arrD
  and smc_is_arrE[elim] = dg.dg_is_arrE
  and smc_in_ArrE[elim] = dg.dg_in_ArrE
  and smc_Hom_in_Vset[smc_cs_intros] = dg.dg_Hom_in_Vset
  and smc_Arr_vsubset_Vset = dg.dg_Arr_vsubset_Vset
  and smc_Dom_vsubset_Vset = dg.dg_Dom_vsubset_Vset
  and smc_Cod_vsubset_Vset = dg.dg_Cod_vsubset_Vset
  and smc_Obj_in_Vset = dg.dg_Obj_in_Vset
  and smc_in_Obj_in_Vset[smc_cs_intros] = dg.dg_in_Obj_in_Vset
  and smc_Arr_in_Vset = dg.dg_Arr_in_Vset
  and smc_in_Arr_in_Vset[smc_cs_intros] = dg.dg_in_Arr_in_Vset
  and smc_Dom_in_Vset = dg.dg_Dom_in_Vset
  and smc_Cod_in_Vset = dg.dg_Cod_in_Vset
  and smc_digraph_if_ge_Limit = dg.dg_digraph_if_ge_Limit
  and smc_Dom_app_in_Obj = dg.dg_Dom_app_in_Obj
  and smc_Cod_app_in_Obj = dg.dg_Cod_app_in_Obj
  and smc_Arr_vempty_if_Obj_vempty = dg.dg_Arr_vempty_if_Obj_vempty
  and smc_Dom_vempty_if_Arr_vempty = dg.dg_Dom_vempty_if_Arr_vempty
  and smc_Cod_vempty_if_Arr_vempty = dg.dg_Cod_vempty_if_Arr_vempty

end

lemmas [smc_cs_intros] =
  semicategory.smc_is_arrD(1-3)
  semicategory.smc_Hom_in_Vset


text‹Elementary properties.›

lemma smc_eqI:
  assumes "semicategory α 𝔄" 
    and "semicategory α 𝔅"
    and "𝔄Obj = 𝔅Obj"
    and "𝔄Arr = 𝔅Arr"
    and "𝔄Dom = 𝔅Dom"
    and "𝔄Cod = 𝔅Cod"
    and "𝔄Comp = 𝔅Comp"
  shows "𝔄 = 𝔅"
proof-
  interpret 𝔄: semicategory α 𝔄 by (rule assms(1))
  interpret 𝔅: semicategory α 𝔅 by (rule assms(2))
  show ?thesis
  proof(rule vsv_eqI)
    have dom: "𝒟 𝔄 = 5" 
      by (cs_concl cs_shallow cs_simp: smc_cs_simps V_cs_simps)
    show "𝒟 𝔄 = 𝒟 𝔅" 
      by (cs_concl cs_shallow cs_simp: dom smc_cs_simps V_cs_simps)
    show "a  𝒟 𝔄  𝔄a = 𝔅a" for a 
      by (unfold dom, elim_in_numeral, insert assms) (auto simp: dg_field_simps)
  qed auto
qed

lemma smc_dg_eqI:
  assumes "semicategory α 𝔄"
    and "semicategory α 𝔅"
    and "𝔄Comp = 𝔅Comp"
    and "smc_dg 𝔄 = smc_dg 𝔅"
  shows "𝔄 = 𝔅"
proof(rule smc_eqI)
  from assms(4) have 
    "smc_dg 𝔄Obj = smc_dg 𝔅Obj"
    "smc_dg 𝔄Arr = smc_dg 𝔅Arr"
    "smc_dg 𝔄Dom = smc_dg 𝔅Dom"
    "smc_dg 𝔄Cod = smc_dg 𝔅Cod" 
    by auto
  then show
    "𝔄Obj = 𝔅Obj" "𝔄Arr = 𝔅Arr" "𝔄Dom = 𝔅Dom" "𝔄Cod = 𝔅Cod"
    unfolding slicing_simps by simp_all
qed (auto intro: assms)

lemma (in semicategory) smc_def: " = [Obj, Arr, Dom, Cod, Comp]"
proof(rule vsv_eqI)
  have dom_lhs: "𝒟  = 5" 
    by (cs_concl cs_shallow cs_simp: smc_cs_simps V_cs_simps)
  have dom_rhs: "𝒟 [Obj, Arr, Dom, Cod, Comp] = 5"
    by (simp add: nat_omega_simps)
  then show "𝒟  = 𝒟 [Obj, Arr, Dom, Cod, Comp]"
    unfolding dom_lhs dom_rhs by simp
  show "a  𝒟   a = [Obj, Arr, Dom, Cod, Comp]a" 
    for a
    unfolding dom_lhs
    by elim_in_numeral (simp_all add: dg_field_simps nat_omega_simps)
qed auto

lemma (in semicategory) smc_Comp_vdomainI[smc_cs_intros]: 
  assumes "g : b c" and "f : a b" and "gf = [g, f]"
  shows "gf  𝒟 (Comp)"
  using assms by (intro smc_Comp_vdomain[THEN iffD2]) auto

lemmas [smc_cs_intros] = semicategory.smc_Comp_vdomainI

lemma (in semicategory) smc_Comp_vdomainE[elim!]: 
  assumes "gf  𝒟 (Comp)" 
  obtains g f a b c where "gf = [g, f]" and "g : b c" and "f : a b"
proof-
  from smc_Comp_vdomain[THEN iffD1, OF assms(1)] obtain g f b c a
    where "gf = [g, f]" and "g : b c" and "f : a b"
    by clarsimp
  with that show ?thesis by simp
qed

lemma (in semicategory) smc_Comp_vdomain_is_composable_arrs: 
  "𝒟 (Comp) = composable_arrs "
  by (intro vsubset_antisym vsubsetI) (auto intro!: smc_cs_intros)+

lemma (in semicategory) smc_Comp_vrange: " (Comp)  Arr"
proof(rule Comp.vsv_vrange_vsubset)
  fix gf assume "gf  𝒟 (Comp)"
  from smc_Comp_vdomain[THEN iffD1, OF this] obtain g f b c a
    where gf_def: "gf = [g, f]" 
      and g: "g : b c" 
      and f: "f : a b"  
    by clarsimp
  from semicategory_axioms g f show "Compgf  Arr"
    by 
      (
        cs_concl cs_shallow 
          cs_simp: gf_def smc_cs_simps cs_intro: smc_cs_intros
      )
qed

sublocale semicategory  Comp: pbinop Arr Comp
proof unfold_locales
  show "𝒟 (Comp)  Arr ^× 2"
  proof(intro vsubsetI; unfold smc_Comp_vdomain)
    fix gf assume "g f b c a. gf = [g, f]  g : b c  f : a b"
    then obtain a b c g f 
      where x_def: "gf = [g, f]" and "g : b c" and "f : a b"
      by auto
    then have "g  Arr" "f  Arr" by auto
    then show "gf  Arr ^× 2" 
      unfolding x_def by (auto simp: nat_omega_simps)
  qed
  show " (Comp)  Arr" by (rule smc_Comp_vrange)
qed auto


text‹Size.›

lemma (in semicategory) smc_Comp_vsubset_Vset: "Comp  Vset α"
proof(intro vsubsetI)
  fix gfh assume "gfh  Comp"
  then obtain gf h 
    where gfh_def: "gfh = gf, h" 
      and gf: "gf  𝒟 (Comp)" 
      and h: "h   (Comp)"
    by (blast elim: Comp.vbrelation_vinE)
  from gf obtain g f a b c
    where gf_def: "gf = [g, f]" and g: "g : b c" and f: "f : a b"  
    by clarsimp
  from h smc_Comp_vrange have "h  Arr" by auto
  with g f show "gfh  Vset α"
    unfolding gfh_def gf_def 
    by (cs_concl cs_shallow cs_intro: smc_cs_intros V_cs_intros)
qed

lemma (in semicategory) smc_semicategory_in_Vset_4: "  Vset (α + 4)"
proof-
  note [folded VPow_iff, folded Vset_succ[OF Ord_α], smc_cs_intros] =
    smc_Obj_vsubset_Vset
    smc_Arr_vsubset_Vset
    smc_Dom_vsubset_Vset
    smc_Cod_vsubset_Vset
    smc_Comp_vsubset_Vset
  show ?thesis
    by (subst smc_def, succ_of_numeral)
      (
        cs_concl  
          cs_simp: plus_V_succ_right V_cs_simps 
          cs_intro: smc_cs_intros V_cs_intros
      )
qed

lemma (in semicategory) smc_Comp_in_Vset: 
  assumes "𝒵 β" and "α  β"
  shows "Comp  Vset β"
  using smc_Comp_vsubset_Vset by (meson Vset_in_mono assms(2) vsubset_in_VsetI)

lemma (in semicategory) smc_in_Vset: 
  assumes "𝒵 β" and "α  β"
  shows "  Vset β"
proof-
  interpret β: 𝒵 β by (rule assms(1))
  note [smc_cs_intros] = 
    smc_Obj_in_Vset 
    smc_Arr_in_Vset
    smc_Dom_in_Vset
    smc_Cod_in_Vset
    smc_Comp_in_Vset
  from assms(2) show ?thesis 
    by (subst smc_def) (cs_concl cs_shallow cs_intro: smc_cs_intros V_cs_intros)
qed

lemma (in semicategory) smc_semicategory_if_ge_Limit:
  assumes "𝒵 β" and "α  β"
  shows "semicategory β "
  by (rule semicategoryI)
    (
      auto 
        intro: smc_cs_intros 
        simp: smc_cs_simps assms vfsequence_axioms smc_digraph_if_ge_Limit 
    )

lemma small_semicategory[simp]: "small {. semicategory α }"
proof(cases 𝒵 α)
  case True
  from semicategory.smc_in_Vset[of α] show ?thesis
    by (intro down[of _ Vset (α + ω)]) 
      (auto simp: True 𝒵.𝒵_Limit_αω 𝒵.𝒵_ω_αω 𝒵.intro 𝒵.𝒵_α_αω)
next
  case False
  then have "{. semicategory α } = {}" by auto
  then show ?thesis by simp
qed

lemma (in 𝒵) semicategories_in_Vset: 
  assumes "𝒵 β" and "α  β"
  shows "set {. semicategory α }  Vset β"
proof(rule vsubset_in_VsetI)
  interpret β: 𝒵 β by (rule assms(1))
  show "set {. semicategory α }  Vset (α + 4)"
  proof(intro vsubsetI)
    fix  assume prems: "  set {. semicategory α }"
    interpret semicategory α  using prems by simp
    show "  Vset (α + 4)"
      unfolding VPow_iff by (rule smc_semicategory_in_Vset_4)
  qed
  from assms(2) show "Vset (α + 4)  Vset β"
    by (cs_concl cs_shallow cs_intro: V_cs_intros Ord_cs_intros)
qed

lemma semicategory_if_semicategory:
  assumes "semicategory β "
    and "𝒵 α"
    and "Obj  Vset α"
    and "A B.  A  Obj; B  Obj; A  Vset α; B  Vset α  
      (aA. bB. Hom  a b)  Vset α"
  shows "semicategory α "
proof-
  interpret semicategory β  by (rule assms(1))
  interpret α: 𝒵 α by (rule assms(2))
  show ?thesis
  proof(intro semicategoryI)
    show "vfsequence " by (simp add: vfsequence_axioms)
    show "digraph α (smc_dg )"
      by (rule digraph_if_digraph, unfold slicing_simps)
        (auto intro!: assms(1,3,4) slicing_intros)
  qed (auto intro: smc_cs_intros simp: smc_cs_simps)
qed


text‹Further properties.›

lemma (in semicategory) smc_Comp_vempty_if_Arr_vempty:
  assumes "Arr = 0"
  shows "Comp = 0"
  using assms smc_Comp_vrange by (auto intro: Comp.vsv_vrange_vempty)



subsection‹Opposite semicategory›


subsubsection‹Definition and elementary properties›


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

definition op_smc :: "V  V"
  where "op_smc  = [Obj, Arr, Cod, Dom, fflip (Comp)]"


text‹Components.›

lemma op_smc_components:
  shows [smc_op_simps]: "op_smc Obj = Obj"
    and [smc_op_simps]: "op_smc Arr = Arr"
    and [smc_op_simps]: "op_smc Dom = Cod"
    and [smc_op_simps]: "op_smc Cod = Dom"
    and "op_smc Comp = fflip (Comp)"
  unfolding op_smc_def dg_field_simps by (auto simp: nat_omega_simps)

lemma op_smc_component_intros[smc_op_intros]:
  shows "a  Obj  a  op_smc Obj"
    and "f  Arr  f  op_smc Arr"
  unfolding smc_op_simps by simp_all


text‹Slicing.›

lemma op_dg_smc_dg[slicing_commute]: "op_dg (smc_dg ) = smc_dg (op_smc )"
  unfolding smc_dg_def op_smc_def op_dg_def dg_field_simps
  by (simp add: nat_omega_simps)


text‹Regular definitions.›

lemma op_smc_Comp_vdomain[smc_op_simps]: 
  "𝒟 (op_smc Comp) = (𝒟 (Comp))¯"
  unfolding op_smc_components by simp

lemma op_smc_is_arr[smc_op_simps]: "f : b op_smc a  f : a b"
  unfolding smc_op_simps is_arr_def by auto

lemmas [smc_op_intros] = op_smc_is_arr[THEN iffD2]

lemma (in semicategory) op_smc_Comp_vrange[smc_op_simps]: 
  " (op_smc Comp) =  (Comp)"
  using Comp.vrange_fflip unfolding op_smc_components by simp

lemmas [smc_op_simps] = semicategory.op_smc_Comp_vrange

lemma (in semicategory) op_smc_Comp[smc_op_simps]: 
  assumes "f : b c" and "g : a b"
  shows "g Aop_smc f = f Ag"
  using assms 
  unfolding op_smc_components 
  by (auto intro!: fflip_app smc_cs_intros)

lemmas [smc_op_simps] = semicategory.op_smc_Comp

lemma op_smc_Hom[smc_op_simps]: "Hom (op_smc ) a b = Hom  b a"
  unfolding smc_op_simps by simp


subsubsection‹Further properties›

lemma (in semicategory) semicategory_op[smc_op_intros]: 
  "semicategory α (op_smc )"
proof(intro semicategoryI)
  from semicategory_axioms smc_digraph show "digraph α (smc_dg (op_smc ))"
    by 
      (
        cs_concl cs_shallow 
          cs_simp: slicing_commute[symmetric] cs_intro: dg_op_intros
      )
  show "vfsequence (op_smc )" unfolding op_smc_def by simp
  show "vcard (op_smc ) = 5"
    unfolding op_smc_def by (simp add: nat_omega_simps)
  show "(gf  𝒟 (op_smc Comp)) 
    (g f b c a. gf = [g, f]  g : b op_smc c  f : a op_smc b)"
    for gf
  proof(rule iffI; unfold smc_op_simps)
    assume prems: "gf  (𝒟 (Comp))¯"
    then obtain g' f' where gf_def: "gf = [g', f']" by clarsimp
    with prems have "[f', g']  𝒟 (Comp)" by (auto intro: smc_cs_intros)
    with smc_Comp_vdomain show 
      "g f b c a. gf = [g, f]  g : c b  f : b a"
      unfolding gf_def by auto
  next
    assume "g f b c a. gf = [g, f]  g : c b  f : b a"
    then obtain g f b c a 
      where gf_def: "gf = [g, f]" and g: "g : c b" and f: "f : b a"
      by clarsimp
    then have "g  Arr" and "f  Arr" by force+
    from g f have "[f, g]  𝒟 (Comp)"
      unfolding gf_def by (intro smc_Comp_vdomainI) auto
    then show "gf  (𝒟 (Comp))¯" 
      unfolding gf_def by (auto intro: smc_cs_intros)
  qed
  from semicategory_axioms show 
    " g : b op_smc c; f : a op_smc b   
      g Aop_smc f : a op_smc c"
    for g b c f a
    unfolding smc_op_simps 
    by (cs_concl cs_shallow cs_simp: smc_op_simps cs_intro: smc_cs_intros)
  fix h c d g b f a
  assume "h : c op_smc d" "g : b op_smc c" "f : a op_smc b"
  with semicategory_axioms show
    "(h Aop_smc g) Aop_smc f = h Aop_smc (g Aop_smc f)"
    unfolding smc_op_simps
    by (cs_concl cs_simp: smc_op_simps smc_cs_simps cs_intro: smc_cs_intros)
qed (auto simp: fflip_vsv op_smc_components(5))

lemmas semicategory_op[smc_op_intros] = semicategory.semicategory_op

lemma (in semicategory) smc_op_smc_op_smc[smc_op_simps]: "op_smc (op_smc ) = "
  by (rule smc_eqI, unfold smc_op_simps op_smc_components)
    (
      auto simp: 
        Comp.pbinop_fflip_fflip 
        semicategory_axioms
        semicategory.semicategory_op semicategory_op
        intro: smc_cs_intros
    )

lemmas smc_op_smc_op_smc[smc_op_simps] = semicategory.smc_op_smc_op_smc

lemma eq_op_smc_iff[smc_op_simps]: 
  assumes "semicategory α 𝔄" and "semicategory α 𝔅"
  shows "op_smc 𝔄 = op_smc 𝔅  𝔄 = 𝔅"
proof
  interpret 𝔄: semicategory α 𝔄 by (rule assms(1))
  interpret 𝔅: semicategory α 𝔅 by (rule assms(2))
  assume prems: "op_smc 𝔄 = op_smc 𝔅" show "𝔄 = 𝔅"
  proof(rule smc_eqI)
    show 
      "𝔄Obj = 𝔅Obj" 
      "𝔄Arr = 𝔅Arr"
      "𝔄Dom = 𝔅Dom" 
      "𝔄Cod = 𝔅Cod"
      "𝔄Comp = 𝔅Comp"
      by (metis prems 𝔄.smc_op_smc_op_smc 𝔅.smc_op_smc_op_smc)+
  qed (auto intro: assms)
qed auto



subsection‹Arrow with a domain and a codomain›

lemma (in semicategory) smc_assoc_helper:
  assumes "f : a b"
    and "g : b c"
    and "h : c d"
    and "h Ag = q"
  shows "h A(g Af) = q Af"
  using semicategory_axioms assms(1-4)
  by (cs_concl cs_simp: assms(4) semicategory.smc_Comp_assoc[symmetric])

lemma (in semicategory) smc_pattern_rectangle_right:
  assumes "aa' : a a'" 
    and "a'a'' : a' a''"
    and "a''b'' : a'' b''"
    and "ab : a b"
    and "bb' : b b'"
    and "b'b'' : b' b''"
    and "a'b' : a' b'"
    and "a'b' Aaa' = bb' Aab"
    and "b'b'' Aa'b' = a''b'' Aa'a''"
  shows "a''b'' A(a'a'' Aaa') = (b'b'' Abb') Aab"
proof-
  from semicategory_axioms assms(3,2,1) have 
    "a''b'' A(a'a'' Aaa') = (a''b'' Aa'a'') Aaa'"
    by (cs_concl cs_shallow cs_simp: smc_cs_simps cs_intro: smc_cs_intros)
  also have " = (b'b'' Aa'b') Aaa'" unfolding assms(9) ..
  also from semicategory_axioms assms(1,6,7) have 
    " = b'b'' A(a'b' Aaa')"
    by (cs_concl cs_shallow cs_simp: smc_cs_simps cs_intro: smc_cs_intros)
  also have " = b'b'' A(bb' Aab)" unfolding assms(8) ..
  also from semicategory_axioms assms(6,5,4) have 
    " = (b'b'' Abb') Aab" 
    by (cs_concl cs_shallow cs_simp: smc_cs_simps cs_intro: smc_cs_intros)
  finally show ?thesis by simp
qed

lemmas (in semicategory) smc_pattern_rectangle_left = 
  smc_pattern_rectangle_right[symmetric]



subsection‹Monic arrow and epic arrow›


text‹See Chapter I-5 in cite"mac_lane_categories_2010".›

definition is_monic_arr :: "V  V  V  V  bool"
  where "is_monic_arr  b c m 
    m : b c 
    (
      f g a.
        f : a b  g : a b  m Af = m Ag  f = g
    )"

syntax "_is_monic_arr" :: "V  V  V  V  bool"
  (‹_ : _ monı _› [51, 51, 51] 51)
syntax_consts "_is_monic_arr"  is_monic_arr
translations "m : b monc"  "CONST is_monic_arr  b c m"

definition is_epic_arr :: "V  V  V  V  bool"
  where "is_epic_arr  a b e  e : b monop_smc a"

syntax "_is_epic_arr" :: "V  V  V  V  bool"
  (‹_ : _ epiı _› [51, 51, 51] 51)
syntax_consts "_is_epic_arr"  is_epic_arr
translations "e : a epib"  "CONST is_epic_arr  a b e"


text‹Rules.›

mk_ide rf is_monic_arr_def
  |intro is_monic_arrI|
  |dest is_monic_arrD[dest]|
  |elim is_monic_arrE[elim!]|

lemmas [smc_arrow_cs_intros] = is_monic_arrD(1)

lemma (in semicategory) is_epic_arrI:
  assumes "e : a b"
    and "f g c.  f : b c; g : b c; f Ae = g Ae  
      f = g"
  shows "e : a epib"
  unfolding is_epic_arr_def
proof(intro is_monic_arrI, unfold smc_op_simps)
  fix f g a 
  assume prems:
    "f : b a" "g : b a" "e Aop_smc f = e Aop_smc g"
  show "f = g"
  proof-
    from prems(3,1,2) assms(1) semicategory_axioms have "g Ae = f Ae"
      by 
        (
          cs_prems cs_shallow
            cs_simp: smc_cs_simps smc_op_simps
            cs_intro: smc_cs_intros smc_op_intros
        )
      simp
    from assms(2)[OF prems(2,1) this] show ?thesis ..
  qed
qed (rule assms(1))

lemma is_epic_arr_is_arr[smc_arrow_cs_intros, dest]:
  assumes "e : a epib"
  shows "e : a b"
  using assms unfolding is_epic_arr_def is_monic_arr_def smc_op_simps by simp

lemma (in semicategory) is_epic_arrD[dest]:
  assumes "e : a epib"
  shows "e : a b"
    and "f g c.  f : b c; g : b c; f Ae = g Ae  
      f = g"
proof-
  note is_monic_arrD = 
    assms(1)[unfolded is_epic_arr_def is_monic_arr_def smc_op_simps] 
  from is_monic_arrD[THEN conjunct1] show e: "e : a b" by simp
  fix f g c 
  assume prems: "f : b c" "g : b c" "f Ae = g Ae"
  with semicategory_axioms e have "e Aop_smc f = e Aop_smc g"
    by (cs_concl cs_shallow cs_simp: smc_op_simps cs_intro: smc_cs_intros)
  then show "f = g" 
    by (rule is_monic_arrD[THEN conjunct2, rule_format, OF prems(1,2)])
qed

lemma (in semicategory) is_epic_arrE[elim!]:
  assumes "e : a epib"
  obtains "e : a b"
    and "f g c.  f : b c; g : b c; f Ae = g Ae   
      f = g"
  using assms by auto


text‹Elementary properties.›

lemma (in semicategory) op_smc_is_epic_arr[smc_op_simps]: 
  "f : b epiop_smc a  f : a monb"
  unfolding is_monic_arr_def is_epic_arr_def smc_op_simps ..

lemma (in semicategory) op_smc_is_monic_arr[smc_op_simps]: 
  "f : b monop_smc a  f : a epib"
  unfolding is_monic_arr_def is_epic_arr_def smc_op_simps ..

lemma (in semicategory) smc_Comp_is_monic_arr[smc_arrow_cs_intros]:
  assumes "g : b monc" and "f : a monb"
  shows "g Af : a monc"
proof(intro is_monic_arrI)
  from assms show "g Af : a c" by (auto intro: smc_cs_intros)
  fix f' g' a'
  assume f': "f' : a' a"
    and g': "g' : a' a"
    and "g Af Af' = g Af Ag'"
  with assms have "g A(f Af') = g A(f Ag')"
    by (force simp: smc_Comp_assoc)
  moreover from assms have "f Af' : a' b" "f Ag' : a' b" 
    by (auto intro: f' g' smc_cs_intros)
  ultimately have "f Af' = f Ag'" using assms(1) by clarsimp
  with assms f' g' show "f' = g'" by clarsimp
qed

lemmas [smc_arrow_cs_intros] = semicategory.smc_Comp_is_monic_arr

lemma (in semicategory) smc_Comp_is_epic_arr[smc_arrow_cs_intros]: 
  assumes "g : b epic" and "f : a epib"
  shows "g Af : a epic"
proof-
  from assms op_smc_is_arr have "g : b c" "f : a b" 
    unfolding is_epic_arr_def by auto
  with semicategory_axioms have "f Aop_smc g = g Af"
    by (cs_concl cs_shallow cs_simp: smc_op_simps)
  with 
    semicategory.smc_Comp_is_monic_arr[
      OF semicategory_op,
      OF assms(2,1)[unfolded is_epic_arr_def],
      folded is_epic_arr_def
      ]
  show ?thesis    
    by auto
qed

lemmas [smc_arrow_cs_intros] = semicategory.smc_Comp_is_epic_arr

lemma (in semicategory) smc_Comp_is_monic_arr_is_monic_arr:
  assumes "g : b c" and "f : a b" and "g Af : a monc"
  shows "f : a monb"
proof(intro is_monic_arrI)
  fix f' g' a'
  assume f': "f' : a' a" 
    and g': "g' : a' a" 
    and f'gg'g: "f Af' = f Ag'"
  from assms(1,2) f' g' have "(g Af) Af' = (g Af) Ag'"
    by (auto simp: smc_Comp_assoc f'gg'g)
  with assms(3) f' g' show "f' = g'" by clarsimp
qed (simp add: assms(2))

lemma (in semicategory) smc_Comp_is_epic_arr_is_epic_arr:
  assumes "g : a b" and "f : b c" and "f Ag : a epic"
  shows "f : b epic"
proof-
  from assms have "g : b op_smc a" "f : c op_smc b" 
    unfolding smc_op_simps by simp_all 
  moreover from semicategory_axioms assms have "g Aop_smc f : a epic"
    by (cs_concl cs_shallow cs_simp: smc_op_simps)
  ultimately show ?thesis 
    using 
      semicategory.smc_Comp_is_monic_arr_is_monic_arr[
        OF semicategory_op, folded is_epic_arr_def
        ]
    by auto
qed



subsection‹Idempotent arrow›


text‹See Chapter I-5 in cite"mac_lane_categories_2010".›

definition is_idem_arr :: "V  V  V  bool"
  where "is_idem_arr  b f  f : b b  f Af = f"

syntax "_is_idem_arr" :: "V  V  V  bool" (‹_ : ideı _› [51, 51] 51)
syntax_consts "_is_idem_arr"  is_idem_arr
translations "f : ideb"  "CONST is_idem_arr  b f"


text‹Rules.›

mk_ide rf is_idem_arr_def
  |intro is_idem_arrI|
  |dest is_idem_arrD[dest]|
  |elim is_idem_arrE[elim!]|

lemmas [smc_cs_simps] = is_idem_arrD(2)


text‹Elementary properties.›

lemma (in semicategory) op_smc_is_idem_arr[smc_op_simps]: 
  "f : ideop_smc b  f : ideb"
  using op_smc_Comp unfolding is_idem_arr_def smc_op_simps by auto



subsection‹Terminal object and initial object›


text‹See Chapter I-5 in cite"mac_lane_categories_2010".›

definition obj_terminal :: "V  V  bool"
  where "obj_terminal  t  
    t  Obj  (a. a  Obj  (∃!f. f : a t))"

definition obj_initial :: "V  V  bool"
  where "obj_initial   obj_terminal (op_smc )"


text‹Rules.›

mk_ide rf obj_terminal_def
  |intro obj_terminalI|
  |dest obj_terminalD[dest]|
  |elim obj_terminalE[elim]|

lemma obj_initialI:
  assumes "a  Obj" and "b. b  Obj  ∃!f. f : a b" 
  shows "obj_initial  a"
  unfolding obj_initial_def
  by (simp add: obj_terminalI[of _ op_smc , unfolded smc_op_simps, OF assms])

lemma obj_initialD[dest]:
  assumes "obj_initial  a" 
  shows "a  Obj" and "b. b  Obj  ∃!f. f : a b"   
  by 
    (
      simp_all add: 
        obj_terminalD[OF assms[unfolded obj_initial_def], unfolded smc_op_simps]
    )

lemma obj_initialE[elim]:
  assumes "obj_initial  a" 
  obtains "a  Obj" and "b. b  Obj  ∃!f. f : a b"   
  using assms by (auto simp: obj_initialD)


text‹Elementary properties.›

lemma op_smc_obj_initial[smc_op_simps]: 
  "obj_initial (op_smc ) = obj_terminal "
  unfolding obj_initial_def obj_terminal_def smc_op_simps ..

lemma op_smc_obj_terminal[smc_op_simps]: 
  "obj_terminal (op_smc ) = obj_initial "
  unfolding obj_initial_def obj_terminal_def smc_op_simps ..



subsection‹Null object›


text‹See Chapter I-5 in cite"mac_lane_categories_2010".›

definition obj_null :: "V  V  bool"
  where "obj_null  a  obj_initial  a  obj_terminal  a"


text‹Rules.›

mk_ide rf obj_null_def
  |intro obj_nullI|
  |dest obj_nullD[dest]|
  |elim obj_nullE[elim]|


text‹Elementary properties.›

lemma op_smc_obj_null[smc_op_simps]: "obj_null (op_smc ) a = obj_null  a"
  unfolding obj_null_def smc_op_simps by auto



subsection‹Zero arrow›

definition is_zero_arr :: "V  V  V  V  bool"
  where "is_zero_arr  a b h 
    (z g f. obj_null  z  h = g Af  f : a z  g : z b)"

syntax "_is_zero_arr" :: "V  V  V  V  bool"
  (‹_ : _ 0ı _› [51, 51, 51] 51)
syntax_consts "_is_zero_arr"  is_zero_arr
translations "h : a 0b"  "CONST is_zero_arr  a b h"


text‹Rules.›

lemma is_zero_arrI:
  assumes "obj_null  z" 
    and "h = g Af" 
    and "f : a z" 
    and "g : z b"
  shows "h : a 0b"
  using assms unfolding is_zero_arr_def by auto

lemma is_zero_arrD[dest]:
  assumes "h : a 0b"
  shows "z g f. obj_null  z  h = g Af  f : a z  g : z b"
  using assms unfolding is_zero_arr_def by simp

lemma is_zero_arrE[elim]:
  assumes "h : a 0b"
  obtains z g f 
    where "obj_null  z"
      and "h = g Af" 
      and "f : a z" 
      and "g : z b"
  using assms by auto


text‹Elementary properties.›

lemma (in semicategory) op_smc_is_zero_arr[smc_op_simps]: 
  "f : b 0op_smc a  f : a 0b"
  using op_smc_Comp unfolding is_zero_arr_def smc_op_simps by metis

lemma (in semicategory) smc_is_zero_arr_Comp_right:
  assumes "h : b 0c" and "h' : a b"
  shows "h Ah' : a 0c"
proof-
  from assms(1) obtain z g f  
    where "obj_null  z" 
      and "h = g Af" 
      and "f : b z" 
      and "g : z c"
    by auto 
  with assms show ?thesis 
    by (auto simp: smc_cs_simps intro: is_zero_arrI smc_cs_intros) 
qed

lemmas [smc_arrow_cs_intros] = semicategory.smc_is_zero_arr_Comp_right

lemma (in semicategory) smc_is_zero_arr_Comp_left:
  assumes "h' : b c" and "h : a 0b" 
  shows "h' Ah : a 0c"
proof-
  from assms(2) obtain z g f 
    where "obj_null  z" 
      and "h = g Af" 
      and "f : a z" 
      and "g : z b"
    by auto
  with assms(1) show ?thesis
    by (intro is_zero_arrI[of _ _ _ h' Ag]) 
      (auto simp: smc_Comp_assoc intro: is_zero_arrI smc_cs_intros)
qed

lemmas [smc_arrow_cs_intros] = semicategory.smc_is_zero_arr_Comp_left

text‹\newpage›

end