Theory Hoare

section ‹Hoare Triples›

theory Hoare
imports Statements
begin

text ‹
A hoare triple for $p,q\in \mathit{State}\ \mathit{set}$, and 
$S : \mathit{State}\ \mathit{set} \to \mathit{State}\ \mathit{set}$ is valid,
denoted $\models p \{|S|\} q$, if every execution of $S$ starting from state $s\in p$
always terminates, and if it terminates in state $s'$, then $s'\in q$. When $S$ is
modeled as a predicate transformer, this definition is equivalent to requiring that
$p$ is a subset of the initial states from which the execution of $S$ is guaranteed
to terminate in $q$, that is $p \subseteq S\ q$.

The formal definition of a valid hoare triple only assumes that $p$ (and also $S\ q$) ranges
over a complete lattice.
›

definition
  Hoare :: "'a::complete_distrib_lattice  ('b  'a)  'b  bool" (" (_){| _ |}(_)" [0,0,900] 900) where
  " p {|S|} q = (p  (S q))"

theorem hoare_sequential:
  "mono S  ( p {| S o T |} r) = ( ( q.  p {| S |} q   q {| T |} r))"
  by (metis (no_types) Hoare_def monoD o_def order_refl order_trans)

theorem hoare_choice:
  " p {| S  T |} q = ( p {| S |} q   p {| T |} q)"
  by (simp_all add: Hoare_def inf_fun_def)

theorem hoare_assume:
  "( P {| [.R.] |} Q) = (P  R  Q)"
  apply (simp add: Hoare_def assume_def)
  apply safe
  apply (case_tac "(inf P R)  (inf (sup (- R) Q) R)")
  apply (simp add: inf_sup_distrib2)
  apply (simp add: le_infI1)
  apply (case_tac "(sup (-R) (inf P R))  sup (- R) Q")
  apply (simp add: sup_inf_distrib1)
  by (simp add: le_supI2)

theorem hoare_mono:
  "mono S  Q  R   P {| S |} Q   P {| S |} R"
  apply (simp add: mono_def Hoare_def)
  apply (rule_tac y = "S Q" in order_trans)
  by auto

theorem hoare_pre:
  "R  P   P {| S |} Q   R {| S |} Q"
  by (simp add: Hoare_def)

theorem hoare_Sup:
  "( p  P .  p {| S |} q) =  Sup P {| S |} q"
  apply (simp add: Hoare_def, safe, simp add: Sup_least)
  apply (rule_tac y = "P" in order_trans, simp_all)
  by (simp add: Sup_upper)
  
lemma hoare_magic [simp]: " P {|  |} Q" 
  by (simp add: Hoare_def top_fun_def)

lemma hoare_demonic: " P {| [:R:] |} Q = ( s . s  P   R s  Q)"
  apply (unfold Hoare_def demonic_def)
  by auto

lemma hoare_not_guard:
  "mono (S :: (_::order_bot)  _)   p {| S |} q =  (p  (- grd S)) {| S |} q"
  apply (simp add: Hoare_def grd_def, safe)
  apply (drule monoD)
  by auto

subsection ‹Hoare rule for recursive statements›

text ‹
A statement $S$ is refined by another statement $S'$ if $\models p \{| S' |\} q$ 
is true for all $p$ and $q$ such that  $\models p \{| S |\} q$ is true. This
is equivalent to $S \le S'$. 

Next theorem can be used to prove refinement of a recursive program. A recursive
program is modeled as the least fixpoint of a monotonic mapping from predicate
transformers to predicate transformers.
›

theorem lfp_wf_induction:
  "mono f  ( w . (p w)  f (Sup_less p w))  Sup (range p)  lfp f"
 apply (rule fp_wf_induction, simp_all)
 by (drule lfp_unfold, simp)

definition
  "post_fun (p::'a::order) q = (if p  q then  else )"

lemma post_mono [simp]: "mono (post_fun p :: (_::{order_bot,order_top}))"
   apply (simp add: post_fun_def  mono_def, safe)
   apply (subgoal_tac "p  y", simp)
   by (rule_tac y = x in order_trans, simp_all)

lemma post_top [simp]: "post_fun p p = "
  by (simp add: post_fun_def)

lemma post_refin [simp]: "mono S  ((S p)::'a::bounded_lattice)  (post_fun p) x  S x"
  apply (simp add: le_fun_def post_fun_def, safe)
  by (rule_tac f = S in monoD, simp_all)

text ‹
Next theorem shows the equivalence between the validity of Hoare
triples and refinement statements. This theorem together with the
theorem for refinement of recursive programs will be used to prove
a Hoare rule for recursive programs.
›

theorem hoare_refinement_post:
  "mono f   ( x {| f |} y) = ({.x.} o (post_fun y)  f)"
  apply safe
  apply (simp_all add: Hoare_def)
  apply (simp_all add: le_fun_def)
  apply (simp add: assert_def, safe)
  apply (rule_tac y = "f y  post_fun y xa" in order_trans, simp_all)
  apply (rule_tac y = "x" in order_trans, simp_all)
  apply (simp add: assert_def)
  by (drule_tac x = "y" in spec, simp)


text ‹
Next theorem gives a Hoare rule for recursive programs. If we can prove correct the unfolding 
of the recursive definition applid to a program $f$, $\models p\ w\ \{| F\  f |\}\  y$, assumming
that $f$ is correct when starting from $p\  v$, $v<w$, $\models SUP-L\  p\  w\  \{| f |\}\  y$, then
the recursive program is correct $\models SUP\ p\ \{| lfp\  F |\}\  y$
›

lemma assert_Sup: "{. (X::'a::complete_distrib_lattice set).} =  (assert ` X)"
  by (simp add: fun_eq_iff assert_def Sup_inf image_comp)

lemma assert_Sup_range: "{. (range (p::'W  'a::complete_distrib_lattice)).} =  (range (assert o p))"
  by (simp add: fun_eq_iff assert_def SUP_inf image_comp)

lemma Sup_range_comp: "( range p) o S =  (range (λ w . ((p w) o S)))"
  by (simp add: fun_eq_iff image_comp)

lemma Sup_less_comp: "(Sup_less P) w o S = Sup_less (λ w . ((P w) o S)) w"
  apply (simp add: Sup_less_def fun_eq_iff, safe)
  apply (subgoal_tac "((λf. f (S x)) ` {y. v<w. x. y x = P v x}) = ((λf. f x) ` {y. v<w. x. y x = P v (S x)})")
  apply (auto cong del: SUP_cong_simp)
  done

lemma Sup_less_assert: "Sup_less (λw. {. (p w)::'a::complete_distrib_lattice .}) w = {.Sup_less p w.}"
  apply (simp add: Sup_less_def assert_Sup image_def)
  apply (subgoal_tac "{y. v<w. y = {. p v .}} = {y. x. (v<w. x = p v)  y = {. x .}}")
  apply (auto simp add: image_def cong del: SUP_cong_simp)
  done


declare mono_comp[simp]

theorem hoare_fixpoint:
  "mono_mono F 
   (!! w f . mono f   Sup_less p w {| f |} y   p w {| F f |} y)   (Sup (range p)) {| lfp F |} y"
  apply (simp add: mono_mono_def hoare_refinement_post assert_Sup_range Sup_range_comp)
  apply (rule lfp_wf_induction)
  apply auto
  apply (simp add: Sup_less_comp [THEN sym])
  apply (simp add: Sup_less_assert)
  apply (drule_tac x = "{. Sup_less p w .}  post_fun y" in spec, safe)
  apply simp
  by (simp add: hoare_refinement_post)

theorem "( t .  ({s . t  R s}) {|S|} q)   ({:R:} p) {| S |} q"
  apply (simp add: Hoare_def angelic_def subset_eq)
  by auto

end