Theory Refine_More_Comb

theory Refine_More_Comb
imports Refine_Heuristics Refine_Leof
section ‹More Combinators›
theory Refine_More_Comb
imports Refine_Basic Refine_Heuristics Refine_Leof
begin

subsubsection ‹OBTAIN Combinator›

text ‹Obtain value with given property, asserting that there exists one.›  
definition OBTAIN :: "('a ⇒ bool) ⇒ 'a nres" 
  where
  "OBTAIN P ≡ ASSERT (∃x. P x) ⪢ SPEC P"

lemma OBTAIN_nofail[refine_pw_simps]: "nofail (OBTAIN P) ⟷ (∃x. P x)"
  unfolding OBTAIN_def
  by (auto simp: refine_pw_simps)
lemma OBTAIN_inres[refine_pw_simps]: "inres (OBTAIN P) x ⟷ (∀x. ¬P x) ∨ P x"
  unfolding OBTAIN_def
  by (auto simp: refine_pw_simps)
lemma OBTAIN_rule[refine_vcg]: "⟦ ∃x. P x; ⋀x. P x ⟹ Q x  ⟧ ⟹ OBTAIN P ≤ SPEC Q"
  unfolding OBTAIN_def
  by auto
lemma OBTAIN_refine_iff: "OBTAIN P ≤⇓R (OBTAIN Q) ⟷ (Ex Q ⟶ Ex P ∧ Collect P ⊆ R¯``Collect Q)"
  unfolding OBTAIN_def by (auto simp: pw_le_iff refine_pw_simps)

lemma OBTAIN_refine[refine]:
  assumes "RELATES R"
  assumes "⋀x. Q x ⟹ Ex P"
  assumes "⋀x y. ⟦Q x; P y⟧ ⟹ ∃x'. (y,x')∈R ∧ Q x'"
  shows "OBTAIN P ≤⇓R (OBTAIN Q)"
  using assms unfolding OBTAIN_refine_iff 
  by blast
  
subsubsection ‹SELECT Combinator›

text ‹Select some value with given property, or ‹None› if there is none.›  
definition SELECT :: "('a ⇒ bool) ⇒ 'a option nres"
  where "SELECT P ≡ if ∃x. P x then RES {Some x| x. P x} else RETURN None"
  
lemma SELECT_rule[refine_vcg]:
  assumes "⋀x. P x ⟹ Q (Some x)"
  assumes "∀x. ¬P x ⟹ Q None"
  shows "SELECT P ≤ SPEC Q"
  unfolding SELECT_def
  using assms
  by auto

lemma SELECT_refine_iff: "(SELECT P ≤⇓(⟨R⟩option_rel) (SELECT P')) 
  ⟷ (  
    (Ex P' ⟶ Ex P) ∧
    (∀x. P x ⟶ (∃x'. (x,x')∈R ∧ P' x'))
  )"  
  by (force simp: SELECT_def pw_le_iff refine_pw_simps) 

lemma SELECT_refine[refine]:
  assumes "RELATES R"
  assumes "⋀x'. P' x' ⟹ ∃x. P x"
  assumes "⋀x. P x ⟹ ∃x'. (x,x')∈R ∧ P' x'"
  shows "SELECT P ≤⇓(⟨R⟩option_rel) (SELECT P')"
  unfolding SELECT_refine_iff using assms by blast

lemma SELECT_as_SPEC: "SELECT P = SPEC (λNone ⇒ ∀x. ¬P x | Some x ⇒ P x)"
  unfolding SELECT_def by (auto simp: pw_eq_iff split: option.split)

lemma SELECT_pw[refine_pw_simps]:
  "nofail (SELECT P)"  
  "inres (SELECT P) r ⟷ (r=None ⟶ (∀x. ¬P x)) ∧ (∀x. r=Some x ⟶ P x)"
  unfolding SELECT_def
  by auto

lemma SELECT_pw_simps[simp]:
  "nofail (SELECT P)"
  "inres (SELECT P) None ⟷ (∀x. ¬P x)"
  "inres (SELECT P) (Some x) ⟷ P x"
  by (auto simp: refine_pw_simps)

end