Theory Multirelations_Basics

section ‹Basic Properties of Multirelations›

theory Multirelations_Basics

imports Power_Allegories_Properties

begin

text ‹This theory extends a previous AFP entry for multirelations with one single objects to
proper multirelations in Rel.›

subsection ‹Peleg composition, parallel composition (inner union) and units›

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

definition s_prod :: "('a,'b) mrel  ('b,'c) mrel  ('a,'c) mrel" (infixl "" 75) where
  "R  S = {(a,A). (B. (a,B)  R  (f. (b  B. (b,f b)  S)  A = (f ` B)))}"

definition s_id :: "('a,'a) mrel" ("1σ") where
  "1σ = (a. {(a,{a})})"

definition p_prod :: "('a,'b) mrel  ('a,'b) mrel  ('a,'b) mrel" (infixl "" 70) where
  "R  S = {(a,A). (B C. A = B  C  (a,B)  R  (a,C)  S)}"

definition p_id :: "('a,'b) mrel" ("1π") where
  "1π = (a. {(a,{})})"

definition U :: "('a,'b) mrel" where
  "U = {(a,A) |a A. True}"

abbreviation "NC  U - 1π"

named_theorems mr_simp
declare s_prod_def [mr_simp] p_prod_def [mr_simp] s_id_def [mr_simp] p_id_def [mr_simp] U_def [mr_simp]

lemma s_prod_idl [simp]: "1σ  R = R"
  by (auto simp: mr_simp)

lemma s_prod_idr [simp]: "R  1σ = R"
  by (auto simp: mr_simp) (metis UN_singleton)

lemma p_prod_ild [simp]: "1π  R = R"
  by (simp add: mr_simp)

lemma c_prod_idr [simp]: "R  1π = R"
  by (simp add: mr_simp)

lemma cl7 [simp]: "1σ  1σ = 1σ"
  by (auto simp: mr_simp)

lemma p_prod_assoc: "R  S  T = R  (S  T)"
  apply (rule set_eqI, clarsimp simp: mr_simp)
  by (metis (no_types, lifting) sup_assoc)

lemma p_prod_comm: "R  S = S  R"
  by (auto simp: mr_simp)

lemma subidem_par: "R  R  R"
  by (auto simp: mr_simp)

lemma meet_le_par: "R  S  R  S"
  by (auto simp: mr_simp)

lemma s_prod_distr: "(R  S)  T = R  T  S  T"
  by (auto simp: mr_simp)

lemma s_prod_sup_distr: "(X)  S = (R  X. R  S)"
  by (auto simp: mr_simp)

lemma s_prod_subdistl: "R  S  R  T  R  (S  T)"
  by (auto simp: mr_simp)

lemma s_prod_sup_subdistl: "X  {}  (S  X. R  S)  R  X"
  by (simp add: mr_simp) blast

lemma s_prod_isol: "R  S  R  T  S  T"
  by (metis s_prod_distr sup.order_iff)

lemma s_prod_isor: "R  S  T  R  T  S"
  by (metis le_supE s_prod_subdistl sup.absorb_iff1)

lemma s_prod_zerol [simp]: "{}  R = {}"
  by (force simp: mr_simp)

lemma s_prod_wzeror: "R  {}  R"
  by (force simp: mr_simp)

lemma p_prod_zeror [simp]: "R  {} = {}"
  by (simp add: mr_simp)

lemma s_prod_p_idl [simp]: "1π  R = 1π"
  by (force simp: mr_simp)

lemma p_id_st: "R  1π = {(a,{}) |a. B. (a,B)  R}"
  by (force simp: mr_simp)

lemma c6: "R  1π  1π"
  by (clarsimp simp: mr_simp)

lemma p_prod_distl: "R  (S  T) = R  S  R  T"
  by (fastforce simp: mr_simp)

lemma p_prod_sup_distl: "R  (X) = (S  X. R  S)"
  by (fastforce simp: mr_simp)

lemma p_prod_isol: "R  S  R  T  S  T"
  by (metis p_prod_comm p_prod_distl sup.orderE sup.orderI)

lemma p_prod_isor: "R  S  T  R  T  S"
  by (simp add: p_prod_comm p_prod_isol)

lemma s_prod_assoc1: "(R  S)  T  R  (S  T)"
  by (clarsimp simp: mr_simp) metis

lemma seq_conc_subdistr: "(R  S)  T  R  T  S  T"
  by (clarsimp simp: mr_simp UnI1 UnI2) blast

lemma U_U [simp]: "U  U = U"
  by (simp add: mr_simp) blast

lemma U_par_idem [simp]: "U  U = U"
  by (simp add: U_def equalityI subidem_par)

lemma p_id_NC: "R - 1π = R  NC"
  by (simp add: Diff_eq U_def)

lemma NC_NC [simp]: "NC  NC = NC"
  by (rule set_eqI, clarsimp simp: mr_simp, metis SUP_bot_conv(2) UN_constant insert_not_empty)

lemma nc_par_idem [simp]: "NC  NC = NC"
  by (force simp: mr_simp)

lemma cl4:
  assumes "T  T  T"
  shows "R  T  S  T  (R  S)  T"
proof clarify
  fix a A
  assume "(a,A)  R  T  S  T"
  hence "B C. A = B  C  (D. (a,D)  R  (f. (d  D. (d,f d)  T)  B =  ((λx. f x) ` D)))  (E. (a,E)  S  (g. (e  E. (e,g e)  T)  C =  ((λx. g x)` E)))"
    by (simp add: mr_simp)
  hence "D E. (a,D  E)  R  S  (f g. (d  D. (d,f d)  T)  (e  E. (e,g e)  T)  A = ( ((λx. f x) ` D))  ( ((λx. g x)` E)))"
    by (auto simp: mr_simp)
  hence "D E. (a,D  E)  R  S  (f g. (d  D-E. (d,f d)  T)  (e  E-D. (e,g e)  T)  (x  D  E. (x,f x)  T  (x,g x)  T)  A = ( ((λx. f x) ` (D-E)))  ( ((λx. g x) ` (E-D))  ( ((λy. f y  g y) ` (D  E)))))"
    by auto blast
  hence "D E. (a,D  E)  R  S  (f g. (d  D-E. (d,f d)  T)  (e  E-D. (e,g e)  T)  (x  D  E. (x,f x  g x)  T)  A = ( ((λx. f x) ` (D-E)))  ( ((λx. g x) ` (E-D))  ( ((λy. f y  g y) ` (D  E)))))"
    apply clarify
    subgoal for D E f g
      apply (rule exI[of _ D])
      apply (rule exI[of _ E])
      apply clarify
      apply (rule exI[of _ f])
      apply (rule exI[of _ g])
      using assms by (auto simp: p_prod_def, blast)
    done
  hence "D E. (a,D  E)  R  S  (h. (d  D-E. (d,h d)  T)  (e  E-D. (e, h e)  T)  (x  D  E. (x, h x)  T)  A = ( ((λx. h x) ` (D-E)))  ( ((λx. h x) ` (E-D))  ( ((λy. h y) ` (D  E)))))"
    apply clarify
    subgoal for D E f g 
      apply (rule exI[of _ D])
      apply (rule exI[of _ E])
      apply clarify
      apply (rule exI[of _ "λx. if x  (D - E) then f x else (if x  D  E then (f x  g x) else g x)"])
      by auto
    done
  hence "(B. (a,B)  R  S  (h. (bB. (b,h b)  T)  A = ((λx. h x) ` B)))"
    by clarsimp blast
  thus "(a,A)  (R  S)  T"
    by (simp add: mr_simp)
qed

lemma cl3: "R  (S  T)  R  S  R  T"
proof clarify
  fix a A
  assume "(a,A)  R  (S  T)"
  hence "B. (a,B)  R  (f. (b  B. C D. f b = C  D  (b,C)  S  (b,D)  T)  A = ((λx. f x) ` B))"
    by (clarsimp simp: mr_simp)
  hence "B. (a,B)  R  (f g h. (b  B. f b = g b  h b  (b,g b)  S  (b,h b)  T)  A = ((λx. f x) ` B))"
    by (clarsimp simp: bchoice, metis)
  hence "B. (a,B)  R  (g h. (b  B. (b,g b)  S  (b,h b)  T)  A = ( ((λx. g x) ` B))  ( ((λx. h x) ` B)))"
    by blast
  hence "C D. (B. (a,B)  R  (g. (b  B. (b,g b)  S)  C =  ((λx. g x) ` B)))  (B. (a,B)  R  (h. (b  B. (b,h b)  T)  D =  ((λx. h x)` B)))  A = C  D"
    by blast
  thus "(a,A)  R  S  R  T"
    by (auto simp: mr_simp)
qed

lemma p_id_assoc1: "(1π  R)  S = 1π  (R  S)"
  by simp

lemma p_id_assoc2: "(R  1π)  T = R  (1π  T)"
  by (rule set_eqI, clarsimp simp: mr_simp) fastforce

lemma cl1 [simp]: "R  1π  R  NC = R  U"
  by (rule set_eqI, clarsimp simp: mr_simp, metis UN_constant UN_empty)

lemma tarski_aux:
  assumes "R - 1π  {}"
  and "(a,A)  NC"
  shows "(a,A)  NC  ((R - 1π)  NC)"
  using assms apply (clarsimp simp: mr_simp)
  by (metis UN_constant insert_not_empty singletonD)

lemma tarski:
  assumes "R - 1π  {}"
  shows "NC  ((R - 1π)  NC) = NC"
  by standard (simp add: U_def p_id_def s_prod_def, force, metis assms tarski_aux subrelI)

lemma tarski_var:
  assumes "R  NC  {}"
  shows "NC  ((R  NC)  NC) = NC"
  by (metis assms p_id_NC tarski)

lemma s_le_nc: "1σ  NC"
  by (auto simp: mr_simp)

lemma U_nc [simp]: "U  NC = U"
  by (metis NC_NC cl1 s_prod_distr s_prod_idl s_prod_p_idl)

lemma x_y_split [simp]: "(R  NC)  S  R  {} = R  S"
  by (auto simp: mr_simp)

lemma c_nc_comp1 [simp]: "1π  NC = U"
  using cl1 s_prod_idl by blast

subsection ‹Tests›

lemma s_id_st: "R  1σ = {(a,{a}) |a. (a,{a})  R}"
  by (force simp: mr_simp)

lemma subid_aux2:
  assumes "(a,A)  R  1σ"
  shows "A = {a}"
  using assms by (auto simp: mr_simp)

lemma s_prod_test_aux1:
  assumes "(a,A)  R  (P  1σ)"
  shows "((a,A)  R  (a  A. (a,{a})  (P  1σ)))"
  using assms by (auto simp: mr_simp)

lemma s_prod_test_aux2:
  assumes "(a,A)  R"
  and "a  A. (a,{a})  S"
  shows "(a,A)  R  S"
  using assms by (fastforce simp: mr_simp)

lemma s_prod_test: "(a,A)  R  (P  1σ)  (a,A)  R  (a  A. (a,{a})  (P  1σ))"
  by (meson s_prod_test_aux1 s_prod_test_aux2)

lemma s_prod_test_var: "R  (P  1σ) = {(a,A). (a,A)  R  (a  A. (a,{a})  (P  1σ))}"
  apply (rule antisym)
  by (fastforce simp: mr_simp)+

lemma test_s_prod_aux1:
  assumes "(a,A)  (P  1σ)  R"
  shows "(a,{a})  (P  1σ)  (a,A)  R"
  using assms by (auto simp: mr_simp)

lemma test_s_prod_aux2:
  assumes "(a,A)  R"
  and "(a,{a})  P"
  shows "(a,A)  P  R"
  using assms s_prod_def by fastforce

lemma test_s_prod: "(a,A)  (P  1σ)  R  (a,{a})  (P  1σ)  (a,A)  R"
  by (meson test_s_prod_aux1 test_s_prod_aux2)

lemma test_s_prod_var: "(P  1σ)  R = {(a,A). (a,{a})  (P  1σ)  (a,A)  R}"
  by (simp add: set_eq_iff test_s_prod)

lemma test_assoc1: "(R  (P  1σ))  S = R  ((P  1σ)  S)"
  apply (rule antisym)
  apply (simp add: s_prod_assoc1)
  apply (clarsimp simp: mr_simp)
  by (metis UN_singleton)

lemma test_assoc2: "((P  1σ)  R)  S = (P  1σ)  (R  S)"
  apply (rule antisym)
  apply (simp add: s_prod_assoc1)
  by (fastforce simp: mr_simp s_prod_assoc1)

lemma test_assoc3: "(R  S)  (P  1σ) = R  (S  (P  1σ))"
proof (rule antisym)
  show "(R  S)  (P  1σ)  R  (S  (P  1σ))"
    by (simp add: s_prod_assoc1)
  show "R  (S  (P  1σ))  (R  S)  (P  1σ)"
    proof clarify
    fix a A
    assume hyp1: "(a, A)  R  (S  (P  1σ))"
    hence "B. (a,B)  R  (f. (bB. (b,f b)  S  (P  1σ))  A = ((λx. f x) ` B))"
      by (simp add: s_prod_test s_prod_def)
    hence "B. (a,B)  R  (f. (bB. (b,f b)  S  (af b. (a,{a})  (P  1σ)))  A = ((λx. f x) ` B))"
      by (simp add: s_prod_test)
    hence "B. (a,B)  R  (f. (bB. (b,f b)  S)  (a((λx. f x) ` B). (a,{a})  (P  1σ))  A = ((λx. f x) ` B))"
      by auto
    hence "B. (a,B)  R  (f. (bB. (b,f b)  S)  (aA. (a,{a})  (P  1σ))  A = ((λx. f x) ` B))"
      by auto blast
    hence "(a,A)  R  S  (aA. (a,{a})  (P  1σ))"
      by (auto simp: mr_simp)
    thus "(a,A)  (R  S)  (P  1σ)"
      by (simp add: s_prod_test)
  qed
qed

lemma s_distl_test: "(P  1σ)  (S  T) = (P  1σ)  S  (P  1σ)  T"
  by (fastforce simp: mr_simp)

lemma s_distl_sup_test: "(P  1σ)  X = (S  X. (P  1σ)  S)"
  by (auto simp: mr_simp)

lemma subid_par_idem [simp]: "(P  1σ)  (P  1σ) = (P  1σ)"
  by (auto simp: mr_simp)

lemma seq_conc_subdistrl: "(P  1σ)  (S  T) = ((P  1σ)  S)  ((P  1σ)  T)"
  apply (rule antisym)
  apply (simp add: cl3)
  by (fastforce simp: mr_simp)

lemma test_s_prod_is_meet [simp]: "(P  1σ)  (Q  1σ) = P  Q  1σ"
  by (auto simp: mr_simp)

lemma test_p_prod_is_meet [simp]: "(P  1σ)  (Q  1σ) = (P  1σ)  (Q  1σ)"
  by (auto simp: mr_simp)

lemma test_multipliciativer: "(P  Q  1σ)  T = ((P  1σ)  T)  ((Q  1σ)  T)"
  by (auto simp: mr_simp)

lemma cl9 [simp]: "(R  1σ)  1π  1σ = R  1σ"
  by (auto simp: mr_simp)

lemma s_subid_closed [simp]: "R  NC  1σ = R  1σ"
  using s_le_nc by auto

lemma sub_id_le_nc: "R  1σ  NC"
  by (simp add: le_infI2 s_le_nc)

lemma x_y_prop: "1σ  ((R  NC)  S) = 1σ  R  S"
  by (auto simp: mr_simp)

lemma s_nc_U: "1σ  R  NC = 1σ  R  U"
  by (rule set_eqI, clarsimp simp: mr_simp, metis SUP_constant UN_empty insert_not_empty)

lemma sid_le_nc_var: "1σ  R  1σ  (R  NC)"
  using meet_le_par s_le_nc by fastforce

lemma s_nc_par_U: "1σ  (R  NC) = 1σ  (R  U)"
  by (metis c_nc_comp1 c_prod_idr inf_sup_distrib1 le_iff_sup p_prod_distl sid_le_nc_var)

lemma s_id_par_s_prod: "(P  1σ)  (Q  1σ) = (P  1σ)  (Q  1σ)"
  by force

subsection ‹Parallel subidentities›

lemma p_id_zero_st: "R  1π = {(a,{}) |a. (a,{})  R}"
  by (auto simp: mr_simp)

lemma p_subid_iff: "R  1π  R  1π = R"
  by (clarsimp simp: mr_simp, safe, simp_all) blast+

lemma p_subid_iff_var: "R  1π  R  {} = R"
  by (clarsimp simp: mr_simp, safe, simp_all) blast+

lemma term_par_idem [simp]: "(R  1π)  (R  1π) = (R  1π)"
  by (metis Int_Un_eq(4) c_prod_idr p_prod_distl subidem_par subset_Un_eq)

lemma c1 [simp]: "R  1π  R = R"
  apply (rule set_eqI, clarsimp simp: mr_simp)
  by (metis (no_types, lifting) SUP_bot SUP_bot_conv(2) sup_bot_left)

lemma p_id_zero: "R  1π = R  {}"
  by (auto simp: mr_simp)

lemma cl5: "(R  S)  (T  {}) = R  (S  (T  {}))"
proof (rule antisym)
  show "(R  S)  (T  {})  R  (S  (T  {}))"
    by (metis s_prod_assoc1)
  show " R  (S  (T  {}))  (R  S)  (T  {})"
  proof clarify
    fix a::"'a" and A::"'f set"
    assume "(a,A)  R  (S  (T  {}))"
    hence "B. (a,B)  R  (f. (b  B. ( C. (b,C)  S  (g. (x  C. (x,g x)  T  {})  f b = ((λx. g x) ` C))))  A = ((λx. f x) ` B))"
      by (clarsimp simp: mr_simp)
    hence "B. (a,B)  R  (f. (b  B. ( C. (b,C)  S  (x  C. (x,{})  T  {})  f b = {}))  A = ((λx. f x) ` B))"
      by (clarsimp simp: mr_simp) fastforce
    hence "B. (a,B)  R  (b  B. ( C. (b,C)  S  (x  C. (x,{})  T  {})))  A = {}"
      by fastforce
    hence "B. (a,B)  R  (f. (b  B. (b,f b)  S  (x  f b. (x,{})  T  {})))  A = {}"
      by (metis (mono_tags))
    hence "B. (a,B)  R  (f. (b  B. (b,f b)  S)  (x  ((λx. f x) ` B). (x,{})  T  {}))  A = {}"
      by (metis UN_E)
    hence "C B. (a,B)  R  (f. (b  B. (b, f b)  S)  C = ((λx. f x) ` B)  (x  C. (x,{})  T  {}))  A = {}"
      by metis
    hence "C. (a,C)  R  S  (x  C. (x,{})  T  {})  A = {}"
      by (auto simp: mr_simp)
    thus "(a,A)  (R  S)  (T  {})"
      by (clarsimp simp: mr_simp) blast
  qed
qed

lemma c4: "(R  S)  1π = R  (S  1π)"
proof -
  have "(R  S)  1π = {(a,{}) | a. B. (a,B)  R  S}"
    by (simp add: p_id_st)
  also have " = R  {(a,{}) | a. B. (a,B)  S}"
    apply (clarsimp simp: mr_simp)
    apply safe
    apply blast
    apply clarsimp
    by metis
  also have " = R  (S  1π)"
    by (simp add: p_id_st)
  finally show ?thesis.
qed

lemma c3: "(R  S)  1π = R  1π  S  1π"
  by (simp add: Orderings.order_eq_iff cl4 seq_conc_subdistr)

lemma p_id_idem [simp]: "(R  1π)  1π = R  1π"
  by (simp add: c4)

lemma x_c_par_idem [simp]: "R  1π  R  1π = R  1π"
  by (metis c1 p_id_idem)

lemma x_zero_le_c: "R  {}  1π"
  by (simp add: c4 p_subid_iff)

lemma p_subid_lb1: "R  {}  S  {}  R  {}"
  by (metis c_prod_idr p_prod_isor x_zero_le_c)

lemma p_subid_lb2: "R  {}  S  {}  S  {}"
  using p_prod_comm p_subid_lb1 by blast

lemma p_subid_idem [simp]: "R  {}  R  {} = R  {}"
  by (simp add: p_subid_lb1 subidem_par subset_antisym)

lemma p_subid_glb: "T  {}  R  {}  T  {}  S  {}  T  {}  (R  {})  (S  {})"
  by (auto simp: mr_simp)

lemma p_subid_glb_iff: "T  {}  R  {}  T  {}  S  {}  T  {}  (R  {})  (S  {})"
  by (auto simp: mr_simp)

lemma x_c_glb: "(T::('a,'b) mrel)  1π  (R::('a,'b) mrel)  1π  T  1π  (S::('a,'b) mrel)  1π  T  1π  (R  1π)  (S  1π)"
  by (smt (verit, best) order_subst1 p_id_idem p_prod_isol p_prod_isor s_prod_isol x_c_par_idem)

lemma x_c_lb1: "R  1π  S  1π  R  1π"
  by (metis c6 c_prod_idr p_prod_isor)

lemma x_c_lb2: "R  1π  S  1π  S  1π"
  using p_prod_comm x_c_lb1 by blast

lemma x_c_glb_iff: "(T::('a,'b) mrel)  1π  (R::('a,'b) mrel)  1π  T  1π  (S::('a,'b) mrel)  1π  T  1π  (R  1π)  (S  1π)"
  by (meson subset_trans x_c_glb x_c_lb1 x_c_lb2)

lemma nc_iff1: "R  NC  R  1π = {}"
  by (metis (no_types, lifting) Diff_Diff_Int Int_Diff Int_absorb diff_shunt_var p_id_NC)

lemma nc_iff2: "R  NC  R  {} = {}"
  by (metis c4 nc_iff1 p_id_zero s_prod_zerol)

lemma zero_assoc3: "(R  S)  {} = R  (S  {})"
  by (metis cl5 s_prod_zerol)

lemma x_zero_interr: "R  {}  S  {} = (R  S)  {}"
  by (clarsimp simp: mr_simp) blast

lemma p_subid_interr: "R  T  1π  S  T  1π = (R  S)  T  1π"
proof -
  have "R  T  1π  S  T  1π = (R  {(a,{}) |a. B. (a,B)  T})  (S  {(a,{}) |a. B. (a,B)  T})"
    by (metis c4 p_id_st)
  also have " = (R  S)  {(a,{}) |a. B. (a,B)  T}"
    apply (rule antisym)
    apply (metis cl4 dual_order.refl p_id_st x_c_par_idem)
    by (simp add: seq_conc_subdistr)
  also have " = (R  S)  T  1π"
    by (metis c4 p_id_st)
  finally show ?thesis.
qed

lemma cl2 [simp]: "1π  (R  NC) = R  {}"
  by (metis Diff_disjoint Int_Un_distrib inf_commute p_id_zero sup_bot.right_neutral)

lemma cl6 [simp]: "R  {}  S = R  {}"
  by (metis c4 p_id_assoc2 s_prod_p_idl s_prod_zerol)

lemma cl11 [simp]: "(R  NC)  1π  NC = (R  NC)  NC"
  apply (rule antisym)
  apply (clarsimp simp: mr_simp)
  apply (metis UN_constant)
  apply (clarsimp simp: mr_simp)
  by (metis UN_empty2 UN_insert Un_empty_left equals0I insert_absorb sup_bot_right)

lemma x_split [simp]: "(R  NC)  (R  1π) = R"
  by (metis Un_Diff_Int p_id_NC)

lemma x_split_var [simp]: "(R  NC)  R  {} = R"
  by (metis p_id_zero x_split)

lemma s_x_c [simp]: "1σ  R  1π = {}"
  using c6 s_le_nc by fastforce

lemma s_x_zero [simp]: "1σ  R  {} = {}"
  using cl6 s_x_c by blast

lemma c_nc [simp]: "R  1π  NC = {}"
  using c6 by blast

lemma zero_nc [simp]: "R  {}  NC = {}"
  using x_zero_le_c by fastforce

lemma nc_zero [simp]: "(R  NC)  {} = {}"
  using nc_iff2 by auto

lemma c_def [simp]: "U  {} = 1π"
  by (metis c_nc_comp1 cl2 cl6 inf_commute p_id_zero s_prod_p_idl)

lemma U_c [simp]: "U  1π = 1π"
  by (metis U_U c_def zero_assoc3)

lemma nc_c [simp]: "NC  1π = 1π"
  by (auto simp: mr_simp)

lemma nc_U [simp]: "NC  U = U"
  using NC_NC c_nc_comp1 cl1 nc_c by blast

lemma x_c_nc_split [simp]: "((R  NC)  NC)  (R  {}  NC) = (R  1π)  NC"
  by (metis cl11 p_prod_comm p_prod_distl x_y_split)

lemma x_c_U_split [simp]: "R  U  (R  {}  U) = R  1π  U"
  apply (rule set_eqI, clarsimp simp: mr_simp)
  by (metis SUP_constant UN_extend_simps(2))

lemma p_subid_par_eq_meet [simp]: "R  {}  S  {} = R  {}  S  {}"
  by (auto simp: mr_simp)

lemma p_subid_par_eq_meet_var [simp]: "R  1π  S  1π = R  1π  S  1π"
  by (metis c_def p_subid_par_eq_meet zero_assoc3)

lemma x_zero_add_closed: "R  {}  S  {} = (R  S)  {}"
  by (simp add: s_prod_distr)

lemma x_zero_meet_closed: "R  {}  S  {} = (R  S)  {}"
  by (force simp: mr_simp)

lemma scomp_univalent_pres: "univalent R  univalent S  univalent (R  S)"
  unfolding univalent_set s_prod_def
  apply clarsimp
  by (metis Sup.SUP_cong)

lemma "univalent s_id"
  unfolding univalent_set s_id_def by simp

lemma det_peleg: "deterministic R  deterministic S  deterministic (R  S)"
  unfolding deterministic_set s_prod_def
  apply clarsimp
  apply safe
  apply metis
  apply (metis UN_I)
  by (metis UN_I)

lemma deterministic_sid: "deterministic 1σ"
  unfolding deterministic_set s_id_def by simp


subsection ‹Domain›

definition Dom :: "('a,'b) mrel  ('a,'a) mrel" where
  "Dom R = {(a,{a}) |a. B. (a,B)  R}"

named_theorems mrd_simp
declare mr_simp [mrd_simp] Dom_def [mrd_simp]

lemma d_def_expl: "Dom R = R  1π  1σ"
  by (force simp: mrd_simp set_eqI)

lemma s_subid_iff2: "(R  1σ = R) = (Dom R = R)"
  by (metis c6 cl9 d_def_expl inf.order_iff p_prod_comm p_prod_ild p_prod_isor)

lemma cl8_var: "Dom R  S = R  1π  S"
  apply (rule antisym)
  apply (metis d_def_expl p_id_assoc2 s_prod_idl s_prod_p_idl seq_conc_subdistr)
  by (force simp: mrd_simp)

lemma cl8 [simp]: "R  1π  1σ  S = R  1π  S"
  by simp

lemma cl10_var: "Dom (R - 1π) = 1σ  ((R - 1π)  NC)"
  apply (rule set_eqI, clarsimp simp: mrd_simp)
  apply safe
  apply (metis SUP_constant insert_not_empty)
  by blast

lemma c10: "(R  NC)  1π  1σ = 1σ  ((R  NC)  NC)"
  by (metis Int_Diff cl10_var d_def_expl)

lemma cl9_var [simp]: "Dom (R  1σ) = R  1σ"
  by (simp add: d_def_expl)

lemma d_s_id [simp]: "Dom R  1σ = Dom R"
  by (metis cl8_var d_def_expl p_prod_comm p_prod_ild s_subid_iff2)

lemma d_s_id_ax: "Dom R  1σ"
  by (simp add: le_iff_inf)

lemma d_assoc1: "Dom R  (S  T) = (Dom R  S)  T"
  by (metis d_s_id test_assoc2)

lemma d_meet_distr_var: "(Dom R  Dom S)  T = Dom R  T  Dom S  T"
  by (metis (no_types, lifting) d_s_id inf_assoc test_multipliciativer)

lemma d_idem [simp]: "Dom (Dom R) = Dom R"
  by (meson d_s_id s_subid_iff2)

lemma cd_2_var: "Dom (R  1π)  S = R  1π  S"
  by (simp add: cl8_var p_id_assoc2)

lemma dc_prop1 [simp]: "Dom R  1π = R  1π"
  by (simp add: cl8_var)

lemma dc_prop2 [simp]: "Dom (R  1π) = Dom R"
  by (simp add: d_def_expl p_id_assoc2)

lemma ds_prop [simp]: "Dom R  1σ = Dom R"
  by (simp add: p_prod_assoc d_def_expl)

lemma dc [simp]: "Dom 1π = 1σ"
  by (simp add: d_def_expl)

lemma cd_iso [simp]: "Dom (R  1π)  1π = R  1π"
  by simp

lemma dc_iso [simp]: "Dom (Dom R  1π) = Dom R"
  by simp

lemma d_s_id_inter [simp]: "Dom R  Dom S = Dom R  Dom S"
  by (metis d_s_id inf_assoc test_s_prod_is_meet)

lemma d_conc6: "Dom (R  S) = Dom R  Dom S"
  by (metis (no_types, lifting) c3 d_def_expl ds_prop p_prod_assoc p_prod_comm)

lemma d_conc_inter [simp]: "Dom R  Dom S = Dom R  Dom S"
  by (metis d_s_id test_p_prod_is_meet)

lemma d_conc_s_prod_ax: "Dom R  Dom S = Dom R  Dom S"
  by simp

lemma d_rest_ax [simp]: "Dom R  R = R"
  by (simp add: cl8_var)

lemma d_loc_ax [simp]: "Dom (R  Dom S) = Dom (R  S)"
  by (metis c4 dc_prop1 dc_prop2)

lemma assoc_p_subid: "(R  S)  (T  1π) = R  (S  (T  1π))"
  by (smt (verit, del_insts) c4 cd_iso d_idem d_loc_ax p_id_idem s_subid_iff2 test_assoc3)

lemma d_exp_ax [simp]: "Dom (Dom R  S) = Dom R  Dom S"
  by (metis d_conc6 d_conc_s_prod_ax d_idem d_loc_ax)

lemma d_comm_ax: "Dom R  Dom S = Dom S  Dom R"
  by force

lemma d_s_id_prop [simp]: "Dom 1σ = 1σ"
  by (simp add: d_def_expl)

lemma d_s_prod_closed [simp]: "Dom (Dom R  Dom S) = Dom R  Dom S"
  using d_exp_ax d_loc_ax by blast

lemma d_p_prod_closed [simp]: "Dom (Dom R  Dom S) = Dom R  Dom S"
  using d_s_prod_closed by auto

lemma d_idem2 [simp]: "Dom R  Dom R = Dom R"
  by (metis d_exp_ax d_rest_ax)

lemma d_assoc: "(Dom R  Dom S)  Dom T = Dom R  (Dom S  Dom T)"
  using d_assoc1 by blast

lemma iso_1 [simp]: "Dom R  1π  1σ = Dom R"
  using d_def_expl by force

lemma d_idem_par [simp]: "Dom R  Dom R = Dom R"
  by (simp add: d_conc_s_prod_ax)

lemma d_inter_r: "Dom R  (S  T) = Dom R  S  Dom R  T"
  by (metis d_s_id seq_conc_subdistrl)

lemma d_add_ax: "Dom (R  S) = Dom R  Dom S"
  by (simp add: d_def_expl p_prod_comm p_prod_distl s_prod_distr)

lemma d_sup_add: "Dom (X) = (R  X. Dom R)"
  by (auto simp: mrd_simp)

lemma d_distl: "Dom R  (S  T) = Dom R  S  Dom R  T"
  by (metis d_s_id s_distl_test)

lemma d_sup_distl: "Dom R  X = (S  X. Dom R  S)"
  by (metis d_s_id s_distl_sup_test)

lemma d_zero_ax [simp]: "Dom {} = {}"
  by (simp add: d_def_expl p_prod_comm)

lemma d_absorb1 [simp]: "Dom R  Dom R  Dom S = Dom R"
  by simp

lemma d_absorb2 [simp]: "Dom R  (Dom R  Dom S) = Dom R"
  by (metis d_absorb1 d_idem2 d_s_id s_distl_test)

lemma d_dist1: "Dom R  (Dom S  Dom T) = Dom R  Dom S  Dom R  Dom T"
  by (simp add: cl8_var p_prod_distl)

lemma d_dist2: "Dom R  (Dom S  Dom T) = (Dom R  Dom S)  (Dom R  Dom T)"
  by (smt (verit) boolean_algebra.disj_conj_distrib d_add_ax d_s_id_inter dc_prop2)

lemma d_add_prod_closed [simp]: "Dom (Dom R  Dom S) = Dom R  Dom S"
  by (simp add: d_add_ax)

lemma x_zero_prop: "R  {}  S = Dom (R  {})  S"
  by (simp add: cl8_var)

lemma cda_add_ax: "Dom ((R  S)  T) = Dom (R  T)  Dom (S  T)"
  by (simp add: d_add_ax s_prod_distr)

lemma d_x_zero: "Dom (R  {}) = R  {}  1σ"
  by (simp add: d_def_expl)

lemma cda_ax2:
  assumes "(R  S)  Dom T = R  Dom T  S  Dom T"
  shows "Dom ((R  S)  T) = Dom (R  T)  Dom (S  T)"
  by (metis assms d_conc6 d_conc_s_prod_ax d_loc_ax)

lemma d_lb1: "Dom R  Dom S  Dom R"
  using d_absorb1 by blast

lemma d_lb2: "Dom R  Dom S  Dom S"
  using d_comm_ax d_lb1 by blast

lemma d_glb: "Dom T  Dom R  Dom T  Dom S  Dom T  Dom R  Dom S"
  by simp

lemma d_glb_iff: "Dom T  Dom R  Dom T  Dom S  Dom T  Dom R  Dom S"
  by force

lemma d_interr: "R  Dom P  S  Dom P = (R  S)  Dom P"
  by (simp add: cl4 seq_conc_subdistr subset_antisym)

lemma cl10_d: "Dom (R  NC) = 1σ  (R  NC)  NC"
  by (simp add: c10 d_def_expl)

lemma cl11_d [simp]: "Dom (R  NC)  NC = (R  NC)  NC"
  by (simp add: cl8_var)

lemma cl10_d_var1: "Dom (R  NC) = 1σ  R  NC"
  by (simp add: cl10_d x_y_prop)

lemma cl10_d_var2: "Dom (R  NC) = 1σ  (R  NC)  U"
  by (simp add: cl10_d_var1 s_nc_U x_y_prop)

lemma cl10_d_var3: "Dom (R  NC) = 1σ  R  U"
  by (simp add: cl10_d_var1 s_nc_U)

lemma d_U [simp]: "Dom U = 1σ"
  by (metis U_c dc dc_prop2)

lemma d_nc [simp]: "Dom NC = 1σ"
  by (metis dc dc_prop2 nc_c)

lemma alt_d_def_nc_nc: "Dom (R  NC) = 1σ  (((R  NC)  1π)  NC)"
  using c10 cl11_d cl8_var d_def_expl by blast

lemma alt_d_def_nc_U: "Dom (R  NC) = 1σ  (((R  NC)  1π)  U)"
  using alt_d_def_nc_nc s_nc_par_U by blast

lemma d_def_split [simp]: "Dom (R  NC)  Dom (R  {}) = Dom R"
  by (metis d_add_ax d_loc_ax d_zero_ax p_id_zero x_split)

lemma d_def_split_var [simp]: "Dom (R  NC)  ((R  {})  1σ) = Dom R"
  using d_def_split d_x_zero by blast

lemma ax7 [simp]: "(1σ  R  U)  (R  {}  1σ) = Dom R"
  using cl10_d_var3 d_def_split d_x_zero by blast

lemma dom12_d: "Dom R = 1σ  (R  1π  NC)"
  by (metis cl10_d_var3 cl8_var d_idem d_s_id inf.orderE s_nc_par_U sub_id_le_nc)

lemma dom12_d_U: "Dom R = 1σ  (R  1π  U)"
  by (simp add: dom12_d s_nc_par_U)

lemma dom_def_var: "Dom R = (R  U  1π)  1σ"
  by (simp add: d_def_expl p_id_zero zero_assoc3)

lemma ax5_d [simp]: "Dom (R  NC)  U = (R  NC)  U"
  by (metis cl1 cl11_d dc_prop1)

lemma ax5_0 [simp]: "Dom (R  {})  U = R  {}  U"
  using x_zero_prop by auto

lemma x_c_U_split2: "Dom R  NC = (R  NC)  NC  (R  {}  NC)"
  by (simp add: cl8_var)

lemma x_c_U_split3: "Dom R  U = (R  NC)  U  (R  {}  U)"
  by (metis ax5_0 ax5_d d_def_split s_prod_distr)

lemma x_c_U_split_d: "Dom R  U = R  U  (R  {}  U)"
  by (simp add: cl8_var)

lemma x_U_prop2: "R  NC = Dom (R  NC)  NC  R  {}"
  by simp

lemma x_U_prop3: "R  U = Dom (R  NC)  U  R  {}"
  by (metis ax5_d x_y_split)

lemma d_x_nc [simp]: "Dom (R  NC) = Dom R"
  by (metis d_loc_ax d_nc dc dc_prop2)

lemma d_x_U [simp]: "Dom (R  U) = Dom R"
  by (metis d_U d_loc_ax dc dc_prop2)

lemma d_llp1: "Dom R  Dom S  R  Dom S  R"
  by (metis d_rest_ax s_prod_isol)

lemma d_llp2: "R  Dom S  R  Dom R  Dom S"
  by (metis d_assoc1 d_exp_ax d_meet_distr_var d_rest_ax d_s_id_inter inf.absorb_iff2)

lemma demod1: "Dom (R  S)  Dom T  R  Dom S  Dom T  R"
proof -
  assume h: "Dom (R  S)  Dom T"
  have "R  Dom S = Dom (R  Dom S)  (R  Dom S)"
    using d_rest_ax by blast
  also have "  Dom T  (R  Dom S)"
    by (metis d_loc_ax h s_prod_distr subset_Un_eq)
  also have "  Dom T  R"
    by (metis d_s_id_ax s_prod_idr s_prod_isor)
  finally show "R  Dom S  Dom T  R".
qed

lemma demod2: "R  Dom S  Dom T  R  Dom (R  S)  Dom T"
proof -
  assume h: "R  Dom S  Dom T  R"
  have "Dom (R  S) = Dom (R  Dom S)"
    by auto
  also have "  Dom (Dom T  R)"
    by (metis d_add_ax h subset_Un_eq)
  also have " = Dom T  Dom R"
    by simp
  also have "  Dom T"
    by (simp add: d_lb1)
  finally show "Dom (R  S)  Dom T".
qed

lemma d_meet_closed [simp]: "Dom (Dom x  Dom y) = Dom x  Dom y"
  by (metis d_s_id inf_assoc s_subid_iff2)

lemma d_add_var: "Dom P  R  Dom Q  R = Dom (P  Q)  R"
  by (simp add: d_add_ax s_prod_distr)

lemma d_interr_U: "Dom x  U  Dom y  U = Dom (x  y)  U"
  by (metis U_nc U_par_idem cl4 d_conc6 seq_conc_subdistr subset_antisym)

lemma d_meet: "Dom x  z  Dom y  z = (Dom x  Dom y)  z"
  by (simp add: d_meet_distr_var)

lemma cs_hom_meet: "Dom (x  1π  y  1π) = Dom (x  1π)  Dom (y  1π)"
  by (metis d_conc6 d_conc_inter dc_prop2 p_subid_par_eq_meet_var)

lemma iso3 [simp]: "Dom (Dom x  U) = Dom x "
  by simp

lemma iso4 [simp]: "Dom (x  1π  U)  U = x  1π  U"
  by (metis cl8_var iso3)

lemma iso3_sharp [simp]: "Dom (Dom (x  NC)  NC) = Dom (x  NC)"
  by simp

lemma iso4_sharp [simp]: "Dom ((x  NC)  NC)  NC = (x  NC)  NC"
  by simp

subsection ‹Vectors›

lemma vec_iff1:
  assumes "a. (A. (a,A)  R)  (A. (a,A)  R)"
  shows "R  1π  U = R"
  using assms by (auto simp: mr_simp)

lemma vec_iff2:
  assumes "R  1π  U = R"
  shows "(a. (A. (a,A)  R)  (A. (a,A)  R))"
  using assms apply (clarsimp simp: mr_simp)
  by (smt (z3) SUP_bot case_prod_conv mem_Collect_eq sup_bot_left)

lemma vec_iff: "(a. (A. (a,A)  R)  (A. (a,A)  R))  R  1π  U = R"
  by (metis vec_iff1 vec_iff2)

lemma U_par_zero [simp]: "{}  R  U = {}"
  by (simp add: p_prod_comm)

lemma U_par_s_id [simp]: "1σ  1π  U = U"
  by auto

lemma U_par_p_id [simp]: "1π  1π  U = U"
  by auto

lemma U_par_nc [simp]: "NC  1π  U = U"
  by auto


subsection ‹Up-closure and Parikh composition›

definition s_prod_pa :: "('a,'b) mrel  ('b,'c) mrel  ('a,'c) mrel" (infixl "" 75) where
  "R  S = {(a,A). (B. (a,B)  R  (b  B. (b,A)  S))}"

lemma U_par_st: "(a,A)  R  U  (B. B  A  (a,B)  R)"
  by (auto simp: mr_simp)

lemma p_id_U: "R  U = {(a,B). A. (a,A)  R  A  B}"
  by (clarsimp simp: mr_simp) blast

lemma ucl_iff: "(a A B. (a,A)  R  A  B  (a,B)  R)  R  U = R"
  by (clarsimp simp: mr_simp) blast

lemma upclosed_ext: "R  R  U"
  by (clarsimp simp: mr_simp) blast

lemma onelem: "R  S  U  R  (S  U)"
  by (auto simp: s_prod_def p_prod_def U_def s_prod_pa_def)

lemma twolem: "R  (S  U)  R  S  U"
proof clarify
  fix a A
  assume "(a,A)  R  (S  U)"
  hence "B. (a,B)  R  (b  B. (b,A)  S  U)"
    by (auto simp: s_prod_pa_def)
  hence "B. (a,B)  R  (b  B. C. C  A  (b,C)  S)"
    by (clarsimp simp: mr_simp) blast
  hence "B. (a,B)  R  (f. (b  B. f b  A  (b,f b)  S))"
    by metis
  hence "C. C  A  (B. (a,B)  R  (f. (b  B. (b,f b)  S)  C =  ((λx. f x) ` B)))"
    by clarsimp blast
  hence "C. C  A  (a,C)  R  S"
    by (clarsimp simp: mr_simp)
  thus "(a,A)  (R  S)  U"
    by (clarsimp simp: mr_simp) blast
  qed

lemma pe_pa_sim: "R  S  U = R  (S  U)"
  by (metis antisym onelem twolem)

lemma pe_pa_sim_var: "(R  U)  (S  U)  U = (R  U)  (S  U)"
  apply (rule order.antisym)
  by (simp add: p_prod_assoc pe_pa_sim)+

lemma pa_assoc1: "((R  U)  (S  U))  (T  U)  (R  U)  ((S  U)  (T  U))"
  by (clarsimp simp: p_prod_def s_prod_pa_def U_def, metis)

lemma up_closed_par_is_meet: "(R  U)  (S  U) = (R  U)  (S  U)"
  by (auto simp: mr_simp)

lemma U_nc_par [simp]: "NC  U = NC"
  by (metis c_nc_comp1 c_prod_idr nc_par_idem p_prod_distl sup_idem)

lemma uc_par_meet: "(R  U)  (S  U) = R  U  S  U"
  using p_prod_assoc up_closed_par_is_meet by blast

lemma uc_unc [simp]: "R  U  R  U = R  U"
  using uc_par_meet by auto

lemma uc_interr: "(R  S)  (T  U) = R  (T  U)  S  (T  U)"
  by (simp add: Orderings.order_eq_iff cl4 seq_conc_subdistr up_closed_par_is_meet)

lemma iso5 [simp]: "(R  1π  U)  1π = R  1π"
  by (simp add: c3)

lemma iso6 [simp]: "(R  1π  U)  1π  U = R  1π  U"
  by simp

lemma sv_hom_par: "(R  S)  U = R  U  S  U"
  by (metis U_par_idem uc_interr)

lemma vs_hom_meet: "Dom ((R  1π  U)  (S  1π  U)) = Dom (R  1π  U)  Dom (S  1π  U)"
  by (metis d_conc6 d_conc_inter dc_prop2 iso5 up_closed_par_is_meet)

lemma cv_hom_meet: "(R  1π  S  1π)  U = (R  1π  U)  (S  1π  U)"
  by (metis U_par_idem p_prod_assoc p_prod_comm p_subid_par_eq_meet_var uc_par_meet)

lemma cv_hom_par [simp]: " R  U  S  U = (R  S)  U"
  by (metis U_par_idem p_prod_assoc p_prod_comm)

lemma vc_hom_meet: "((R  1π  U)  (S  1π  U))  1π = ((R  1π  U)  1π)  ((S  1π  U)  1π)"
  by (metis c4 cl8_var cv_hom_meet iso5 p_subid_par_eq_meet_var)

lemma vc_hom_seq: "((R  1π  U)  (S  1π  U))  1π = ((R  1π  U)  1π)  ((S  1π  U)  1π)"
proof -
  have "((R  1π  U)  (S  1π  U))  1π = (R  1π  U)  (S  1π)"
    by (metis c4 iso5)
  also have "... = R  1π  U  (S  1π)"
    by (metis cl8_var d_assoc1)
  also have "... = R  1π  (NC  (S  1π)  1π  (S  1π))"
    by (metis c_nc_comp1 s_prod_distr sup_commute)
  also have "... = R  1π  1π"
    by (metis Un_absorb1 c4 c6 s_prod_p_idl)
  thus ?thesis
    by (simp add: assoc_p_subid calculation)
qed


subsection ‹Nonterminal and terminal multirelations›

definition tau :: "('a,'b) mrel  ('a,'b) mrel" ("τ") where
  "τ R = R  {}"

definition nu :: "('a,'b) mrel  ('a,'b) mrel" ("ν") where
  "ν R = R  NC"

lemma nc_s [simp]: "ν 1σ = 1σ"
  using nu_def s_le_nc by auto

lemma nc_scomp_closed: "ν R  ν S  NC"
  by (simp add: nu_def nc_iff1 p_id_zero zero_assoc3)

lemma nc_scomp_closed_alt [simp]: "ν (ν R  ν S) = ν R  ν S"
  by (metis inf.orderE nc_scomp_closed nu_def)

lemma nc_ccomp_closed: "ν R  ν S  NC"
  unfolding nu_def by (clarsimp simp: mr_simp)

lemma nc_ccomp_closed_alt [simp]: "ν (R  ν S) = R  ν S"
  unfolding nu_def by (clarsimp simp: mr_simp) blast

lemma tarski_prod: "(ν R  NC)  (ν S  NC) = (if ν S = {} then {} else ν R  NC)"
proof (cases "ν S = {}")
  case True
  show ?thesis
    by (metis True nc_zero nu_def p_id_NC s_prod_zerol zero_assoc3)
next
  case False
  hence a: "NC  (ν S  NC) = NC"
    unfolding nu_def by (metis p_id_NC tarski)
  have "(ν R  NC)  (ν S  NC) = (Dom (ν R)  NC)  (ν S  NC)"
    by (simp add: nu_def)
  also have "... = Dom (ν R)  (NC  (ν S  NC))"
    using d_assoc1 by blast
  also have "... = Dom (ν R)  NC"
    by (simp add: a)
  also have "... = ν R  NC"
    by (simp add: nu_def)
  finally have "(ν R  NC)  (ν S  NC) = ν R  NC".
  thus ?thesis
    using False by auto
qed

lemma nc_prod_aux [simp]: "(ν R  NC)  NC = ν R  NC"
  apply (clarsimp simp: mr_simp)
  apply safe
  apply clarsimp
  apply (smt (verit) SUP_bot_conv(1) ex_in_conv)
  apply clarsimp
  by (smt (verit, best) SUP_bot_conv(2) UNIV_I UN_constant)

lemma nc_vec_add_closed: "(ν R  NC  ν S  NC)  NC = ν R  NC  ν S  NC"
  by (simp add: s_prod_distr)

lemma nc_vec_par_is_meet: "ν R  NC  ν S  NC = ν R  NC  ν S  NC"
  by (metis (no_types, lifting) U_nc_par cl11 nu_def p_prod_assoc up_closed_par_is_meet)

lemma nc_vec_meet_closed: "(ν R  NC  ν S  NC)  NC = ν R  NC  ν S  NC"
  apply (clarsimp simp: nu_def mr_simp)
  apply safe
  apply (metis SUP_const UN_I ex_in_conv)
  apply (clarsimp, smt (verit) SUP_bot_conv(2) ex_in_conv)
  by (clarsimp, smt (verit, ccfv_threshold) SUP_bot_conv(1) SUP_const UNIV_I all_not_in_conv)

lemma nc_vec_par_closed: "(ν R  NC  ν S  NC)  NC = ν R  NC  ν S  NC"
  by (metis U_nc_par nc_prod_aux uc_interr)

lemma nc_vec_seq_closed: "((ν R  NC)  (ν S  NC))  NC = (ν R  NC)  (ν S  NC)"
proof (cases "ν S = {}")
  case True thus ?thesis
    by simp
next
  case False thus ?thesis
    by (simp add: tarski_prod)
qed

lemma iso5_sharp [simp]: "(ν R  1π  NC)  1π = ν R  1π"
  by (simp add: c3)

lemma iso6_sharp [simp]: "(ν R  NC  1π)  NC = ν R  NC"
  by (simp add: c4 nu_def)

lemma nsv_hom_par: "(R  S)  NC = R  NC  S  NC"
  by (simp add: cl4 seq_conc_subdistr subset_antisym)

lemma nvs_hom_meet: "Dom (ν R  NC  ν S  NC) = Dom (ν R  NC)  Dom (ν S  NC)"
  by (rule antisym) (fastforce simp: nu_def mrd_simp)+

lemma ncv_hom_meet: "R  1π  S  1π  NC = (R  1π  NC)  (S  1π  NC)"
  by (metis c4 cl8_var d_exp_ax d_meet d_s_id_inter p_subid_par_eq_meet_var)

lemma ncv_hom_par: "(R  S)  NC = R  NC  S  NC"
  by (metis nc_par_idem p_prod_assoc p_prod_comm)

lemma nvc_hom_meet: "(ν R  NC  ν S  NC)  1π = (ν R  NC)  1π  (ν S  NC)  1π"
  by (rule antisym) (fastforce simp: nu_def mr_simp)+

lemma tau_int: "τ R  R"
  using p_id_zero tau_def by auto

lemma nu_int: "ν R  R"
  by (simp add: nu_def)

lemma tau_ret [simp]: "τ (τ R) = τ R"
  by (simp add: tau_def)

lemma nu_ret [simp]: "ν (ν R) = ν R"
  by (simp add: nu_def)

lemma tau_iso: "R  S  τ R  τ S"
  by (simp add: inf.order_iff tau_def x_zero_meet_closed)

lemma nu_iso: "R  S  ν R  ν S"
  by (metis Int_mono nu_def order_refl)

lemma tau_zero [simp]: "τ {} = {}"
  by (simp add: tau_def)

lemma nu_zero [simp]: "ν {} = {}"
  using nu_def by auto

lemma tau_s [simp]: "τ 1σ = {}"
  by (simp add: tau_def)

lemma tau_c [simp]: "τ 1π = 1π"
  by (simp add: tau_def)

lemma nu_c [simp]: "ν 1π = {}"
  by (simp add: nu_def)

lemma tau_nc [simp]: "τ NC = {}"
  by (metis nc_iff2 order_refl tau_def)

lemma nu_nc [simp]: "ν NC = NC"
  using nu_def by auto

lemma tau_U [simp]: "τ U = 1π"
  by (simp add: tau_def)

lemma nu_U [simp]: "ν U = NC"
  by (simp add: Diff_eq nu_def)

lemma tau_add [simp]: "τ (R  S) = τ R  τ S"
  by (simp add: tau_def x_zero_add_closed)

lemma nu_add [simp]: "ν (R  S) = ν R  ν S"
  by (simp add: Int_Un_distrib2 nu_def)

lemma tau_meet [simp]: "τ (R  S) = τ R  τ S"
  by (simp add: tau_def x_zero_meet_closed)

lemma nu_meet [simp]: "ν (R  S) = ν R  ν S"
  by (simp add: inf_commute inf_left_commute nu_def)

lemma tau_seq: "τ (R  S) = τ R  ν R  τ S"
  unfolding nu_def tau_def
  by (metis sup_commute x_y_split zero_assoc3)

lemma tau_par [simp]: "τ (R  S) = τ R  τ S"
  by (metis U_par_zero tau_def uc_interr)

lemma nu_par_aux1: "R  τ S = Dom (τ S)  R"
  by (metis p_prod_comm tau_def x_zero_prop)

lemma nu_par_aux3 [simp]: "ν (ν R  τ S) = ν R  τ S"
  by (metis nc_ccomp_closed_alt p_prod_comm)

lemma nu_par_aux4 [simp]: "ν (τ R  τ S) = {}"
  by (metis nu_def tau_def tau_par zero_nc)

lemma nu_par: "ν (R  S) = Dom (τ R)  ν S  Dom (τ S)  ν R  (ν R  ν S)"
  apply (rule antisym)
  apply (fastforce simp: mrd_simp nu_def tau_def)
  by (auto simp: mrd_simp nu_def tau_def)

lemma sprod_tau_nu: "R  S = τ R  ν R  S"
  by (metis nu_def sup_commute tau_def x_y_split)

lemma pprod_tau_nu: "R  S = (ν R  ν S)  Dom (τ R)  ν S  Dom (τ S)  ν R  (τ R  τ S)"
  by (smt (verit) nu_def nu_par sup_assoc sup_left_commute tau_def tau_par x_split_var)

lemma tau_idem [simp]: "τ R  τ R = τ R"
  by (simp add: tau_def)

lemma tau_interr: "(R  S)  τ T = R  τ T  S  τ T"
  by (simp add: tau_def cl4 seq_conc_subdistr subset_antisym)

lemma tau_le_c: "τ R  1π"
  by (simp add: tau_def x_zero_le_c)

lemma c_le_tauc: "1π  τ 1π"
  by simp

lemma x_alpha_tau [simp]: "ν R  τ R = R"
  by (simp add: nu_def tau_def)

lemma alpha_tau_zero [simp]: "ν (τ R) = {}"
  by (simp add: nu_def tau_def)

lemma tau_alpha_zero [simp]: "τ (ν R) = {}"
  by (simp add: nu_def tau_def)

lemma sprod_tau_nu_var [simp]: "ν (ν R  S) = ν (R  S)"
  by (metis nu_add nu_def nu_ret x_y_split zero_nc)

lemma tau_s_prod [simp]: "τ (R  S) = R  τ S"
  by (simp add: tau_def zero_assoc3)

lemma alpha_fp: "ν R = R  R  {} = {}"
  by (metis inf.orderE nc_iff2 nc_zero nu_def)

lemma p_prod_tau_alpha: "R  S = (R  ν S)  (ν R  S)  (τ R  τ S)"
  by (smt (verit) p_prod_comm p_prod_distl sup.idem sup_assoc sup_commute x_alpha_tau)

lemma p_prod_tau_alpha_var: "R  S = (R  ν S)  (ν R  S)  τ (R  S)"
  using p_prod_tau_alpha tau_par by blast

lemma alpha_par: "ν (R  S) = (ν R  S)  (R  ν S)"
  by (metis alpha_tau_zero nc_ccomp_closed_alt nu_add p_prod_comm p_prod_tau_alpha sup_bot_right tau_par)

lemma alpha_tau [simp]: "ν (R  τ S) = {}"
  by (metis alpha_tau_zero tau_s_prod)

lemma nu_par_prop: "ν R = R  ν (R  S) = R  S"
  by (metis nc_ccomp_closed_alt p_prod_comm)

lemma tau_seq_prop: "τ R = R  R  S = R"
  by (metis cl6 tau_def)

lemma tau_seq_prop2: "τ R = R  τ (R  S) = R  S"
  by (metis cl6 tau_def)

lemma d_nu: "ν (Dom R  S) = Dom R  ν S"
  by (auto simp: nu_def mrd_simp)

lemma nu_ideal1: "ν R = R  S  R  ν S = S"
  unfolding nu_def by blast

lemma tau_ideal1: "τ R = R  S  R  τ S = S"
  by (metis dual_order.trans p_subid_iff_var tau_def)

lemma nu_ideal2: "ν R = R  ν S = S  ν (R  S) = R  S"
  by simp

lemma tau_ideal2: "τ R = R  τ S = S  τ (R  S) = R  S"
  by simp

lemma tau_add_precong: "τ R  τ S  τ (R  T)  τ (S  T)"
  by auto

lemma tau_meet_precong: "τ R  τ S  τ (R  T)  τ (S  T)"
  by force

lemma tau_par_precong: "τ R  τ S  τ (R  T)  τ (S  T)"
  by (simp add: p_prod_isol)

lemma tau_seq_precongl: "τ R  τ S  τ (T  R)  τ (T  S)"
  by (simp add: s_prod_isor)

lemma nu_add_precong: "ν R  ν S  ν (R  T)  ν (S  T)"
  by auto

lemma nu_meet_precong: "ν R  ν S  ν (R  T)  ν (S  T)"
  by force

lemma nu_seq_precongr: "ν R  ν S  ν (R  T)  ν (S  T)"
  by (metis nu_iso s_prod_isol sprod_tau_nu_var)

definition
  "tcg R S = (τ R  τ S  τ S  τ R)"

definition
  "ncg R S = (ν R  ν S  ν S  ν R)"

lemma tcg_refl: "tcg R R"
  by (simp add: tcg_def)

lemma tcg_trans: "tcg R S  tcg S T  tcg R T"
  by (meson subset_trans tcg_def)

lemma tcg_sym: "tcg R S  tcg S R"
  by (simp add: tcg_def)

lemma ncg_refl: "ncg R R"
  using ncg_def by blast

lemma ncg_trans: "ncg R S  ncg S T  ncg R T"
  by (meson ncg_def order_trans)

lemma ncg_sym: "ncg R S  ncg S R"
  by (simp add: ncg_def)

lemma tcg_alt: "tcg R S = (τ R = τ S)"
  using tcg_def by auto

lemma ncg_alt: "ncg R S = (ν R = ν S)"
  by (simp add: Orderings.order_eq_iff ncg_def)

lemma tcg_add: "τ R = τ S  τ (R  T) = τ (S  T)"
  by simp

lemma tcg_meet: "τ R = τ S  τ (R  T) = τ (S  T)"
  by simp

lemma tcg_par: "τ R = τ S  τ (R  T) = τ (S  T)"
  by simp

lemma tcg_seql: "τ R = τ S  τ (T  R) = τ (T  S)"
  by simp

lemma ncg_add: "ν R = ν S  ν (R  T) = ν (S  T)"
  by simp

lemma ncg_meet: "ν R = ν S  ν (R  T) = ν (S  T)"
  by simp

lemma ncg_seqr: "ν R = ν S  ν (R  T) = ν (S  T)"
  by (metis sprod_tau_nu_var)


subsection ‹Powers›

primrec p_power :: "('a,'a) mrel  nat  ('a,'a) mrel" where
  "p_power R 0       = 1σ" |
  "p_power R (Suc n) = R  p_power R n"

primrec power_rd :: "('a,'a) mrel  nat  ('a,'a) mrel" where
  "power_rd R 0       = {}" |
  "power_rd R (Suc n) = 1σ  R  power_rd R n"

primrec power_sq :: "('a,'a) mrel  nat  ('a,'a) mrel" where
  "power_sq R 0       = 1σ" |
  "power_sq R (Suc n) = 1σ  R  power_sq R n"

lemma power_rd_chain: "power_rd R n  power_rd R (n + 1)"
  apply (induct n)
  apply simp
  by (smt (verit, best) Suc_eq_plus1 Un_subset_iff le_iff_sup power_rd.simps(2) s_prod_subdistl subsetI)

lemma power_sq_chain: "power_sq R n  power_sq R (n + 1)"
  apply (induct n)
  apply clarsimp
  by (smt (verit, ccfv_SIG) UnCI Un_subset_iff add.commute le_iff_sup plus_1_eq_Suc power_sq.simps(2) s_prod_subdistl subsetI)

lemma pow_chain: "p_power (1σ  R) n  p_power (1σ  R) (n + 1)"
  apply (induct n)
  apply simp
  by (simp add: s_prod_isor)

lemma pow_prop: "p_power (1σ  R) (n + 1) = 1σ  R  p_power (1σ  R) n"
  apply (induct n)
  apply simp
  by (smt (verit, best) add.commute p_power.simps(2) plus_1_eq_Suc s_prod_distr s_prod_idl s_prod_subdistl subset_antisym sup.commute sup.left_commute sup.right_idem sup_ge1)

lemma power_rd_le_sq: "power_rd R n  power_sq R n"
  apply (induct n)
  apply simp
  by (smt (verit, best) UnCI UnE le_iff_sup power_rd.simps(2) power_sq.simps(2) s_prod_subdistl subsetI)

lemma power_sq_le_rd: "power_sq R n  power_rd R (Suc n)"
  apply (induct n)
  apply simp
  by (smt (verit, del_insts) UnCI UnE power_rd.simps(2) power_sq.simps(2) s_prod_subdistl subsetI sup.absorb_iff1)

lemma power_sq_power: "power_sq R n = p_power (1σ  R) n"
  apply (induct n)
  apply simp
  using pow_prop by auto


subsection ‹Star›

lemma iso_prop: "mono (λX. S  R  X)"
  by (rule monoI, (clarsimp simp: mr_simp), blast)

lemma gfp_lfp_prop: "gfp (λX. R  X)  lfp (λX. S  R  X)  gfp (λX. S  R  X)"
  by (simp add: lfp_le_gfp gfp_mono iso_prop)

definition star :: "('a,'a) mrel  ('a,'a) mrel" where
  "star R = lfp (λX. s_id  R  X)"

lemma star_unfold: "1σ  R  star R  star R"
  unfolding star_def using iso_prop lfp_unfold by blast

lemma star_induct: "1σ  R  S  S  star R  S"
  unfolding star_def by (meson lfp_lowerbound)

lemma star_refl: "1σ  star R"
  using star_unfold by auto

lemma star_unfold_part: "R  star R  star R"
  using star_unfold by auto

lemma star_ext_aux: "R  R  star R"
  by (metis s_prod_idr s_prod_isor star_refl)

lemma star_ext: "R  star R"
  using star_ext_aux star_unfold_part by blast

lemma star_co_trans: "star R  star R  star R"
  by (metis s_prod_idr s_prod_isor star_refl)

lemma star_iso: "R  S  star R  star S"
  by (metis (no_types, lifting) le_sup_iff s_prod_distr star_induct star_refl star_unfold_part subset_Un_eq)

lemma star_unfold_eq [simp]: "1σ  R  star R = star R"
  by (metis iso_prop lfp_unfold star_def)

lemma nu_star1:
  assumes "(R::('a,'a) mrel) (S::('a,'a) mrel) (T::('a,'a) mrel). R  (S  T) = (R  S)  T"
  shows "star (R::('a,'a) mrel)  star (ν R)  (1σ  τ R)"
  by (smt (verit, ccfv_threshold) assms s_prod_distr s_prod_idl sprod_tau_nu star_induct star_unfold_eq subsetI sup_assoc)

lemma nu_star2:
  assumes "(R::('a,'a) mrel). star R  star R  star R"
  shows "star (ν (R::('a,'a) mrel))  (1σ  τ R)  star R"
  by (smt (verit) assms le_sup_iff nu_int s_prod_isol s_prod_isor star_ext star_refl star_iso subset_trans tau_int)

lemma nu_star:
  assumes "(R::('a,'a) mrel). star R  star R  star R"
  and "(R::('a,'a) mrel) (S::('a,'a) mrel) (T::('a,'a) mrel). R  (S  T) = (R  S)  T"
  shows "star (ν (R::('a,'a) mrel))  (1σ  τ R) = star R"
  using assms nu_star1 nu_star2 by blast

lemma tau_star: "star (τ R) = 1σ  τ R"
  by (metis cl6 tau_def star_unfold_eq)

lemma tau_star_var:
  assumes "(R::('a,'a) mrel) (S::('a,'a) mrel) (T::('a,'a) mrel). R  (S  T) = (R  S)  T"
  and "(R::('a,'a) mrel). star R  star R  star R"
  shows "τ (star (R::('a,'a) mrel)) = star (ν R)  τ R"
  by (metis (mono_tags, lifting) assms nu_star s_prod_distr s_prod_zerol sup_bot_left tau_def tau_s)

lemma nu_star_sub: "star (ν R)  ν (star R)"
proof -
  have a: "1σ  star R"
    by (simp add: star_refl)
  have b: "(R  NC)  (star R  NC)  star R"
    by (metis nu_def nu_int s_prod_isol s_prod_isor star_unfold_part subset_trans)
  have c: "1σ  NC"
    by (simp add: s_le_nc)
  have "(R  NC)  (star R  NC)  NC"
    by (metis nc_scomp_closed nu_def)
  thus ?thesis
    by (metis Un_least a b c le_infI nu_def star_induct)
qed

lemma nu_star_nu [simp]: "ν (star (ν R)) = star (ν R)"
  using nu_int nu_star_sub by fastforce

lemma nu_star_tau [simp]: "ν (star (τ R)) = 1σ"
  using tau_star by (metis alpha_tau_zero nu_add tau_s x_alpha_tau)

lemma tau_star_tau [simp]: "τ (star (τ R)) = τ R"
  by (simp add: tau_star)

lemma tau_star_nu [simp]: "τ (star (ν R)) = {}"
  using alpha_fp tau_def nu_star_nu by metis

lemma d_star_unfold [simp]: "Dom S  Dom (R  Dom (star R  S)) = Dom (star R  S)"
proof -
  have "Dom S  Dom (R  Dom (star R  S)) = Dom S  Dom (R  (star R  Dom S))"
    by (metis d_loc_ax)
  also have "... = Dom (1σ  Dom S  (R  (star R  Dom S)))"
    by (simp add: d_add_ax)
  also have "... = Dom (1σ  Dom S  (R  star R)  Dom S)"
    by (metis d_comm_ax d_s_id_inter d_s_id_prop s_prod_idl test_assoc3)
  moreover have "... = Dom ((1σ  R  star R)  Dom S)"
    using s_prod_distr by metis
  ultimately show ?thesis
    by simp
qed

lemma d_star_sim1:
  assumes "R S T. Dom (T::('a,'b) mrel)  (R::('a,'a) mrel)  (S::('a,'a) mrel)  S  star R  Dom T  S"
  shows "(R::('a,'a) mrel)  Dom (T::('a,'b) mrel)  Dom T  (S::('a,'a) mrel)  star R  Dom T  Dom T  star S"
proof -
  fix R S::"('a,'a) mrel" and T ::"('a,'b) mrel"
  assume a: "R  Dom T  Dom T  S"
  hence "(R  Dom T)  star S  (Dom T  S)  star S"
    by (simp add: s_prod_isol)
  hence b: "R  (Dom T  star S)  Dom T  (S  star S)"
    by (metis d_assoc1 d_s_id_ax inf.order_iff test_assoc1)
  hence "R  (Dom T  star S)  Dom T  star S"
    by (meson order_trans s_prod_isor star_unfold_part)
  hence "Dom T  R  (Dom T  star S)  Dom T  star S"
    by (metis le_supI s_prod_idr s_prod_isor star_refl)
  thus "star R  Dom T  Dom T  star S"
    using assms by presburger
qed

lemma d_star_induct:
  assumes "R S T. Dom (T::('a,'b) mrel)  (R::('a,'a) mrel)  (S::('a,'a) mrel)  S  star R  Dom T  S"
  shows "Dom ((R::('a,'a) mrel)  (S::('a,'a) mrel))  Dom S  Dom (star R  S)  Dom S"
  by (metis assms d_star_sim1 dc_prop2 demod1 demod2)


subsection ‹Omega›

definition omega :: "('a,'a) mrel  ('a,'a) mrel" where
  "omega R  gfp (λX. R  X)"

lemma om_unfold: "omega R  R  omega R"
  unfolding omega_def
  by (metis (no_types, lifting) gfp_least gfp_upperbound order_trans s_prod_isor)

lemma om_coinduct: "S  R  S  S  omega R"
  unfolding omega_def by (simp add: gfp_upperbound omega_def)

lemma om_unfold_eq [simp]: "R  omega R = omega R"
  by (rule antisym) (auto simp: om_coinduct om_unfold s_prod_isor)

lemma om_iso: "R  S  omega R  omega S"
  by (metis om_coinduct s_prod_isol om_unfold_eq)

lemma zero_om [simp]: "omega {} = {}"
  using om_unfold_eq s_prod_zerol by blast

lemma s_id_om [simp]: "omega 1σ = U"
  by (simp add: U_def eq_iff om_coinduct)

lemma p_id_om [simp]: "omega 1π = 1π"
  using om_unfold_eq s_prod_p_idl by blast

lemma nc_om [simp]: "omega NC = U"
  by (metis dual_order.refl nc_U om_coinduct s_id_om s_prod_idl subset_antisym)

lemma U_om [simp]: "omega U = U"
  by (metis U_U dual_order.refl om_coinduct s_id_om s_prod_idl subset_antisym)

lemma tau_om1: "τ R  τ (omega R)"
  by (metis om_unfold_eq order_refl sup.boundedE tau_seq)

lemma tau_om2 [simp]: "omega (τ R) = τ R"
  by (metis cl6 om_unfold_eq tau_def)

lemma tau_om3: "omega (τ R)  τ (omega R)"
  by (simp add: tau_om1)

lemma om_nu_tau: "omega (ν R)  star (ν R)  τ R  omega R"
proof -
  have "omega (ν R)  star (ν R)  τ R = omega (ν R)  (1σ  ν R  star (ν R))  τ R"
    by auto
  also have "... = omega (ν R)  τ R  ν R  star (ν R)  τ R"
    using s_prod_distr s_prod_idl by blast
  also have "... = τ R  ν R  omega (ν R)  ν R  (star (ν R)  τ R)"
    by (simp add: cl5 sup_commute tau_def)
  also have "...  τ R  ν R  (omega (ν R)  star (ν R)  τ R)"
    by (smt (verit) Un_subset_iff s_prod_isor sup.cobounded2 sup.coboundedI2 sup_commute)
  also have "... = R  (omega (ν R)  star (ν R)  τ R)"
    using sprod_tau_nu by blast
  finally show ?thesis
    using om_coinduct by blast
qed

end