lib: move empty_fail lemmas up into NonDetMonadVCG

This enables a few more moves of remaining lemmas in
NonDetMonadLemmaBucket into the theories they belong thematically.

Signed-off-by: Gerwin Klein <gerwin.klein@proofcraft.systems>
This commit is contained in:
Gerwin Klein 2023-01-11 12:03:26 +11:00
parent f19364a38b
commit d275068826
No known key found for this signature in database
GPG Key ID: 20A847CE6AB7F5F3
4 changed files with 86 additions and 101 deletions

View File

@ -13,10 +13,6 @@ theory Monad_Commute
More_Monad (* for mapM_x *)
begin
lemma empty_fail_not_snd:
"\<lbrakk> \<not> snd (m s); empty_fail m \<rbrakk> \<Longrightarrow> \<exists>v. v \<in> fst (m s)"
by (fastforce simp: empty_fail_def)
definition monad_commute where
"monad_commute P a b \<equiv>

View File

@ -523,4 +523,38 @@ lemma simple_bind_fail [simp]:
"(gets X >>= (\<lambda>_. fail)) = fail"
by (auto intro!: bind_fail_propagates)
lemma bind_inv_inv_comm:
"\<lbrakk> \<And>P. \<lbrace>P\<rbrace> f \<lbrace>\<lambda>_. P\<rbrace>; \<And>P. \<lbrace>P\<rbrace> g \<lbrace>\<lambda>_. P\<rbrace>;
empty_fail f; empty_fail g \<rbrakk> \<Longrightarrow>
do x \<leftarrow> f; y \<leftarrow> g; n x y od = do y \<leftarrow> g; x \<leftarrow> f; n x y od"
apply (rule ext)
apply (rename_tac s)
apply (rule_tac s="(do (x, y) \<leftarrow> do x \<leftarrow> f; y \<leftarrow> (\<lambda>_. g s) ; (\<lambda>_. return (x, y) s) od;
n x y od) s" in trans)
apply (simp add: bind_assoc)
apply (intro bind_apply_cong, simp_all)[1]
apply (metis in_inv_by_hoareD)
apply (simp add: return_def bind_def)
apply (metis in_inv_by_hoareD)
apply (rule_tac s="(do (x, y) \<leftarrow> do y \<leftarrow> g; x \<leftarrow> (\<lambda>_. f s) ; (\<lambda>_. return (x, y) s) od;
n x y od) s" in trans[rotated])
apply (simp add: bind_assoc)
apply (intro bind_apply_cong, simp_all)[1]
apply (metis in_inv_by_hoareD)
apply (simp add: return_def bind_def)
apply (metis in_inv_by_hoareD)
apply (rule bind_apply_cong, simp_all)
apply (clarsimp simp: bind_def split_def return_def)
apply (auto | drule(1) empty_failD3)+
done
lemma bind_known_operation_eq:
"\<lbrakk> no_fail P f; \<lbrace>Q\<rbrace> f \<lbrace>\<lambda>rv s. rv = x \<and> s = t\<rbrace>; P s; Q s; empty_fail f \<rbrakk>
\<Longrightarrow> (f >>= g) s = g x t"
apply (drule(1) no_failD)
apply (subgoal_tac "fst (f s) = {(x, t)}")
apply (clarsimp simp: bind_def)
apply (fastforce simp: valid_def empty_fail_def)
done
end

View File

@ -12,6 +12,11 @@ imports
Strengthen
begin
(* FIXME lib: split this theory into at least: Hoare logic things, Det, EmptyFail, NoFail *)
(* FIXME lib: put definitions of det, empty_fail, no_fail, into Det, EmptyFail, NoFail *)
(* FIXME lib: move Hoare logic stuff from NonDetMonadLemmas to here *)
(* FIXME lib: move monad equalities from here to NonDetMonadLemmas *)
section "Satisfiability"
text \<open>
@ -796,8 +801,7 @@ lemma empty_fail_return [simp, wp]:
by (simp add: empty_fail_def return_def)
lemma empty_fail_bindE:
"\<lbrakk> empty_fail f; \<And>rv. empty_fail (g rv) \<rbrakk>
\<Longrightarrow> empty_fail (f >>=E g)"
"\<lbrakk> empty_fail f; \<And>rv. empty_fail (g rv) \<rbrakk> \<Longrightarrow> empty_fail (f >>=E g)"
apply (simp add: bindE_def)
apply (erule empty_fail_bind)
apply (simp add: lift_def throwError_def split: sum.split)
@ -825,6 +829,10 @@ lemma empty_fail [simp]:
"empty_fail fail"
by (simp add: fail_def empty_fail_def)
lemma empty_fail_assert:
"empty_fail (assert P)"
unfolding assert_def by simp
lemma empty_fail_assert_opt [simp]:
"empty_fail (assert_opt x)"
by (simp add: assert_opt_def split: option.splits)
@ -837,6 +845,44 @@ lemma empty_fail_gets_map[simp]:
"empty_fail (gets_map f p)"
unfolding gets_map_def by simp
lemma empty_fail_error_bits[simp]:
"empty_fail (returnOk v)"
"empty_fail (throwError v)"
"empty_fail (liftE f) = empty_fail f"
by (fastforce simp: returnOk_def throwError_def liftE_def empty_fail_def bind_def return_def)+
lemma empty_fail_whenEs:
"empty_fail f \<Longrightarrow> empty_fail (whenE P f)"
"empty_fail f \<Longrightarrow> empty_fail (unlessE P f)"
by (auto simp add: whenE_def unlessE_def)
lemma empty_fail_assertE:
"empty_fail (assertE P)"
by (simp add: assertE_def split: if_split)
lemma empty_fail_get:
"empty_fail get"
by (simp add: empty_fail_def get_def)
lemma empty_fail_catch:
"\<lbrakk> empty_fail f; \<And>x. empty_fail (g x) \<rbrakk> \<Longrightarrow> empty_fail (catch f g)"
by (simp add: catch_def split: sum.split)
lemma empty_fail_select[simp]:
"empty_fail (select V) = (V \<noteq> {})"
by (clarsimp simp: select_def empty_fail_def)
lemma empty_fail_not_snd:
"\<lbrakk> \<not> snd (m s); empty_fail m \<rbrakk> \<Longrightarrow> \<exists>v. v \<in> fst (m s)"
by (fastforce simp: empty_fail_def)
lemmas empty_failD2 = empty_fail_not_snd[rotated]
lemma empty_failD3:
"\<lbrakk> empty_fail f; \<not> snd (f s) \<rbrakk> \<Longrightarrow> fst (f s) \<noteq> {}"
by (drule(1) empty_failD2, clarsimp)
subsection "Failure"
lemma fail_wp: "\<lbrace>\<lambda>x. True\<rbrace> fail \<lbrace>Q\<rbrace>"

View File

@ -98,18 +98,6 @@ lemma mapME_x_inv_wp:
apply assumption
done
lemma empty_fail_error_bits:
"empty_fail (returnOk v)"
"empty_fail (throwError v)"
"empty_fail (liftE f) = empty_fail f"
apply (simp_all add: returnOk_def throwError_def)
apply (rule iffI, simp_all add: liftE_def)
apply (simp add: empty_fail_def bind_def return_def)
apply (erule allEI)
apply clarsimp
done
lemma mapM_upd:
assumes "\<And>x rv s s'. (rv,s') \<in> fst (f x s) \<Longrightarrow> x \<in> set xs \<Longrightarrow> (rv, g s') \<in> fst (f x (g s))"
shows "(rv,s') \<in> fst (mapM f xs s) \<Longrightarrow> (rv, g s') \<in> fst (mapM f xs (g s))"
@ -130,15 +118,6 @@ next
done
qed
lemma empty_fail_whenEs:
"empty_fail f \<Longrightarrow> empty_fail (whenE P f)"
"empty_fail f \<Longrightarrow> empty_fail (unlessE P f)"
by (auto simp add: whenE_def unlessE_def empty_fail_error_bits split: if_split)
lemma empty_fail_assertE:
"empty_fail (assertE P)"
by (simp add: assertE_def empty_fail_error_bits split: if_split)
lemma gets_the_validE_R_wp:
"\<lbrace>\<lambda>s. f s \<noteq> None \<and> isRight (the (f s)) \<and> Q (theRight (the (f s))) s\<rbrace>
gets_the f
@ -173,45 +152,12 @@ lemma list_case_return: (* FIXME lib: move to Lib *)
= return (case xs of [] \<Rightarrow> v | y # ys \<Rightarrow> f y ys)"
by (simp split: list.split)
lemma lifted_if_collapse: (* FIXME lib: move to Lib *)
"(if P then \<top> else f) = (\<lambda>s. \<not>P \<longrightarrow> f s)"
by auto
lemmas list_case_return2 = list_case_return (* FIXME lib: eliminate *)
lemma empty_fail_get:
"empty_fail get"
by (simp add: empty_fail_def get_def)
lemma empty_failD2:
"\<lbrakk> empty_fail f; \<not> snd (f s) \<rbrakk> \<Longrightarrow> \<exists>v. v \<in> fst (f s)"
by (fastforce simp add: empty_fail_def)
lemma empty_failD3:
"\<lbrakk> empty_fail f; \<not> snd (f s) \<rbrakk> \<Longrightarrow> fst (f s) \<noteq> {}"
by (drule(1) empty_failD2, clarsimp)
lemma bind_inv_inv_comm:
"\<lbrakk> \<And>P. \<lbrace>P\<rbrace> f \<lbrace>\<lambda>_. P\<rbrace>; \<And>P. \<lbrace>P\<rbrace> g \<lbrace>\<lambda>_. P\<rbrace>;
empty_fail f; empty_fail g \<rbrakk> \<Longrightarrow>
do x \<leftarrow> f; y \<leftarrow> g; n x y od = do y \<leftarrow> g; x \<leftarrow> f; n x y od"
apply (rule ext)
apply (rename_tac s)
apply (rule_tac s="(do (x, y) \<leftarrow> do x \<leftarrow> f; y \<leftarrow> (\<lambda>_. g s) ; (\<lambda>_. return (x, y) s) od;
n x y od) s" in trans)
apply (simp add: bind_assoc)
apply (intro bind_apply_cong, simp_all)[1]
apply (metis in_inv_by_hoareD)
apply (simp add: return_def bind_def)
apply (metis in_inv_by_hoareD)
apply (rule_tac s="(do (x, y) \<leftarrow> do y \<leftarrow> g; x \<leftarrow> (\<lambda>_. f s) ; (\<lambda>_. return (x, y) s) od;
n x y od) s" in trans[rotated])
apply (simp add: bind_assoc)
apply (intro bind_apply_cong, simp_all)[1]
apply (metis in_inv_by_hoareD)
apply (simp add: return_def bind_def)
apply (metis in_inv_by_hoareD)
apply (rule bind_apply_cong, simp_all)
apply (clarsimp simp: bind_def split_def return_def)
apply (auto | drule(1) empty_failD3)+
done
lemma no_fail_mapM:
"\<forall>x. no_fail \<top> (f x) \<Longrightarrow> no_fail \<top> (mapM f xs)"
apply (induct xs)
@ -220,11 +166,6 @@ lemma no_fail_mapM:
apply (wp|fastforce)+
done
lemma lifted_if_collapse: (* FIXME lib: move to Lib *)
"(if P then \<top> else f) = (\<lambda>s. \<not>P \<longrightarrow> f s)"
by auto
lemma filterM_preserved:
"\<lbrakk> \<And>x. x \<in> set xs \<Longrightarrow> \<lbrace>P\<rbrace> m x \<lbrace>\<lambda>rv. P\<rbrace> \<rbrakk>
\<Longrightarrow> \<lbrace>P\<rbrace> filterM m xs \<lbrace>\<lambda>rv. P\<rbrace>"
@ -314,10 +255,6 @@ lemma mapM_x_wp:
shows "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> mapM_x f xs \<lbrace>\<lambda>rv. P\<rbrace>"
by (subst mapM_x_mapM) (wp mapM_wp x)
lemma empty_fail_assert : "empty_fail (assert P)"
unfolding assert_def by simp
lemma no_fail_mapM':
assumes rl: "\<And>x. no_fail (\<lambda>_. P x) (f x)"
shows "no_fail (\<lambda>_. \<forall>x \<in> set xs. P x) (mapM f xs)"
@ -361,19 +298,6 @@ lemma empty_fail_sequence_x :
shows "empty_fail (sequence_x ms)" using assms
by (induct ms) (auto simp: sequence_x_def)
lemma bind_known_operation_eq:
"\<lbrakk> no_fail P f; \<lbrace>Q\<rbrace> f \<lbrace>\<lambda>rv s. rv = x \<and> s = t\<rbrace>; P s; Q s; empty_fail f \<rbrakk>
\<Longrightarrow> (f >>= g) s = g x t"
apply (drule(1) no_failD)
apply (subgoal_tac "fst (f s) = {(x, t)}")
apply (clarsimp simp: bind_def)
apply (rule not_psubset_eq)
apply (drule(1) empty_failD2, clarsimp)
apply fastforce
apply clarsimp
apply (drule(1) use_valid, simp+)
done
lemma mapME_set:
assumes est: "\<And>x. \<lbrace>R\<rbrace> f x \<lbrace>P\<rbrace>, -"
and invp: "\<And>x y. \<lbrace>R and P x\<rbrace> f y \<lbrace>\<lambda>_. P x\<rbrace>, -"
@ -415,13 +339,6 @@ lemma empty_fail_mapM_x [simp]:
apply (clarsimp simp: mapM_x_Cons)
done
lemma empty_fail_catch:
"\<lbrakk> empty_fail f; \<And>x. empty_fail (g x) \<rbrakk> \<Longrightarrow> empty_fail (catch f g)"
apply (simp add: catch_def)
apply (erule empty_fail_bind)
apply (simp split: sum.split)
done
lemma valid_isRight_theRight_split:
"\<lbrace>P\<rbrace> f \<lbrace>\<lambda>rv s. Q True rv s\<rbrace>,\<lbrace>\<lambda>e s. \<forall>v. Q False v s\<rbrace> \<Longrightarrow>
\<lbrace>P\<rbrace> f \<lbrace>\<lambda>rv s. Q (isRight rv) (theRight rv) s\<rbrace>"
@ -470,12 +387,4 @@ lemma case_option_find_give_me_a_map:
apply (simp add: lift_def throwError_def returnOk_def split: sum.split)
done
lemma empty_fail_select [simp]: "empty_fail (select V) = (V \<noteq> {})"
apply (clarsimp simp: select_def empty_fail_def)
done
lemma empty_fail_liftE [simp]:
"empty_fail (liftE X) = empty_fail X"
by (rule empty_fail_error_bits)
end