Theory Relational_Properties

section ‹Properties of Binary Relations›

theory Relational_Properties

imports Main

begin

text ‹This is a general-purpose theory for enrichments of Rel, which is still quite basic,
but helpful for developing properties of multirelations.›

notation relcomp (infixl ; 75)
notation converse (‹_ [1000] 999)

type_synonym ('a,'b) rel = "('a × 'b) set"

lemma modular_law: "R ; S  T  (R  T ; S) ; S"
  by blast

lemma compl_conv: "-(R) = (-R)"
  by fastforce

definition top :: "('a,'b) rel" where
  "top = {(a,b) |a b. True}"

abbreviation "neg R  Id  -R"


subsection ‹Univalence, totality, determinism, and related properties›

definition univalent :: "('a,'b) rel  bool" where
  "univalent R = (R ; R  Id)"

definition total :: "('a,'b) rel  bool" where
  "total R = (Id  R ; R)"

definition injective :: "('a,'b) rel  bool" where
  "injective R = (R ; R  Id)"

definition surjective :: "('a,'b) rel  bool" where
  "surjective R = (Id  R ; R)"

definition deterministic :: "('a,'b) rel  bool" where
  "deterministic R = (univalent R  total R)"

definition bijective :: "('a,'b) rel  bool" where
  "bijective R = (injective R  surjective R)"

lemma univalent_set: "univalent R = (a b c. (a,b)  R  (a,c)  R  b = c)"
  unfolding univalent_def converse_unfold Id_def by force

text ‹Univalent relations feature as single-valued relations in Main.›

lemma univ_single_valued: "univalent R = single_valued R"
  unfolding univalent_set single_valued_def by auto

lemma total_set: "total R = (a. b. (a,b)  R)"
  unfolding total_def converse_unfold Id_def by force

lemma total_var: "total R = (R ; top = top)"
  unfolding total_set top_def by force

lemma deterministic_set: "deterministic R = (a . ∃!B . (a,B)  R)"
  unfolding deterministic_def univalent_set total_set by force

lemma deterministic_var1: "deterministic R = (R ; -Id = -R)"
  unfolding deterministic_set Id_def by force

lemma deterministic_var2: "deterministic R = (S. R ; -S = -(R ; S))"
  unfolding deterministic_set by (standard, force, blast)

lemma inj_univ: "injective R = univalent (R)"
  by (simp add: injective_def univalent_def)

lemma injective_set: "injective S = (a b c. (a,c)  S  (b,c)  S  a = b)"
  by (meson converseD converseI inj_univ univalent_set)

lemma surj_tot: "surjective R = total (R)"
  by (simp add: surjective_def total_def)

lemma surjective_set: "surjective S = (b. a. (a,b)  S)"
  by (simp add: surj_tot total_set)

lemma surj_var: "surjective R = (R ; top = top)"
  by (simp add: surj_tot total_var)

lemma bij_det: "bijective R = deterministic (R)"
  by (simp add: bijective_def deterministic_def inj_univ surj_tot)

lemma univ_relcomp: "univalent R  univalent S  univalent (R ; S)"
  by (simp add: single_valued_relcomp univ_single_valued)

lemma tot_relcomp: "total R  total S  total (R ; S)"
  by (meson relcomp.simps total_set)

lemma det_relcomp: "deterministic R  deterministic S  deterministic (R ; S)"
  by (simp add: deterministic_def tot_relcomp univ_relcomp)

lemma inj_relcomp: "injective R  injective S  injective (R ; S)"
  by (simp add: converse_relcomp inj_univ univ_relcomp)

lemma surj_relcomp: "surjective R  surjective S  surjective (R ; S)"
  by (simp add: converse_relcomp surj_tot tot_relcomp)

lemma bij_relcomp: "bijective R  bijective S  bijective (R ; S)"
  by (simp add: bijective_def inj_relcomp surj_relcomp)

lemma det_Id: "deterministic Id"
  by (simp add: deterministic_var1)

lemma bij_Id: "bijective Id"
  by (simp add: bij_det det_Id)

lemma tot_top: "total top"
  by (simp add: top_def total_set)

lemma tot_surj: "surjective top"
  by (simp add: surjective_set top_def)

lemma det_meet_distl: "univalent R  R ; (S  T) = R ; S  R ; T"
  unfolding univalent_set relcomp_def relcompp_apply by force

lemma inj_meet_distr: "injective T  (R  S) ; T = R ; T  S ; T"
  unfolding injective_def converse_def Id_def relcomp.simps by force

lemma univ_modular: "univalent S  R ; S  T = (R  T ; S) ; S"
  unfolding univalent_set converse_unfold relcomp.simps by force


subsection ‹Inverse image and the diagonal and graph functors›

definition Invim :: "('a,'b) rel  'b set  'a set" where
  "Invim R = Image (R)"

definition Delta :: "'a set  ('a,'a) rel" (Δ) where
  "Δ P = {(p,p) |p. p  P}"

definition Grph :: "('a  'b)  ('a,'b) rel" where
  "Grph f = {(x,y). y = f x}"

lemma Image_Grph [simp]: "Image  Grph = image"
  unfolding Image_def Grph_def image_def by auto

subsection ‹Relational domain, codomain and modalities›

text ‹Domain and codomain (range) maps have been defined in Main, but they return sets instead of relations.›

definition dom :: "('a,'b) rel  ('a,'a) rel" where
  "dom R = Id  R ; R"

definition cod :: "('a,'b) rel  ('b,'b) rel" where
  "cod R = dom (R)"

definition rel_fdia :: "('a,'b) rel  ('b,'b) rel  ('a,'a) rel" ((|__) [61,81] 82) where
  "|R Q = dom (R ; dom Q)"

definition rel_bdia :: "('a,'b) rel  ('a,'a) rel  ('b,'b) rel" ((_|_) [61,81] 82) where
  "rel_bdia R = rel_fdia (R)"

definition rel_fbox :: "('a,'b) rel  ('b,'b) rel  ('a,'a) rel" ((|_]_) [61,81] 82) where
  "|R]Q = neg (dom (R ; neg (dom Q)))"

definition rel_bbox :: "('a,'b) rel  ('a,'a) rel  ('b,'b) rel" (([_|_) [61,81] 82) where
  "rel_bbox R = rel_fbox (R)"

lemma rel_bdia_def_var: "rel_bdia = rel_fdia  converse"
  unfolding rel_fdia_def fun_eq_iff comp_def rel_bdia_def by simp

lemma dom_set: "dom R = {(a,a) |a. b. (a,b)  R}"
  unfolding dom_def Id_def converse_unfold relcomp_unfold by force

lemma dom_Domain: "dom = Δ  Domain"
  unfolding fun_eq_iff dom_set Delta_def Domain_def by clarsimp blast

lemma cod_set: "cod R = {(b,b) |b. a. (a,b)  R}"
  by (smt (verit) Collect_cong cod_def converseD converseI dom_set)

lemma cod_Range: "cod = Δ  Range"
  unfolding fun_eq_iff cod_set Delta_def Range_def by clarsimp blast

lemma rel_fdia_set: "|R Q = {(a,a) |a. b. (a,b)  R  (b,b)  dom Q}"
  unfolding rel_fdia_def dom_set relcomp_unfold by force

lemma rel_bdia_set: "R| P = {(b,b) |b. a. (a,b)  R  (a,a)  dom P}"
  by (smt (verit, best) Collect_cong converseD converseI rel_bdia_def rel_fdia_set)

lemma rel_fbox_set: "|R] Q = {(a,a) |a. b. (a,b)  R  (b,b)  dom Q}"
  unfolding rel_fbox_def dom_set relcomp_unfold by force

lemma rel_bbox_set: "[R| P = {(b,b) |b. a. (a,b)  R  (a,a)  dom P}"
  by (smt (verit) Collect_cong converseD converseI rel_bbox_def rel_fbox_set)

lemma dom_alt_def: "dom R = Id  R ; top"
  unfolding dom_set top_def Id_def by force

lemma dom_gla: "(dom R  Id  S) = (R  (Id  S) ; R)"
  unfolding dom_set Id_def relcomp_unfold by blast

lemma dom_gla_top: "(dom R  Id  S) = (R  (Id  S) ; top)"
  unfolding dom_set Id_def top_def relcomp_unfold by blast

lemma dom_subid: "(dom R = R) = (R = Id  R)"
  by (metis (no_types, lifting) Id_O_R R_O_Id dom_alt_def dom_gla_top equalityD1 inf.absorb_iff2 inf.commute inf.idem le_inf_iff relcomp_mono)

lemma dom_cod: "(dom R = R) = (cod R = R)"
  by (metis dom_def cod_def converse_Id converse_Int converse_converse converse_relcomp)

lemma dom_top: "R ; top = dom R ; top"
  unfolding dom_set top_def by blast

lemma top_dom: "dom R = dom (R ; top)"
  unfolding dom_def top_def by blast

lemma cod_top: "cod R = Id  top ; R"
  by (metis dom_def cod_def converse_Id converse_Int converse_converse converse_relcomp dom_alt_def surj_var tot_surj)

lemma dom_conv [simp]: "(dom R) = dom R"
  by (simp add: dom_def converse_Int converse_relcomp)

lemma total_dom: "total R = (dom R = Id)"
  by (metis dom_def inf.orderE inf_le2 total_def)

lemma surj_cod: "surjective R = (cod R = Id)"
  by (simp add: cod_def surj_tot total_dom)

lemma fdia_demod: "( |R P  dom Q) = (R ; dom P  dom Q ; R)"
  unfolding rel_fdia_set dom_set relcomp_unfold by force

lemma bbox_demod: "(dom P  [R| Q) = (R ; dom P  dom Q ; R)"
  unfolding rel_bbox_set dom_def by force

lemma bdia_demod: "(R| P  dom Q) = (dom P ; R  R ; dom Q)"
proof -
  have "(R| P  dom Q) = ( |R P  dom Q)"
    by (simp add: rel_bdia_def)
  also have " = ((R) ; dom P  dom Q ; (R))"
    by (simp add: fdia_demod)
  also have " = (((dom P ; R))  ((R ; dom Q)))"
    by (simp add: converse_relcomp)
  also have " = (dom P ; R  R ; dom Q)"
    by simp
  finally show ?thesis.
qed

lemma fbox_demod: "(dom P  |R] Q) = (dom P ; R  R ; dom Q)"
  unfolding rel_fbox_set dom_set relcomp_unfold by force

lemma fdia_demod_top: "( |R P  dom Q) = (R ; dom P ; top  dom Q ; top)"
  by (metis dom_def dom_gla_top rel_fdia_def top_dom)

lemma bbox_demod_top: "(dom P  [R| Q) = (R ; dom P ; top  dom Q ; top)"
  unfolding rel_bbox_def rel_fbox_def dom_def top_def by force

lemma fdia_bbox_galois: "( |R P  dom Q) = (dom P  [R| Q)"
  by (meson bbox_demod_top fdia_demod_top)

lemma bdia_fbox_galois: "(R| P  dom Q) = (dom P  |R] Q)"
  by (simp add: fdia_bbox_galois rel_bbox_def rel_bdia_def)

lemma fdia_bdia_conjugation: "( |R P  neg (dom Q)) = (R| Q  neg (dom P))"
  unfolding rel_fdia_set rel_bdia_set dom_set by force

lemma bfox_bbox_conjugation: "(neg (dom Q)  |R] P) = (neg (dom P)  [R| Q)"
  unfolding rel_fbox_set rel_bbox_set dom_set by clarsimp blast


subsection ‹Residuation›

definition lres :: "('a,'c) rel  ('b,'c) rel  ('a,'b) rel" (infixl  75)
  where "R  S = {(a,b). c. (b,c)  S  (a,c)  R}"

definition rres :: "('c,'a) rel  ('c,'b) rel  ('a,'b) rel" (infixl  75)
  where "R  S = {(b,a). c. (c,b)  R  (c,a)  S}"

lemma rres_lres_conv: "R  S = (S  R)"
  unfolding rres_def lres_def by clarsimp fastforce

lemma lres_galois: "(R ; S  T) = (R  T  S)"
  unfolding lres_def by blast

lemma rres_galois: "(R ; S  T) = (S  R  T)"
  by (metis converse_converse converse_mono converse_relcomp lres_galois rres_lres_conv)

lemma lres_compl: "R  S = -(-R ; S)"
  unfolding lres_def converse_unfold by force

lemma rres_compl: "R  S = -(R ; -S)"
  unfolding rres_def converse_unfold by force

lemma lres_simp [simp]: "(R  R) ; R = R"
  by (metis Id_O_R lres_galois relcomp_mono subsetI subsetI subset_antisym)

lemma rres_simp [simp]: "R ; (R  R) = R"
  by (metis converse_converse converse_relcomp lres_simp rres_lres_conv)

lemma lres_curry: "R  (T ; S) = (R  S)  T"
  by (metis (no_types, opaque_lifting) O_assoc dual_order.refl lres_galois subset_antisym)

lemma rres_curry: "(R ; S)  T = S  (R  T)"
  by (simp add: converse_relcomp lres_curry rres_lres_conv)

lemma lres_Id: "Id  R  R"
  unfolding lres_def Id_def by force

lemma det_lres: "deterministic R  (R ; S)  S = R ; (S  S)"
  by (metis (no_types, lifting) O_assoc deterministic_var2 lres_compl)

lemma det_rres: "deterministic (R)  S  (S ; R) = (S  S) ; R"
  by (simp add: converse_relcomp det_lres rres_lres_conv)

lemma rres_bij: "bijective S  (R  T) ; S = R  (T ; S)"
  unfolding bijective_def injective_set surjective_set relcomp_unfold cod_def Id_def rres_def by clarsimp blast

lemma lres_bij: "bijective S  (R  T) ; S = R  (T ; S)"
  unfolding bijective_def injective_set surjective_set relcomp_unfold cod_def Id_def lres_def converse_unfold by blast

lemma dom_rres_top: "(dom P  R  (dom Q ; top)) = (dom P ; top  R  (dom Q ; top))"
  unfolding dom_def top_def rres_def relcomp_unfold Id_def converse_unfold by clarsimp blast

lemma dom_rres_top_var: "(dom P  R  (dom Q ; top)) = (P ; top  R  (Q ; top))"
  by (metis dom_rres_top dom_top)

lemma fdia_rres_top: "( |RP  dom Q) = (dom P  R  (dom Q ; top))"
  by (metis dom_alt_def dom_gla_top rel_fdia_def rres_galois)

lemma fdia_rres_top_var: "( |R P  dom Q) = (dom P  R  (Q ; top))"
  by (metis dom_top fdia_rres_top)

lemma dom_galois_var2: "( |R (Id  P)  Id  Q) = (Id  P  R  ((Id  Q) ; top))"
  by (metis dom_subid fdia_rres_top_var inf_sup_aci(4))

lemma rres_top: "R  (dom Q ; top) ; top = R  (dom Q ; top)"
  unfolding rres_def top_def dom_def relcomp_unfold by clarsimp

lemma ddd_var: "( |R P  dom Q) = (dom P  dom ((R  (dom Q ; top)) ; top))"
  unfolding rel_fdia_def dom_def rres_def top_def relcomp_unfold Id_def by force

lemma wlp_prop: "dom ((R  (dom Q ; top)) ; top) = neg (cod (neg (dom Q); R))"
  unfolding rres_def Id_def cod_def dom_def top_def relcomp_unfold by fastforce

lemma wlp_prop_var: "dom ((R  (dom Q ; top))) = neg (cod ((neg (dom Q)); R))"
  by (metis rres_top wlp_prop)

lemma dom_demod: "( |R (Id  P)  Id  Q) = (R ; (Id  P)  (Id  Q) ; R)"
proof
  assume "|R (Id  P)  Id  Q"
  hence "R ; (Id  P)  (Id  Q) ; R ; (Id  P)"
    by (metis O_assoc dom_gla dom_subid inf.absorb_iff2 inf_le1 rel_fdia_def)
  thus "R ; (Id  P)  (Id  Q) ; R"
    by auto
next
  assume "R ; (Id  P)  (Id  Q) ; R"
  hence "|R (Id  P)  dom ((Id  Q) ; R)"
    by (metis (no_types, lifting) dom_subid dom_top fdia_demod_top inf.absorb_iff2 inf_le1 relcomp_distrib2 sup.order_iff)
  hence "|R (Id  P)  (Id  Q)  dom R"
    unfolding dom_def Id_def by blast
  thus "|R (Id  P)  Id  Q"
    by blast
qed

lemma fdia_bbox_galois_var: "( |R (Id  P)  Id  Q) = (Id  P  Id  - cod ((Id  -Q); R))"
  unfolding rel_fdia_def dom_def cod_def Id_def by blast

lemma dom_demod_var2: "( |R (Id  P)  Id  Q) = (Id  P  R  ((Id  Q) ; R))"
  by (meson dom_demod rres_galois)


subsection ‹Symmetric quotient›

definition syq :: "('c,'a) rel  ('c,'b) rel  ('a,'b) rel" (infixl ÷ 75)
  where "R ÷ S = (R  S)  (R  S)"

lemma syq_set: "R ÷ S = {(a,b). c. (c,a)  R  (c,b)  S}"
  unfolding syq_def relcomp_unfold lres_def rres_def by force

lemma converse_syq [simp]: "(R ÷ S) = S ÷ R"
  unfolding syq_def converse_def rres_def lres_def by blast

lemma syq_compl: "R ÷ S = - (R ; -S)  - (-(R) ; S)"
  by (simp add: lres_compl rres_compl syq_def)

lemma syq_compl2 [simp]: "-R ÷ -S = R ÷ S"
  unfolding syq_compl by blast

lemma syq_expand1: "R ; (R ÷ S) = S  (top ; (R ÷ S))"
  unfolding syq_set top_def relcomp_unfold by force

lemma syq_expand2: "(R ÷ S) ; S = R  ((R ÷ S) ; top)"
  unfolding syq_set top_def relcomp_unfold by force

lemma syq_comp1: "(R ÷ S) ; (S ÷ T) = (R ÷ T)  (top ; (S ÷ T))"
  unfolding syq_set top_def relcomp_unfold by fastforce

lemma syq_comp2: "(R ÷ S) ; (S ÷ T) = (R ÷ T)  ((R ÷ S) ; top)"
  unfolding syq_set top_def relcomp_unfold by fastforce

lemma syq_bij: "bijective T  (R ÷ S) ; T = R ÷ (S ; T)"
  by (simp add: bijective_def inj_meet_distr lres_bij rres_bij syq_def)

end