Theory OptionMonadWP
theory OptionMonadWP
imports
OptionMonadND
"wp/WP"
begin
declare K_def [simp]
definition ovalid :: "('s ⇒ bool) ⇒ ('s ⇒ 'a option) ⇒ ('a ⇒ 's ⇒ bool) ⇒ bool" where
"ovalid P f Q ≡ ∀s r. P s ∧ f s = Some r ⟶ Q r s"
definition ovalidNF :: "('s ⇒ bool) ⇒ ('s ⇒ 'a option) ⇒ ('a ⇒ 's ⇒ bool) ⇒ bool" where
"ovalidNF P f Q ≡ ∀s. P s ⟶ (f s ≠ None ∧ (∀r. f s = Some r ⟶ Q r s))"
definition no_ofail where "no_ofail P f ≡ ∀s. P s ⟶ f s ≠ None"
lemma no_ofail_is_ovalidNF: "no_ofail P f ≡ ovalidNF P f (λ_ _. True)"
by (simp add: no_ofail_def ovalidNF_def)
lemma ovalidNF_combine: "⟦ ovalid P f Q; no_ofail P f ⟧ ⟹ ovalidNF P f Q"
by (auto simp: ovalidNF_def ovalid_def no_ofail_def)
definition owhile_inv ::
"('a ⇒ 's ⇒ bool) ⇒ ('a ⇒ 's ⇒ 'a option) ⇒ 'a
⇒ ('a ⇒ 's ⇒ bool) ⇒ ('a ⇒ 's ⇒ nat) ⇒ 's ⇒ 'a option"
where "owhile_inv C B x I M = owhile C B x"
lemmas owhile_add_inv = owhile_inv_def[symmetric]
lemma obind_wp [wp]:
"⟦ ⋀r. ovalid (R r) (g r) Q; ovalid P f R ⟧ ⟹ ovalid P (obind f g) Q"
by (simp add: ovalid_def obind_def split: option.splits, fast)
lemma oreturn_wp [wp]:
"ovalid (P x) (oreturn x) P"
by (simp add: ovalid_def oreturn_def K_def)
lemma ocondition_wp [wp]:
"⟦ ovalid L l Q; ovalid R r Q ⟧
⟹ ovalid (λs. if C s then L s else R s) (ocondition C l r) Q"
by (auto simp: ovalid_def ocondition_def)
lemma ofail_wp [wp]:
"ovalid (λ_. True) ofail Q"
by (simp add: ovalid_def ofail_def)
lemma ovalid_K_bind_wp [wp]:
"ovalid P f Q ⟹ ovalid P (K_bind f x) Q"
by simp
lemma ogets_wp [wp]: "ovalid (λs. P (f s) s) (ogets f) P"
by (simp add: ovalid_def ogets_def)
lemma oguard_wp [wp]: "ovalid (λs. f s ⟶ P () s) (oguard f) P"
by (simp add: ovalid_def oguard_def)
lemma oskip_wp [wp]:
"ovalid (λs. P () s) oskip P"
by (simp add: ovalid_def oskip_def)
lemma ovalid_case_prod [wp]:
assumes "(⋀x y. ovalid (P x y) (B x y) Q)"
shows "ovalid (case v of (x, y) ⇒ P x y) (case v of (x, y) ⇒ B x y) Q"
using assms unfolding ovalid_def by auto
lemma owhile_ovalid [wp]:
"⟦⋀a. ovalid (λs. I a s ∧ C a s) (B a) I;
⋀a s. ⟦I a s; ¬ C a s⟧ ⟹ Q a s⟧
⟹ ovalid (I a) (owhile_inv C B a I M) Q"
unfolding owhile_inv_def owhile_def ovalid_def
apply clarify
apply (frule_tac I = "λa. I a s" in option_while_rule)
apply auto
done
definition ovalid_property where "ovalid_property P x = (λs f. (∀r. Some r = x s f ⟶ P r s))"
lemma ovalid_is_triple [wp_trip]:
"ovalid P f Q = triple_judgement P f (ovalid_property Q (λs f. f s))"
by (auto simp: triple_judgement_def ovalid_def ovalid_property_def)
lemma ovalid_wp_comb1 [wp_comb]:
"⟦ ovalid P' f Q; ovalid P f Q'; ⋀s. P s ⟹ P' s ⟧ ⟹ ovalid P f (λr s. Q r s ∧ Q' r s)"
by (simp add: ovalid_def)
lemma ovalid_wp_comb2 [wp_comb]:
"⟦ ovalid P f Q; ⋀s. P' s ⟹ P s ⟧ ⟹ ovalid P' f Q"
by (auto simp: ovalid_def)
lemma ovalid_wp_comb3 [wp_comb]:
"⟦ ovalid P f Q; ovalid P' f Q' ⟧ ⟹ ovalid (λs. P s ∧ P' s) f (λr s. Q r s ∧ Q' r s)"
by (auto simp: ovalid_def)
lemma obind_NF_wp [wp]:
"⟦ ⋀r. ovalidNF (R r) (g r) Q; ovalidNF P f R ⟧ ⟹ ovalidNF P (obind f g) Q"
by (auto simp: ovalidNF_def obind_def split: option.splits)
lemma oreturn_NF_wp [wp]:
"ovalidNF (P x) (oreturn x) P"
by (simp add: ovalidNF_def oreturn_def)
lemma ocondition_NF_wp [wp]:
"⟦ ovalidNF L l Q; ovalidNF R r Q ⟧
⟹ ovalidNF (λs. if C s then L s else R s) (ocondition C l r) Q"
by (simp add: ovalidNF_def ocondition_def)
lemma ofail_NF_wp [wp]:
"ovalidNF (λ_. False) ofail Q"
by (simp add: ovalidNF_def ofail_def)
lemma ovalidNF_K_bind_wp [wp]:
"ovalidNF P f Q ⟹ ovalidNF P (K_bind f x) Q"
by simp
lemma ogets_NF_wp [wp]:
"ovalidNF (λs. P (f s) s) (ogets f) P"
by (simp add: ovalidNF_def ogets_def)
lemma oguard_NF_wp [wp]:
"ovalidNF (λs. f s ∧ P () s) (oguard f) P"
by (simp add: ovalidNF_def oguard_def)
lemma oskip_NF_wp [wp]:
"ovalidNF (λs. P () s) oskip P"
by (simp add: ovalidNF_def oskip_def)
lemma ovalid_NF_case_prod [wp]:
assumes "(⋀x y. ovalidNF (P x y) (B x y) Q)"
shows "ovalidNF (case v of (x, y) ⇒ P x y) (case v of (x, y) ⇒ B x y) Q"
using assms unfolding ovalidNF_def by auto
lemma owhile_NF [wp]:
"⟦⋀a. ovalidNF (λs. I a s ∧ C a s) (B a) I;
⋀a m. ovalid (λs. I a s ∧ C a s ∧ M a s = m) (B a) (λr s. M r s < m);
⋀a s. ⟦I a s; ¬ C a s⟧ ⟹ Q a s⟧
⟹ ovalidNF (I a) (owhile_inv C B a I M) Q"
unfolding owhile_inv_def ovalidNF_def ovalid_def
apply clarify
apply (rename_tac s, rule_tac I = I and M = "measure (λr. M r s)" in owhile_rule)
apply fastforce
apply fastforce
apply fastforce
apply blast+
done
definition ovalidNF_property where "ovalidNF_property P x = (λs f. (x s f ≠ None ∧ (∀r. Some r = x s f ⟶ P r s)))"
lemma ovalidNF_is_triple [wp_trip]:
"ovalidNF P f Q = triple_judgement P f (ovalidNF_property Q (λs f. f s))"
by (auto simp: triple_judgement_def ovalidNF_def ovalidNF_property_def)
lemma ovalidNF_wp_comb1 [wp_comb]:
"⟦ ovalidNF P' f Q; ovalidNF P f Q'; ⋀s. P s ⟹ P' s ⟧ ⟹ ovalidNF P f (λr s. Q r s ∧ Q' r s)"
by (simp add: ovalidNF_def)
lemma ovalidNF_wp_comb2 [wp_comb]:
"⟦ ovalidNF P f Q; ⋀s. P' s ⟹ P s ⟧ ⟹ ovalidNF P' f Q"
by (simp add: ovalidNF_def)
lemma ovalidNF_wp_comb3 [wp_comb]:
"⟦ ovalidNF P f Q; ovalidNF P' f Q' ⟧ ⟹ ovalidNF (λs. P s ∧ P' s) f (λr s. Q r s ∧ Q' r s)"
by (simp add: ovalidNF_def)
lemma no_ofail_ofail [wp]: "no_ofail (λ_. False) ofail"
by (simp add: no_ofail_def ofail_def)
lemma no_ofail_ogets [wp]: "no_ofail (λ_. True) (ogets f)"
by (simp add: no_ofail_def ogets_def)
lemma no_ofail_obind [wp]:
"⟦ ⋀r. no_ofail (P r) (g r); no_ofail Q f; ovalid Q f P ⟧ ⟹ no_ofail Q (obind f g)"
by (auto simp: no_ofail_def obind_def ovalid_def)
lemma no_ofail_K_bind [wp]:
"no_ofail P f ⟹ no_ofail P (K_bind f x)"
by simp
lemma no_ofail_oguard [wp]:
"no_ofail (λs. f s) (oguard f)"
by (auto simp: no_ofail_def oguard_def)
lemma no_ofail_ocondition [wp]:
"⟦ no_ofail L l; no_ofail R r ⟧
⟹ no_ofail (λs. if C s then L s else R s) (ocondition C l r)"
by (simp add: no_ofail_def ocondition_def)
lemma no_ofail_oreturn [wp]:
"no_ofail (λ_. True) (oreturn x)"
by (simp add: no_ofail_def oreturn_def)
lemma no_ofail_oskip [wp]:
"no_ofail (λ_. True) oskip"
by (simp add: no_ofail_def oskip_def)
lemma no_ofail_is_triple [wp_trip]:
"no_ofail P f = triple_judgement P f (λs f. f s ≠ None)"
by (auto simp: triple_judgement_def no_ofail_def)
lemma no_ofail_wp_comb1 [wp_comb]:
"⟦ no_ofail P f; ⋀s. P' s ⟹ P s ⟧ ⟹ no_ofail P' f"
by (simp add: no_ofail_def)
lemma no_ofail_wp_comb2 [wp_comb]:
"⟦ no_ofail P f; no_ofail P' f ⟧ ⟹ no_ofail (λs. P s ∧ P' s) f"
by (simp add: no_ofail_def)
lemma ovalid_grab_asm:
"(G ⟹ ovalid P f Q) ⟹ ovalid (λs. G ∧ P s) f Q"
by (simp add: ovalid_def)
lemma ovalidNF_grab_asm:
"(G ⟹ ovalidNF P f Q) ⟹ ovalidNF (λs. G ∧ P s) f Q"
by (simp add: ovalidNF_def)
lemma no_ofail_grab_asm:
"(G ⟹ no_ofail P f) ⟹ no_ofail (λs. G ∧ P s) f"
by (simp add: no_ofail_def)
lemma ovalid_assume_pre:
"(⋀s. P s ⟹ ovalid P f Q) ⟹ ovalid P f Q"
by (auto simp: ovalid_def)
lemma ovalidNF_assume_pre:
"(⋀s. P s ⟹ ovalidNF P f Q) ⟹ ovalidNF P f Q"
by (simp add: ovalidNF_def)
lemma no_ofail_assume_pre:
"(⋀s. P s ⟹ no_ofail P f) ⟹ no_ofail P f"
by (simp add: no_ofail_def)
lemma ovalid_pre_imp:
"⟦ ⋀s. P' s ⟹ P s; ovalid P f Q ⟧ ⟹ ovalid P' f Q"
by (simp add: ovalid_def)
lemma ovalidNF_pre_imp:
"⟦ ⋀s. P' s ⟹ P s; ovalidNF P f Q ⟧ ⟹ ovalidNF P' f Q"
by (simp add: ovalidNF_def)
lemma no_ofail_pre_imp:
"⟦ ⋀s. P' s ⟹ P s; no_ofail P f ⟧ ⟹ no_ofail P' f"
by (simp add: no_ofail_def)
lemma ovalid_post_imp:
"⟦ ⋀r s. Q r s ⟹ Q' r s; ovalid P f Q ⟧ ⟹ ovalid P f Q'"
by (simp add: ovalid_def)
lemma ovalidNF_post_imp:
"⟦ ⋀r s. Q r s ⟹ Q' r s; ovalidNF P f Q ⟧ ⟹ ovalidNF P f Q'"
by (simp add: ovalidNF_def)
lemma ovalid_post_imp_assuming_pre:
"⟦ ⋀r s. ⟦ P s; Q r s ⟧ ⟹ Q' r s; ovalid P f Q ⟧ ⟹ ovalid P f Q'"
by (simp add: ovalid_def)
lemma ovalidNF_post_imp_assuming_pre:
"⟦ ⋀r s. ⟦ P s; Q r s ⟧ ⟹ Q' r s; ovalidNF P f Q ⟧ ⟹ ovalidNF P f Q'"
by (simp add: ovalidNF_def)
end