Theory Refine_Imp_Hol

section ‹Refinement for Imperative-HOL Programs›
theory Refine_Imp_Hol
  imports "Hoare_Triple"
            "HOL-Eisbach.Eisbach"
begin

  subsection ‹Assertions›
    
  text ‹We add assertions that consume no time to Imperative HOL Time.
  
    Note that the original constassert consumes one time unit, i.e., is designed for 
    actually being checked at runtime. On the other hand, our assertions are not executable, 
    and must be refined before code generation.
  ›
  definition [code del]: "assert' P  if P then ureturn () else raise ''assert''"

  lemma execute_assert'[execute_simps]: "execute (assert' P) h = (if P then Some ((),h,0) else None)"
    by (auto simp: assert'_def execute_simps)

  
  lemma assert'_rule: "h. hP  φ  <P> assert' φ <λ_. P>"  
    apply rule
    apply (auto simp: execute_simps in_range.simps relH_refl)
    done
    
  lemma assert'_bind_rule: 
    assumes "h. hP  φ"
    assumes "φ  <P> c <Q>"
    shows "<P> do {assert' φ; c} <Q>"  
    apply rule
    using assms
    apply (auto simp: execute_simps in_range.simps relH_refl elim!: hoare_tripleE)
    done    
    
  subsection ‹Refinement Predicate›  
  text ‹An imperative-HOL program p› refines a program q›, if either q› fails, or p› returns the
    same result as q›. In case q› is already proved correct (in particular does not fail), this
    implies correctness of p›. Moreover, for the refinement proof, we can assume that q› does not fail,
    in particular, that all assertions in q› hold. This can be used to transfer knowledge from the 
    correctness proof (proving the assertions) to the refinement proof (assuming the assertions).
  ›
  definition "refines p q  h. case execute q h of None  True | Some (r,h',t)  execute p h = Some (r,h',t)"

  lemma hoare_triple_refines:
    assumes "<P> c <Q>"
    assumes "refines c' c"
    shows "<P> c' <Q>"
    apply rule
    using assms
    by (auto simp: refines_def elim!: hoare_tripleE split: option.splits)
  
    
  subsubsection ‹Admissibility›
  context begin
  
  private lemma refines_adm_aux: "option.admissible (λxa. h a aa b. xa h = Some (a, aa, b)  execute (t x) h = Some (a, aa, b))"
  proof-
    have "option.admissible (λxa. h y. xa h = Some y  execute (t x) h = Some y)" 
      using option_admissible by metis
    thus ?thesis by auto
  qed
  
  lemma refines_adm: "heap.admissible (λf. x. refines (t x) (f x) )"
    unfolding refines_def
    apply (rule admissible_fun[OF heap_interpretation])
  
    unfolding Heap_lub_def Heap_ord_def
    apply (rule admissible_image)
    using option.partial_function_definitions_axioms partial_function_lift apply auto[1]
      apply(simp split: option.splits)
      apply auto[3]
    subgoal for x
      apply (simp add: comp_def)
      apply(rule refines_adm_aux)
      done
    subgoal for xa y 
      apply (metis Heap_execute)  
      done
    done
  
  end  

  subsection ‹Syntactic rules for constrefines  

  named_theorems refines_rule
  
  lemma refines_assert'[refines_rule]: "refines (ureturn ()) (assert' φ)"
    unfolding refines_def
    by (simp add: execute_simps)
  
  lemma refines_assert'_bind[refines_rule]: "refines p q  refines p (do {assert' φ; q})"  
    unfolding refines_def
    apply (cases φ)
    apply (auto simp add: execute_simps split: option.splits)
    done
    
  lemma refines_bind[refines_rule]: "refines m m'  (x. refines (f x) (f' x))  refines (do {xm; f x}) (do {xm'; f' x})"
    unfolding refines_def
    apply clarsimp
    subgoal for h
      apply (cases "execute m' h"; cases "execute m h")
      apply (auto simp add: execute_simps split: option.splits)
      by (smt (verit, best) option.case(2) prod.simps(2) timeFrame.elims)
    done
    
  lemma refines_If[refines_rule]: "brefines t t'  ¬brefines e e'  refines (If b t e) (If b t' e')" by auto
  lemma refines_Let[refines_rule]: " x. x=v  refines (f x) (f' x)   refines (let x=v in f x) (let x=v in f' x)" by auto
    
  
  lemma refines_refl: "refines p p"  
    unfolding refines_def
    by (auto split: option.splits)
 
  lemma refines_empty[simp]: "refines m  (Heap.Heap Map.empty)" 
    apply(simp add: refines_def)
    done
 
  lemma refines_let_right: assumes "refines m (m' a)"
    shows "refines m (let x = a in m' x)"
    using assms by simp
  
  lemma refines_case_prod_right: assumes " a b. refines m (m' a b)"
    shows "refines m (case t of (a,b)  m' a b)"
    using assms apply(cases t)
    by simp
  
  lemma refines_option[refines_rule]: assumes "a=a'" "refines m1 m1'" " x. refines (m2 x) (m2' x)"
    shows "refines (case a of None  m1 | Some x  m2 x)  (case a' of None  m1' | Some x  m2' x)"
    using assms apply(cases a')
     apply simp_all
    done
  
  lemma prod_case_refines[refines_rule]: assumes "p= p'" "  a b. refines (f a b) (f' a b)"
    shows " refines (case p of (a, b)  f a b) (case p' of (a, b)  f' a b )" 
    using assms apply(cases p') by simp

subsection ‹Automation›    
    
  method refines_step= determrule refines_rule refl refines_refl refines_let_right refines_case_prod_right 
                               | assumption | simp only:
  
  method refines = refines_step+    
    
end