Theory Domain_Quantale

(* Title: Domain Quantales
   Author: Victor Gomes, Georg Struth
   Maintainer: Victor Gomes <victor.gomes@cl.cam.ac.uk>
               Georg Struth <g.struth@sheffield.ac.uk> 
*)

section ‹Component for Recursive Programs›

theory Domain_Quantale
  imports KAD.Modal_Kleene_Algebra

begin

text ‹This component supports the verification and step-wise refinement of recursive programs
in a partial correctness setting.›

notation
  times (infixl ‹⋅› 70) and
  bot (‹⊥›) and
  top (‹⊤›) and
  inf (infixl ‹⊓› 65) and
  sup (infixl ‹⊔› 65)

subsection ‹Lattice-Ordered Monoids with Domain›

class bd_lattice_ordered_monoid = bounded_lattice + distrib_lattice + monoid_mult +
  assumes left_distrib: "x ⋅ (y ⊔ z) = x ⋅ y ⊔ x ⋅ z"
  and right_distrib: "(x ⊔ y) ⋅ z = x ⋅ z ⊔ y ⋅ z"
  and bot_annil [simp]: "⊥ ⋅ x = ⊥"
  and bot_annir [simp]: "x ⋅ ⊥ = ⊥"

begin

sublocale semiring_one_zero "(⊔)" "(⋅)" "1" "bot" 
  by (standard, auto simp: sup.assoc sup.commute sup_left_commute left_distrib right_distrib sup_absorb1)   

sublocale dioid_one_zero "(⊔)" "(⋅)" "1" bot "(≤)" "(<)"
  by (standard, simp add: le_iff_sup, auto)

end

no_notation ads_d (‹d›)
  and ars_r (‹r›)
  and antirange_op (‹ar _› [999] 1000)

class domain_bdlo_monoid = bd_lattice_ordered_monoid +
  assumes rdv: "(z ⊓ x ⋅ top) ⋅ y = z ⋅ y ⊓ x ⋅ top"  

begin 

definition "d x = 1 ⊓ x ⋅ ⊤"

sublocale ds: domain_semiring "(⊔)" "(⋅)" "1" "⊥" "d" "(≤)" "(<)"
proof standard
  fix x y
  show "x ⊔ d x ⋅ x = d x ⋅ x"
    by (metis d_def inf_sup_absorb left_distrib mult_1_left mult_1_right rdv sup.absorb_iff1 sup.idem sup.left_commute top_greatest)
  show "d (x ⋅ d y) = d (x ⋅ y)"
    by (simp add: d_def inf_absorb2 rdv  mult_assoc)
  show "d x ⊔ 1 = 1"
    by (simp add: d_def sup.commute)
  show "d bot = bot"
    by (simp add: d_def inf.absorb1 inf.commute)
  show "d (x ⊔ y) = d x ⊔ d y"
    by (simp add: d_def inf_sup_distrib1)
qed

end

subsection‹Boolean Monoids with Domain›

class boolean_monoid = boolean_algebra + monoid_mult +  
  assumes left_distrib': "x ⋅ (y ⊔ z) = x ⋅ y ⊔ x ⋅ z"
  and right_distrib': "(x ⊔ y) ⋅ z = x ⋅ z ⊔ y ⋅ z"
  and bot_annil' [simp]: "⊥ ⋅ x = ⊥"
  and bot_annir' [simp]: "x ⋅ ⊥ = ⊥"

begin

subclass bd_lattice_ordered_monoid
  by (standard, simp_all add: left_distrib' right_distrib')

lemma inf_bot_iff_le: "x ⊓ y = ⊥ ⟷ x ≤ -y"
  by (metis le_iff_inf inf_sup_distrib1 inf_top_right sup_bot.left_neutral sup_compl_top compl_inf_bot inf.assoc inf_bot_right)

end

class domain_boolean_monoid = boolean_monoid + 
  assumes rdv': "(z ⊓ x ⋅ ⊤) ⋅ y = z ⋅ y ⊓ x ⋅ ⊤"     

begin

sublocale dblo: domain_bdlo_monoid "1" "(⋅)" "(⊓)" "(≤)" "(<)" "(⊔)" "⊥" "⊤"
  by (standard, simp add: rdv')

definition "a x = 1 ⊓ -(dblo.d x)"
                                
lemma a_d_iff: "a x = 1 ⊓ -(x ⋅ ⊤)"
  by (clarsimp simp: a_def dblo.d_def inf_sup_distrib1) 

lemma topr: "-(x ⋅ ⊤) ⋅ ⊤ = -(x ⋅ ⊤)" 
proof (rule order.antisym)
  show "-(x ⋅ ⊤) ≤ -(x ⋅ ⊤) ⋅ ⊤"
    by (metis mult_isol_var mult_oner order_refl top_greatest)
  have "-(x ⋅ ⊤) ⊓ (x ⋅ ⊤) = ⊥"
    by simp
  hence "(-(x ⋅ ⊤) ⊓ (x ⋅ ⊤)) ⋅ ⊤  = ⊥"
    by simp 
  hence "-(x ⋅ ⊤) ⋅ ⊤ ⊓ (x ⋅ ⊤)  = ⊥"
    by (metis rdv') 
  thus "-(x ⋅ ⊤) ⋅ ⊤ ≤ -(x ⋅ ⊤)"
    by (simp add: inf_bot_iff_le)
qed

lemma dd_a: "dblo.d x = a (a x)"
  by (metis a_d_iff dblo.d_def double_compl inf_top.left_neutral mult_1_left rdv' topr)

lemma ad_a [simp]: "a (dblo.d x) = a x"
  by (simp add: a_def)

lemma da_a [simp]: "dblo.d (a x) = a x"
  using ad_a dd_a by auto

lemma a1 [simp]: "a x ⋅ x = ⊥"
proof -
  have "a x ⋅ x ⋅ ⊤ = ⊥"
    by (metis a_d_iff inf_compl_bot mult_1_left rdv' topr)
  then show ?thesis
    by (metis (no_types) dblo.d_def dblo.ds.domain_very_strict inf_bot_right)
qed

lemma a2 [simp]: "a (x ⋅ y) ⊔ a (x ⋅ a (a y)) = a (x ⋅ a (a y))"
  by (metis a_def dblo.ds.dsr2 dd_a sup.idem)

lemma a3 [simp]: "a (a x) ⊔ a x = 1"
  by (metis a_def da_a inf.commute sup.commute sup_compl_top sup_inf_absorb sup_inf_distrib1)

subclass domain_bdlo_monoid ..

text ‹The next statement shows that every boolean monoid with domain is an antidomain semiring. 
In this setting the domain operation has been defined explicitly.›

sublocale ad: antidomain_semiring a "(⊔)" "(⋅)" "1" "⊥" "(≤)" "(<)"
  rewrites ad_eq: "ad.ads_d x = d x"
proof -
  show "class.antidomain_semiring a (⊔) (⋅) 1 ⊥ (≤) (<)"
    by (standard, simp_all)
  then interpret ad: antidomain_semiring a "(⊔)" "(⋅)" "1" "⊥" "(≤)" "(<)" .
  show "ad.ads_d x = d x"
    by (simp add: ad.ads_d_def dd_a)
qed

end 

subsection‹Boolean Monoids with Range›

class range_boolean_monoid = boolean_monoid + 
  assumes ldv': "y ⋅ (z ⊓ ⊤ ⋅ x) = y ⋅ z ⊓ ⊤ ⋅ x"

begin

definition "r x = 1 ⊓ ⊤ ⋅ x"

definition "ar x = 1 ⊓ -(r x)"
                                
lemma ar_r_iff: "ar x = 1 ⊓ -(⊤ ⋅ x)"
  by (simp add: ar_def inf_sup_distrib1 r_def)

lemma topl: "⊤⋅(-(⊤ ⋅ x)) = -(⊤ ⋅ x)" 
proof (rule order.antisym)
  show "⊤ ⋅ - (⊤ ⋅ x) ≤ - (⊤ ⋅ x)"
    by (metis bot_annir' compl_inf_bot inf_bot_iff_le ldv')
  show "- (⊤ ⋅ x) ≤ ⊤ ⋅ - (⊤ ⋅ x)"
    by (metis inf_le2 inf_top.right_neutral mult_1_left mult_isor)
qed

lemma r_ar: "r x = ar (ar x)"
  by (metis ar_r_iff double_compl inf.commute inf_top.right_neutral ldv' mult_1_right r_def topl)

lemma ar_ar [simp]: "ar (r x) = ar x"
  by (simp add: ar_def ldv' r_def)

lemma rar_ar [simp]: "r (ar x) = ar x"
  using r_ar ar_ar by force

lemma ar1 [simp]: "x ⋅ ar x = ⊥"
proof -
  have "⊤ ⋅ x ⋅ ar x = ⊥"
    by (metis ar_r_iff inf_compl_bot ldv' mult_oner topl)
  then show ?thesis
    by (metis inf_bot_iff_le inf_le2 inf_top.right_neutral mult_1_left mult_isor mult_oner topl)
qed

lemma ars: "r (r x ⋅ y) = r (x ⋅ y)"
  by (metis inf.commute inf_top.right_neutral ldv' mult_oner mult_assoc r_def)

lemma ar2 [simp]: "ar (x ⋅ y) ⊔ ar (ar (ar x) ⋅ y) = ar (ar (ar x) ⋅ y)"
  by (metis ar_def ars r_ar sup.idem)
                         
lemma ar3 [simp]: "ar (ar x) ⊔ ar x = 1 "
  by (metis ar_def rar_ar inf.commute sup.commute sup_compl_top sup_inf_absorb sup_inf_distrib1)

sublocale ar: antirange_semiring "(⊔)" "(⋅)" "1" "⊥" ar "(≤)" "(<)"
  rewrites ar_eq: "ar.ars_r x = r x"
proof -
  show "class.antirange_semiring (⊔) (⋅) 1 ⊥ ar (≤) (<)"
    by (standard, simp_all)
  then interpret ar: antirange_semiring "(⊔)" "(⋅)" "1" "⊥" ar "(≤)" "(<)" .
  show "ar.ars_r x = r x"
    by (simp add: ar.ars_r_def r_ar)
qed

end

subsection ‹Quantales›

text ‹This part will eventually move into an AFP quantale entry.› 

class quantale = complete_lattice + monoid_mult +
  assumes Sup_distr: "Sup X ⋅ y = Sup {z. ∃x ∈ X. z = x ⋅ y}"
  and Sup_distl: "x ⋅ Sup Y = Sup {z. ∃y ∈ Y. z = x ⋅ y}"       

begin

lemma bot_annil'' [simp]: "⊥ ⋅ x = ⊥"
  using Sup_distr[where X="{}"] by auto

lemma bot_annirr'' [simp]: "x ⋅ ⊥ = ⊥"
  using Sup_distl[where Y="{}"] by auto

lemma sup_distl: "x ⋅ (y ⊔ z) = x ⋅ y ⊔ x ⋅ z"
  using Sup_distl[where Y="{y, z}"] by (fastforce intro!: Sup_eqI)

lemma sup_distr: "(x ⊔ y) ⋅ z = x ⋅ z ⊔ y ⋅ z"
  using Sup_distr[where X="{x, y}"] by (fastforce intro!: Sup_eqI)

sublocale semiring_one_zero "(⊔)" "(⋅)" "1" "⊥" 
  by (standard, auto simp: sup.assoc sup.commute sup_left_commute sup_distl sup_distr)     

sublocale dioid_one_zero "(⊔)" "(⋅)" "1" "⊥" "(≤)" "(<)"
  by (standard, simp add: le_iff_sup, auto)

lemma Sup_sup_pred: "x ⊔ Sup{y. P y} = Sup{y. y = x ∨ P y}"
  apply (rule order.antisym)
  apply (simp add: Collect_mono Sup_subset_mono Sup_upper) 
  using Sup_least Sup_upper le_supI2 by fastforce

definition star :: "'a ⇒ 'a" where
  "star x = (SUP i. x ^ i)"

lemma star_def_var1: "star x = Sup{y. ∃i. y = x ^ i}"
  by (simp add: star_def full_SetCompr_eq)

lemma star_def_var2: "star x = Sup{x ^ i |i. True}"
  by (simp add: star_def full_SetCompr_eq)

lemma star_unfoldl' [simp]: "1 ⊔ x ⋅ (star x) = star x"
proof -
  have "1 ⊔ x ⋅ (star x) = x ^ 0 ⊔ x ⋅ Sup{y. ∃i. y = x ^ i}"
    by (simp add: star_def_var1)
  also have "... = x ^ 0 ⊔ Sup{y. ∃i. y = x ^ (i + 1)}"
    by (simp add: Sup_distl, metis)
  also have "... = Sup{y. y = x ^ 0 ∨ (∃i. y = x ^ (i + 1))}"
    using Sup_sup_pred by simp
  also have "... = Sup{y. ∃i. y = x ^ i}"
    by (metis Suc_eq_plus1 power.power.power_Suc power.power_eq_if)
  finally show ?thesis
    by (simp add: star_def_var1)
qed

lemma star_unfoldr' [simp]: "1 ⊔ (star x) ⋅ x = star x"
proof -
  have "1 ⊔ (star x) ⋅ x = x ^ 0 ⊔ Sup{y. ∃i. y = x ^ i} ⋅ x"
    by (simp add: star_def_var1)
  also have "... = x ^ 0 ⊔ Sup{y. ∃i. y = x ^ i ⋅ x}"
    by (simp add: Sup_distr, metis)
  also have "... = x ^ 0 ⊔ Sup{y. ∃i. y = x ^ (i + 1)}"
    using power_Suc2 by simp 
   also have "... = Sup{y. y = x ^ 0 ∨ (∃i. y = x ^ (i + 1))}"
    using Sup_sup_pred by simp
  also have "... = Sup{y. ∃i. y = x ^ i}"
    by (metis Suc_eq_plus1 power.power.power_Suc power.power_eq_if)
  finally show ?thesis
    by (simp add: star_def_var1)
qed

lemma (in dioid_one_zero) power_inductl: "z + x ⋅ y ≤ y ⟹ (x ^ n) ⋅ z ≤ y"
proof (induct n)
  case 0 show ?case
    using "0.prems" by simp
  case Suc thus ?case
    by (simp, metis mult.assoc mult_isol order_trans)
qed

lemma (in dioid_one_zero) power_inductr: "z + y ⋅ x ≤ y ⟹ z ⋅ (x ^ n) ≤ y"
proof (induct n)
  case 0 show ?case
    using "0.prems" by auto
  case Suc
  {
    fix n
    assume "z + y ⋅ x ≤ y ⟹ z ⋅ x ^ n ≤ y"
      and "z + y ⋅ x ≤ y"
    hence "z ⋅ x ^ n ≤ y"
      by simp
    also have "z ⋅ x ^ Suc n = z ⋅ x ⋅ x ^ n"
      by (metis mult.assoc power_Suc)
    moreover have "... = (z ⋅ x ^ n) ⋅ x"
      by (metis mult.assoc power_commutes)
    moreover have "... ≤ y ⋅ x"
      by (metis calculation(1) mult_isor)
    moreover have "... ≤ y"
      using ‹z + y ⋅ x ≤ y› by simp
    ultimately have "z ⋅ x ^ Suc n ≤ y" by simp
  }
  thus ?case
    by (metis Suc)
qed

lemma star_inductl': "z ⊔ x ⋅ y ≤ y ⟹ (star x) ⋅ z ≤ y" 
proof -
  assume "z ⊔ x ⋅ y ≤ y"
  hence "∀i. x ^ i ⋅ z ≤ y"
    by (simp add: power_inductl)
  hence "Sup{w. ∃i. w = x ^ i ⋅ z} ≤ y"
    by (intro Sup_least, fast)
  hence "Sup{w. ∃i. w = x ^ i} ⋅ z ≤ y"
    using Sup_distr Sup_le_iff by auto
  thus "(star x) ⋅ z ≤ y"
    by (simp add: star_def_var1)
qed

lemma star_inductr': "z ⊔ y ⋅ x ≤ y ⟹ z ⋅ (star x) ≤ y" 
proof -
  assume "z ⊔ y ⋅ x ≤ y"
  hence "∀i. z ⋅ x ^ i  ≤ y"
    by (simp add: power_inductr)
  hence "Sup{w. ∃i. w = z ⋅ x ^ i} ≤ y"
    by (intro Sup_least, fast)
  hence "z ⋅ Sup{w. ∃i. w = x ^ i} ≤ y"
    using Sup_distl Sup_le_iff by auto
  thus "z ⋅ (star x) ≤ y"
    by (simp add: star_def_var1)
qed

sublocale ka: kleene_algebra "(⊔)" "(⋅)" "1" "⊥" "(≤)" "(<)" star
  by standard (simp_all add: star_inductl' star_inductr')

end

text ‹Distributive quantales are often assumed to satisfy infinite distributivity laws between
joins and meets, but finite ones suffice for our purposes.›

class distributive_quantale = quantale + distrib_lattice 

begin

subclass bd_lattice_ordered_monoid
  by (standard, simp_all add: distrib_left)

lemma "(1 ⊓ x ⋅ ⊤) ⋅ x = x"
(* nitpick [expect=genuine]*)
oops

end 

subsection ‹Domain Quantales›

class domain_quantale = distributive_quantale +
  assumes rdv'': "(z ⊓ x ⋅ ⊤) ⋅ y = z ⋅ y ⊓ x ⋅ ⊤"  

begin

subclass domain_bdlo_monoid 
  by (standard, simp add: rdv'')

end

class range_quantale = distributive_quantale +
  assumes ldv'': "y ⋅ (z ⊓ ⊤ ⋅ x) = y ⋅ z ⊓ ⊤ ⋅ x"

class boolean_quantale = quantale + complete_boolean_algebra

begin

subclass boolean_monoid
  by (standard, simp_all add: sup_distl)

lemma "(1 ⊓ x ⋅ ⊤) ⋅ x = x"
(*nitpick[expect=genuine]*)
oops

lemma "(1 ⊓ -(x ⋅ ⊤)) ⋅ x = ⊥"
(*nitpick[expect=genuine]*)
oops

end

subsection‹Boolean Domain Quantales› 

class domain_boolean_quantale = domain_quantale + boolean_quantale

begin

subclass domain_boolean_monoid
  by (standard, simp add: rdv'')

lemma fbox_eq: "ad.fbox x q = Sup{d p |p. d p ⋅ x ≤ x ⋅ d q}"
  apply (rule Sup_eqI[symmetric])
  apply clarsimp
  using ad.fbox_demodalisation3 ad.fbox_simp apply auto[1]
  apply clarsimp
  by (metis ad.fbox_def ad.fbox_demodalisation3 ad.fbox_simp da_a eq_refl)

lemma fdia_eq: "ad.fdia x p = Inf{d q |q. x ⋅ d p ≤ d q ⋅ x}"
  apply (rule Inf_eqI[symmetric])
  apply clarsimp
  using ds.fdemodalisation2 apply auto[1]
  apply clarsimp
  by (metis ad.fd_eq_fdia ad.fdia_def da_a double_compl ds.fdemodalisation2 inf_bot_iff_le inf_compl_bot)

text ‹The specification statement can be defined explicitly.›

definition R :: "'a ⇒ 'a ⇒ 'a" where
  "R p q ≡ Sup{x. (d p) ⋅ x ≤ x ⋅ d q}"

lemma "x ≤ R p q ⟹ d p ≤ ad.fbox x (d q)"
proof (simp add: R_def ad.kat_1_equiv ad.kat_2_equiv)
  assume "x ≤ Sup{x. d p ⋅ x ⋅ a q = ⊥}"
  hence "d p ⋅ x ⋅ a q ≤ d p ⋅ Sup{x. d p ⋅ x ⋅ a q = ⊥} ⋅ a q "
    using mult_double_iso by blast
  also have "... = Sup{d p ⋅ x ⋅ a q |x. d p ⋅ x ⋅ a q = ⊥}"
    apply (subst Sup_distl)
    apply (subst Sup_distr)
    apply clarsimp
    by metis
  also have "... = ⊥"
    by (auto simp: Sup_eqI)
  finally show ?thesis
    using ad.fbox_demodalisation3 ad.kat_3 ad.kat_4 le_bot by blast
qed

lemma "d p ≤ ad.fbox x (d q) ⟹ x ≤ R p q"
  apply (simp add: R_def)
  apply (rule Sup_upper)
  apply simp
  using ad.fbox_demodalisation3 ad.fbox_simp apply auto[1]
done

end

subsection‹Relational Model of Boolean Domain Quantales›

interpretation rel_dbq: domain_boolean_quantale
  ‹(-)› uminus ‹(∩)› ‹(⊆)› ‹(⊂)› ‹(∪)› ‹{}› UNIV ‹⋂› ‹⋃› Id ‹(O)›
  by standard auto


subsection‹Modal Boolean Quantales›

class range_boolean_quantale = range_quantale + boolean_quantale

begin

subclass range_boolean_monoid
  by (standard, simp add: ldv'')

lemma fbox_eq: "ar.bbox x (r q) = Sup{r p |p. x ⋅ r p ≤ (r q) ⋅ x}"
  apply (rule Sup_eqI[symmetric])
  apply clarsimp
  using ar.ardual.fbox_demodalisation3 ar.ardual.fbox_simp apply auto[1]
  apply clarsimp
  by (metis ar.ardual.fbox_def ar.ardual.fbox_demodalisation3 eq_refl rar_ar)

lemma fdia_eq: "ar.bdia x (r p) = Inf{r q |q. (r p) ⋅ x ≤ x ⋅ r q}"
  apply (rule Inf_eqI[symmetric])
  apply clarsimp
  using ar.ars_r_def ar.ardual.fdemodalisation22 ar.ardual.kat_3_equiv_opp ar.ardual.kat_4_equiv_opp apply auto[1]
  apply clarsimp
  using ar.bdia_def ar.ardual.ds.fdemodalisation2 r_ar by fastforce

end

class modal_boolean_quantale = domain_boolean_quantale + range_boolean_quantale +
  assumes domrange' [simp]: "d (r x) = r x"
  and rangedom' [simp]: "r (d x) = d x"

begin

sublocale mka: modal_kleene_algebra "(⊔)" "(⋅)" 1 ⊥ "(≤)" "(<)" star a ar
  by standard (simp_all add: ar_eq ad_eq)

end

no_notation fbox (‹( |_] _)› [61,81] 82)
  and antidomain_semiringl_class.fbox (‹( |_] _)› [61,81] 82)

notation ad.fbox (‹( |_] _)› [61,81] 82)

subsection ‹Recursion Rule›

lemma recursion: "mono (f :: 'a ⇒ 'a :: domain_boolean_quantale) ⟹ 
  (⋀x. d p ≤ |x] d q ⟹ d p ≤ |f x] d q) ⟹  d p ≤ |lfp f] d q"
  apply (erule lfp_ordinal_induct [where f=f], simp)
  by (auto simp: ad.addual.ardual.fbox_demodalisation3 Sup_distr Sup_distl intro: Sup_mono)

text ‹We have already tested this rule in the context of test quantales~cite‹"ArmstrongGS15"›, which is based
on a formalisation of quantales that is currently not in the AFP. The two theories will be merged as
soon as the quantale is available in the AFP.›

end