Theory Relation_Toolkit

section ‹ Relation Toolkit ›

theory Relation_Toolkit
  imports Set_Toolkit Overriding
begin

subsection ‹ Conversions ›

text ‹ The majority of the relation toolkit is also part of HOL. We just need to generalise
  some of the syntax. ›

declare [[coercion rel_apply]]
declare [[coercion pfun_app]]
declare [[coercion pfun_of]]


text ‹ The following definition is semantically identical to @{const pfun_graph}, but is used to 
  represent coercions with associated reasoning. ›

definition rel_of_pfun :: "'a  'b  'a  'b" ("[_]") where
[code_unfold]: "rel_of_pfun = pfun_graph"

declare [[coercion rel_of_pfun]]
declare [[coercion pfun_of_pinj]]

notation pfun_of_pinj ("[_]")

subsection ‹ First component projection ›

text ‹ Z supports n-ary Cartesian products. We cannot support such structures directly in 
  Isabelle/HOL, but instead add the projection notations for the first and second components.
  A homogeneous finite Cartesian product type also exists in the Multivariate Analysis package. ›

abbreviation (input) "first  fst"
notation first ("_.1" [999] 999)

subsection ‹ Second component projection ›

abbreviation (input) "second  snd"
notation second ("_.2" [999] 999)

subsection ‹ Maplet ›

subsection ‹ Domain ›

hide_const (open) dom

consts dom :: "'f  'a set"

adhoc_overloading
  dom  Map.dom and
  dom  Relation.Domain and
  dom  Partial_Fun.pdom and
  dom  Finite_Fun.fdom and
  dom  Partial_Inj.pidom

subsection ‹ Range ›

hide_const (open) ran

consts ran :: "'f  'a set"

adhoc_overloading
  ran  Map.ran and
  ran  Relation.Range and
  ran  Partial_Fun.pran and
  ran  Finite_Fun.fran and
  ran  Partial_Inj.piran

subsection ‹ Identity relation ›

notation Id_on ("id[_]")

subsection ‹ Relational composition ›

notation relcomp (infixr ";" 75)

subsection ‹ Functional composition ›

text ‹ Composition is probably the most difficult of the Z functions to implement correctly. Firstly,
  the notation @{term "(∘)"} is already defined for HOL functions, and we need to respect that
  in order to use the HOL library functions. Secondly, Z composition can be used to compose 
  heterogeneous relations and functions, which is not easy to type infer. Consequently, we opt
  to use adhoc overloading here. ›

consts zcomp :: "'f  'g  'h" 

adhoc_overloading
  zcomp  Fun.comp and
  zcomp  pfun_comp and
  zcomp  ffun_comp

text ‹ Once we overload @{term Fun.comp}, we need to at least have output syntax set up. ›

notation (output) zcomp (infixl "" 55)

bundle Z_Relation_Syntax
begin

no_notation Fun.comp (infixl "" 55)
notation zcomp (infixl "" 55)

end

subsection ‹ Domain restriction and subtraction ›

consts dom_res :: "'a set  'r  'r" (infixr "" 85)

abbreviation ndres (infixr "" 85) where "ndres A P  CONST dom_res (- A) P" 

adhoc_overloading 
  dom_res  rel_domres
  and dom_res  pdom_res
  and dom_res  fdom_res
  and dom_res  pinj_dres

syntax "_ndres" :: "logic  logic  logic" 
translations "_ndres A P" == "CONST dom_res (- A) P"

subsection ‹ Range restriction and subtraction ›

consts ran_res :: "'r  'a set  'r" (infixl "" 86)

abbreviation nrres (infixl "" 86) where "nrres P A  CONST ran_res P (- A)"

adhoc_overloading 
  ran_res  rel_ranres
  and ran_res  pran_res
  and ran_res  fran_res
  and ran_res  pinj_rres

subsection ‹ Relational inversion ›

notation converse ("(_)" [1000] 999)

lemma relational_inverse: "r = {(p.2, p.1) | p. p  r}"
  by auto

subsection ‹ Relational image ›

notation Image ("__" [990] 990)

lemma Image_eq: "Image r a = {p.2 | p. p  r  p.1  a}"
  by (auto simp add: Image_def)

subsection ‹ Overriding ›

lemma dom_override: "dom ((Q :: 'a  'b)  R) = (dom Q)  (dom R)"
  by (simp add: Un_Int_distrib2)

lemma override_Un: "dom Q  dom R = {}  Q  R = Q  R"
  by (simp add: override_eq Int_commute rel_domres_compl_disj)

subsection ‹ Proof Support ›

text ‹ The objective of these laws is to, as much as possible, convert relational constructions
  into functional ones. The benefit is better proof automation in the more type constrained setting. ›

lemma rel_of_pfun_eq_iff [simp]: "[f] = [g]  f = g"
  by (simp add: pfun_eq_graph rel_of_pfun_def)

lemma rel_of_pfun_le_iff [simp]: "[f]  [g]  f  g"
  by (simp add: pfun_graph_le_iff rel_of_pfun_def)

lemma rel_of_pfun_pabs: "[pabs A P f] = {(k, v). k  A  P k  v = f k}"
  by (simp add: rel_of_pfun_def pfun_graph_pabs)

lemma rel_of_pfun_apply [simp]: "[f] x = f x"
  by (simp add: rel_of_pfun_def)

lemma rel_of_pfun_functional [simp]: "functional [f]"
  by (simp add: rel_of_pfun_def)

lemma rel_of_pfun_override [simp]: "[f]  [g] = [f  g]"
  by (simp add: pfun_graph_override rel_of_pfun_def)

lemma rel_of_pfun_comp [simp]: "[f] O [g] = [g p f]"
  by (simp add: pfun_graph_comp rel_of_pfun_def)

lemma pfun_comp_inv: "[f p g] = [f] O [g]"
  by (metis converse_relcomp rel_of_pfun_comp)

lemma rel_of_pfun_dom [simp]: "Domain [f] = pdom f"
  by (simp add: Dom_pfun_graph rel_of_pfun_def)

lemma rel_of_pfun_ran [simp]: "Range [f] = pran f"
  by (simp add: Range_pfun_graph rel_of_pfun_def)

lemma rel_of_pfun_domres [simp]: "A  [f] = [A  f]"
  by (simp add: pfun_graph_domres rel_of_pfun_def)

lemma rel_of_pfun_ranres [simp]: "[f]  A = [f  A]"
  by (simp add: rel_of_pfun_def pfun_graph_rres)

lemma rel_of_pfun_image [simp]: "[f]  A  = pfun_image f A"
  by (simp add: Image_as_rel_domres)

lemma rel_of_pfun_member_iff [simp]:
  "(k, v)  [f]  (k  dom f  f k = v)"
  by (simp add: rel_of_pfun_def)

lemma rel_of_pinj_conv [simp]: "[[f]]¯ = [[pinv f]]"
  by (simp add: pfun_graph_pfun_inv pinv.rep_eq rel_of_pfun_def)

lemma dom_pinv [simp]: "dom [pinv f] = ran [f]"
  by (simp add: pinv.rep_eq)

lemma ran_pinv [simp]: "ran [pinv f] = dom [f]"
  by (metis dom_pinv pinv_pinv)

lemma pfun_inj_rel_conv [simp]: "pfun_inj f  [f] = [pfun_inv f]"
  by (simp add: pfun_graph_pfun_inv rel_of_pfun_def)

end