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