(* * Copyright 2023, Proofcraft Pty Ltd * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) (* Hoare logic lemmas over the nondet monad. Hoare triples, lifting lemmas, etc. If it doesn't contain a Hoare triple it likely doesn't belong in here. *) theory More_NonDetMonadVCG imports Monads.NonDetMonadVCG begin lemma gets_exs_valid: "\(=) s\ gets f \\\r. (=) s\" by (rule exs_valid_gets) lemma hoare_take_disjunct: "\P\ f \\rv s. P' rv s \ (False \ P'' rv s)\ \ \P\ f \P''\" by (erule hoare_strengthen_post, simp) lemma hoare_post_add: "\P\ S \\r s. R r s \ Q r s\ \ \P\ S \Q\" by (erule hoare_strengthen_post, simp) lemma hoare_disjI1: "\R\ f \P\ \ \R\ f \\r s. P r s \ Q r s\" apply (erule hoare_post_imp [rotated]) apply simp done lemma hoare_disjI2: "\R\ f \Q\ \ \R\ f \\r s. P r s \ Q r s \" by (rule hoare_post_imp [OF _ hoare_disjI1, where P1=Q], auto) lemma hoare_name_pre_state: "\ \s. P s \ \(=) s\ f \Q\ \ \ \P\ f \Q\" by (clarsimp simp: valid_def) lemma hoare_name_pre_stateE: "\\s. P s \ \(=) s\ f \Q\, \E\\ \ \P\ f \Q\, \E\" by (clarsimp simp: validE_def2) lemma valid_prove_more: (* FIXME: duplicate *) "\P\ f \\rv s. Q rv s \ Q' rv s\ \ \P\ f \Q'\" by (rule hoare_post_add) lemma hoare_vcg_if_lift: "\R\ f \\rv s. (P \ X rv s) \ (\P \ Y rv s)\ \ \R\ f \\rv s. if P then X rv s else Y rv s\" "\R\ f \\rv s. (P \ X rv s) \ (\P \ Y rv s)\ \ \R\ f \\rv. if P then X rv else Y rv\" by (auto simp: valid_def split_def) lemma hoare_lift_Pf: assumes P: "\x. \P x\ m \\_. P x\" assumes f: "\P. \\s. P (f s)\ m \\_ s. P (f s)\" shows "\\s. P (f s) s\ m \\_ s. P (f s) s\" using f P by (rule hoare_use_eq) lemma hoare_lift_Pf2: assumes P: "\x. \Q x\ m \\_. P x\" assumes f: "\P. \\s. P (f s)\ m \\_ s. P (f s)\" shows "\\s. Q (f s) s\ m \\_ s. P (f s) s\" using f P by (rule hoare_use_eq) lemma hoare_lift_Pf3: assumes P: "\x. \Q x\ m \P x\" assumes f: "\P. \\s. P (f s)\ m \\_ s. P (f s)\" shows "\\s. Q (f s) s\ m \\rv s. P (f s) rv s\" apply (clarsimp simp add: valid_def) apply (frule (1) use_valid [OF _ P], drule (2) use_valid [OF _ f]) done lemma hoare_if_r_and: "\P\ f \\r. if R r then Q r else Q' r\ = \P\ f \\r s. (R r \ Q r s) \ (\R r \ Q' r s)\" by (fastforce simp: valid_def) lemma hoare_convert_imp: "\ \\s. \ P s\ f \\rv s. \ Q s\; \R\ f \S\ \ \ \\s. P s \ R s\ f \\rv s. Q s \ S rv s\" apply (simp only: imp_conv_disj) apply (erule(1) hoare_vcg_disj_lift) done lemma hoare_vcg_ex_lift_R: "\ \v. \P v\ f \Q v\,- \ \ \\s. \v. P v s\ f \\rv s. \v. Q v rv s\,-" apply (simp add: validE_R_def validE_def) apply (rule hoare_strengthen_post, erule hoare_vcg_ex_lift) apply (auto split: sum.split) done lemma hoare_case_option_wpR: "\\P\ f None \Q\,-; \x. \P' x\ f (Some x) \Q' x\,-\ \ \case_option P P' v\ f v \\rv. case v of None \ Q rv | Some x \ Q' x rv\,-" by (cases v) auto lemma hoare_vcg_conj_liftE_R: "\ \P\ f \P'\,-; \Q\ f \Q'\,- \ \ \P and Q\ f \\rv s. P' rv s \ Q' rv s\, -" apply (simp add: validE_R_def validE_def valid_def split: sum.splits) apply blast done lemma K_valid[wp]: "\K P\ f \\_. K P\" by (simp add: valid_def) lemma hoare_vcg_exI: "\P\ f \Q x\ \ \P\ f \\rv s. \x. Q x rv s\" apply (simp add: valid_def split_def) apply blast done lemma hoare_exI_tuple: "\P\ f \\(rv,rv') s. Q x rv rv' s\ \ \P\ f \\(rv,rv') s. \x. Q x rv rv' s\" by (fastforce simp: valid_def) lemma hoare_ex_all: "(\x. \P x\ f \Q\) = \\s. \x. P x s\ f \Q\" apply (rule iffI) apply (fastforce simp: valid_def)+ done lemma hoare_imp_eq_substR: "\P\ f \Q\,- \ \P\ f \\rv s. rv = x \ Q x s\,-" by (fastforce simp add: valid_def validE_R_def validE_def split: sum.splits) lemma hoare_split_bind_case_sum: assumes x: "\rv. \R rv\ g rv \Q\" "\rv. \S rv\ h rv \Q\" assumes y: "\P\ f \S\,\R\" shows "\P\ f >>= case_sum g h \Q\" apply (rule hoare_seq_ext [OF _ y[unfolded validE_def]]) apply (case_tac x, simp_all add: x) done lemma hoare_split_bind_case_sumE: assumes x: "\rv. \R rv\ g rv \Q\,\E\" "\rv. \S rv\ h rv \Q\,\E\" assumes y: "\P\ f \S\,\R\" shows "\P\ f >>= case_sum g h \Q\,\E\" apply (unfold validE_def) apply (rule hoare_seq_ext [OF _ y[unfolded validE_def]]) apply (case_tac x, simp_all add: x [unfolded validE_def]) done lemma assertE_sp: "\P\ assertE Q \\rv s. Q \ P s\,\E\" by (clarsimp simp: assertE_def) wp lemma throwErrorE_E [wp]: "\Q e\ throwError e -, \Q\" by (simp add: validE_E_def) wp lemma gets_inv [simp]: "\ P \ gets f \ \r. P \" by (simp add: gets_def, wp) lemma select_inv: "\ P \ select S \ \r. P \" by (simp add: select_def valid_def) lemmas return_inv = hoare_return_drop_var lemma assert_inv: "\P\ assert Q \\r. P\" unfolding assert_def by (cases Q) simp+ lemma assert_opt_inv: "\P\ assert_opt Q \\r. P\" unfolding assert_opt_def by (cases Q) simp+ lemma case_options_weak_wp: "\ \P\ f \Q\; \x. \P'\ g x \Q\ \ \ \P and P'\ case opt of None \ f | Some x \ g x \Q\" apply (cases opt) apply (clarsimp elim!: hoare_weaken_pre) apply (rule hoare_weaken_pre [where Q=P']) apply simp+ done lemma case_option_wp_None_return: assumes [wp]: "\x. \P' x\ f x \\_. Q\" shows "\\x s. (Q and P x) s \ P' x s \ \ \Q and (\s. opt \ None \ P (the opt) s)\ (case opt of None \ return () | Some x \ f x) \\_. Q\" by (cases opt; wpsimp) lemma case_option_wp_None_returnOk: assumes [wp]: "\x. \P' x\ f x \\_. Q\,\E\" shows "\\x s. (Q and P x) s \ P' x s \ \ \Q and (\s. opt \ None \ P (the opt) s)\ (case opt of None \ returnOk () | Some x \ f x) \\_. Q\,\E\" by (cases opt; wpsimp) lemma list_cases_weak_wp: assumes "\P_A\ a \Q\" assumes "\x xs. \P_B\ b x xs \Q\" shows "\P_A and P_B\ case ts of [] \ a | x#xs \ b x xs \Q\" apply (cases ts) apply (simp, rule hoare_weaken_pre, rule assms, simp)+ done lemmas hoare_FalseE_R = hoare_FalseE[where E="\\", folded validE_R_def] lemma hoare_vcg_if_lift2: "\R\ f \\rv s. (P rv s \ X rv s) \ (\ P rv s \ Y rv s)\ \ \R\ f \\rv s. if P rv s then X rv s else Y rv s\" "\R\ f \\rv s. (P' rv \ X rv s) \ (\ P' rv \ Y rv s)\ \ \R\ f \\rv. if P' rv then X rv else Y rv\" by (auto simp: valid_def split_def) lemma hoare_vcg_if_lift_ER: (* Required because of lack of rv in lifting rules *) "\R\ f \\rv s. (P rv s \ X rv s) \ (\ P rv s \ Y rv s)\, - \ \R\ f \\rv s. if P rv s then X rv s else Y rv s\, -" "\R\ f \\rv s. (P' rv \ X rv s) \ (\ P' rv \ Y rv s)\, - \ \R\ f \\rv. if P' rv then X rv else Y rv\, -" by (auto simp: valid_def validE_R_def validE_def split_def) lemma undefined_valid: "\\\ undefined \Q\" by (rule hoare_pre_cont) lemma assertE_wp: "\\s. F \ Q () s\ assertE F \Q\,\E\" apply (rule hoare_pre) apply (unfold assertE_def) apply wp apply simp done lemma doesn't_grow_proof: assumes y: "\s. finite (S s)" assumes x: "\x. \\s. x \ S s \ P s\ f \\rv s. x \ S s\" shows "\\s. card (S s) < n \ P s\ f \\rv s. card (S s) < n\" apply (clarsimp simp: valid_def) apply (subgoal_tac "S b \ S s") apply (drule card_mono [OF y], simp) apply clarsimp apply (rule ccontr) apply (subgoal_tac "x \ S b", simp) apply (erule use_valid [OF _ x]) apply simp done lemma hoare_vcg_propE_R: "\\s. P\ f \\rv s. P\, -" by (simp add: validE_R_def validE_def valid_def split_def split: sum.split) lemma set_preserved_proof: assumes y: "\x. \\s. Q s \ x \ S s\ f \\rv s. x \ S s\" assumes x: "\x. \\s. Q s \ x \ S s\ f \\rv s. x \ S s\" shows "\\s. Q s \ P (S s)\ f \\rv s. P (S s)\" apply (clarsimp simp: valid_def) by (metis (mono_tags, lifting) equalityI post_by_hoare subsetI x y) lemma set_shrink_proof: assumes x: "\x. \\s. x \ S s\ f \\rv s. x \ S s\" shows "\\s. \S'. S' \ S s \ P S'\ f \\rv s. P (S s)\" apply (clarsimp simp: valid_def) apply (drule spec, erule mp) apply (clarsimp simp: subset_iff) apply (rule ccontr) apply (drule(1) use_valid [OF _ x]) apply simp done lemma shrinks_proof: assumes y: "\s. finite (S s)" assumes x: "\x. \\s. x \ S s \ P s\ f \\rv s. x \ S s\" assumes z: "\P\ f \\rv s. x \ S s\" assumes w: "\s. P s \ x \ S s" shows "\\s. card (S s) \ n \ P s\ f \\rv s. card (S s) < n\" apply (clarsimp simp: valid_def) apply (subgoal_tac "S b \ S s") apply (drule psubset_card_mono [OF y], simp) apply (rule psubsetI) apply clarsimp apply (rule ccontr) apply (subgoal_tac "x \ S b", simp) apply (erule use_valid [OF _ x]) apply simp by (metis use_valid w z) lemmas unlessE_wp = hoare_unlessE_wp (* FIXME lib: eliminate *) lemma use_validE_R: "\ (Inr r, s') \ fst (f s); \P\ f \Q\,-; P s \ \ Q r s'" unfolding validE_R_def validE_def by (frule(2) use_valid, simp) lemma valid_preservation_ex: assumes x: "\x P. \\s. P (f s x :: 'b)\ m \\rv s. P (f s x)\" shows "\\s. P (f s :: 'a \ 'b)\ m \\rv s. P (f s)\" apply (clarsimp simp: valid_def) apply (erule subst[rotated, where P=P]) apply (rule ext) apply (erule use_valid [OF _ x]) apply simp done lemmas valid_prove_more' = valid_prove_more[where Q="\rv. Q" for Q] lemma whenE_inv: assumes a: "\P\ f \\_. P\" shows "\P\ whenE Q f \\_. P\" by (wpsimp wp: a) lemma whenE_throwError_wp: "\\s. \ P \ Q s\ whenE P (throwError e) \\_. Q\, \\\\" by wpsimp lemma gets_the_inv: "\P\ gets_the V \\rv. P\" by wpsimp lemma select_f_inv: "\P\ select_f S \\_. P\" by (simp add: select_f_def valid_def) lemmas state_unchanged = in_inv_by_hoareD [THEN sym] lemma validI: assumes rl: "\s r s'. \ P s; (r, s') \ fst (S s) \ \ Q r s'" shows "\P\ S \Q\" unfolding valid_def using rl by safe lemma opt_return_pres_lift: assumes x: "\v. \P\ f v \\rv. P\" shows "\P\ case x of None \ return () | Some v \ f v \\rv. P\" by (wpsimp wp: x) lemma valid_return_unit: "\P\ f >>= (\_. return ()) \\r. Q\ \ \P\ f \\r. Q\" apply (rule validI) apply (fastforce simp: valid_def return_def bind_def split_def) done lemma static_imp_wp: "\Q\ m \R\ \ \\s. P \ Q s\ m \\rv s. P \ R rv s\" by (cases P, simp_all add: valid_def) lemma static_imp_wpE : "\Q\ m \R\,- \ \\s. P \ Q s\ m \\rv s. P \ R rv s\,-" by (cases P, simp_all) lemma static_imp_conj_wp: "\ \Q\ m \Q'\; \R\ m \R'\ \ \ \\s. (P \ Q s) \ R s\ m \\rv s. (P \ Q' rv s) \ R' rv s\" apply (rule hoare_vcg_conj_lift) apply (rule static_imp_wp) apply assumption+ done lemma hoare_eq_P: assumes "\P. \P\ f \\_. P\" shows "\(=) s\ f \\_. (=) s\" by (rule assms) lemma hoare_validE_R_conj: "\\P\ f \Q\, -; \P\ f \R\, -\ \ \P\ f \Q and R\, -" by (simp add: valid_def validE_def validE_R_def Let_def split_def split: sum.splits) lemma hoare_vcg_const_imp_lift_R: "\P\ f \Q\,- \ \\s. F \ P s\ f \\rv s. F \ Q rv s\,-" by (cases F, simp_all) lemma hoare_vcg_disj_lift_R: assumes x: "\P\ f \Q\,-" assumes y: "\P'\ f \Q'\,-" shows "\\s. P s \ P' s\ f \\rv s. Q rv s \ Q' rv s\,-" using assms by (fastforce simp: validE_R_def validE_def valid_def split: sum.splits) lemmas throwError_validE_R = throwError_wp [where E="\\", folded validE_R_def] lemma valid_case_option_post_wp: "(\x. \P x\ f \\rv. Q x\) \ \\s. case ep of Some x \ P x s | _ \ True\ f \\rv s. case ep of Some x \ Q x s | _ \ True\" by (cases ep, simp_all add: hoare_vcg_prop) lemma P_bool_lift: assumes t: "\Q\ f \\r. Q\" assumes f: "\\s. \Q s\ f \\r s. \Q s\" shows "\\s. P (Q s)\ f \\r s. P (Q s)\" apply (clarsimp simp: valid_def) apply (subgoal_tac "Q b = Q s") apply simp apply (rule iffI) apply (rule classical) apply (drule (1) use_valid [OF _ f]) apply simp apply (erule (1) use_valid [OF _ t]) done lemmas fail_inv = hoare_fail_any[where Q="\_. P" and P=P for P] lemma gets_sp: "\P\ gets f \\rv. P and (\s. f s = rv)\" by (wp, simp) lemma post_by_hoare2: "\ \P\ f \Q\; (r, s') \ fst (f s); P s \ \ Q r s'" by (rule post_by_hoare, assumption+) lemma hoare_Ball_helper: assumes x: "\x. \P x\ f \Q x\" assumes y: "\P. \\s. P (S s)\ f \\rv s. P (S s)\" shows "\\s. \x \ S s. P x s\ f \\rv s. \x \ S s. Q x rv s\" apply (clarsimp simp: valid_def) apply (subgoal_tac "S b = S s") apply (erule post_by_hoare2 [OF x]) apply (clarsimp simp: Ball_def) apply (erule_tac P1="\x. x = S s" in post_by_hoare2 [OF y]) apply (rule refl) done lemmas hoare_gets_post = hoare_gets_sp (* FIXME lib: eliminate *) lemmas hoare_return_post = return_sp (* FIXME lib: eliminate, rename original *) lemma handy_prop_divs: assumes x: "\P. \\s. P (Q s) \ S s\ f \\rv s. P (Q' rv s)\" "\P. \\s. P (R s) \ S s\ f \\rv s. P (R' rv s)\" shows "\\s. P (Q s \ R s) \ S s\ f \\rv s. P (Q' rv s \ R' rv s)\" "\\s. P (Q s \ R s) \ S s\ f \\rv s. P (Q' rv s \ R' rv s)\" apply (clarsimp simp: valid_def elim!: subst[rotated, where P=P]) apply (rule use_valid [OF _ x(1)], assumption) apply (rule use_valid [OF _ x(2)], assumption) apply simp apply (clarsimp simp: valid_def elim!: subst[rotated, where P=P]) apply (rule use_valid [OF _ x(1)], assumption) apply (rule use_valid [OF _ x(2)], assumption) apply simp done lemma hoare_as_subst: "\ \P. \\s. P (fn s)\ f \\rv s. P (fn s)\; \v :: 'a. \P v\ f \Q v\ \ \ \\s. P (fn s) s\ f \\rv s. Q (fn s) rv s\" by (rule hoare_lift_Pf3) lemmas hoare_vcg_ball_lift = hoare_vcg_const_Ball_lift lemma hoare_set_preserved: assumes x: "\x. \fn' x\ m \\rv. fn x\" shows "\\s. set xs \ {x. fn' x s}\ m \\rv s. set xs \ {x. fn x s}\" apply (induct xs) apply simp apply wp apply simp apply (rule hoare_vcg_conj_lift) apply (rule x) apply assumption done lemmas hoare_ex_wp = hoare_vcg_ex_lift (* FIXME lib: eliminate *) lemma hoare_ex_pre: (* safe, unlike hoare_ex_wp *) "(\x. \P x\ f \Q\) \ \\s. \x. P x s\ f \Q\" by (fastforce simp: valid_def) lemma hoare_ex_pre_conj: "(\x. \\s. P x s \ P' s\ f \Q\) \ \\s. (\x. P x s) \ P' s\ f \Q\" by (fastforce simp: valid_def) lemma hoare_conj_lift_inv: "\\P\ f \Q\; \\s. P' s \ I s\ f \\rv. I\; \s. P s \ P' s\ \ \\s. P s \ I s\ f \\rv s. Q rv s \ I s\" by (fastforce simp: valid_def) lemma hoare_in_monad_post : assumes x: "\P. \P\ f \\x. P\" shows "\\\ f \\rv s. (rv, s) \ fst (f s)\" apply (clarsimp simp: valid_def) apply (subgoal_tac "s = b", simp) apply (simp add: state_unchanged [OF x]) done lemma list_case_throw_validE_R: "\ \y ys. xs = y # ys \ \P\ f y ys \Q\,- \ \ \P\ case xs of [] \ throwError e | x # xs \ f x xs \Q\,-" apply (case_tac xs, simp_all) apply wp done lemma validE_R_sp: assumes x: "\P\ f \Q\,-" assumes y: "\x. \Q x\ g x \R\,-" shows "\P\ f >>=E (\x. g x) \R\,-" by (rule hoare_pre, wp x y, simp) lemma valid_set_take_helper: "\P\ f \\rv s. \x \ set (xs rv s). Q x rv s\ \ \P\ f \\rv s. \x \ set (take (n rv s) (xs rv s)). Q x rv s\" apply (erule hoare_strengthen_post) apply (clarsimp dest!: in_set_takeD) done lemma whenE_throwError_sp: "\P\ whenE Q (throwError e) \\rv s. \ Q \ P s\, -" apply (simp add: whenE_def validE_R_def) apply (intro conjI impI; wp) done lemma weaker_hoare_ifE: assumes x: "\P \ a \Q\,\E\" assumes y: "\P'\ b \Q\,\E\" shows "\P and P'\ if test then a else b \Q\,\E\" apply (rule hoare_vcg_precond_impE) apply (wp x y) apply simp done lemma wp_split_const_if: assumes x: "\P\ f \Q\" assumes y: "\P'\ f \Q'\" shows "\\s. (G \ P s) \ (\ G \ P' s)\ f \\rv s. (G \ Q rv s) \ (\ G \ Q' rv s)\" by (case_tac G, simp_all add: x y) lemma wp_split_const_if_R: assumes x: "\P\ f \Q\,-" assumes y: "\P'\ f \Q'\,-" shows "\\s. (G \ P s) \ (\ G \ P' s)\ f \\rv s. (G \ Q rv s) \ (\ G \ Q' rv s)\,-" by (case_tac G, simp_all add: x y) lemma wp_throw_const_imp: assumes x: "\P\ f \Q\" shows "\\s. G \ P s\ f \\rv s. G \ Q rv s\" by (case_tac G, simp_all add: x hoare_vcg_prop) lemma wp_throw_const_impE: assumes x: "\P\ f \Q\,\E\" shows "\\s. G \ P s\ f \\rv s. G \ Q rv s\,\\rv s. G \ E rv s\" apply (case_tac G, simp_all add: x) apply wp done lemma hoare_const_imp_R: "\Q\ f \R\,- \ \\s. P \ Q s\ f \\rv s. P \ R rv s\,-" by (cases P, simp_all) lemma hoare_vcg_imp_lift_R: "\ \P'\ f \\rv s. \ P rv s\, -; \Q'\ f \Q\, - \ \ \\s. P' s \ Q' s\ f \\rv s. P rv s \ Q rv s\, -" by (auto simp add: valid_def validE_R_def validE_def split_def split: sum.splits) lemma hoare_disj_division: "\ P \ Q; P \ \R\ f \S\; Q \ \T\ f \S\ \ \ \\s. (P \ R s) \ (Q \ T s)\ f \S\" apply safe apply (rule hoare_pre_imp) prefer 2 apply simp apply simp apply (rule hoare_pre_imp) prefer 2 apply simp apply simp done lemma hoare_grab_asm: "\ G \ \P\ f \Q\ \ \ \\s. G \ P s\ f \Q\" by (cases G, simp+) lemma hoare_grab_asm2: "(P' \ \\s. P s \ R s\ f \Q\) \ \\s. P s \ P' \ R s\ f \Q\" by (fastforce simp: valid_def) lemma hoare_grab_exs: assumes x: "\x. P x \ \P'\ f \Q\" shows "\\s. \x. P x \ P' s\ f \Q\" apply (clarsimp simp: valid_def) apply (erule(2) use_valid [OF _ x]) done lemma hoare_prop_E: "\\rv. P\ f -,\\rv s. P\" unfolding validE_E_def by (rule hoare_pre, wp, simp) lemma hoare_vcg_conj_lift_R: "\ \P\ f \Q\,-; \R\ f \S\,- \ \ \\s. P s \ R s\ f \\rv s. Q rv s \ S rv s\,-" apply (simp add: validE_R_def validE_def) apply (drule(1) hoare_vcg_conj_lift) apply (erule hoare_strengthen_post) apply (clarsimp split: sum.splits) done lemma hoare_walk_assmsE: assumes x: "\P\ f \\rv. P\" and y: "\s. P s \ Q s" and z: "\P\ g \\rv. Q\" shows "\P\ doE x \ f; g odE \\rv. Q\" apply (wp z) apply (simp add: validE_def) apply (rule hoare_strengthen_post [OF x]) apply (case_tac r, simp_all add: y) done lemma univ_wp: "\\s. \(rv, s') \ fst (f s). Q rv s'\ f \Q\" by (simp add: valid_def) lemma univ_get_wp: assumes x: "\P. \P\ f \\rv. P\" shows "\\s. \(rv, s') \ fst (f s). s = s' \ Q rv s'\ f \Q\" apply (rule hoare_pre_imp [OF _ univ_wp]) apply clarsimp apply (drule bspec, assumption, simp) apply (subgoal_tac "s = b", simp) apply (simp add: state_unchanged [OF x]) done lemma result_in_set_wp : assumes x: "\P. \P\ fn \\rv. P\" shows "\\s. True\ fn \\v s'. (v, s') \ fst (fn s')\" by (rule hoare_pre_imp [OF _ univ_get_wp], simp_all add: x split_def) clarsimp lemma other_result_in_set_wp: assumes x: "\P. \P\ fn \\rv. P\" shows "\\s. \(v, s) \ fst (fn s). F v = v\ fn \\v s'. (F v, s') \ fst (fn s')\" proof - have P: "\v s. (F v = v) \ (v, s) \ fst (fn s) \ (F v, s) \ fst (fn s)" by simp show ?thesis apply (rule hoare_post_imp [OF P], assumption) apply (rule hoare_pre_imp) defer apply (rule hoare_vcg_conj_lift) apply (rule univ_get_wp [OF x]) apply (rule result_in_set_wp [OF x]) apply clarsimp apply (drule bspec, assumption, simp) done qed lemma weak_if_wp: "\ \P\ f \Q\; \P'\ f \Q'\ \ \ \P and P'\ f \\r. if C r then Q r else Q' r\" by (auto simp add: valid_def split_def) lemma bindE_split_recursive_asm: assumes x: "\x s'. \ (Inr x, s') \ fst (f s) \ \ \\s. B x s \ s = s'\ g x \C\, \E\" shows "\A\ f \B\, \E\ \ \\st. A st \ st = s\ f >>=E g \C\, \E\" apply (clarsimp simp: validE_def valid_def bindE_def bind_def lift_def) apply (erule allE, erule(1) impE) apply (drule(1) bspec, simp) apply (case_tac a, simp_all add: throwError_def return_def) apply (drule x) apply (clarsimp simp: validE_def valid_def) apply (drule(1) bspec, simp) done lemma validE_R_abstract_rv: "\P\ f \\rv s. \rv'. Q rv' s\,- \ \P\ f \Q\,-" by (erule hoare_post_imp_R, simp) lemma validE_cases_valid: "\P\ f \\rv s. Q (Inr rv) s\,\\rv s. Q (Inl rv) s\ \ \P\ f \Q\" apply (simp add: validE_def) apply (erule hoare_strengthen_post) apply (simp split: sum.split_asm) done lemma liftM_pre: assumes rl: "\\s. \ P s \ a \ \_ _. False \" shows "\\s. \ P s \ liftM f a \ \_ _. False \" unfolding liftM_def apply (rule seq) apply (rule rl) apply wp apply simp done lemma hoare_gen_asm': "(P \ \P'\ f \Q\) \ \P' and (\_. P)\ f \Q\" apply (auto intro: hoare_assume_pre) done lemma hoare_gen_asm_conj: "(P \ \P'\ f \Q\) \ \\s. P' s \ P\ f \Q\" by (fastforce simp: valid_def) lemma hoare_add_K: "\P\ f \Q\ \ \\s. P s \ I\ f \\rv s. Q rv s \ I\" by (fastforce simp: valid_def) lemma valid_rv_lift: "\P'\ f \\rv s. rv \ Q rv s\ \ \\s. P \ P' s\ f \\rv s. rv \ P \ Q rv s\" by (fastforce simp: valid_def) lemma valid_imp_ex: "\P\ f \\rv s. \x. rv \ Q rv s x\ \ \P\ f \\rv s. rv \ (\x. Q rv s x)\" by (fastforce simp: valid_def) lemma valid_rv_split: "\\P\ f \\rv s. rv \ Q s\; \P\ f \\rv s. \rv \ Q' s\\ \ \P\ f \\rv s. if rv then Q s else Q' s\" by (fastforce simp: valid_def) lemma hoare_rv_split: "\\P\ f \\rv s. rv \ (Q rv s)\; \P\ f \\rv s. (\rv) \ (Q rv s)\\ \ \P\ f \Q\" apply (clarsimp simp: valid_def) apply (case_tac a, fastforce+) done lemma combine_validE: "\ \ P \ x \ Q \,\ E \; \ P' \ x \ Q' \,\ E' \ \ \ \ P and P' \ x \ \r. (Q r) and (Q' r) \,\\r. (E r) and (E' r) \" apply (clarsimp simp: validE_def valid_def split: sum.splits) apply (erule allE, erule (1) impE)+ apply (drule (1) bspec)+ apply clarsimp done lemma valid_case_prod: "\ \x y. valid (P x y) (f x y) Q \ \ valid (case_prod P v) (case_prod (\x y. f x y) v) Q" by (simp add: split_def) lemma validE_case_prod: "\ \x y. validE (P x y) (f x y) Q E \ \ validE (case_prod P v) (case_prod (\x y. f x y) v) Q E" by (simp add: split_def) lemma valid_pre_satisfies_post: "\ \s r' s'. P s \ Q r' s' \ \ \ P \ m \ Q \" by (clarsimp simp: valid_def) lemma validE_pre_satisfies_post: "\ \s r' s'. P s \ Q r' s'; \s r' s'. P s \ R r' s' \ \ \ P \ m \ Q \,\ R \" by (clarsimp simp: validE_def2 split: sum.splits) lemma hoare_assume_preNF: "(\s. P s \ \P\ f \Q\!) \ \P\ f \Q\!" by (metis validNF_alt_def) lemma hoare_validE_R_conjI: "\ \P\ f \Q\, - ; \P\ f \Q'\, - \ \ \P\ f \\rv s. Q rv s \ Q' rv s\, -" apply (clarsimp simp: Ball_def validE_R_def validE_def valid_def) by (case_tac a; fastforce) lemma validE_R_post_conjD1: "\P\ f \\r s. Q r s \ R r s\,- \ \P\ f \Q\,-" apply (clarsimp simp: validE_R_def validE_def valid_def) by (case_tac a; fastforce) lemma validE_R_post_conjD2: "\P\ f \\r s. Q r s \ R r s\,- \ \P\ f \R\,-" apply (clarsimp simp: validE_R_def validE_def valid_def) by (case_tac a; fastforce) lemma throw_opt_wp[wp]: "\if v = None then E ex else Q (the v)\ throw_opt ex v \Q\,\E\" unfolding throw_opt_def by wpsimp auto lemma hoare_name_pre_state2: "(\s. \P and ((=) s)\ f \Q\) \ \P\ f \Q\" by (auto simp: valid_def intro: hoare_name_pre_state) lemma returnOk_E': "\P\ returnOk r -,\E\" by (clarsimp simp: returnOk_def validE_E_def validE_def valid_def return_def) lemma throwError_R': "\P\ throwError e \Q\,-" by (clarsimp simp:throwError_def validE_R_def validE_def valid_def return_def) end