Theory Power_Allegories_Multirelations

section ‹Multirelational Properties of Power Allegories›

theory Power_Allegories_Multirelations

imports Multirelations_Basics

begin

text ‹We start with random little properties.›

lemma eta_s_id: "η = s_id"
  unfolding s_id_def eta_set by force

lemma Lambda_empty [simp]: "Λ {} = p_id"
  unfolding Lambda_def p_id_def by blast

lemma alpha_pid [simp]: "α p_id = {}"
  unfolding alpha_def epsiloff_def p_id_def by force


subsection ‹Peleg lifting›

definition plift :: "('a,'b) mrel ⇒ ('a set,'b set) rel" (‹_*› [1000] 999) where
  "R* = {(A,B). ∃f. (∀a ∈ A. (a,f(a)) ∈ R) ∧ B = ⋃(f ` A)}"

lemma pcomp_plift: "R ⋅ S = R ; S*"
  unfolding s_prod_def plift_def relcomp_unfold by simp

lemma det_plift_klift: "deterministic R ⟹ R* = (R)𝒫"
  unfolding deterministic_set plift_def klift_set_var
  apply (simp add: set_eq_iff)
  apply safe
  by metis+

lemma plift_ext2 [simp]: "η ; R* = R"
  by (metis eta_s_id pcomp_plift s_prod_idl)

lemma pliftext_3 [simp]: "η* = Id"
  by (simp add: det_eta det_plift_klift)

lemma d_dom_plift: "(Dom R)* = dom (R*)"
  unfolding Dom_def dom_set plift_def
  apply clarsimp
  apply safe
  apply (metis (full_types) UN_singleton image_cong)
  by (metis UN_singleton)

lemma d_pid_plift: "(Dom R)* ⊆ Id"
  by (metis d_dom_plift d_idem dom_subid inf.absorb_iff2)

lemma d_plift_sub: "A ⊆ B ⟹ (B,B) ∈ (Dom R)* ⟹ (A,A) ∈ (Dom R)*"
  by (smt (z3) Pair_inject UN_singleton Dom_def mem_Collect_eq plift_def split_conv subsetD)

lemma plift_empty: "({},A) ∈ R* ⟷ A = {}"
  using plift_def by auto

lemma univ_plift_klift:
  assumes "univalent R"
  shows "R* = (Dom R)* ; (R)𝒫"
proof -
  have "∀A B . (A,B) ∈ R* ⟷ (A,B) ∈ (Dom R)* ; (R)𝒫"
  proof (intro allI, rule iffI)
    fix A B
    assume 1: "(A,B) ∈ R*"
    hence "(A,B) ∈ (R)𝒫"
      unfolding klift_set_var
      apply clarsimp
      by (smt (z3) Collect_cong Pair_inject Union_eq assms case_prodE image_iff mem_Collect_eq plift_def univalent_set)
    thus "(A,B) ∈ (Dom R)* ; (R)𝒫"
      using 1 d_dom_plift dom_set by fastforce
  next
    fix A B
    assume "(A,B) ∈ (Dom R)* ; (R)𝒫"
    from this obtain C where 2: "(A,C) ∈ (Dom R)* ∧ (C,B) ∈ (R)𝒫"
      by auto
    from this obtain f where 3: "(∀a ∈ A. (a,f(a)) ∈ Dom R) ∧ C = ⋃(f ` A)"
      by (smt (verit) Pair_inject case_prodE mem_Collect_eq plift_def)
    hence "∀a ∈ A . ∃D . (a,D) ∈ R"
      by (simp add: Dom_def)
    from this obtain g where 4: "∀a ∈ A . (a,g(a)) ∈ R"
      by metis
    hence "∀a ∈ A. f(a) = {a}"
      using 3 by (simp add: Dom_def)
    hence "A = C"
      using 2 3 by (smt (verit) Pair_inject UN_singleton case_prodE image_cong mem_Collect_eq plift_def)
    hence "(A,B) ∈ (R)𝒫"
      using 2 by simp
    thus "(A,B) ∈ R*"
      unfolding plift_def klift_set_var
      apply clarsimp
      apply (rule exI[where ?x="g"])
      using 4 by (smt (verit, ccfv_SIG) Collect_cong assms image_def univalent_set)
  qed
  thus "R* = (Dom R)* ; (R)𝒫"
    by force
qed

lemma plift_ext1:
  assumes "univalent f"
  shows "(R ; f*)* = R* ; f*"
proof -
  have "∀A B . (A,B) ∈ (R ; (Dom f)* ; (f)𝒫)* ⟷ (A,B) ∈ R* ; (Dom f)* ; (f)𝒫"
  proof (intro allI, rule iffI)
    fix A B
    assume 1: "(A,B) ∈ (R ; (Dom f)* ; (f)𝒫)*"
    from this obtain g where 2: "(∀a ∈ A. (a,g(a)) ∈ R ; (Dom f)* ; (f)𝒫) ∧ B = ⋃(g ` A)"
      by (smt (verit) Pair_inject case_prodE mem_Collect_eq plift_def)
    hence "∀a ∈ A . ∃C D . (a,C) ∈ R ∧ (C,D) ∈ (Dom f)* ∧ (D,g(a)) ∈ (f)𝒫"
      by (meson relcompEpair)
    hence "∀a ∈ A . ∃C . (a,C) ∈ R ∧ (C,C) ∈ (Dom f)* ∧ (C,g(a)) ∈ (f)𝒫"
      using d_pid_plift by fastforce
    from this obtain h where 3: "∀a ∈ A . (a,h a) ∈ R ∧ (h a,h a) ∈ (Dom f)* ∧ (h a,g(a)) ∈ (f)𝒫"
      by metis
    let ?h = "⋃(h ` A)"
    have 4: "(A,?h) ∈ R*"
      using 3 plift_def by fastforce
    have 5: "(?h,?h) ∈ (Dom f)*"
      using 3
      unfolding plift_def Dom_def
      apply clarsimp
      by (metis UN_extend_simps(9) UN_singleton)
    have "(?h,B) ∈ (f)𝒫"
      using 2 3
      unfolding klift_set
      by auto
    thus "(A,B) ∈ R* ; (Dom f)* ; (f)𝒫"
      using 4 5 by blast
  next
    fix A B
    assume "(A,B) ∈ R* ; (Dom f)* ; (f)𝒫"
    from this obtain C D where 6: "(A,C) ∈ R* ∧ (C,D) ∈ (Dom f)* ∧ (D,B) ∈ (f)𝒫"
      by blast
    hence 7: "C = D"
      using d_pid_plift by auto
    from 6 obtain g where 8: "(∀a ∈ A. (a,g(a)) ∈ R) ∧ C = ⋃(g ` A)"
      by (smt (verit) Pair_inject case_prodE mem_Collect_eq plift_def)
    hence 9: "∀a ∈ A. (g(a),g(a)) ∈ (Dom f)*"
      using 6 7 by (metis d_plift_sub UN_iff subsetI)
    let ?h = "λa . ⋃(f `` g a)"
    have "∀a ∈ A. (g(a),?h a) ∈ (f)𝒫"
      using 6 by (simp add: klift_set)
    hence 10: "∀a ∈ A. (a,?h a) ∈ R ; (Dom f)* ; (f)𝒫"
      using 8 9 by blast
    have "B = ⋃(f `` D)"
      using 6 klift_set by fastforce
    hence 11: "B = (⋃a∈A . ?h a)"
      using 7 8 image_empty by blast
    show "(A,B) ∈ (R ; (Dom f)* ; (f)𝒫)*"
      apply (subst plift_def)
      apply clarsimp
      apply (rule exI[where ?x="?h"])
      using 10 11 by simp
  qed
  hence "(R ; (Dom f)* ; (f)𝒫)* = R* ; (Dom f)* ; (f)𝒫"
    by force
  thus ?thesis
    by (metis (no_types, opaque_lifting) assms univ_plift_klift O_assoc)
qed

lemma plift_assoc_univ: "univalent f ⟹ (R ⋅ S) ⋅ f = R ⋅ (S ⋅ f)"
  by (simp add: pcomp_plift O_assoc plift_ext1)

lemma Lambda_funct: "Λ (R ; S) = Λ R ⋅ Λ S"
  by (simp add: Lambda_pow det_lambda det_plift_klift klift_def pcomp_plift)

lemma eta_funct: "R ; S ; η = (R ; η) ⋅ (S ; η)"
proof -
  have "(R ; η) ⋅ (S ; η) = R ; η ; (S ; η)*"
    by (simp add: pcomp_plift)
  also have "… = R ; (η ⋅ (S ; η))"
    by (simp add: O_assoc pcomp_plift)
  also have "… = R ; S ; η"
    by (simp add: O_assoc pcomp_plift)
  finally show ?thesis..
qed

lemma alpha_funct_det: "deterministic R ⟹ deterministic S ⟹ α (R ⋅ S) = α R ; α S"
  by (metis Lambda_epsiloff_up2 Lambda_funct alpha_Lambda_canc)

lemma pcomp_det: "deterministic S ⟹ R ⋅ S = R ; (S)𝒫"
  by (simp add: det_plift_klift pcomp_plift)

lemma pcomp_det2: "deterministic R ⟹ deterministic S ⟹ (R ⋅ S)𝒫 = (R)𝒫 ; (S)𝒫"
  by (simp add: klift_ext1 pcomp_det)

lemma pcomp_alpha: "α (R ⋅ S) = R ; α ((S)*)"
  by (simp add: pcomp_plift)


subsection ‹Fusion and fission›

definition fus :: "('a,'b) mrel ⇒ ('a,'b) mrel" where
  "fus R = Λ (α R)"

definition fis :: "('a,'b) mrel ⇒ ('a,'b) mrel" where
  "fis R = α R ; η"

lemma fus_set: "fus R = {(a,B) |a B. B = ⋃(Image R {a})}"
  unfolding fus_def Lambda_def alpha_set by force

lemma fis_set: "fis R = {(a,{b}) |a b. b ∈ ⋃(Image R {a})}"
  unfolding fis_def alpha_set eta_set relcomp_unfold by force

lemma fis_det_comp: "deterministic R ⟹ deterministic S ⟹ fis (R ⋅ S) = fis R ⋅ fis S"
  by (simp add: alpha_funct_det eta_funct fis_def)

lemma fis_fix_det: "deterministic R = (fus R = R)"
  by (metis Lambda_alpha_canc det_lambda fus_def)


subsection ‹Galois connections for multirelations›

lemma sub_subh: "R ⊆ S ⟹ R ⊆ S ; (epsiloff ⫽ epsiloff)"
  by (metis R_O_Id alpha_def alpha_epsiloff lres_galois order_refl relcomp_mono)

lemma alpha_Lambda_galois: "(α R ⊆ S) = (R ⊆ Λ S ; (epsiloff ⫽ epsiloff))"
proof -
  have a: "(α R ⊆ S) = (R ⊆ S ⫽ epsiloff)"
    by (simp add: alpha_def lres_galois)
  have "S ⫽ epsiloff = (Λ S ; epsiloff) ⫽ epsiloff"
    by (metis alpha_Lambda_canc alpha_def)
  also have "… = Λ S ; (epsiloff ⫽ epsiloff)"
    by (simp add: det_lambda det_lres)
  finally have "S ⫽ epsiloff = Λ S ; (epsiloff ⫽ epsiloff)"
    .
  thus ?thesis
    using a by presburger
qed

lemma alpha_Lambda_galois_set: "(α R ⊆ S) = (R ⊆ {(a,A). ∃B. (a,B) ∈ Λ S ∧ A ⊆ B})"
  unfolding alpha_set Lambda_def by blast

lemma epsiloff_eta_lres: "epsiloff ; η ⊆ epsiloff ⫽ epsiloff"
proof -
  have "epsiloff ; η ; epsiloff = epsiloff ; α (Λ Id)"
    by (simp add: O_assoc alpha_def eta_def)
  also have "… = epsiloff"
    by simp
  finally have "epsiloff ; η ; epsiloff = epsiloff".
  thus ?thesis
    by (smt (verit) lres_galois order_refl)
qed

lemma eta_alpha_galois: "(R ; η ⊆ S ; (epsiloff ⫽ epsiloff)) = (R ⊆ α S)"
proof
  assume "R ; η ⊆ S ; (epsiloff ⫽ epsiloff)"
  hence "R ⊆ S ; (epsiloff ⫽ epsiloff) ; epsiloff"
    by (metis R_O_Id alpha_def alpha_eta alpha_ord_pres alpha_relcomp)
  thus "R ⊆ α S"
    by (simp add: O_assoc alpha_def)
next
  assume "R ⊆ α S"
  hence "R ; η ⊆ α S ; η"
    by (simp add: relcomp_mono)
  hence "R ; η ⊆ S ; epsiloff ; η"
    by (simp add: alpha_def)
  thus "R ; η ⊆ S ; (epsiloff ⫽ epsiloff)"
    using epsiloff_eta_lres in_mono by fastforce
qed

lemma eta_alpha_galois_set: "(R ; η ⊆ {(a,A). ∃B. (a,B) ∈ S ∧ A ⊆ B}) = (R ⊆ α S)"
  unfolding eta_set alpha_set by auto

lemma Lambda_iso: "R ⊆ S ⟹ Λ R ⊆ Λ S ; (epsiloff ⫽ epsiloff)"
  by (metis alpha_Lambda_canc alpha_Lambda_galois)

lemma eta_iso: "R ⊆ S ⟹ R ; η ⊆ S ; η ; (epsiloff ⫽ epsiloff)"
  by (simp add: eta_alpha_galois)

lemma alpha_iso: "R ⊆ S ; (epsiloff ⫽ epsiloff) ⟹ α R ⊆ α S"
  by (metis (no_types, lifting) alpha_def alpha_ord_pres alpha_relcomp conv_Omega conv_Omega_epsiloff)

lemma Lambda_canc_dcl: "R ⊆ Λ (α R) ; (epsiloff ⫽ epsiloff)"
  using alpha_Lambda_galois by blast

lemma eta_canc_dcl: "α R ; η ⊆ R ; (epsiloff ⫽ epsiloff)"
  by (simp add: eta_alpha_galois)

lemma alpha_surj: "surj α"
  using alpha_Lambda_canc by blast

lemma Lambda_inj: "inj Λ"
  by (metis alpha_Lambda_canc injI)

lemma eta_inj: "inj (λx. x ; η)"
  by (metis alpha_eta_id injI)

lemma fus_least_odet:
  assumes "Λ (α S) = S"
  and "R ⊆ S ; (epsiloff ⫽ epsiloff)"
  shows "Λ (α R) ⊆ S ; (epsiloff ⫽ epsiloff)"
proof -
  have "α R ⊆ α S"
    by (simp add: alpha_iso assms(2))
  hence "Λ (α R) ⊆ Λ (α S) ; (epsiloff ⫽ epsiloff)"
    by (simp add: Lambda_iso)
  thus ?thesis
    using assms(1) by auto
qed

lemma fis_greatest_idet:
  assumes "α S ; η = S"
  and "S ⊆ R ; (epsiloff ⫽ epsiloff)"
  shows "S ⊆ α R ; η ; (epsiloff ⫽ epsiloff)"
proof -
  have "α S ⊆ α R"
    by (simp add: alpha_iso assms(2))
  hence "α S ; η ⊆ α R ; η ; (epsiloff ⫽ epsiloff)"
    by (simp add: eta_iso)
  thus ?thesis
    using assms(1) by auto
qed

lemma fis_fus_galois: "(α R ; η ⊆ S ; (epsiloff ⫽ epsiloff)) = (R ⊆ Λ (α S) ; (epsiloff ⫽ epsiloff))"
  by (simp add: alpha_Lambda_galois eta_alpha_galois)


subsection ‹Properties of alpha, fission and fusion›

lemma alpha_lax: "α (R ⋅ S) ⊆ α R ; α S"
  unfolding alpha_def s_prod_def epsiloff_def relcomp_unfold by blast

lemma alpha_down [simp]: "α (R ; Ω⌣) = α R"
  by (metis alpha_def alpha_relcomp conv_Omega_epsiloff)

lemma fis_fis [simp]: "fis ∘ fis = fis"
  unfolding fun_eq_iff fis_def by simp

lemma fus_fus [simp]: "fus ∘ fus = fus"
  unfolding fun_eq_iff fus_def by simp

lemma fis_fus [simp]: "fis ∘ fus = fis"
  unfolding fun_eq_iff fus_def fis_def by simp

lemma fus_fis [simp]: "fus ∘ fis = fus"
  unfolding fun_eq_iff fus_def fis_def by simp

lemma fis_alpha: "fis R ⋅ S = α R ; S"
  by (simp add: O_assoc fis_def pcomp_plift)

lemma fis_lax: "fis (R ⋅ S) ⊆ fis R ⋅ fis S"
  by (metis fis_def alpha_lax eta_funct relcomp_mono subsetI)

lemma klift_fus: "(R)𝒫 = fus (epsiloff ; R)"
  by (simp add: alpha_def fus_def klift_var)

lemma fus_eta_klift: "fus R = η ; (R)𝒫"
  by (metis Id_O_R Lambda_pow eta_def fus_def klift_def)

lemma fus_Lambda_mu: "fus R = Λ R ; μ"
  by (simp add: fus_def lambda_alpha_mu)


subsection ‹Properties of fusion, fission, nu and tau›

lemma alpha_tau [simp]: "α (τ R) = {}"
  by (metis alpha_ord_pres alpha_pid subset_empty tau_le_c)

lemma alpha_nu [simp]: "α (ν R) = α R"
  unfolding alpha_def nu_def epsiloff_def U_def p_id_def relcomp_unfold by force

lemma nu_fis [simp]: "ν (fis R) = fis R"
  by (metis alpha_fp empty_iff equals0I fis_alpha relcompE)

lemma nu_fis_var: "ν (fis R) = fis (ν R)"
  by (metis alpha_nu fis_def nu_fis)

lemma tau_fis [simp]: "τ (fis R) = {}"
  by (metis nu_fis tau_alpha_zero)


text ‹Properties of tests and domain›

lemma subid_plift: "(P ∩ η)* = {(A,A)|A. ∀a ∈ A. (a,{a}) ∈ (P ∩ η)}"
  unfolding plift_def eta_set by safe auto

lemma U_subid: "R ; (P ∩ η)* = R ∩ U ; (P ∩ η)*"
  unfolding plift_def U_def eta_set relcomp_unfold
  apply safe
  apply force
  apply blast
  by force

lemma subid_plift_down: "U ; (P ∩ η)* ; Ω⌣ = U ; (P ∩ η)*"
  unfolding U_def relcomp_unfold plift_def Omega_set eta_set converse_def
  apply safe
  apply clarsimp
  apply (metis IntE UN_singleton inf.orderE)
  by blast

lemma nu_subid_plift: "ν (R ; (P ∩ η)*) = ν R ; ( P ∩ η)*"
  unfolding nu_def relcomp_unfold plift_def U_def p_id_def eta_set by safe fastforce+

lemma dom_fis1: "dom (fis R) = dom (α R)"
  unfolding dom_set fis_set alpha_set by blast

lemma dom_fis2: "dom (fis R) = dom (α (ν R))"
  by (simp add: dom_fis1)

lemma dom_fis3: "dom (fis R) = dom (ν R)"
  unfolding dom_set fis_set nu_def U_def p_id_def by safe fastforce+

lemma dom_fis4: "dom (fis R) = dom (ν (fus R))"
  by (metis comp_eq_dest_lhs dom_fis3 fis_fus)

lemma dom_alpha: "dom (α R ; (P ∩ η)) = dom (ν (R ; Ω⌣) ; (P ∩ η)*)"
  unfolding dom_set alpha_set eta_set Omega_set plift_def nu_def relcomp_unfold U_def p_id_def
  apply safe
  apply (clarsimp, metis empty_iff empty_subsetI insert_subset singletonD singletonI UN_singleton)
  by clarsimp fastforce


subsection ‹Box and diamond›

definition box :: "('a, 'b) mrel ⇒ ('b set, 'a set) rel" where
  "box R = rbox (α R)"

definition dia :: "('a, 'b) mrel ⇒ ('b set, 'a set) rel" where
  "dia R = 𝒫 ((α R)⌣)"

lemma box_set: "box R = {(B, A). A = {a. ∀C. (a, C) ∈ R ⟶ C ⊆ B}}"
  unfolding box_def rbox_set alpha_set by force

lemma dia_set: "dia R = {(B, A). A = {a. ∃C. (a, C) ∈ R ∧ C ∩ B ≠ {}}}"
  unfolding dia_def pow_set Image_def alpha_set converse_def by force

lemma box_Omega: "box R = Λ (Ω⌣ ⫽ R)"
  unfolding box_set Lambda_def lres_def Omega_set by auto

end