(* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) theory TraceMonadVCG imports TraceMonad WPSimp Strengthen begin lemma trace_steps_append: "trace_steps (xs @ ys) s = trace_steps xs s \ trace_steps ys (last_st_tr (rev xs) s)" by (induct xs arbitrary: s, simp_all add: last_st_tr_def hd_append) lemma rely_cond_append: "rely_cond R s (xs @ ys) = (rely_cond R s ys \ rely_cond R (last_st_tr ys s) xs)" by (simp add: rely_cond_def trace_steps_append ball_Un conj_comms) lemma guar_cond_append: "guar_cond G s (xs @ ys) = (guar_cond G s ys \ guar_cond G (last_st_tr ys s) xs)" by (simp add: guar_cond_def trace_steps_append ball_Un conj_comms) lemma prefix_closed_bind: "prefix_closed f \ (\x. prefix_closed (g x)) \ prefix_closed (f >>= g)" apply (subst prefix_closed_def, clarsimp simp: bind_def) apply (auto simp: Cons_eq_append_conv split: tmres.split_asm dest!: prefix_closedD[rotated]; fastforce elim: rev_bexI) done lemmas prefix_closed_bind[rule_format, wp_split] lemma last_st_tr_append[simp]: "last_st_tr (tr @ tr') s = last_st_tr tr (last_st_tr tr' s)" by (simp add: last_st_tr_def hd_append) lemma last_st_tr_Nil[simp]: "last_st_tr [] s = s" by (simp add: last_st_tr_def) lemma last_st_tr_Cons[simp]: "last_st_tr (x # xs) s = snd x" by (simp add: last_st_tr_def) lemma bind_twp[wp_split]: "\ \r. \Q' r\,\R\ g r \G\,\Q\; \P\,\R\ f \G\,\Q'\ \ \ \P\,\R\ f >>= (\r. g r) \G\,\Q\" apply (subst validI_def, rule conjI) apply (blast intro: prefix_closed_bind validI_prefix_closed) apply (clarsimp simp: bind_def rely_def) apply (drule(2) validI_D) apply (clarsimp simp: rely_cond_append split: tmres.split_asm) apply (clarsimp split: tmres.split_asm) apply (drule meta_spec, frule(2) validI_D) apply (clarsimp simp: rely_cond_append split: if_split_asm) apply (clarsimp simp: guar_cond_append) done lemma trace_steps_rev_drop_nth: "trace_steps (rev (drop n tr)) s = (\i. (fst (rev tr ! i), (if i = 0 then s else snd (rev tr ! (i - 1))), snd (rev tr ! i))) ` {..< length tr - n}" apply (simp add: trace_steps_nth) apply (intro image_cong refl) apply (simp add: rev_nth) done lemma prefix_closed_drop: "(tr, res) \ f s \ prefix_closed f \ \res'. (drop n tr, res') \ f s" proof (induct n arbitrary: res) case 0 then show ?case by auto next case (Suc n) have drop_1: "\tr res. (tr, res) \ f s \ \res'. (drop 1 tr, res') \ f s" by (case_tac tr; fastforce dest: prefix_closedD[rotated] intro: Suc) show ?case using Suc.hyps[OF Suc.prems] by (metis drop_1[simplified] drop_drop add_0 add_Suc) qed lemma validI_GD_drop: "\ \P\, \R\ f \G\, \Q\; P s0 s; (tr, res) \ f s; rely_cond R s0 (drop n tr) \ \ guar_cond G s0 (drop n tr)" apply (drule prefix_closed_drop[where n=n], erule validI_prefix_closed) apply (auto dest: validI_GD) done lemma parallel_prefix_closed[wp_split]: "prefix_closed f \ prefix_closed g \ prefix_closed (parallel f g)" apply (subst prefix_closed_def, clarsimp simp: parallel_def) apply (case_tac f_steps; clarsimp) apply (drule(1) prefix_closedD)+ apply fastforce done lemma rely_cond_drop: "rely_cond R s0 xs \ rely_cond R s0 (drop n xs)" using rely_cond_append[where xs="take n xs" and ys="drop n xs"] by simp lemma rely_cond_is_drop: "rely_cond R s0 xs \ (ys = drop (length xs - length ys) xs) \ rely_cond R s0 ys" by (metis rely_cond_drop) lemma bounded_rev_nat_induct: "(\n. N \ n \ P n) \ (\n. n < N \ P (Suc n) \ P n) \ P n" by (induct diff\"N - n" arbitrary: n; simp) lemma drop_n_induct: "P [] \ (\n. n < length xs \ P (drop (Suc n) xs) \ P (drop n xs)) \ P (drop n xs)" by (induct len\"length (drop n xs)" arbitrary: n xs; simp) lemma guar_cond_Cons_eq: "guar_cond R s0 (x # xs) = (guar_cond R s0 xs \ (fst x \ Env \ R (last_st_tr xs s0) (snd x)))" by (cases "fst x"; simp add: guar_cond_def trace_steps_append conj_comms) lemma guar_cond_Cons: "guar_cond R s0 xs \ fst x \ Env \ R (last_st_tr xs s0) (snd x) \ guar_cond R s0 (x # xs)" by (simp add: guar_cond_Cons_eq) lemma guar_cond_drop_Suc_eq: "n < length xs \ guar_cond R s0 (drop n xs) = (guar_cond R s0 (drop (Suc n) xs) \ (fst (xs ! n) \ Env \ R (last_st_tr (drop (Suc n) xs) s0) (snd (xs ! n))))" apply (rule trans[OF _ guar_cond_Cons_eq]) apply (simp add: Cons_nth_drop_Suc) done lemma guar_cond_drop_Suc: "guar_cond R s0 (drop (Suc n) xs) \ fst (xs ! n) \ Env \ R (last_st_tr (drop (Suc n) xs) s0) (snd (xs ! n)) \ guar_cond R s0 (drop n xs)" by (case_tac "n < length xs"; simp add: guar_cond_drop_Suc_eq) lemma rely_cond_Cons_eq: "rely_cond R s0 (x # xs) = (rely_cond R s0 xs \ (fst x = Env \ R (last_st_tr xs s0) (snd x)))" by (simp add: rely_cond_def trace_steps_append conj_comms) lemma rely_cond_Cons: "rely_cond R s0 xs \ fst x = Env \ R (last_st_tr xs s0) (snd x) \ rely_cond R s0 (x # xs)" by (simp add: rely_cond_Cons_eq) lemma rely_cond_drop_Suc_eq: "n < length xs \ rely_cond R s0 (drop n xs) = (rely_cond R s0 (drop (Suc n) xs) \ (fst (xs ! n) = Env \ R (last_st_tr (drop (Suc n) xs) s0) (snd (xs ! n))))" apply (rule trans[OF _ rely_cond_Cons_eq]) apply (simp add: Cons_nth_drop_Suc) done lemma rely_cond_drop_Suc: "rely_cond R s0 (drop (Suc n) xs) \ fst (xs ! n) = Env \ R (last_st_tr (drop (Suc n) xs) s0) (snd (xs ! n)) \ rely_cond R s0 (drop n xs)" by (cases "n < length xs"; simp add: rely_cond_drop_Suc_eq) lemma last_st_tr_map_zip_hd: "length flags = length tr \ tr \ [] \ snd (f (hd flags, hd tr)) = snd (hd tr) \ last_st_tr (map f (zip flags tr)) = last_st_tr tr" apply (cases tr; simp) apply (cases flags; simp) apply (simp add: fun_eq_iff) done lemma last_st_tr_drop_map_zip_hd: "length flags = length tr \ n < length tr \ snd (f (flags ! n, tr ! n)) = snd (tr ! n) \ last_st_tr (drop n (map f (zip flags tr))) = last_st_tr (drop n tr)" apply (simp add: drop_map drop_zip) apply (rule last_st_tr_map_zip_hd; clarsimp) apply (simp add: hd_drop_conv_nth) done lemma last_st_tr_map_zip: "length flags = length tr \ \fl tmid s. snd (f (fl, (tmid, s))) = s \ last_st_tr (map f (zip flags tr)) = last_st_tr tr" apply (erule last_st_tr_map_zip_hd) apply (clarsimp simp: neq_Nil_conv) done lemma parallel_rely_induct: assumes preds: "(tr, v) \ parallel f g s" "Pf s0 s" "Pg s0 s" assumes validI: "\Pf\,\Rf\ f' \Gf\,\Qf\" "\Pg\,\Rg\ g' \Gg\,\Qg\" "f s \ f' s" "g s \ g' s" and compat: "R \ Rf" "R \ Rg" "Gf \ G" "Gg \ G" "Gf \ Rg" "Gg \ Rf" and rely: "rely_cond R s0 (drop n tr)" shows "\tr_f tr_g. (tr_f, v) \ f s \ (tr_g, v) \ g s \ rely_cond Rf s0 (drop n tr_f) \ rely_cond Rg s0 (drop n tr_g) \ map snd tr_f = map snd tr \ map snd tr_g = map snd tr \ (\i \ length tr. last_st_tr (drop i tr_g) s0 = last_st_tr (drop i tr_f) s0) \ guar_cond G s0 (drop n tr)" (is "\ys zs. _ \ _ \ ?concl ys zs") proof - obtain ys zs where tr: "tr = map parallel_mrg (zip ys zs)" and all2: "list_all2 (\y z. (fst y = Env \ fst z = Env) \ snd y = snd z) ys zs" and ys: "(ys, v) \ f s" and zs: "(zs, v) \ g s" using preds by (clarsimp simp: parallel_def2) note len[simp] = list_all2_lengthD[OF all2] have ys': "(ys, v) \ f' s" and zs': "(zs, v) \ g' s" using ys zs validI by auto note rely_f_step = validI_GD_drop[OF validI(1) preds(2) ys' rely_cond_drop_Suc] note rely_g_step = validI_GD_drop[OF validI(2) preds(3) zs' rely_cond_drop_Suc] note snd[simp] = list_all2_nthD[OF all2, THEN conjunct2] have "?concl ys zs" using rely tr all2 rely_f_step rely_g_step apply (induct n rule: bounded_rev_nat_induct) apply (subst drop_all, assumption) apply clarsimp apply (simp add: list_all2_conv_all_nth last_st_tr_def drop_map[symmetric] hd_drop_conv_nth hd_append) apply (fastforce simp: split_def intro!: nth_equalityI) apply clarsimp apply (erule_tac x=n in meta_allE)+ apply (drule meta_mp, erule rely_cond_is_drop, simp) apply (subst(asm) rely_cond_drop_Suc_eq[where xs="map f xs" for f xs], simp) apply (clarsimp simp: last_st_tr_drop_map_zip_hd if_split[where P="\x. x = Env"] split_def) apply (intro conjI; (rule guar_cond_drop_Suc rely_cond_drop_Suc, assumption)) apply (auto simp: guar_cond_drop_Suc_eq last_st_tr_drop_map_zip_hd intro: compat[THEN predicate2D]) done thus ?thesis using ys zs by auto qed lemmas parallel_rely_induct0 = parallel_rely_induct[where n=0, simplified] lemma rg_validI: assumes validI: "\Pf\,\Rf\ f \Gf\,\Qf\" "\Pg\,\Rg\ g \Gg\,\Qg\" and compat: "R \ Rf" "R \ Rg" "Gf \ G" "Gg \ G" "Gf \ Rg" "Gg \ Rf" shows "\Pf And Pg\,\R\ parallel f g \G\,\\rv. Qf rv And Qg rv\" apply (clarsimp simp: validI_def rely_def bipred_conj_def parallel_prefix_closed validI[THEN validI_prefix_closed]) apply (drule(3) parallel_rely_induct0[OF _ _ _ validI order_refl order_refl compat]) apply clarsimp apply (drule(2) validI[THEN validI_rvD])+ apply (simp add: last_st_tr_def) done lemma validI_weaken_pre[wp_pre]: "\P'\,\R\ f \G\,\Q\ \ (\s0 s. P s0 s \ P' s0 s) \ \P\,\R\ f \G\,\Q\" by (simp add: validI_def, blast) lemma rely_weaken: "(\s0 s. R s0 s \ R' s0 s) \ (tr, res) \ rely f R s s0 \ (tr, res) \ rely f R' s s0" by (simp add: rely_def rely_cond_def, blast) lemma validI_weaken_rely[wp_pre]: "\P\,\R'\ f \G\,\Q\ \ (\s0 s. R s0 s \ R' s0 s) \ \P\,\R\ f \G\,\Q\" apply (simp add: validI_def) by (metis rely_weaken) lemma validI_strengthen_post: "\P\,\R\ f \G\,\Q'\ \ (\v s0 s. Q' v s0 s \ Q v s0 s) \ \P\,\R\ f \G\,\Q\" by (simp add: validI_def) lemma validI_strengthen_guar: "\P\, \R\ f \G'\, \Q\ \ (\s0 s. G' s0 s \ G s0 s) \ \P\, \R\ f \G\, \Q\" by (force simp: validI_def guar_cond_def) lemma rely_prim[simp]: "rely (\s. insert (v s) (f s)) R s0 = (\s. {x. x = v s \ rely_cond R s0 (fst x)} \ (rely f R s0 s))" "rely (\s. {}) R s0 = (\_. {})" by (auto simp: rely_def prod_eq_iff) lemma prefix_closed_put_trace_elem[iff]: "prefix_closed (put_trace_elem x)" by (clarsimp simp: prefix_closed_def put_trace_elem_def) lemma prefix_closed_return[iff]: "prefix_closed (return x)" by (simp add: prefix_closed_def return_def) lemma prefix_closed_put_trace[iff]: "prefix_closed (put_trace tr)" by (induct tr; clarsimp simp: prefix_closed_bind) lemma put_trace_eq_drop: "put_trace xs s = ((\n. (drop n xs, if n = 0 then Result ((), s) else Incomplete)) ` {.. length xs})" apply (induct xs) apply (clarsimp simp: return_def) apply (clarsimp simp: put_trace_elem_def bind_def) apply (simp add: atMost_Suc_eq_insert_0 image_image) apply (rule equalityI; clarsimp) apply (split if_split_asm; clarsimp) apply (auto intro: image_eqI[where x=0])[1] apply (rule rev_bexI, simp) apply clarsimp done lemma put_trace_res: "(tr, res) \ put_trace xs s \ \n. tr = drop n xs \ n \ length xs \ res = (case n of 0 \ Result ((), s) | _ \ Incomplete)" apply (clarsimp simp: put_trace_eq_drop) apply (case_tac n; auto intro: exI[where x=0]) done lemma put_trace_twp[wp]: "\\s0 s. (\n. rely_cond R s0 (drop n xs) \ guar_cond G s0 (drop n xs)) \ (rely_cond R s0 xs \ Q () (last_st_tr xs s0) s)\,\R\ put_trace xs \G\,\Q\" apply (clarsimp simp: validI_def rely_def) apply (drule put_trace_res) apply (clarsimp; clarsimp split: nat.split_asm) done lemmas put_trace_elem_twp = put_trace_twp[where xs="[x]" for x, simplified] lemma prefix_closed_select[iff]: "prefix_closed (select S)" by (simp add: prefix_closed_def select_def image_def) lemma select_wp[wp]: "\\s. \x \ S. Q x s\ select S \Q\" by (simp add: select_def valid_def mres_def image_def) lemma rely_cond_rtranclp: "rely_cond R s (map (Pair Env) xs) \ rtranclp R s (last_st_tr (map (Pair Env) xs) s)" apply (induct xs arbitrary: s rule: rev_induct) apply simp apply (clarsimp simp add: rely_cond_def) apply (erule converse_rtranclp_into_rtranclp) apply simp done lemma put_wp[wp]: "\\_. Q () s\ put s \Q\" by (simp add: put_def valid_def mres_def) lemma get_wp[wp]: "\\s. Q s s\ get \Q\" by (simp add: get_def valid_def mres_def) lemma bind_wp[wp_split]: "\ \r. \Q' r\ g r \Q\; \P\f \Q'\ \ \ \P\ f >>= (\r. g r) \Q\" by (fastforce simp: valid_def bind_def2 mres_def intro: image_eqI[rotated]) lemma modify_wp[wp]: "\\s. Q () (f s)\ modify f \Q\" unfolding modify_def by wp definition no_trace :: "('s,'a) tmonad \ bool" where "no_trace f = (\tr res s. (tr, res) \ f s \ tr = [] \ res \ Incomplete)" lemmas no_traceD = no_trace_def[THEN iffD1, rule_format] lemma no_trace_emp: "no_trace f \ (tr, r) \ f s \ tr = []" by (simp add: no_traceD) lemma no_trace_Incomplete_mem: "no_trace f \ (tr, Incomplete) \ f s" by (auto dest: no_traceD) lemma no_trace_Incomplete_eq: "no_trace f \ (tr, res) \ f s \ res \ Incomplete" by (auto dest: no_traceD) lemma no_trace_prefix_closed: "no_trace f \ prefix_closed f" by (auto simp add: prefix_closed_def dest: no_trace_emp) (* Attempt to define triple_judgement to use valid_validI_wp as wp_comb rule. It doesn't work. It seems that wp_comb rules cannot take more than 1 assumption *) lemma validI_is_triple: "\P\,\R\ f \G\,\Q\ = triple_judgement (\(s0, s). prefix_closed f \ P s0 s) f (\(s0,s) f. prefix_closed f \ (\tr res. (tr, res) \ rely f R s0 s \ guar_cond G s0 tr \ (\rv s'. res = Result (rv, s') \ Q rv (last_st_tr tr s0) s')))" apply (simp add: triple_judgement_def validI_def ) apply (cases "prefix_closed f"; simp) done lemma valid_is_triple: "valid P f Q = triple_judgement P f (\s f. (\(r,s') \ (mres (f s)). Q r s'))" by (simp add: triple_judgement_def valid_def mres_def) lemma no_trace_is_triple: "no_trace f = triple_judgement \ f (\() f. id no_trace f)" by (simp add: triple_judgement_def split: unit.split) lemmas [wp_trip] = valid_is_triple validI_is_triple no_trace_is_triple lemma valid_validI_wp[wp_comb]: "no_trace f \ (\s0. \P s0\ f \\v. Q v s0 \) \ \P\,\R\ f \G\,\Q\" by (fastforce simp: rely_def validI_def valid_def mres_def no_trace_prefix_closed dest: no_trace_emp elim: image_eqI[rotated]) (* Since valid_validI_wp in wp_comb doesn't work, we add the rules directly in the wp set *) lemma no_trace_prim: "no_trace get" "no_trace (put s)" "no_trace (modify f)" "no_trace (return v)" "no_trace fail" by (simp_all add: no_trace_def get_def put_def modify_def bind_def return_def select_def fail_def) lemma no_trace_select: "no_trace (select S)" by (clarsimp simp add: no_trace_def select_def) lemma no_trace_bind: "no_trace f \ \rv. no_trace (g rv) \ no_trace (do rv \ f; g rv od)" apply (subst no_trace_def) apply (clarsimp simp add: bind_def split: tmres.split_asm; auto dest: no_traceD[rotated]) done lemma no_trace_extra: "no_trace (gets f)" "no_trace (assert P)" "no_trace (assert_opt Q)" by (simp_all add: gets_def assert_def assert_opt_def no_trace_bind no_trace_prim split: option.split) lemmas no_trace_all[wp, iff] = no_trace_prim no_trace_select no_trace_extra lemma env_steps_twp[wp]: "\\s0 s. (\s'. R\<^sup>*\<^sup>* s0 s' \ Q () s' s') \ Q () s0 s\,\R\ env_steps \G\,\Q\" apply (simp add: interference_def env_steps_def) apply wp apply (clarsimp simp: guar_cond_def trace_steps_rev_drop_nth rev_nth) apply (drule rely_cond_rtranclp) apply (clarsimp simp add: last_st_tr_def hd_append) done lemma interference_twp[wp]: "\\s0 s. (\s'. R\<^sup>*\<^sup>* s s' \ Q () s' s') \ G s0 s\,\R\ interference \G\,\Q\" apply (simp add: interference_def commit_step_def del: put_trace.simps) apply wp apply clarsimp apply (simp add: drop_Cons nat.split rely_cond_def guar_cond_def) done (* what Await does if we haven't committed our step is a little strange. this assumes we have, which means s0 = s. we should revisit this if we find a use for Await when this isn't the case *) lemma Await_sync_twp: "\\s0 s. s = s0 \ (\x. R\<^sup>*\<^sup>* s0 x \ c x \ Q () x x)\,\R\ Await c \G\,\Q\" apply (simp add: Await_def split_def) apply wp apply clarsimp apply (clarsimp simp: guar_cond_def trace_steps_rev_drop_nth rev_nth) apply (drule rely_cond_rtranclp) apply (simp add: o_def) done (* Wrap up the standard usage pattern of wp/wpc/simp into its own command: *) method wpsimp uses wp simp split split_del cong = ((determ \wp add: wp|wpc|clarsimp simp: simp split: split split del: split_del cong: cong\)+)[1] declare K_def [simp] section "Satisfiability" text \ The dual to validity: an existential instead of a universal quantifier for the post condition. In refinement, it is often sufficient to know that there is one state that satisfies a condition. \ definition exs_valid :: "('a \ bool) \ ('a, 'b) tmonad \ ('b \ 'a \ bool) \ bool" ("\_\ _ \\_\") where "exs_valid P f Q \ (\s. P s \ (\(rv, s') \ mres (f s). Q rv s'))" text \The above for the exception monad\ definition ex_exs_validE :: "('a \ bool) \ ('a, 'e + 'b) tmonad \ ('b \ 'a \ bool) \ ('e \ 'a \ bool) \ bool" ("\_\ _ \\_\, \_\") where "ex_exs_validE P f Q E \ exs_valid P f (\rv. case rv of Inl e \ E e | Inr v \ Q v)" section "Lemmas" subsection \Determinism\ lemma det_set_iff: "det f \ (r \ mres (f s)) = (mres (f s) = {r})" apply (simp add: det_def mres_def) apply (fastforce elim: allE[where x=s]) done lemma return_det [iff]: "det (return x)" by (simp add: det_def return_def) lemma put_det [iff]: "det (put s)" by (simp add: det_def put_def) lemma get_det [iff]: "det get" by (simp add: det_def get_def) lemma det_gets [iff]: "det (gets f)" by (auto simp add: gets_def det_def get_def return_def bind_def) lemma det_UN: "det f \ (\x \ mres (f s). g x) = (g (THE x. x \ mres (f s)))" unfolding det_def mres_def apply simp apply (drule spec [of _ s]) apply (clarsimp simp: vimage_def) done lemma bind_detI [simp, intro!]: "\ det f; \x. det (g x) \ \ det (f >>= g)" apply (simp add: bind_def det_def split_def) apply clarsimp apply (erule_tac x=s in allE) apply clarsimp done lemma det_modify[iff]: "det (modify f)" by (simp add: modify_def) lemma the_run_stateI: "mres (M s) = {s'} \ the_run_state M s = s'" by (simp add: the_run_state_def) lemma the_run_state_det: "\ s' \ mres (M s); det M \ \ the_run_state M s = s'" by (simp only: the_run_stateI det_set_iff[where f=M and s=s]) subsection "Lifting and Alternative Basic Definitions" lemma liftE_liftM: "liftE = liftM Inr" apply (rule ext) apply (simp add: liftE_def liftM_def) done lemma liftME_liftM: "liftME f = liftM (case_sum Inl (Inr \ f))" apply (rule ext) apply (simp add: liftME_def liftM_def bindE_def returnOk_def lift_def) apply (rule_tac f="bind x" in arg_cong) apply (rule ext) apply (case_tac xa) apply (simp_all add: lift_def throwError_def) done lemma liftE_bindE: "(liftE a) >>=E b = a >>= b" apply (simp add: liftE_def bindE_def lift_def bind_assoc) done lemma liftM_id[simp]: "liftM id = id" apply (rule ext) apply (simp add: liftM_def) done lemma liftM_bind: "(liftM t f >>= g) = (f >>= (\x. g (t x)))" by (simp add: liftM_def bind_assoc) lemma gets_bind_ign: "gets f >>= (\x. m) = m" apply (rule ext) apply (simp add: bind_def simpler_gets_def) done lemma get_bind_apply: "(get >>= f) x = f x x" by (simp add: get_def bind_def) lemma exec_gets: "(gets f >>= m) s = m (f s) s" by (simp add: simpler_gets_def bind_def) lemma exec_get: "(get >>= m) s = m s s" by (simp add: get_def bind_def) lemma bind_eqI: "\ f = f'; \x. g x = g' x \ \ f >>= g = f' >>= g'" apply (rule ext) apply (simp add: bind_def) done subsection "Simplification Rules for Lifted And/Or" lemma pred_andE[elim!]: "\ (A and B) x; \ A x; B x \ \ R \ \ R" by(simp add:pred_conj_def) lemma pred_andI[intro!]: "\ A x; B x \ \ (A and B) x" by(simp add:pred_conj_def) lemma pred_conj_app[simp]: "(P and Q) x = (P x \ Q x)" by(simp add:pred_conj_def) lemma bipred_andE[elim!]: "\ (A And B) x y; \ A x y; B x y \ \ R \ \ R" by(simp add:bipred_conj_def) lemma bipred_andI[intro!]: "\ A x y; B x y \ \ (A And B) x y" by (simp add:bipred_conj_def) lemma bipred_conj_app[simp]: "(P And Q) x = (P x and Q x)" by(simp add:pred_conj_def bipred_conj_def) lemma pred_disjE[elim!]: "\ (P or Q) x; P x \ R; Q x \ R \ \ R" by (fastforce simp: pred_disj_def) lemma pred_disjI1[intro]: "P x \ (P or Q) x" by (simp add: pred_disj_def) lemma pred_disjI2[intro]: "Q x \ (P or Q) x" by (simp add: pred_disj_def) lemma pred_disj_app[simp]: "(P or Q) x = (P x \ Q x)" by auto lemma bipred_disjI1[intro]: "P x y \ (P Or Q) x y" by (simp add: bipred_disj_def) lemma bipred_disjI2[intro]: "Q x y \ (P Or Q) x y" by (simp add: bipred_disj_def) lemma bipred_disj_app[simp]: "(P Or Q) x = (P x or Q x)" by(simp add:pred_disj_def bipred_disj_def) lemma pred_notnotD[simp]: "(not not P) = P" by(simp add:pred_neg_def) lemma pred_and_true[simp]: "(P and \) = P" by(simp add:pred_conj_def) lemma pred_and_true_var[simp]: "(\ and P) = P" by(simp add:pred_conj_def) lemma pred_and_false[simp]: "(P and \) = \" by(simp add:pred_conj_def) lemma pred_and_false_var[simp]: "(\ and P) = \" by(simp add:pred_conj_def) lemma bipred_disj_op_eq[simp]: "reflp R \ (=) Or R = R" apply (rule ext, rule ext) apply (auto simp: reflp_def) done lemma bipred_le_true[simp]: "R \ \\" by clarsimp subsection "Hoare Logic Rules" lemma validE_def2: "validE P f Q R \ \s. P s \ (\(r,s') \ mres (f s). case r of Inr b \ Q b s' | Inl a \ R a s')" by (unfold valid_def validE_def) lemma seq': "\ \A\ f \B\; \x. P x \ \C\ g x \D\; \x s. B x s \ P x \ C s \ \ \A\ do x \ f; g x od \D\" apply (erule bind_wp[rotated]) apply (clarsimp simp: valid_def) apply (fastforce elim: rev_bexI image_eqI[rotated]) done lemma seq: assumes f_valid: "\A\ f \B\" assumes g_valid: "\x. P x \ \C\ g x \D\" assumes bind: "\x s. B x s \ P x \ C s" shows "\A\ do x \ f; g x od \D\" apply (insert f_valid g_valid bind) apply (blast intro: seq') done lemma seq_ext': "\ \A\ f \B\; \x. \B x\ g x \C\ \ \ \A\ do x \ f; g x od \C\" by (metis bind_wp) lemmas seq_ext = bind_wp[rotated] lemma seqE': "\ \A\ f \B\,\E\ ; \x. \B x\ g x \C\,\E\ \ \ \A\ doE x \ f; g x odE \C\,\E\" apply (simp add: bindE_def validE_def) apply (erule seq_ext') apply (auto simp: lift_def valid_def throwError_def return_def mres_def split: sum.splits) done lemma seqE: assumes f_valid: "\A\ f \B\,\E\" assumes g_valid: "\x. \B x\ g x \C\,\E\" shows "\A\ doE x \ f; g x odE \C\,\E\" apply(insert f_valid g_valid) apply(blast intro: seqE') done lemma hoare_TrueI: "\P\ f \\_. \\" by (simp add: valid_def) lemma hoareE_TrueI: "\P\ f \\_. \\, \\r. \\" by (simp add: validE_def valid_def) lemma hoare_True_E_R [simp]: "\P\ f \\r s. True\, -" by (auto simp add: validE_R_def validE_def valid_def split: sum.splits) lemma hoare_post_conj [intro!]: "\ \ P \ a \ Q \; \ P \ a \ R \ \ \ \ P \ a \ Q And R \" by (fastforce simp: valid_def split_def bipred_conj_def) lemma hoare_pre_disj [intro!]: "\ \ P \ a \ R \; \ Q \ a \ R \ \ \ \ P or Q \ a \ R \" by (simp add:valid_def pred_disj_def) lemma hoare_conj: "\ \P\ f \Q\; \P'\ f \Q'\ \ \ \P and P'\ f \Q And Q'\" unfolding valid_def by (auto) lemma hoare_post_taut: "\ P \ a \ \\ \" by (simp add:valid_def) lemma wp_post_taut: "\\r. True\ f \\r s. True\" by (rule hoare_post_taut) lemma wp_post_tautE: "\\r. True\ f \\r s. True\,\\f s. True\" proof - have P: "\r. (case r of Inl a \ True | _ \ True) = True" by (case_tac r, simp_all) show ?thesis by (simp add: validE_def P wp_post_taut) qed lemma hoare_pre_cont [simp]: "\ \ \ a \ P \" by (simp add:valid_def) subsection \Strongest Postcondition Rules\ lemma get_sp: "\P\ get \\a s. s = a \ P s\" by(simp add:get_def valid_def mres_def) lemma put_sp: "\\\ put a \\_ s. s = a\" by(simp add:put_def valid_def mres_def) lemma return_sp: "\P\ return a \\b s. b = a \ P s\" by(simp add:return_def valid_def mres_def) lemma assert_sp: "\ P \ assert Q \ \r s. P s \ Q \" by (simp add: assert_def fail_def return_def valid_def mres_def) lemma hoare_gets_sp: "\P\ gets f \\rv s. rv = f s \ P s\" by (simp add: valid_def simpler_gets_def mres_def) lemma hoare_return_drop_var [iff]: "\ Q \ return x \ \r. Q \" by (simp add:valid_def return_def mres_def) lemma hoare_gets [intro!]: "\ \s. P s \ Q (f s) s \ \ \ P \ gets f \ Q \" by (simp add:valid_def gets_def get_def bind_def return_def mres_def) lemma hoare_modifyE_var [intro!]: "\ \s. P s \ Q (f s) \ \ \ P \ modify f \ \r s. Q s \" by(simp add: valid_def modify_def put_def get_def bind_def mres_def) lemma hoare_if [intro!]: "\ P \ \ Q \ a \ R \; \ P \ \ Q \ b \ R \ \ \ \ Q \ if P then a else b \ R \" by (simp add:valid_def) lemma hoare_pre_subst: "\ A = B; \A\ a \C\ \ \ \B\ a \C\" by(clarsimp simp:valid_def split_def) lemma hoare_post_subst: "\ B = C; \A\ a \B\ \ \ \A\ a \C\" by(clarsimp simp:valid_def split_def) lemma hoare_pre_tautI: "\ \A and P\ a \B\; \A and not P\ a \B\ \ \ \A\ a \B\" by(fastforce simp:valid_def split_def pred_conj_def pred_neg_def) lemma hoare_pre_imp: "\ \s. P s \ Q s; \Q\ a \R\ \ \ \P\ a \R\" by (fastforce simp add:valid_def) lemma hoare_post_imp: "\ \r s. Q r s \ R r s; \P\ a \Q\ \ \ \P\ a \R\" by(fastforce simp:valid_def split_def) lemma hoare_post_impErr': "\ \P\ a \Q\,\E\; \r s. Q r s \ R r s; \e s. E e s \ F e s \ \ \P\ a \R\,\F\" apply (simp add: validE_def) apply (rule_tac Q="\r s. case r of Inl a \ E a s | Inr b \ Q b s" in hoare_post_imp) apply (case_tac r) apply simp_all done lemma hoare_post_impErr: "\ \P\ a \Q\,\E\; \r s. Q r s \ R r s; \e s. E e s \ F e s \ \ \P\ a \R\,\F\" apply (blast intro: hoare_post_impErr') done lemma hoare_validE_cases: "\ \ P \ f \ Q \, \ \_ _. True \; \ P \ f \ \_ _. True \, \ R \ \ \ \ P \ f \ Q \, \ R \" by (simp add: validE_def valid_def split: sum.splits) blast lemma hoare_post_imp_dc: "\\P\ a \\r. Q\; \s. Q s \ R s\ \ \P\ a \\r. R\,\\r. R\" by (simp add: validE_def valid_def split: sum.splits) blast lemma hoare_post_imp_dc2: "\\P\ a \\r. Q\; \s. Q s \ R s\ \ \P\ a \\r. R\,\\r s. True\" by (simp add: validE_def valid_def split: sum.splits) blast lemma hoare_post_imp_dc2E: "\\P\ a \\r. Q\; \s. Q s \ R s\ \ \P\ a \\r s. True\, \\r. R\" by (simp add: validE_def valid_def split: sum.splits) fast lemma hoare_post_imp_dc2E_actual: "\\P\ a \\r. R\\ \ \P\ a \\r s. True\, \\r. R\" by (simp add: validE_def valid_def split: sum.splits) fast lemma hoare_post_imp_dc2_actual: "\\P\ a \\r. R\\ \ \P\ a \\r. R\, \\r s. True\" by (simp add: validE_def valid_def split: sum.splits) fast lemma hoare_post_impE: "\ \r s. Q r s \ R r s; \P\ a \Q\ \ \ \P\ a \R\" by (fastforce simp:valid_def split_def) lemma hoare_conjD1: "\P\ f \\rv. Q rv and R rv\ \ \P\ f \\rv. Q rv\" unfolding valid_def by auto lemma hoare_conjD2: "\P\ f \\rv. Q rv and R rv\ \ \P\ f \\rv. R rv\" unfolding valid_def by auto lemma hoare_post_disjI1: "\P\ f \\rv. Q rv\ \ \P\ f \\rv. Q rv or R rv\" unfolding valid_def by auto lemma hoare_post_disjI2: "\P\ f \\rv. R rv\ \ \P\ f \\rv. Q rv or R rv\" unfolding valid_def by auto lemma hoare_weaken_pre: "\\Q\ a \R\; \s. P s \ Q s\ \ \P\ a \R\" apply (rule hoare_pre_imp) prefer 2 apply assumption apply blast done lemma hoare_strengthen_post: "\\P\ a \Q\; \r s. Q r s \ R r s\ \ \P\ a \R\" apply (rule hoare_post_imp) prefer 2 apply assumption apply blast done lemma use_valid: "\(r, s') \ mres (f s); \P\ f \Q\; P s \ \ Q r s'" apply (simp add: valid_def) apply blast done lemma use_validE_norm: "\ (Inr r', s') \ mres (B s); \ P \ B \ Q \,\ E \; P s \ \ Q r' s'" apply (clarsimp simp: validE_def valid_def) apply force done lemma use_validE_except: "\ (Inl r', s') \ mres (B s); \ P \ B \ Q \,\ E \; P s \ \ E r' s'" apply (clarsimp simp: validE_def valid_def) apply force done lemma in_inv_by_hoareD: "\ \P. \P\ f \\_. P\; (x,s') \ mres (f s) \ \ s' = s" apply (drule_tac x="(=) s" in meta_spec) apply (auto simp add: valid_def mres_def) done subsection "Satisfiability" lemma exs_hoare_post_imp: "\\r s. Q r s \ R r s; \P\ a \\Q\\ \ \P\ a \\R\" apply (simp add: exs_valid_def) apply safe apply (erule_tac x=s in allE, simp) apply blast done lemma use_exs_valid: "\\P\ f \\Q\; P s \ \ \(r, s') \ mres (f s). Q r s'" by (simp add: exs_valid_def) definition "exs_postcondition P f \ (\a b. \(rv, s)\ f a b. P rv s)" lemma exs_valid_is_triple: "exs_valid P f Q = triple_judgement P f (exs_postcondition Q (\s f. mres (f s)))" by (simp add: triple_judgement_def exs_postcondition_def exs_valid_def) lemmas [wp_trip] = exs_valid_is_triple lemma exs_valid_weaken_pre [wp_comb]: "\ \ P' \ f \\ Q \; \s. P s \ P' s \ \ \ P \ f \\ Q \" apply atomize apply (clarsimp simp: exs_valid_def) done lemma exs_valid_chain: "\ \ P \ f \\ Q \; \s. R s \ P s; \r s. Q r s \ S r s \ \ \ R \ f \\ S \" by (fastforce simp only: exs_valid_def Bex_def ) lemma exs_valid_assume_pre: "\ \s. P s \ \ P \ f \\ Q \ \ \ \ P \ f \\ Q \" apply (fastforce simp: exs_valid_def) done lemma exs_valid_bind [wp_split]: "\ \x. \B x\ g x \\C\; \A\ f \\B\ \ \ \ A \ f >>= (\x. g x) \\ C \" apply atomize apply (clarsimp simp: exs_valid_def bind_def2 mres_def) apply (drule spec, drule(1) mp, clarsimp) apply (drule spec2, drule(1) mp, clarsimp) apply (simp add: image_def bex_Un) apply (strengthen subst[where P="\x. x \ f s" for s, mk_strg I _ E], simp) apply (fastforce elim: rev_bexI) done lemma exs_valid_return [wp]: "\ Q v \ return v \\ Q \" by (clarsimp simp: exs_valid_def return_def mres_def) lemma exs_valid_select [wp]: "\ \s. \r \ S. Q r s \ select S \\ Q \" apply (clarsimp simp: exs_valid_def select_def mres_def) apply (auto simp add: image_def) done lemma exs_valid_get [wp]: "\ \s. Q s s \ get \\ Q \" by (clarsimp simp: exs_valid_def get_def mres_def) lemma exs_valid_gets [wp]: "\ \s. Q (f s) s \ gets f \\ Q \" by (clarsimp simp: gets_def) wp lemma exs_valid_put [wp]: "\ Q v \ put v \\ Q \" by (clarsimp simp: put_def exs_valid_def mres_def) lemma exs_valid_state_assert [wp]: "\ \s. Q () s \ G s \ state_assert G \\ Q \" by (clarsimp simp: state_assert_def exs_valid_def get_def assert_def bind_def2 return_def mres_def) lemmas exs_valid_guard = exs_valid_state_assert lemma exs_valid_fail [wp]: "\ \_. False \ fail \\ Q \" by (clarsimp simp: fail_def exs_valid_def) lemma exs_valid_condition [wp]: "\ \ P \ L \\ Q \; \ P' \ R \\ Q \ \ \ \ \s. (C s \ P s) \ (\ C s \ P' s) \ condition C L R \\ Q \" by (clarsimp simp: condition_def exs_valid_def split: sum.splits) subsection MISC lemma hoare_return_simp: "\P\ return x \Q\ = (\s. P s \ Q x s)" by (simp add: valid_def return_def mres_def) lemma hoare_gen_asm: "(P \ \P'\ f \Q\) \ \P' and K P\ f \Q\" by (fastforce simp add: valid_def) lemma hoare_when_wp [wp]: "\ P \ \Q\ f \R\ \ \ \if P then Q else R ()\ when P f \R\" by (clarsimp simp: when_def valid_def return_def mres_def) lemma hoare_conjI: "\ \P\ f \Q\; \P\ f \R\ \ \ \P\ f \\r s. Q r s \ R r s\" unfolding valid_def by blast lemma hoare_disjI1: "\ \P\ f \Q\ \ \ \P\ f \\r s. Q r s \ R r s \" unfolding valid_def by blast lemma hoare_disjI2: "\ \P\ f \R\ \ \ \P\ f \\r s. Q r s \ R r s \" unfolding valid_def by blast lemma hoare_assume_pre: "(\s. P s \ \P\ f \Q\) \ \P\ f \Q\" by (auto simp: valid_def) lemma hoare_returnOk_sp: "\P\ returnOk x \\r s. r = x \ P s\, \Q\" by (simp add: valid_def validE_def returnOk_def return_def mres_def) lemma hoare_assume_preE: "(\s. P s \ \P\ f \Q\,\R\) \ \P\ f \Q\,\R\" by (auto simp: valid_def validE_def) lemma hoare_allI: "(\x. \P\f\Q x\) \ \P\f\\r s. \x. Q x r s\" by (simp add: valid_def) blast lemma validE_allI: "(\x. \P\ f \\r s. Q x r s\,\E\) \ \P\ f \\r s. \x. Q x r s\,\E\" by (fastforce simp: valid_def validE_def split: sum.splits) lemma hoare_exI: "\P\ f \Q x\ \ \P\ f \\r s. \x. Q x r s\" by (simp add: valid_def) blast lemma hoare_impI: "(R \ \P\f\Q\) \ \P\f\\r s. R \ Q r s\" by (simp add: valid_def) blast lemma validE_impI: " \\E. \P\ f \\_ _. True\,\E\; (P' \ \P\ f \Q\,\E\)\ \ \P\ f \\r s. P' \ Q r s\, \E\" by (fastforce simp: validE_def valid_def split: sum.splits) lemma hoare_case_option_wp: "\ \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 subsection "Reasoning directly about states" lemma in_throwError: "((v, s') \ mres (throwError e s)) = (v = Inl e \ s' = s)" by (simp add: throwError_def return_def mres_def) lemma in_returnOk: "((v', s') \ mres (returnOk v s)) = (v' = Inr v \ s' = s)" by (simp add: returnOk_def return_def mres_def) lemma in_bind: "((r,s') \ mres ((do x \ f; g x od) s)) = (\s'' x. (x, s'') \ mres (f s) \ (r, s') \ mres (g x s''))" apply (simp add: bind_def split_def mres_def) apply (auto split: tmres.splits; force elim: rev_bexI image_eqI[rotated]) done lemma in_bindE_R: "((Inr r,s') \ mres ((doE x \ f; g x odE) s)) = (\s'' x. (Inr x, s'') \ mres (f s) \ (Inr r, s') \ mres (g x s''))" apply (simp add: bindE_def in_bind) apply (simp add: lift_def split_def) apply (clarsimp simp: throwError_def return_def lift_def mres_def split: sum.splits) apply force done lemma in_bindE_L: "((Inl r, s') \ mres ((doE x \ f; g x odE) s)) \ (\s'' x. (Inr x, s'') \ mres (f s) \ (Inl r, s') \ mres (g x s'')) \ ((Inl r, s') \ mres (f s))" apply (simp add: bindE_def in_bind lift_def) apply safe apply (simp add: return_def throwError_def lift_def split_def mres_def split: sum.splits if_split_asm) apply force+ done lemma in_return: "(r, s') \ mres (return v s) = (r = v \ s' = s)" by (simp add: return_def mres_def) lemma in_liftE: "((v, s') \ mres (liftE f s)) = (\v'. v = Inr v' \ (v', s') \ mres (f s))" by (auto simp add: liftE_def in_bind in_return) lemma in_whenE: "((v, s') \ mres (whenE P f s)) = ((P \ (v, s') \ mres (f s)) \ (\P \ v = Inr () \ s' = s))" by (simp add: whenE_def in_returnOk) lemma inl_whenE: "((Inl x, s') \ mres (whenE P f s)) = (P \ (Inl x, s') \ mres (f s))" by (auto simp add: in_whenE) lemma in_fail: "r \ mres (fail s) = False" by (simp add: fail_def mres_def) lemma in_assert: "(r, s') \ mres (assert P s) = (P \ s' = s)" by (auto simp add: assert_def return_def fail_def mres_def) lemma in_assertE: "(r, s') \ mres (assertE P s) = (P \ r = Inr () \ s' = s)" by (auto simp add: assertE_def returnOk_def return_def fail_def mres_def) lemma in_assert_opt: "(r, s') \ mres (assert_opt v s) = (v = Some r \ s' = s)" by (auto simp: assert_opt_def in_fail in_return split: option.splits) lemma in_get: "(r, s') \ mres (get s) = (r = s \ s' = s)" by (simp add: get_def mres_def) lemma in_gets: "(r, s') \ mres (gets f s) = (r = f s \ s' = s)" by (simp add: simpler_gets_def mres_def) lemma in_put: "(r, s') \ mres (put x s) = (s' = x \ r = ())" by (simp add: put_def mres_def) lemma in_when: "(v, s') \ mres (when P f s) = ((P \ (v, s') \ mres (f s)) \ (\P \ v = () \ s' = s))" by (simp add: when_def in_return) lemma in_modify: "(v, s') \ mres (modify f s) = (s'=f s \ v = ())" by (auto simp add: modify_def bind_def get_def put_def mres_def) lemma gets_the_in_monad: "((v, s') \ mres (gets_the f s)) = (s' = s \ f s = Some v)" by (auto simp: gets_the_def in_bind in_gets in_assert_opt split: option.split) lemma in_alternative: "(r,s') \ mres ((f \ g) s) = ((r,s') \ mres (f s) \ (r,s') \ mres (g s))" by (auto simp add: alternative_def mres_def) lemmas in_monad = inl_whenE in_whenE in_liftE in_bind in_bindE_L in_bindE_R in_returnOk in_throwError in_fail in_assertE in_assert in_return in_assert_opt in_get in_gets in_put in_when (* unlessE_whenE *) (* unless_when *) in_modify gets_the_in_monad in_alternative subsection "Non-Failure" lemma no_failD: "\ no_fail P m; P s \ \ Failed \ snd ` m s" by (simp add: no_fail_def) lemma non_fail_modify [wp,simp]: "no_fail \ (modify f)" by (simp add: no_fail_def modify_def get_def put_def bind_def) lemma non_fail_gets_simp[simp]: "no_fail P (gets f)" unfolding no_fail_def gets_def get_def return_def bind_def by simp lemma non_fail_gets: "no_fail \ (gets f)" by simp lemma snd_pair_image: "snd ` Pair x ` S = S" by (simp add: image_def) lemma non_fail_select [simp]: "no_fail \ (select S)" by (simp add: no_fail_def select_def image_def) lemma no_fail_pre: "\ no_fail P f; \s. Q s \ P s\ \ no_fail Q f" by (simp add: no_fail_def) lemma no_fail_alt [wp]: "\ no_fail P f; no_fail Q g \ \ no_fail (P and Q) (f OR g)" by (auto simp add: no_fail_def alternative_def) lemma no_fail_return [simp, wp]: "no_fail \ (return x)" by (simp add: return_def no_fail_def) lemma no_fail_get [simp, wp]: "no_fail \ get" by (simp add: get_def no_fail_def) lemma no_fail_put [simp, wp]: "no_fail \ (put s)" by (simp add: put_def no_fail_def) lemma no_fail_when [wp]: "(P \ no_fail Q f) \ no_fail (if P then Q else \) (when P f)" by (simp add: when_def) lemma no_fail_unless [wp]: "(\P \ no_fail Q f) \ no_fail (if P then \ else Q) (unless P f)" by (simp add: unless_def when_def) lemma no_fail_fail [simp, wp]: "no_fail \ fail" by (simp add: fail_def no_fail_def) lemmas [wp] = non_fail_gets lemma no_fail_assert [simp, wp]: "no_fail (\_. P) (assert P)" by (simp add: assert_def) lemma no_fail_assert_opt [simp, wp]: "no_fail (\_. P \ None) (assert_opt P)" by (simp add: assert_opt_def split: option.splits) lemma no_fail_case_option [wp]: assumes f: "no_fail P f" assumes g: "\x. no_fail (Q x) (g x)" shows "no_fail (if x = None then P else Q (the x)) (case_option f g x)" by (clarsimp simp add: f g) lemma no_fail_if [wp]: "\ P \ no_fail Q f; \P \ no_fail R g \ \ no_fail (if P then Q else R) (if P then f else g)" by simp lemma no_fail_apply [wp]: "no_fail P (f (g x)) \ no_fail P (f $ g x)" by simp lemma no_fail_undefined [simp, wp]: "no_fail \ undefined" by (simp add: no_fail_def) lemma no_fail_returnOK [simp, wp]: "no_fail \ (returnOk x)" by (simp add: returnOk_def) (* text {* Empty results implies non-failure *} lemma empty_fail_modify [simp]: "empty_fail (modify f)" by (simp add: empty_fail_def simpler_modify_def) lemma empty_fail_gets [simp]: "empty_fail (gets f)" by (simp add: empty_fail_def simpler_gets_def) lemma empty_failD: "\ empty_fail m; fst (m s) = {} \ \ snd (m s)" by (simp add: empty_fail_def) lemma empty_fail_select_f [simp]: assumes ef: "fst S = {} \ snd S" shows "empty_fail (select_f S)" by (fastforce simp add: empty_fail_def select_f_def intro: ef) lemma empty_fail_bind [simp]: "\ empty_fail a; \x. empty_fail (b x) \ \ empty_fail (a >>= b)" apply (simp add: bind_def empty_fail_def split_def) apply clarsimp apply (case_tac "fst (a s) = {}") apply blast apply (clarsimp simp: ex_in_conv [symmetric]) done lemma empty_fail_return [simp]: "empty_fail (return x)" by (simp add: empty_fail_def return_def) lemma empty_fail_mapM [simp]: assumes m: "\x. empty_fail (m x)" shows "empty_fail (mapM m xs)" proof (induct xs) case Nil thus ?case by (simp add: mapM_def sequence_def) next case Cons have P: "\m x xs. mapM m (x # xs) = (do y \ m x; ys \ (mapM m xs); return (y # ys) od)" by (simp add: mapM_def sequence_def Let_def) from Cons show ?case by (simp add: P m) qed lemma empty_fail [simp]: "empty_fail fail" by (simp add: fail_def empty_fail_def) lemma empty_fail_assert_opt [simp]: "empty_fail (assert_opt x)" by (simp add: assert_opt_def split: option.splits) lemma empty_fail_mk_ef: "empty_fail (mk_ef o m)" by (simp add: empty_fail_def mk_ef_def) *) subsection "Failure" lemma fail_wp: "\\x. True\ fail \Q\" by (simp add: valid_def fail_def mres_def vimage_def) lemma failE_wp: "\\x. True\ fail \Q\,\E\" by (simp add: validE_def fail_wp) lemma fail_update [iff]: "fail (f s) = fail s" by (simp add: fail_def) text \We can prove postconditions using hoare triples\ lemma post_by_hoare: "\ \P\ f \Q\; P s; (r, s') \ mres (f s) \ \ Q r s'" apply (simp add: valid_def) apply blast done text \Weakest Precondition Rules\ lemma hoare_vcg_prop: "\\s. P\ f \\rv s. P\" by (simp add: valid_def) lemma return_wp: "\P x\ return x \P\" by(simp add:valid_def return_def mres_def) (* lemma get_wp: "\\s. P s s\ get \P\" by(auto simp add:valid_def split_def get_def mres_def) *) lemma gets_wp: "\\s. P (f s) s\ gets f \P\" by(simp add:valid_def split_def gets_def return_def get_def bind_def mres_def) (* lemma modify_wp: "\\s. P () (f s)\ modify f \P\" by(simp add:valid_def split_def modify_def get_def put_def bind_def ) *) (* lemma put_wp: "\\s. P () x\ put x \P\" by(simp add:valid_def put_def) *) lemma returnOk_wp: "\P x\ returnOk x \P\,\E\" by(simp add:validE_def2 returnOk_def return_def mres_def) lemma throwError_wp: "\E e\ throwError e \P\,\E\" by(simp add:validE_def2 throwError_def return_def mres_def) lemma returnOKE_R_wp : "\P x\ returnOk x \P\, -" by (simp add: validE_R_def validE_def valid_def returnOk_def return_def mres_def) lemma catch_wp: "\ \x. \E x\ handler x \Q\; \P\ f \Q\,\E\ \ \ \P\ catch f handler \Q\" apply (unfold catch_def validE_def) apply (erule seq_ext) apply (simp add: return_wp split: sum.splits) done lemma handleE'_wp: "\ \x. \F x\ handler x \Q\,\E\; \P\ f \Q\,\F\ \ \ \P\ f handler \Q\,\E\" apply (unfold handleE'_def validE_def) apply (erule seq_ext) apply (clarsimp split: sum.splits) apply (simp add: valid_def return_def mres_def) done lemma handleE_wp: assumes x: "\x. \F x\ handler x \Q\,\E\" assumes y: "\P\ f \Q\,\F\" shows "\P\ f handler \Q\,\E\" by (simp add: handleE_def handleE'_wp [OF x y]) lemma hoare_vcg_split_if: "\ P \ \Q\ f \S\; \P \ \R\ g \S\ \ \ \\s. (P \ Q s) \ (\P \ R s)\ if P then f else g \S\" by simp lemma hoare_vcg_split_ifE: "\ P \ \Q\ f \S\,\E\; \P \ \R\ g \S\,\E\ \ \ \\s. (P \ Q s) \ (\P \ R s)\ if P then f else g \S\,\E\" by simp lemma in_image_constant: "(x \ (\_. v) ` S) = (x = v \ S \ {})" by (simp add: image_constant_conv) lemma hoare_liftM_subst: "\P\ liftM f m \Q\ = \P\ m \Q \ f\" apply (simp add: liftM_def bind_def2 return_def split_def mres_def) apply (simp add: valid_def Ball_def mres_def image_Un) apply (simp add: image_image in_image_constant) apply (rule_tac f=All in arg_cong) apply (rule ext) apply force done lemma liftE_validE[simp]: "\P\ liftE f \Q\,\E\ = \P\ f \Q\" apply (simp add: liftE_liftM validE_def hoare_liftM_subst o_def) done lemma liftE_wp: "\P\ f \Q\ \ \P\ liftE f \Q\,\E\" by simp lemma liftM_wp: "\P\ m \Q \ f\ \ \P\ liftM f m \Q\" by (simp add: hoare_liftM_subst) lemma hoare_liftME_subst: "\P\ liftME f m \Q\,\E\ = \P\ m \Q \ f\,\E\" apply (simp add: validE_def liftME_liftM hoare_liftM_subst o_def) apply (rule_tac f="valid P m" in arg_cong) apply (rule ext)+ apply (case_tac x, simp_all) done lemma liftME_wp: "\P\ m \Q \ f\,\E\ \ \P\ liftME f m \Q\,\E\" by (simp add: hoare_liftME_subst) (* FIXME: Move *) lemma o_const_simp[simp]: "(\x. C) \ f = (\x. C)" by (simp add: o_def) lemma hoare_vcg_split_case_option: "\ \x. x = None \ \P x\ f x \R x\; \x y. x = Some y \ \Q x y\ g x y \R x\ \ \ \\s. (x = None \ P x s) \ (\y. x = Some y \ Q x y s)\ case x of None \ f x | Some y \ g x y \R x\" apply(simp add:valid_def split_def) apply(case_tac x, simp_all) done lemma hoare_vcg_split_case_optionE: assumes none_case: "\x. x = None \ \P x\ f x \R x\,\E x\" assumes some_case: "\x y. x = Some y \ \Q x y\ g x y \R x\,\E x\" shows "\\s. (x = None \ P x s) \ (\y. x = Some y \ Q x y s)\ case x of None \ f x | Some y \ g x y \R x\,\E x\" apply(case_tac x, simp_all) apply(rule none_case, simp) apply(rule some_case, simp) done lemma hoare_vcg_split_case_sum: "\ \x a. x = Inl a \ \P x a\ f x a \R x\; \x b. x = Inr b \ \Q x b\ g x b \R x\ \ \ \\s. (\a. x = Inl a \ P x a s) \ (\b. x = Inr b \ Q x b s) \ case x of Inl a \ f x a | Inr b \ g x b \R x\" apply(simp add:valid_def split_def) apply(case_tac x, simp_all) done lemma hoare_vcg_split_case_sumE: assumes left_case: "\x a. x = Inl a \ \P x a\ f x a \R x\" assumes right_case: "\x b. x = Inr b \ \Q x b\ g x b \R x\" shows "\\s. (\a. x = Inl a \ P x a s) \ (\b. x = Inr b \ Q x b s) \ case x of Inl a \ f x a | Inr b \ g x b \R x\" apply(case_tac x, simp_all) apply(rule left_case, simp) apply(rule right_case, simp) done lemma hoare_vcg_precond_imp: "\ \Q\ f \R\; \s. P s \ Q s \ \ \P\ f \R\" by (fastforce simp add:valid_def) lemma hoare_vcg_precond_impE: "\ \Q\ f \R\,\E\; \s. P s \ Q s \ \ \P\ f \R\,\E\" by (fastforce simp add:validE_def2) lemma hoare_seq_ext: assumes g_valid: "\x. \B x\ g x \C\" assumes f_valid: "\A\ f \B\" shows "\A\ do x \ f; g x od \C\" apply(insert f_valid g_valid) apply(blast intro: seq_ext') done lemma hoare_vcg_seqE: assumes g_valid: "\x. \B x\ g x \C\,\E\" assumes f_valid: "\A\ f \B\,\E\" shows "\A\ doE x \ f; g x odE \C\,\E\" apply(insert f_valid g_valid) apply(blast intro: seqE') done lemma hoare_seq_ext_nobind: "\ \B\ g \C\; \A\ f \\r s. B s\ \ \ \A\ do f; g od \C\" apply (erule seq_ext) apply (clarsimp simp: valid_def) done lemma hoare_seq_ext_nobindE: "\ \B\ g \C\,\E\; \A\ f \\r s. B s\,\E\ \ \ \A\ doE f; g odE \C\,\E\" apply (erule seqE) apply (clarsimp simp:validE_def) done lemma hoare_chain: "\ \P\ f \Q\; \s. R s \ P s; \r s. Q r s \ S r s \ \ \R\ f \S\" by(fastforce simp add:valid_def split_def) lemma validE_weaken: "\ \P'\ A \Q'\,\E'\; \s. P s \ P' s; \r s. Q' r s \ Q r s; \r s. E' r s \ E r s \ \ \P\ A \Q\,\E\" by (fastforce simp: validE_def2 split: sum.splits) lemmas hoare_chainE = validE_weaken lemma hoare_vcg_handle_elseE: "\ \P\ f \Q\,\E\; \e. \E e\ g e \R\,\F\; \x. \Q x\ h x \R\,\F\ \ \ \P\ f g h \R\,\F\" apply (simp add: handle_elseE_def validE_def) apply (rule seq_ext) apply assumption apply (simp split: sum.split) done lemma in_mres: "(tr, Result (rv, s)) \ S \ (rv, s) \ mres S" by (fastforce simp: mres_def intro: image_eqI[rotated]) lemma alternative_valid: assumes x: "\P\ f \Q\" assumes y: "\P\ f' \Q\" shows "\P\ f OR f' \Q\" apply (simp add: valid_def alternative_def mres_def) using post_by_hoare[OF x _ in_mres] post_by_hoare[OF y _ in_mres] apply auto done lemma alternative_wp: assumes x: "\P\ f \Q\" assumes y: "\P'\ f' \Q\" shows "\P and P'\ f OR f' \Q\" apply (rule alternative_valid) apply (rule hoare_pre_imp [OF _ x], simp) apply (rule hoare_pre_imp [OF _ y], simp) done lemma alternativeE_wp: assumes x: "\P\ f \Q\,\E\" and y: "\P'\ f' \Q\,\E\" shows "\P and P'\ f OR f' \Q\,\E\" apply (unfold validE_def) apply (wp add: x y alternative_wp | simp | fold validE_def)+ done lemma alternativeE_R_wp: "\ \P\ f \Q\,-; \P'\ f' \Q\,- \ \ \P and P'\ f OR f' \Q\,-" apply (simp add: validE_R_def) apply (rule alternativeE_wp) apply assumption+ done lemma alternative_R_wp: "\ \P\ f -,\Q\; \P'\ g -,\Q\ \ \ \P and P'\ f \ g -, \Q\" apply (simp add: validE_E_def) apply (rule alternativeE_wp) apply assumption+ done lemma state_select_wp [wp]: "\ \s. \t. (s, t) \ f \ P () t \ state_select f \ P \" apply (clarsimp simp: state_select_def assert_def) apply (rule hoare_weaken_pre) apply (wp select_wp hoare_vcg_split_if return_wp fail_wp) apply simp done lemma condition_wp [wp]: "\ \ Q \ A \ P \; \ R \ B \ P \ \ \ \ \s. if C s then Q s else R s \ condition C A B \ P \" apply (clarsimp simp: condition_def) apply (clarsimp simp: valid_def pred_conj_def pred_neg_def split_def) done lemma conditionE_wp [wp]: "\ \ P \ A \ Q \,\ R \; \ P' \ B \ Q \,\ R \ \ \ \ \s. if C s then P s else P' s \ condition C A B \Q\,\R\" apply (clarsimp simp: condition_def) apply (clarsimp simp: validE_def valid_def) done lemma state_assert_wp [wp]: "\ \s. f s \ P () s \ state_assert f \ P \" apply (clarsimp simp: state_assert_def get_def assert_def bind_def valid_def return_def fail_def mres_def) done text \The weakest precondition handler which works on conjunction\ lemma hoare_vcg_conj_lift: 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\" apply (subst bipred_conj_def[symmetric], rule hoare_post_conj) apply (rule hoare_pre_imp [OF _ x], simp) apply (rule hoare_pre_imp [OF _ y], simp) done lemma hoare_vcg_conj_liftE1: "\ \P\ f \Q\,-; \P'\ f \Q'\,\E\ \ \ \P and P'\ f \\r s. Q r s \ Q' r s\,\E\" unfolding valid_def validE_R_def validE_def apply (clarsimp simp: split_def split: sum.splits) apply (erule allE, erule (1) impE) apply (erule allE, erule (1) impE) apply (drule (1) bspec) apply (drule (1) bspec) apply clarsimp done lemma hoare_vcg_disj_lift: 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\" apply (simp add: valid_def) apply safe apply (erule(1) post_by_hoare [OF x]) apply (erule notE) apply (erule(1) post_by_hoare [OF y]) done lemma hoare_vcg_const_Ball_lift: "\ \x. x \ S \ \P x\ f \Q x\ \ \ \\s. \x\S. P x s\ f \\rv s. \x\S. Q x rv s\" by (fastforce simp: valid_def) lemma hoare_vcg_const_Ball_lift_R: "\ \x. x \ S \ \P x\ f \Q x\,- \ \ \\s. \x \ S. P x s\ f \\rv s. \x \ S. Q x rv s\,-" apply (simp add: validE_R_def validE_def) apply (rule hoare_strengthen_post) apply (erule hoare_vcg_const_Ball_lift) apply (simp split: sum.splits) done lemma hoare_vcg_all_lift: "\ \x. \P x\ f \Q x\ \ \ \\s. \x. P x s\ f \\rv s. \x. Q x rv s\" by (fastforce simp: valid_def) lemma hoare_vcg_all_lift_R: "(\x. \P x\ f \Q x\, -) \ \\s. \x. P x s\ f \\rv s. \x. Q x rv s\, -" by (rule hoare_vcg_const_Ball_lift_R[where S=UNIV, simplified]) lemma hoare_vcg_const_imp_lift: "\ P \ \Q\ m \R\ \ \ \\s. P \ Q s\ m \\rv s. P \ R rv s\" by (cases P, simp_all add: hoare_vcg_prop) lemma hoare_vcg_const_imp_lift_R: "(P \ \Q\ m \R\,-) \ \\s. P \ Q s\ m \\rv s. P \ R rv s\,-" by (fastforce simp: validE_R_def validE_def valid_def split_def split: sum.splits) lemma hoare_weak_lift_imp: "\P'\ f \Q\ \ \\s. P \ P' s\ f \\rv s. P \ Q rv s\" by (auto simp add: valid_def split_def) lemma hoare_vcg_ex_lift: "\ \x. \P x\ f \Q x\ \ \ \\s. \x. P x s\ f \\rv s. \x. Q x rv s\" by (clarsimp simp: valid_def, blast) lemma hoare_vcg_ex_lift_R1: "(\x. \P x\ f \Q\, -) \ \\s. \x. P x s\ f \Q\, -" by (fastforce simp: valid_def validE_R_def validE_def split: sum.splits) (* for instantiations *) lemma hoare_triv: "\P\f\Q\ \ \P\f\Q\" . lemma hoare_trivE: "\P\ f \Q\,\E\ \ \P\ f \Q\,\E\" . lemma hoare_trivE_R: "\P\ f \Q\,- \ \P\ f \Q\,-" . lemma hoare_trivR_R: "\P\ f -,\E\ \ \P\ f -,\E\" . lemma hoare_weaken_preE_E: "\ \P'\ f -,\Q\; \s. P s \ P' s \ \ \P\ f -,\Q\" by (fastforce simp add: validE_E_def validE_def valid_def) lemma hoare_vcg_E_conj: "\ \P\ f -,\E\; \P'\ f \Q'\,\E'\ \ \ \\s. P s \ P' s\ f \Q'\, \\rv s. E rv s \ E' rv s\" apply (unfold validE_def validE_E_def) apply (rule hoare_post_imp [OF _ hoare_vcg_conj_lift], simp_all) apply (case_tac r, simp_all) done lemma hoare_vcg_E_elim: "\ \P\ f -,\E\; \P'\ f \Q\,- \ \ \\s. P s \ P' s\ f \Q\,\E\" by (rule hoare_post_impErr [OF hoare_vcg_E_conj], (simp add: validE_R_def)+) lemma hoare_vcg_R_conj: "\ \P\ f \Q\,-; \P'\ f \Q'\,- \ \ \\s. P s \ P' s\ f \\rv s. Q rv s \ Q' rv s\,-" apply (unfold validE_R_def validE_def) apply (rule hoare_post_imp [OF _ hoare_vcg_conj_lift], simp_all) apply (case_tac r, simp_all) done lemma valid_validE: "\P\ f \\rv. Q\ \ \P\ f \\rv. Q\,\\rv. Q\" apply (simp add: validE_def) done lemma valid_validE2: "\ \P\ f \\_. Q'\; \s. Q' s \ Q s; \s. Q' s \ E s \ \ \P\ f \\_. Q\,\\_. E\" unfolding valid_def validE_def by (clarsimp split: sum.splits) blast lemma validE_valid: "\P\ f \\rv. Q\,\\rv. Q\ \ \P\ f \\rv. Q\" apply (unfold validE_def) apply (rule hoare_post_imp) defer apply assumption apply (case_tac r, simp_all) done lemma valid_validE_R: "\P\ f \\rv. Q\ \ \P\ f \\rv. Q\,-" by (simp add: validE_R_def hoare_post_impErr [OF valid_validE]) lemma valid_validE_E: "\P\ f \\rv. Q\ \ \P\ f -,\\rv. Q\" by (simp add: validE_E_def hoare_post_impErr [OF valid_validE]) lemma validE_validE_R: "\P\ f \Q\,\\\\ \ \P\ f \Q\,-" by (simp add: validE_R_def) lemma validE_R_validE: "\P\ f \Q\,- \ \P\ f \Q\,\\\\" by (simp add: validE_R_def) lemma hoare_post_imp_R: "\ \P\ f \Q'\,-; \r s. Q' r s \ Q r s \ \ \P\ f \Q\,-" apply (unfold validE_R_def) apply (rule hoare_post_impErr, simp+) done lemma hoare_post_comb_imp_conj: "\ \P'\ f \Q\; \P\ f \Q'\; \s. P s \ P' s \ \ \P\ f \\rv s. Q rv s \ Q' rv s\" apply (rule hoare_pre_imp) defer apply (rule hoare_vcg_conj_lift) apply assumption+ apply simp done lemma hoare_vcg_precond_impE_R: "\ \P'\ f \Q\,-; \s. P s \ P' s \ \ \P\ f \Q\,-" by (unfold validE_R_def, rule hoare_vcg_precond_impE, simp+) (* lemma valid_is_triple: "valid P f Q = triple_judgement P f (postcondition Q (\s f. fst (f s)))" by (simp add: triple_judgement_def valid_def postcondition_def) *) lemma validE_is_triple: "validE P f Q E = triple_judgement P f (postconditions (\s f. (\(r,s') \ {(rv, s'). (Inr rv, s') \ (mres (f s))}. Q r s')) (\s f. (\(r,s') \ {(rv, s'). (Inl rv, s') \ (mres (f s))}. E r s')))" apply (simp add: validE_def triple_judgement_def valid_def postcondition_def postconditions_def split_def split: sum.split) apply (fastforce elim: image_eqI[rotated]) done lemma validE_R_is_triple: "validE_R P f Q = triple_judgement P f (\s f. (\(r,s') \ {(rv, s'). (Inr rv, s') \ mres (f s)}. Q r s'))" by (simp add: validE_R_def validE_is_triple postconditions_def postcondition_def) lemma validE_E_is_triple: "validE_E P f E = triple_judgement P f (\s f. (\(r,s') \ {(rv, s'). (Inl rv, s') \ mres (f s)}. E r s'))" by (simp add: validE_E_def validE_is_triple postconditions_def postcondition_def) lemmas hoare_wp_combs = hoare_post_comb_imp_conj hoare_vcg_precond_imp hoare_vcg_conj_lift lemmas hoare_wp_combsE = hoare_vcg_precond_impE hoare_vcg_precond_impE_R validE_validE_R hoare_vcg_R_conj hoare_vcg_E_elim hoare_vcg_E_conj lemmas hoare_wp_state_combsE = hoare_vcg_precond_impE[OF valid_validE] hoare_vcg_precond_impE_R[OF valid_validE_R] valid_validE_R hoare_vcg_R_conj[OF valid_validE_R] hoare_vcg_E_elim[OF valid_validE_E] hoare_vcg_E_conj[OF valid_validE_E] lemmas hoare_wp_splits [wp_split] = hoare_seq_ext hoare_vcg_seqE handleE'_wp handleE_wp validE_validE_R [OF hoare_vcg_seqE [OF validE_R_validE]] validE_validE_R [OF handleE'_wp [OF validE_R_validE]] validE_validE_R [OF handleE_wp [OF validE_R_validE]] catch_wp hoare_vcg_split_if hoare_vcg_split_ifE validE_validE_R [OF hoare_vcg_split_ifE [OF validE_R_validE validE_R_validE]] liftM_wp liftME_wp validE_validE_R [OF liftME_wp [OF validE_R_validE]] validE_valid lemmas [wp_comb] = hoare_wp_state_combsE hoare_wp_combsE hoare_wp_combs lemmas [wp] = hoare_vcg_prop wp_post_taut return_wp put_wp get_wp gets_wp modify_wp returnOk_wp throwError_wp fail_wp failE_wp liftE_wp lemmas [wp_trip] = valid_is_triple validE_is_triple validE_E_is_triple validE_R_is_triple text \Simplifications on conjunction\ lemma hoare_post_eq: "\ Q = Q'; \P\ f \Q'\ \ \ \P\ f \Q\" by simp lemma hoare_post_eqE1: "\ Q = Q'; \P\ f \Q'\,\E\ \ \ \P\ f \Q\,\E\" by simp lemma hoare_post_eqE2: "\ E = E'; \P\ f \Q\,\E'\ \ \ \P\ f \Q\,\E\" by simp lemma hoare_post_eqE_R: "\ Q = Q'; \P\ f \Q'\,- \ \ \P\ f \Q\,-" by simp lemma pred_conj_apply_elim: "(\r. Q r and Q' r) = (\r s. Q r s \ Q' r s)" by (simp add: pred_conj_def) lemma pred_conj_conj_elim: "(\r s. (Q r and Q' r) s \ Q'' r s) = (\r s. Q r s \ Q' r s \ Q'' r s)" by simp lemma conj_assoc_apply: "(\r s. (Q r s \ Q' r s) \ Q'' r s) = (\r s. Q r s \ Q' r s \ Q'' r s)" by simp lemma all_elim: "(\rv s. \x. P rv s) = P" by simp lemma all_conj_elim: "(\rv s. (\x. P rv s) \ Q rv s) = (\rv s. P rv s \ Q rv s)" by simp lemmas vcg_rhs_simps = pred_conj_apply_elim pred_conj_conj_elim conj_assoc_apply all_elim all_conj_elim lemma if_apply_reduct: "\P\ If P' (f x) (g x) \Q\ \ \P\ If P' f g x \Q\" by (cases P', simp_all) lemma if_apply_reductE: "\P\ If P' (f x) (g x) \Q\,\E\ \ \P\ If P' f g x \Q\,\E\" by (cases P', simp_all) lemma if_apply_reductE_R: "\P\ If P' (f x) (g x) \Q\,- \ \P\ If P' f g x \Q\,-" by (cases P', simp_all) lemmas hoare_wp_simps [wp_split] = vcg_rhs_simps [THEN hoare_post_eq] vcg_rhs_simps [THEN hoare_post_eqE1] vcg_rhs_simps [THEN hoare_post_eqE2] vcg_rhs_simps [THEN hoare_post_eqE_R] if_apply_reduct if_apply_reductE if_apply_reductE_R TrueI schematic_goal if_apply_test: "\?Q\ (if A then returnOk else K fail) x \P\,\E\" by wpsimp lemma hoare_elim_pred_conj: "\P\ f \\r s. Q r s \ Q' r s\ \ \P\ f \\r. Q r and Q' r\" by (unfold pred_conj_def) lemma hoare_elim_pred_conjE1: "\P\ f \\r s. Q r s \ Q' r s\,\E\ \ \P\ f \\r. Q r and Q' r\,\E\" by (unfold pred_conj_def) lemma hoare_elim_pred_conjE2: "\P\ f \Q\, \\x s. E x s \ E' x s\ \ \P\ f \Q\,\\x. E x and E' x\" by (unfold pred_conj_def) lemma hoare_elim_pred_conjE_R: "\P\ f \\r s. Q r s \ Q' r s\,- \ \P\ f \\r. Q r and Q' r\,-" by (unfold pred_conj_def) lemmas hoare_wp_pred_conj_elims = hoare_elim_pred_conj hoare_elim_pred_conjE1 hoare_elim_pred_conjE2 hoare_elim_pred_conjE_R lemmas hoare_weaken_preE = hoare_vcg_precond_impE lemmas hoare_pre [wp_pre] = hoare_weaken_pre hoare_weaken_preE hoare_vcg_precond_impE_R hoare_weaken_preE_E declare no_fail_pre [wp_pre] bundle no_pre = hoare_pre [wp_pre del] no_fail_pre [wp_pre del] text \Miscellaneous lemmas on hoare triples\ lemma hoare_vcg_mp: assumes a: "\P\ f \Q\" assumes b: "\P\ f \\r s. Q r s \ Q' r s\" shows "\P\ f \Q'\" using assms by (auto simp: valid_def split_def) (* note about this precond stuff: rules get a chance to bind directly before any of their combined forms. As a result, these precondition implication rules are only used when needed. *) lemma hoare_add_post: assumes r: "\P'\ f \Q'\" assumes impP: "\s. P s \ P' s" assumes impQ: "\P\ f \\rv s. Q' rv s \ Q rv s\" shows "\P\ f \Q\" apply (rule hoare_chain) apply (rule hoare_vcg_conj_lift) apply (rule r) apply (rule impQ) apply simp apply (erule impP) apply simp done lemma hoare_whenE_wp: "(P \ \Q\ f \R\, \E\) \ \if P then Q else R ()\ whenE P f \R\, \E\" unfolding whenE_def by clarsimp wp lemma hoare_gen_asmE: "(P \ \P'\ f \Q\,-) \ \P' and K P\ f \Q\, -" by (simp add: validE_R_def validE_def valid_def) blast lemma hoare_list_case: assumes P1: "\P1\ f f1 \Q\" assumes P2: "\y ys. xs = y#ys \ \P2 y ys\ f (f2 y ys) \Q\" shows "\case xs of [] \ P1 | y#ys \ P2 y ys\ f (case xs of [] \ f1 | y#ys \ f2 y ys) \Q\" apply (cases xs; simp) apply (rule P1) apply (rule P2) apply simp done lemma hoare_unless_wp: "(\P \ \Q\ f \R\) \ \if P then R () else Q\ unless P f \R\" unfolding unless_def by wp auto lemma hoare_use_eq: assumes x: "\P. \\s. P (f s)\ m \\rv s. P (f s)\" assumes y: "\f. \\s. P f s\ m \\rv s. Q f s\" shows "\\s. P (f s) s\ m \\rv s. Q (f s :: 'c :: type) s \" apply (rule_tac Q="\rv s. \f'. f' = f s \ Q f' s" in hoare_post_imp) apply simp apply (wpsimp wp: hoare_vcg_ex_lift x y) done lemma hoare_return_sp: "\P\ return x \\r. P and K (r = x)\" by (simp add: valid_def return_def mres_def) lemma hoare_fail_any [simp]: "\P\ fail \Q\" by wp lemma hoare_failE [simp]: "\P\ fail \Q\,\E\" by wp lemma hoare_FalseE [simp]: "\\s. False\ f \Q\,\E\" by (simp add: valid_def validE_def) lemma hoare_K_bind [wp]: "\P\ f \Q\ \ \P\ K_bind f x \Q\" by simp text \Setting up the precondition case splitter.\ lemma wpc_helper_valid: "\Q\ g \S\ \ wpc_helper (P, P') (Q, Q') \P\ g \S\" by (clarsimp simp: wpc_helper_def elim!: hoare_pre) lemma wpc_helper_validE: "\Q\ f \R\,\E\ \ wpc_helper (P, P') (Q, Q') \P\ f \R\,\E\" by (clarsimp simp: wpc_helper_def elim!: hoare_pre) lemma wpc_helper_validE_R: "\Q\ f \R\,- \ wpc_helper (P, P') (Q, Q') \P\ f \R\,-" by (clarsimp simp: wpc_helper_def elim!: hoare_pre) lemma wpc_helper_validR_R: "\Q\ f -,\E\ \ wpc_helper (P, P') (Q, Q') \P\ f -,\E\" by (clarsimp simp: wpc_helper_def elim!: hoare_pre) lemma wpc_helper_no_fail_final: "no_fail Q f \ wpc_helper (P, P') (Q, Q') (no_fail P f)" by (clarsimp simp: wpc_helper_def elim!: no_fail_pre) lemma wpc_helper_validNF: "\Q\ g \S\! \ wpc_helper (P, P') (Q, Q') \P\ g \S\!" apply (clarsimp simp: wpc_helper_def) by (metis hoare_wp_combs(2) no_fail_pre validNF_def) lemma wpc_helper_validI: "(\Q\,\R\ g \G\,\S\) \ wpc_helper (P, P') (split Q, Q') (\curry P\,\R\ g \G\,\S\)" by (clarsimp simp: wpc_helper_def elim!: validI_weaken_pre) wpc_setup "\m. \P\ m \Q\" wpc_helper_valid wpc_setup "\m. \P\ m \Q\,\E\" wpc_helper_validE wpc_setup "\m. \P\ m \Q\,-" wpc_helper_validE_R wpc_setup "\m. \P\ m -,\E\" wpc_helper_validR_R wpc_setup "\m. no_fail P m" wpc_helper_no_fail_final wpc_setup "\m. \P\ m \Q\!" wpc_helper_validNF wpc_setup "\m. \P\,\R\ m \G\,\S\" wpc_helper_validI lemma in_liftM: "((r, s') \ mres (liftM t f s)) = (\r'. (r', s') \ mres (f s) \ r = t r')" by (simp add: liftM_def in_return in_bind) (* FIXME: eliminate *) lemmas handy_liftM_lemma = in_liftM lemma hoare_fun_app_wp[wp]: "\P\ f' x \Q'\ \ \P\ f' $ x \Q'\" "\P\ f x \Q\,\E\ \ \P\ f $ x \Q\,\E\" "\P\ f x \Q\,- \ \P\ f $ x \Q\,-" "\P\ f x -,\E\ \ \P\ f $ x -,\E\" by simp+ lemma hoare_validE_pred_conj: "\ \P\f\Q\,\E\; \P\f\R\,\E\ \ \ \P\f\Q And R\,\E\" unfolding valid_def validE_def by (simp add: split_def split: sum.splits) lemma hoare_validE_conj: "\ \P\f\Q\,\E\; \P\f\R\,\E\ \ \ \P\ f \\r s. Q r s \ R r s\,\E\" unfolding valid_def validE_def by (simp add: split_def split: sum.splits) lemma hoare_valid_validE: "\P\f\\r. Q\ \ \P\f\\r. Q\,\\r. Q\" unfolding valid_def validE_def by (simp add: split_def split: sum.splits) lemma liftE_validE_E [wp]: "\\\ liftE f -, \Q\" by (clarsimp simp: validE_E_def valid_def) lemma validE_validE_E [wp_comb]: "\P\ f \\\\, \E\ \ \P\ f -, \E\" by (simp add: validE_E_def) lemma validE_E_validE: "\P\ f -, \E\ \ \P\ f \\\\, \E\" by (simp add: validE_E_def) (* * if_validE_E: * * \?P1 \ \?Q1\ ?f1 -, \?E\; \ ?P1 \ \?R1\ ?g1 -, \?E\\ \ \\s. (?P1 \ ?Q1 s) \ (\ ?P1 \ ?R1 s)\ if ?P1 then ?f1 else ?g1 -, \?E\ *) lemmas if_validE_E [wp_split] = validE_validE_E [OF hoare_vcg_split_ifE [OF validE_E_validE validE_E_validE]] lemma returnOk_E [wp]: "\\\ returnOk r -, \Q\" by (simp add: validE_E_def) wp lemma hoare_drop_imp: "\P\ f \Q\ \ \P\ f \\r s. R r s \ Q r s\" by (auto simp: valid_def) lemma hoare_drop_impE: "\\P\ f \\r. Q\, \E\\ \ \P\ f \\r s. R r s \ Q s\, \E\" by (simp add: validE_weaken) lemma hoare_drop_impE_R: "\P\ f \Q\,- \ \P\ f \\r s. R r s \ Q r s\, -" by (auto simp: validE_R_def validE_def valid_def split_def split: sum.splits) lemma hoare_drop_impE_E: "\P\ f -,\Q\ \ \P\ f -,\\r s. R r s \ Q r s\" by (auto simp: validE_E_def validE_def valid_def split_def split: sum.splits) lemmas hoare_drop_imps = hoare_drop_imp hoare_drop_impE_R hoare_drop_impE_E lemma mres_union: "mres (a \ b) = mres a \ mres b" by (simp add: mres_def image_Un) lemma mres_Failed_empty: "mres ((\xs. (xs, Failed)) ` X ) = {}" "mres ((\xs. (xs, Incomplete)) ` X ) = {}" by (auto simp add: mres_def image_def) lemma det_set_option_eq: "(\a\m. set_option (snd a)) = {(r, s')} \ (ts, Some (rr, ss)) \ m \ rr = r \ ss = s'" by (metis UN_I option.set_intros prod.inject singleton_iff snd_conv) lemma det_set_option_eq': "(\a\m. set_option (snd a)) = {(r, s')} \ Some (r, s') \ snd ` m" using image_iff by fastforce lemma bind_det_exec: "mres (a s) = {(r,s')} \ mres ((a >>= b) s) = mres (b r s')" by (simp add: in_bind set_eq_iff) lemma in_bind_det_exec: "mres (a s) = {(r,s')} \ (s'' \ mres ((a >>= b) s)) = (s'' \ mres (b r s'))" by (cases s'', simp add: in_bind) lemma exec_put: "(put s' >>= m) s = m () s'" by (auto simp add: bind_def put_def mres_def split_def) lemma bind_execI: "\ (r'',s'') \ mres (f s); \x \ mres (g r'' s''). P x \ \ \x \ mres ((f >>= g) s). P x" by (fastforce simp add: Bex_def in_bind) lemma True_E_E [wp]: "\\\ f -,\\\\" by (auto simp: validE_E_def validE_def valid_def split: sum.splits) (* * \\x. \?B1 x\ ?g1 x -, \?E\; \?P\ ?f1 \?B1\, \?E\\ \ \?P\ ?f1 >>=E ?g1 -, \?E\ *) lemmas [wp_split] = validE_validE_E [OF hoare_vcg_seqE [OF validE_E_validE]] lemma case_option_wp: assumes x: "\x. \P x\ m x \Q\" assumes y: "\P'\ m' \Q\" shows "\\s. (x = None \ P' s) \ (x \ None \ P (the x) s)\ case_option m' m x \Q\" apply (cases x; simp) apply (rule y) apply (rule x) done lemma case_option_wpE: assumes x: "\x. \P x\ m x \Q\,\E\" assumes y: "\P'\ m' \Q\,\E\" shows "\\s. (x = None \ P' s) \ (x \ None \ P (the x) s)\ case_option m' m x \Q\,\E\" apply (cases x; simp) apply (rule y) apply (rule x) done lemma in_bindE: "(rv, s') \ mres ((f >>=E (\rv'. g rv')) s) = ((\ex. rv = Inl ex \ (Inl ex, s') \ mres (f s)) \ (\rv' s''. (rv, s') \ mres (g rv' s'') \ (Inr rv', s'') \ mres (f s)))" apply (clarsimp simp: bindE_def in_bind lift_def in_throwError) apply (safe del: disjCI; strengthen subst[where P="\x. x \ mres (f s)", mk_strg I _ E]; auto simp: in_throwError split: sum.splits) done (* * \?P\ ?m1 -, \?E\ \ \?P\ liftME ?f1 ?m1 -, \?E\ *) lemmas [wp_split] = validE_validE_E [OF liftME_wp, simplified, OF validE_E_validE] lemma assert_A_True[simp]: "assert True = return ()" by (simp add: assert_def) lemma assert_wp [wp]: "\\s. P \ Q () s\ assert P \Q\" by (cases P, (simp add: assert_def | wp)+) lemma list_cases_wp: assumes a: "\P_A\ a \Q\" assumes b: "\x xs. ts = x#xs \ \P_B x xs\ b x xs \Q\" shows "\case_list P_A P_B ts\ case ts of [] \ a | x # xs \ b x xs \Q\" by (cases ts, auto simp: a b) (* FIXME: make wp *) lemma whenE_throwError_wp: "\\s. \Q \ P s\ whenE Q (throwError e) \\rv. P\, -" unfolding whenE_def by wp blast lemma select_throwError_wp: "\\s. \x\S. Q x s\ select S >>= throwError -, \Q\" by (clarsimp simp add: bind_def throwError_def return_def select_def validE_E_def validE_def valid_def mres_def) section "validNF Rules" subsection "Basic validNF theorems" lemma validNF [intro?]: "\ \ P \ f \ Q \; no_fail P f \ \ \ P \ f \ Q \!" by (clarsimp simp: validNF_def) lemma validNF_valid: "\ \ P \ f \ Q \! \ \ \ P \ f \ Q \" by (clarsimp simp: validNF_def) lemma validNF_no_fail: "\ \ P \ f \ Q \! \ \ no_fail P f" by (clarsimp simp: validNF_def) lemma snd_validNF: "\ \ P \ f \ Q \!; P s \ \ Failed \ snd ` (f s)" by (clarsimp simp: validNF_def no_fail_def) lemma use_validNF: "\ (r', s') \ mres (f s); \ P \ f \ Q \!; P s \ \ Q r' s'" by (fastforce simp: validNF_def valid_def) subsection "validNF weakest pre-condition rules" lemma validNF_return [wp]: "\ P x \ return x \ P \!" by (wp validNF)+ lemma validNF_get [wp]: "\ \s. P s s \ get \ P \!" by (wp validNF)+ lemma validNF_put [wp]: "\ \s. P () x \ put x \ P \!" by (wp validNF)+ lemma validNF_K_bind [wp]: "\ P \ x \ Q \! \ \ P \ K_bind x f \ Q \!" by simp lemma validNF_fail [wp]: "\ \s. False \ fail \ Q \!" by (clarsimp simp: validNF_def fail_def no_fail_def) lemma validNF_prop [wp_unsafe]: "\ no_fail (\s. P) f \ \ \ \s. P \ f \ \rv s. P \!" by (wp validNF)+ lemma validNF_post_conj [intro!]: "\ \ P \ a \ Q \!; \ P \ a \ R \! \ \ \ P \ a \ Q And R \!" by (clarsimp simp: validNF_def) lemma no_fail_or: "\no_fail P a; no_fail Q a\ \ no_fail (P or Q) a" by (clarsimp simp: no_fail_def) lemma validNF_pre_disj [intro!]: "\ \ P \ a \ R \!; \ Q \ a \ R \! \ \ \ P or Q \ a \ R \!" by (rule validNF) (auto dest: validNF_valid validNF_no_fail intro: no_fail_or) (* * Set up combination rules for WP, which also requires * a "wp_trip" rule for validNF. *) definition "validNF_property Q s b \ Failed \ snd ` (b s) \ (\(r', s') \ mres (b s). Q r' s')" lemma validNF_is_triple [wp_trip]: "validNF P f Q = triple_judgement P f (validNF_property Q)" apply (clarsimp simp: validNF_def triple_judgement_def validNF_property_def) apply (auto simp: no_fail_def valid_def) done lemma validNF_weaken_pre [wp_comb]: "\\Q\ a \R\!; \s. P s \ Q s\ \ \P\ a \R\!" by (metis hoare_pre_imp no_fail_pre validNF_def) lemma validNF_post_comb_imp_conj: "\ \P'\ f \Q\!; \P\ f \Q'\!; \s. P s \ P' s \ \ \P\ f \\rv s. Q rv s \ Q' rv s\!" by (fastforce simp: validNF_def valid_def) lemma validNF_post_comb_conj_L: "\ \P'\ f \Q\!; \P\ f \Q'\ \ \ \\s. P s \ P' s \ f \\rv s. Q rv s \ Q' rv s\!" apply (clarsimp simp: validNF_def valid_def no_fail_def) apply force done lemma validNF_post_comb_conj_R: "\ \P'\ f \Q\; \P\ f \Q'\! \ \ \\s. P s \ P' s \ f \\rv s. Q rv s \ Q' rv s\!" apply (clarsimp simp: validNF_def valid_def no_fail_def) apply force done lemma validNF_post_comb_conj: "\ \P'\ f \Q\!; \P\ f \Q'\! \ \ \\s. P s \ P' s \ f \\rv s. Q rv s \ Q' rv s\!" apply (clarsimp simp: validNF_def valid_def no_fail_def) apply force done lemma validNF_split_if [wp_split]: "\P \ \Q\ f \S\!; \ P \ \R\ g \S\!\ \ \\s. (P \ Q s) \ (\ P \ R s)\ if P then f else g \S\!" by simp lemma validNF_vcg_conj_lift: "\ \P\ f \Q\!; \P'\ f \Q'\! \ \ \\s. P s \ P' s\ f \\rv s. Q rv s \ Q' rv s\!" apply (subst bipred_conj_def[symmetric], rule validNF_post_conj) apply (erule validNF_weaken_pre, fastforce) apply (erule validNF_weaken_pre, fastforce) done lemma validNF_vcg_disj_lift: "\ \P\ f \Q\!; \P'\ f \Q'\! \ \ \\s. P s \ P' s\ f \\rv s. Q rv s \ Q' rv s\!" apply (clarsimp simp: validNF_def) apply safe apply (auto intro!: hoare_vcg_disj_lift)[1] apply (clarsimp simp: no_fail_def) done lemma validNF_vcg_all_lift [wp]: "\ \x. \P x\ f \Q x\! \ \ \\s. \x. P x s\ f \\rv s. \x. Q x rv s\!" apply atomize apply (rule validNF) apply (clarsimp simp: validNF_def) apply (rule hoare_vcg_all_lift) apply force apply (clarsimp simp: no_fail_def validNF_def) done lemma no_fail_bind[wp_split]: "\ no_fail P f; \x. no_fail (R x) (g x); \Q\ f \R\ \ \ no_fail (P and Q) (do x \ f; g x od)" apply (simp add: no_fail_def bind_def2 image_Un image_image in_image_constant) apply (intro allI conjI impI) apply (fastforce simp: image_def) apply clarsimp apply (drule(1) post_by_hoare, erule in_mres) apply (fastforce simp: image_def) done lemma validNF_bind [wp_split]: "\ \x. \B x\ g x \C\!; \A\ f \B\! \ \ \A\ do x \ f; g x od \C\!" apply (rule validNF) apply (metis validNF_valid hoare_seq_ext) apply (frule no_fail_bind[OF validNF_no_fail, where g=g]) apply (rule validNF_no_fail, assumption) apply (erule validNF_valid) apply (simp add: no_fail_def) done lemmas validNF_seq_ext = validNF_bind subsection "validNF compound rules" lemma validNF_state_assert [wp]: "\ \s. P () s \ G s \ state_assert G \ P \!" apply (rule validNF) apply wpsimp apply (clarsimp simp: no_fail_def state_assert_def bind_def2 assert_def return_def get_def) done lemma validNF_modify [wp]: "\ \s. P () (f s) \ modify f \ P \!" apply (clarsimp simp: modify_def) apply wp done lemma validNF_gets [wp]: "\\s. P (f s) s\ gets f \P\!" apply (clarsimp simp: gets_def) apply wp done lemma validNF_condition [wp]: "\ \ Q \ A \P\!; \ R \ B \P\!\ \ \\s. if C s then Q s else R s\ condition C A B \P\!" apply rule apply (drule validNF_valid)+ apply (erule (1) condition_wp) apply (drule validNF_no_fail)+ apply (clarsimp simp: no_fail_def condition_def) done lemma validNF_alt_def: "validNF P m Q = (\s. P s \ ((\(r', s') \ mres (m s). Q r' s') \ Failed \ snd ` (m s)))" by (auto simp: validNF_def valid_def no_fail_def mres_def image_def) lemma validNF_assert [wp]: "\ (\s. P) and (R ()) \ assert P \ R \!" apply (rule validNF) apply (clarsimp simp: valid_def in_return) apply (clarsimp simp: no_fail_def return_def) done lemma validNF_false_pre: "\ \_. False \ P \ Q \!" by (clarsimp simp: validNF_def no_fail_def) lemma validNF_chain: "\\P'\ a \R'\!; \s. P s \ P' s; \r s. R' r s \ R r s\ \ \P\ a \R\!" by (fastforce simp: validNF_def valid_def no_fail_def Ball_def) lemma validNF_case_prod [wp]: "\ \x y. validNF (P x y) (B x y) Q \ \ validNF (case_prod P v) (case_prod (\x y. B x y) v) Q" by (metis prod.exhaust split_conv) lemma validE_NF_case_prod [wp]: "\ \a b. \P a b\ f a b \Q\, \E\! \ \ \case x of (a, b) \ P a b\ case x of (a, b) \ f a b \Q\, \E\!" apply (clarsimp simp: validE_NF_alt_def) apply (erule validNF_case_prod) done lemma no_fail_is_validNF_True: "no_fail P s = (\ P \ s \ \_ _. True \!)" by (clarsimp simp: no_fail_def validNF_def valid_def) subsection "validNF reasoning in the exception monad" lemma validE_NF [intro?]: "\ \ P \ f \ Q \,\ E \; no_fail P f \ \ \ P \ f \ Q \,\ E \!" apply (clarsimp simp: validE_NF_def) done lemma validE_NF_valid: "\ \ P \ f \ Q \,\ E \! \ \ \ P \ f \ Q \,\ E \" apply (clarsimp simp: validE_NF_def) done lemma validE_NF_no_fail: "\ \ P \ f \ Q \,\ E \! \ \ no_fail P f" apply (clarsimp simp: validE_NF_def) done lemma validE_NF_weaken_pre [wp_comb]: "\\Q\ a \R\,\E\!; \s. P s \ Q s\ \ \P\ a \R\,\E\!" apply (clarsimp simp: validE_NF_alt_def) apply (erule validNF_weaken_pre) apply simp done lemma validE_NF_post_comb_conj_L: "\ \P\ f \Q\, \ E \!; \P'\ f \Q'\, \ \_ _. True \ \ \ \\s. P s \ P' s \ f \\rv s. Q rv s \ Q' rv s\, \ E \!" apply (clarsimp simp: validE_NF_alt_def validE_def validNF_def valid_def no_fail_def split: sum.splits) apply force done lemma validE_NF_post_comb_conj_R: "\ \P\ f \Q\, \ \_ _. True \; \P'\ f \Q'\, \ E \! \ \ \\s. P s \ P' s \ f \\rv s. Q rv s \ Q' rv s\, \ E \!" apply (clarsimp simp: validE_NF_alt_def validE_def validNF_def valid_def no_fail_def split: sum.splits) apply force done lemma validE_NF_post_comb_conj: "\ \P\ f \Q\, \ E \!; \P'\ f \Q'\, \ E \! \ \ \\s. P s \ P' s \ f \\rv s. Q rv s \ Q' rv s\, \ E \!" apply (clarsimp simp: validE_NF_alt_def validE_def validNF_def valid_def no_fail_def split: sum.splits) apply force done lemma validE_NF_chain: "\\P'\ a \R'\,\E'\!; \s. P s \ P' s; \r' s'. R' r' s' \ R r' s'; \r'' s''. E' r'' s'' \ E r'' s''\ \ \\s. P s \ a \\r' s'. R r' s'\,\\r'' s''. E r'' s''\!" by (fastforce simp: validE_NF_def validE_def2 no_fail_def Ball_def split: sum.splits) lemma validE_NF_bind_wp [wp]: "\\x. \B x\ g x \C\, \E\!; \A\ f \B\, \E\!\ \ \A\ f >>=E (\x. g x) \C\, \E\!" apply (unfold validE_NF_alt_def bindE_def) apply (rule validNF_bind [rotated]) apply assumption apply (clarsimp simp: lift_def throwError_def split: sum.splits) apply wpsimp done lemma validNF_catch [wp]: "\\x. \E x\ handler x \Q\!; \P\ f \Q\, \E\!\ \ \P\ f (\x. handler x) \Q\!" apply (unfold validE_NF_alt_def catch_def) apply (rule validNF_bind [rotated]) apply assumption apply (clarsimp simp: lift_def throwError_def split: sum.splits) apply wp done lemma validNF_throwError [wp]: "\E e\ throwError e \P\, \E\!" by (unfold validE_NF_alt_def throwError_def o_def) wpsimp lemma validNF_returnOk [wp]: "\P e\ returnOk e \P\, \E\!" by (clarsimp simp: validE_NF_alt_def returnOk_def) wpsimp lemma validNF_whenE [wp]: "(P \ \Q\ f \R\, \E\!) \ \if P then Q else R ()\ whenE P f \R\, \E\!" unfolding whenE_def by clarsimp wp lemma validNF_nobindE [wp]: "\ \B\ g \C\,\E\!; \A\ f \\r s. B s\,\E\! \ \ \A\ doE f; g odE \C\,\E\!" by clarsimp wp (* * Setup triple rules for validE_NF so that we can use the * "wp_comb" attribute. *) definition "validE_NF_property Q E s b \ Failed \ snd ` (b s) \ (\(r', s') \ mres (b s). case r' of Inl x \ E x s' | Inr x \ Q x s')" lemma validE_NF_is_triple [wp_trip]: "validE_NF P f Q E = triple_judgement P f (validE_NF_property Q E)" apply (clarsimp simp: validE_NF_def validE_def2 no_fail_def triple_judgement_def validE_NF_property_def split: sum.splits) apply blast done lemmas [wp_comb] = validE_NF_weaken_pre lemma validNF_cong: "\ \s. P s = P' s; \s. P s \ m s = m' s; \r' s' s. \ P s; (r', s') \ mres (m s) \ \ Q r' s' = Q' r' s' \ \ (\ P \ m \ Q \!) = (\ P' \ m' \ Q' \!)" by (fastforce simp: validNF_alt_def) lemma validE_NF_liftE [wp]: "\P\ f \Q\! \ \P\ liftE f \Q\,\E\!" by (wpsimp simp: validE_NF_alt_def liftE_def) lemma validE_NF_handleE' [wp]: "\ \x. \F x\ handler x \Q\,\E\!; \P\ f \Q\,\F\! \ \ \P\ f (\x. handler x) \Q\,\E\!" apply (unfold validE_NF_alt_def handleE'_def) apply (rule validNF_bind [rotated]) apply assumption apply (clarsimp split: sum.splits) apply wpsimp done lemma validE_NF_handleE [wp]: "\ \x. \F x\ handler x \Q\,\E\!; \P\ f \Q\,\F\! \ \ \P\ f handler \Q\,\E\!" apply (unfold handleE_def) apply (metis validE_NF_handleE') done lemma validE_NF_condition [wp]: "\ \ Q \ A \P\,\ E \!; \ R \ B \P\,\ E \!\ \ \\s. if C s then Q s else R s\ condition C A B \P\,\ E \!" apply rule apply (drule validE_NF_valid)+ apply wp apply (drule validE_NF_no_fail)+ apply (clarsimp simp: no_fail_def condition_def) done lemma validI_name_pre: "prefix_closed f \ (\s0 s. P s0 s \ \\s0' s'. s0' = s0 \ s' = s\,\R\ f \G\,\Q\) \ \P\,\R\ f \G\,\Q\" unfolding validI_def by metis lemma validI_well_behaved': "prefix_closed f \ \P\,\R'\ f \G'\,\Q\ \ R \ R' \ G' \ G \ \P\,\R\ f \G\,\Q\" apply (subst validI_def, clarsimp) apply (clarsimp simp add: rely_def) apply (drule (2) validI_D) apply (fastforce simp: rely_cond_def guar_cond_def)+ done lemmas validI_well_behaved = validI_well_behaved'[unfolded le_fun_def, simplified] text \Strengthen setup.\ context strengthen_implementation begin lemma strengthen_hoare [strg]: "(\r s. st F (\) (Q r s) (R r s)) \ st F (\) (\P\ f \Q\) (\P\ f \R\)" by (cases F, auto elim: hoare_strengthen_post) lemma strengthen_validE_R_cong[strg]: "(\r s. st F (\) (Q r s) (R r s)) \ st F (\) (\P\ f \Q\, -) (\P\ f \R\, -)" by (cases F, auto intro: hoare_post_imp_R) lemma strengthen_validE_cong[strg]: "(\r s. st F (\) (Q r s) (R r s)) \ (\r s. st F (\) (S r s) (T r s)) \ st F (\) (\P\ f \Q\, \S\) (\P\ f \R\, \T\)" by (cases F, auto elim: hoare_post_impErr) lemma strengthen_validE_E_cong[strg]: "(\r s. st F (\) (S r s) (T r s)) \ st F (\) (\P\ f -, \S\) (\P\ f -, \T\)" by (cases F, auto elim: hoare_post_impErr simp: validE_E_def) lemma strengthen_validI[strg]: "(\r s0 s. st F (\) (Q r s0 s) (Q' r s0 s)) \ st F (\) (\P\,\G\ f \R\,\Q\) (\P\,\G\ f \R\,\Q'\)" by (cases F, auto elim: validI_strengthen_post) end end