Theory KAT2

(* Title:      Kleene Algebra with Tests
   Author:     Alasdair Armstrong, Victor B. F. Gomes, Georg Struth
   Maintainer: Georg Struth <g.struth at sheffield.ac.uk>
*)

section ‹Two sorted Kleene Algebra with Tests›

theory KAT2
  imports Kleene_Algebra.Kleene_Algebra
begin

text ‹
  As an alternative to the one-sorted implementation of tests, we provide a two-sorted, more 
  conventional one. In this setting, Isabelle's Boolean algebra theory can be used.
  This alternative can be developed further along the lines of the one-sorted implementation.
›

syntax "_kat" :: "'a  'a" (`_`)

ML val kat_test_vars = ["p","q","r","s","t","p'","q'","r'","s'","t'","p''","q''","r''","s''","t''"]

fun map_ast_variables ast =
  case ast of
    (Ast.Variable v) =>
      if exists (fn tv => tv = v) kat_test_vars
      then Ast.Appl [Ast.Variable "test", Ast.Variable v]
      else Ast.Variable v
  | (Ast.Constant c) => Ast.Constant c
  | (Ast.Appl []) => Ast.Appl []
  | (Ast.Appl (f :: xs)) => Ast.Appl (f :: map map_ast_variables xs)

structure KATHomRules = Named_Thms
  (val name = @{binding "kat_hom"}
   val description = "KAT test homomorphism rules")

fun kat_hom_tac ctxt n =
  let
    val rev_rules = map (fn thm => thm RS @{thm sym}) (KATHomRules.get ctxt)
  in
    asm_full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps rev_rules) n
  end

setup KATHomRules.setup

method_setup kat_hom = Scan.succeed (fn ctxt => SIMPLE_METHOD (CHANGED (kat_hom_tac ctxt 1)))

parse_ast_translation let
  fun kat_tr ctxt [t] = map_ast_variables t
in [(@{syntax_const "_kat"}, kat_tr)] end

ML structure VCGRules = Named_Thms
  (val name = @{binding "vcg"}
   val description = "verification condition generator rules")

fun vcg_tac ctxt n =
  let
    fun vcg' [] = no_tac
      | vcg' (r :: rs) = resolve_tac ctxt [r] n ORELSE vcg' rs;
  in REPEAT (CHANGED
       (kat_hom_tac ctxt n
        THEN REPEAT (vcg' (VCGRules.get ctxt))
        THEN kat_hom_tac ctxt n
        THEN TRY (resolve_tac ctxt @{thms order_refl} n ORELSE asm_full_simp_tac (put_simpset HOL_basic_ss ctxt) n)))
  end

method_setup vcg = Scan.succeed (fn ctxt => SIMPLE_METHOD (CHANGED (vcg_tac ctxt 1)))

setup VCGRules.setup

locale dioid_tests =
  fixes test :: "'a::boolean_algebra  'b::dioid_one_zerol"
  and not :: "'b::dioid_one_zerol  'b::dioid_one_zerol" (-)
  assumes test_sup [simp,kat_hom]: "test (sup p q) = `p + q`"
  and test_inf [simp,kat_hom]: "test (inf p q) = `p  q`"
  and test_top [simp,kat_hom]: "test top = 1"
  and test_bot [simp,kat_hom]: "test bot = 0"
  and test_not [simp,kat_hom]: "test (- p) = `-p`"
  and test_iso_eq [kat_hom]: "p  q  `p  q`"
begin

notation test (ι)

lemma test_eq [kat_hom]: "p = q  `p = q`"
  by (metis eq_iff test_iso_eq)

ML_val map (fn thm => thm RS @{thm sym}) (KATHomRules.get @{context})

lemma test_iso: "p  q  `p  q`"
  by (simp add: test_iso_eq)

(* Import lemmas and modify them to fit KAT syntax *)

lemma test_meet_comm: "`p  q = q  p`"
  by kat_hom (fact inf_commute)

lemmas test_one_top[simp] = test_iso[OF top_greatest, simplified]

lemma [simp]: "`-p + p = 1`"
  by kat_hom (metis compl_sup_top)

lemma [simp]: "`p + (-p) = 1`"
  by kat_hom (metis sup_compl_top)

lemma [simp]: "`(-p)  p = 0`"
  by (metis inf.commute inf_compl_bot test_bot test_inf test_not)

lemma [simp]: "`p  (-p) = 0`"
  by (metis inf_compl_bot test_bot test_inf test_not)

end

locale kat = 
  fixes test :: "'a::boolean_algebra  'b::kleene_algebra"
  and not :: "'b::kleene_algebra  'b::kleene_algebra" (!)
  assumes is_dioid_tests: "dioid_tests test not"

sublocale kat  dioid_tests using is_dioid_tests .

context kat
begin

notation test (ι)

lemma test_eq [kat_hom]: "p = q  `p = q`"
  by (metis eq_iff test_iso_eq)

ML_val map (fn thm => thm RS @{thm sym}) (KATHomRules.get @{context})

lemma test_iso: "p  q  `p  q`"
  by (simp add: test_iso_eq)

(* Import lemmas and modify them to fit KAT syntax *)

lemma test_meet_comm: "`p  q = q  p`"
  by kat_hom (fact inf_commute)

lemmas test_one_top[simp] = test_iso[OF top_greatest, simplified]

lemma test_star [simp]: "`p = 1`"
  by (metis star_subid test_iso test_top top_greatest)

lemmas [kat_hom] = test_star[symmetric]

lemma [simp]: "`!p + p = 1`"
  by kat_hom (metis compl_sup_top)

lemma [simp]: "`p + !p = 1`"
  by kat_hom (metis sup_compl_top)

lemma [simp]: "`!p  p = 0`"
  by (metis inf.commute inf_compl_bot test_bot test_inf test_not)

lemma [simp]: "`p  !p = 0`"
  by (metis inf_compl_bot test_bot test_inf test_not)

definition hoare_triple :: "'b  'b  'b  bool" (_ _ _) where
  "p c q  pc  cq"

declare hoare_triple_def[iff]

lemma hoare_triple_def_var: "`pc  cq  pc!q = 0`"
  apply (intro iffI antisym)
  apply (rule order_trans[of _ "`c  q  !q`"])
  apply (rule mult_isor[rule_format])
  apply (simp add: mult.assoc)+
  apply (simp add: mult.assoc[symmetric])
  apply (rule order_trans[of _ "`pc(!q + q)`"])
  apply simp
  apply (simp only: distrib_left add_zerol)
  apply (rule order_trans[of _ "`1  c  q`"])
  apply (simp only: mult.assoc)
  apply (rule mult_isor[rule_format])
  by simp_all

lemmas [intro!] = star_sim2[rule_format]

lemma hoare_weakening: "p  p'  q'  q  `p' c q'`  `p c q`"
  by auto (metis mult_isol mult_isor order_trans test_iso)

lemma hoare_star: "`p c p`  `p c p`"
  by auto

lemmas [vcg] = hoare_weakening[OF order_refl _ hoare_star]

lemma hoare_test [vcg]: "`p  t  q`  `p t q`"
  by auto (metis inf_le2 le_inf_iff test_inf test_iso_eq)

lemma hoare_mult [vcg]: "`p x r`  `r y q`  `p xy q`"
proof auto
  assume [simp]: "`p  x  x  r`" and [simp]: "`r  y  y  q`"
  have "`p  (x  y)  x  r  y`"
    by (auto simp add: mult.assoc[symmetric] intro!: mult_isor[rule_format])
  also have "`...  x  y  q`"
    by (auto simp add: mult.assoc intro!: mult_isol[rule_format])
  finally show "`p  (x  y)  x  y  q`" .
qed

lemma [simp]: "`!p  !p = !p`"
  by (metis inf.idem test_inf test_not)

lemma hoare_plus [vcg]: "`p x q`  `p y q`  `p x + y q`"
proof -
  assume a1: "ι p x ι q"
  assume "ι p y ι q"
  hence "ι p  (x + y)  x  ι q + y  ι q"
    using a1 by (metis (no_types) distrib_left hoare_triple_def join.sup.mono)
  thus ?thesis
    by force
qed

definition While :: "'b  'b  'b" (While _ Do _ End [50,50] 51) where
  "While t Do c End = (tc)!t"

lemma hoare_while: "`p  t c p`  `p While t Do c End !t  p`"
  unfolding While_def by vcg (metis inf_commute order_refl)

lemma [vcg]: "`p  t c p`  `!t  p  q`  `p While t Do c End q`"
  by (metis hoare_weakening hoare_while order_refl test_inf test_iso_eq test_not)

definition If :: "'b  'b  'b  'b" (If _ Then _ Else _› [50,50,50] 51) where
  "If p Then c1 Else c2  pc1 + !pc2"

lemma hoare_if [vcg]: "`p  t c1 q`  `p  !t c2 q`  `p If t Then c1 Else c2 q`"
  unfolding If_def by vcg assumption

end

end