Theory HS_VC_MKA

(*  Title:       Verification components with MKAs
    Author:      Jonathan Julián Huerta y Munive, 2020
    Maintainer:  Jonathan Julián Huerta y Munive <jonjulian23@gmail.com>
*)

section ‹ Verification components with MKA ›

text ‹ We use the forward box operator of antidomain Kleene algebras to derive rules for weakest 
liberal preconditions (wlps) of regular programs. ›

theory HS_VC_MKA
  imports "KAD.Modal_Kleene_Algebra"

begin


subsection ‹ Verification in AKA ›

text ‹Here we derive verification components with weakest liberal preconditions based on 
antidomain Kleene algebra ›

no_notation Range_Semiring.antirange_semiring_class.ars_r (r)
        and HOL.If ((‹notation=‹mixfix if expression››if (_)/ then (_)/ else (_)) [0, 0, 10] 10)

notation zero_class.zero (0)

context antidomain_kleene_algebra
begin

― ‹ Skip ›

lemma "|1] x = d x"
  using fbox_one .

― ‹ Abort ›

lemma "|0] q = 1"
  using fbox_zero .

― ‹ Sequential composition ›

lemma "|x  y] q = |x] |y] q"
  using fbox_mult .

declare fbox_mult [simp]

― ‹ Nondeterministic choice ›

lemma "|x + y] q = |x] q  |y] q"
  using fbox_add2 .

lemma le_fbox_choice_iff: "d p  |x + y]q  (d p  |x]q)  (d p  |y]q)"
  by (metis local.a_closure' local.ads_d_def local.dnsz.dom_glb_eq local.fbox_add2 local.fbox_def)

― ‹ Conditional statement › (* by Victor Gomes, Georg Struth *)

definition aka_cond :: "'a  'a  'a  'a" (if _ then _ else _› [64,64,64] 63) 
  where "if p then x else y = d p  x + ad p  y"

lemma fbox_export1: "ad p + |x] q = |d p  x] q"
  using a_d_add_closure addual.ars_r_def fbox_def fbox_mult by auto

lemma fbox_cond [simp]: "|if p then x else y] q = (ad p + |x] q)  (d p + |y] q)"
  using fbox_export1 local.ans_d_def local.fbox_mult 
  unfolding aka_cond_def ads_d_def fbox_def by auto

lemma fbox_cond2: "|if p then x else y] q = (d p  |x] q) + (ad p  |y] q)" (is "?lhs = ?d1 + ?d2")
proof -
  have obs: "?lhs = d p  ?lhs + ad p  ?lhs"
    by (metis (no_types, lifting) local.a_closure' local.a_de_morgan fbox_def ans_d_def
        ads_d_def local.am2 local.am5_lem local.dka.dsg3 local.dka.dsr5) 
  have "d p  ?lhs = d p  |x] q  (d p + d ( |y] q))"
    using fbox_cond local.a_d_add_closure local.ads_d_def 
      local.ds.ddual.mult_assoc local.fbox_def by auto
  also have "... = d p  |x] q"
    by (metis local.ads_d_def local.am2 local.dka.dns5 local.ds.ddual.mult_assoc local.fbox_def)
  finally have "d p  ?lhs = d p  |x] q" .
  moreover have "ad p  ?lhs = ad p  |y] q"
    by (metis add_commute fbox_cond local.a_closure' local.a_mult_add ads_d_def ans_d_def
        local.dnsz.dns5 local.ds.ddual.mult_assoc local.fbox_def)
  ultimately show ?thesis
    using obs by simp
qed

― ‹ While loop › (* by Victor Gomes, Georg Struth *)

definition aka_whilei :: "'a  'a  'a  'a" (while _ do _ inv _› [64,64,64] 63) where
  "while t do x inv i  = (d t  x)  ad t"

lemma fbox_frame: "d p  x  x  d p  d q  |x] r  d p  d q  |x] (d p  d r)"    
  using dual.mult_isol_var fbox_add1 fbox_demodalisation3 fbox_simp by auto

lemma fbox_shunt: "d p  d q  |x] t  d p  ad q + |x] t"
  by (metis a_6 a_antitone' a_loc add_commute addual.ars_r_def am_d_def da_shunt2 fbox_def)

lemma fbox_export2: "|x] p  |x  ad q] (d p  ad q)"
proof -
  {fix t
   have "d t  x  x  d p  d t  x  ad q  x  ad q  d p  ad q"
     by (metis (full_types) a_comm_var a_mult_idem ads_d_def am2 ds.ddual.mult_assoc phl_export2)
   hence "d t  |x] p  d t  |x  ad q] (d p  ad q)"
     by (metis a_closure' addual.ars_r_def ans_d_def dka.dsg3 ds.ddual.mult_assoc fbox_def fbox_demodalisation3)}
  thus ?thesis
    by (metis a_closure' addual.ars_r_def ans_d_def fbox_def order_refl)
qed

lemma fbox_while: "d p  d t  |x] p  d p  |(d t  x)  ad t] (d p  ad t)"
proof -
  assume "d p  d t  |x] p"
  hence "d p  |d t  x] p"
    by (simp add: fbox_export1 fbox_shunt)
  hence "d p  |(d t  x)] p"
    by (simp add: fbox_star_induct_var)
  thus ?thesis
    using order_trans fbox_export2 by presburger
qed

lemma fbox_whilei: 
  assumes "d p  d i" and "d i  ad t  d q" and "d i  d t  |x] i"
  shows "d p  |while t do x inv i] q"
proof-
  have "d i  |(d t  x)  ad t] (d i  ad t)"
    using fbox_while assms by blast
  also have "...  |(d t  x)  ad t] q"
    by (metis assms(2) local.dka.dom_iso local.dka.domain_invol local.fbox_iso)
  finally show ?thesis
    unfolding aka_whilei_def 
    using assms(1) local.dual_order.trans by blast 
qed

lemma fbox_seq_var: "p  |x] p'  p'  |y] q   p  |x  y] q"
proof -
  assume h1: "p  |x] p'" and h2: "p'  |y] q"
  hence "|x] p'  |x] |y] q"
    by (metis ads_d_def fbox_antitone_var fbox_dom fbox_iso)
  thus ?thesis
    by (metis dual_order.trans fbox_mult h1)
qed

lemma fbox_whilei_break: 
  "d p  |y] i  d i  ad t  d q  d i  d t  |x] i  d p  |y  (while t do x inv i)] q"
  apply (rule fbox_seq_var[OF _ fbox_whilei]) 
  using fbox_simp by auto

― ‹ Finite iteration ›

definition aka_loopi :: "'a  'a  'a" (loop _ inv _ › [64,64] 63)
  where "loop x inv i = x"

lemma "d p  |x] p  d p  |x] p"
  using fbox_star_induct_var .

lemma fbox_loopi: "p  d i  d i  |x] i  d i  d q  p  |loop x inv i] q"
  unfolding aka_loopi_def by (meson dual_order.trans fbox_iso fbox_star_induct_var)

lemma fbox_loopi_break: 
  "p  |y] d i  d i  |x] i  d i  d q  p  |y  (loop x inv i)] q"
  by (rule fbox_seq_var, force) (rule fbox_loopi, auto) 

― ‹ Invariants ›

lemma "p  i  i  |x]i  i  q  p  |x]q"
  by (metis local.ads_d_def local.dpdz.dom_iso local.dual_order.trans local.fbox_iso)

lemma "p  d i  d i  |x]i  i  d q  p  |x]q"
  by (metis local.a_4 local.a_antitone' local.a_subid_aux2 ads_d_def order.antisym fbox_def
      local.dka.dsg1 local.dual.mult_isol_var local.dual_order.trans local.order.refl)

lemma "(i  |x] i)  (j  |x] j)  (i + j)  |x] (i + j)"
  (*nitpick*)
  oops

lemma "d i  |x] i  d j  |x] j  (d i + d j)  |x] (d i + d j)"
  by (metis (no_types, lifting) dual_order.trans fbox_simp fbox_subdist join.le_supE join.le_supI)

lemma plus_inv: "i  |x] i  j  |x] j  (i + j)  |x] (i + j)"
  by (metis ads_d_def dka.dsr5 fbox_simp fbox_subdist join.sup_mono order_trans)

lemma mult_inv: "d i  |x] i  d j  |x] j  (d i  d j)  |x] (d i  d j)"
  using fbox_demodalisation3 fbox_frame fbox_simp by auto

end

end