diff --git a/lib/Monads/Fun_Pred_Syntax.thy b/lib/Monads/Fun_Pred_Syntax.thy index 6675f35f295..691b929717d 100644 --- a/lib/Monads/Fun_Pred_Syntax.thy +++ b/lib/Monads/Fun_Pred_Syntax.thy @@ -173,6 +173,17 @@ lemmas pred_neg_bot_eq[simp] = entirely in the future *) +subsection "Simplification Rules for Lifted And/Or" + +lemma bipred_disj_op_eq[simp]: + "reflp R \ ((=) or R) = R" + "reflp R \ (R or (=)) = R" + by (auto simp: reflp_def) + +lemma bipred_le_true[simp]: "R \ \\" + by clarsimp + + section \Examples\ experiment diff --git a/lib/Monads/Monad_Lib.thy b/lib/Monads/Monad_Lib.thy index 9147968b1c0..d1dc62120a5 100644 --- a/lib/Monads/Monad_Lib.thy +++ b/lib/Monads/Monad_Lib.thy @@ -69,4 +69,8 @@ lemma sum_all_ex[simp]: "(\a. x \ Inr a) = (\a. x = Inl a)" by (metis Inr_not_Inl sum.exhaust)+ +lemma context_disjE: + "\P \ Q; P \ R; \\P; Q\ \ R\ \ R" + by auto + end \ No newline at end of file diff --git a/lib/Monads/trace/Trace_Empty_Fail.thy b/lib/Monads/trace/Trace_Empty_Fail.thy index 02dd0b2a3cf..472ec988afe 100644 --- a/lib/Monads/trace/Trace_Empty_Fail.thy +++ b/lib/Monads/trace/Trace_Empty_Fail.thy @@ -14,14 +14,16 @@ begin section \Monads that are wellformed w.r.t. failure\ text \ - Usually, well-formed monads constructed from the primitives in Nondet_Monad will have the following - property: if they return an empty set of results, they will have the failure flag set.\ -definition empty_fail :: "('s,'a) nondet_monad \ bool" where - "empty_fail m \ \s. fst (m s) = {} \ snd (m s)" + Usually, well-formed monads constructed from the primitives in Trace_Monad will have the following + property: if they return an empty set of completed results, there exists a trace corresponding to + a failed result.\ +definition empty_fail :: "('s,'a) tmonad \ bool" where + "empty_fail m \ \s. mres (m s) = {} \ Failed \ snd ` (m s)" text \Useful in forcing otherwise unknown executions to have the @{const empty_fail} property.\ -definition mk_ef :: "'a set \ bool \ 'a set \ bool" where - "mk_ef S \ (fst S, fst S = {} \ snd S)" +definition mk_ef :: + "((tmid \ 's) list \ ('s, 'a) tmres) set \ ((tmid \ 's) list \ ('s, 'a) tmres) set" where + "mk_ef S \ if mres S = {} then S \ {([], Failed)} else S" subsection \WPC setup\ @@ -36,34 +38,36 @@ wpc_setup "\m. empty_fail m" wpc_helper_empty_fail_final subsection \@{const empty_fail} intro/dest rules\ lemma empty_failI: - "(\s. fst (m s) = {} \ snd (m s)) \ empty_fail m" + "(\s. mres (m s) = {} \ Failed \ snd ` (m s)) \ empty_fail m" by (simp add: empty_fail_def) lemma empty_failD: - "\ empty_fail m; fst (m s) = {} \ \ snd (m s)" + "\ empty_fail m; mres (m s) = {} \ \ Failed \ snd ` (m s)" by (simp add: empty_fail_def) lemma empty_fail_not_snd: - "\ \ snd (m s); empty_fail m \ \ \v. v \ fst (m s)" + "\ Failed \ snd ` (m s); empty_fail m \ \ \v. v \ mres (m s)" by (fastforce simp: empty_fail_def) lemmas empty_failD2 = empty_fail_not_snd[rotated] lemma empty_failD3: - "\ empty_fail f; \ snd (f s) \ \ fst (f s) \ {}" + "\ empty_fail f; Failed \ snd ` (f s) \ \ mres (f s) \ {}" by (drule(1) empty_failD2, clarsimp) lemma empty_fail_bindD1: "empty_fail (a >>= b) \ empty_fail a" unfolding empty_fail_def bind_def - by (fastforce simp: split_def image_image) + apply clarsimp + apply (drule_tac x=s in spec) + by (force simp: split_def mres_def vimage_def split: tmres.splits) subsection \Wellformed monads\ (* Collect generic empty_fail lemmas here: - - naming convention is emtpy_fail_NAME. + - naming convention is empty_fail_NAME. - add lemmas with assumptions to [empty_fail_cond] set - add lemmas without assumption to [empty_fail_term] set *) @@ -91,32 +95,53 @@ lemma empty_fail_If_applied[empty_fail_cond]: lemma empty_fail_put[empty_fail_term]: "empty_fail (put f)" - by (simp add: put_def empty_fail_def) + by (simp add: put_def empty_fail_def mres_def vimage_def) lemma empty_fail_modify[empty_fail_term]: "empty_fail (modify f)" - by (simp add: empty_fail_def simpler_modify_def) + by (simp add: empty_fail_def simpler_modify_def mres_def vimage_def) lemma empty_fail_gets[empty_fail_term]: "empty_fail (gets f)" - by (simp add: empty_fail_def simpler_gets_def) + by (simp add: empty_fail_def simpler_gets_def mres_def vimage_def) lemma empty_fail_select[empty_fail_cond]: "S \ {} \ empty_fail (select S)" - by (simp add: empty_fail_def select_def) - -lemma empty_fail_select_f[empty_fail_cond]: - assumes ef: "fst S = {} \ snd S" - shows "empty_fail (select_f S)" - by (fastforce simp add: empty_fail_def select_f_def intro: ef) + by (simp add: empty_fail_def select_def mres_def image_def) + +lemma mres_bind_empty: + "mres ((f >>= g) s) = {} + \ mres (f s) = {} \ (\res\mres (f s). mres (g (fst res) (snd res)) = {})" + apply clarsimp + apply (clarsimp simp: mres_def split_def vimage_def bind_def) + apply (rename_tac rv s' trace) + apply (drule_tac x=rv in spec, drule_tac x=s' in spec) + apply (clarsimp simp: image_def) + apply fastforce + done + +lemma bind_FailedI1: + "Failed \ snd ` f s \ Failed \ snd ` (f >>= g) s" + by (force simp: bind_def vimage_def) + +lemma bind_FailedI2: + "\\res\mres (f s). Failed \ snd ` (g (fst res) (snd res)); mres (f s) \ {}\ + \ Failed \ snd ` (f >>= g) s" + by (force simp: bind_def mres_def image_def split_def) lemma empty_fail_bind[empty_fail_cond]: "\ empty_fail a; \x. empty_fail (b x) \ \ empty_fail (a >>= b)" - by (fastforce simp: bind_def empty_fail_def split_def) + unfolding empty_fail_def + apply clarsimp + apply (drule mres_bind_empty) + apply (erule context_disjE) + apply (fastforce intro: bind_FailedI1) + apply (fastforce intro!: bind_FailedI2) + done lemma empty_fail_return[empty_fail_term]: "empty_fail (return x)" - by (simp add: empty_fail_def return_def) + by (simp add: empty_fail_def return_def mres_def vimage_def) lemma empty_fail_returnOk[empty_fail_term]: "empty_fail (returnOk v)" @@ -191,7 +216,7 @@ lemma empty_fail_assertE[empty_fail_term]: lemma empty_fail_get[empty_fail_term]: "empty_fail get" - by (simp add: empty_fail_def get_def) + by (simp add: empty_fail_def get_def mres_def vimage_def) lemma empty_fail_catch[empty_fail_cond]: "\ empty_fail f; \x. empty_fail (g x) \ \ empty_fail (catch f g)" @@ -203,7 +228,7 @@ lemma empty_fail_guard[empty_fail_term]: lemma empty_fail_spec[empty_fail_term]: "empty_fail (state_select F)" - by (clarsimp simp: state_select_def empty_fail_def) + by (clarsimp simp: state_select_def empty_fail_def default_elem_def mres_def image_def) lemma empty_fail_when[empty_fail_cond]: "(P \ empty_fail x) \ empty_fail (when P x)" @@ -321,7 +346,7 @@ subsection \Equations and legacy names\ lemma empty_fail_select_eq[simp]: "empty_fail (select V) = (V \ {})" - by (clarsimp simp: select_def empty_fail_def) + by (clarsimp simp: select_def empty_fail_def mres_def image_def) lemma empty_fail_liftM_eq[simp]: "empty_fail (liftM f m) = empty_fail m" @@ -330,7 +355,7 @@ lemma empty_fail_liftM_eq[simp]: lemma empty_fail_liftE_eq[simp]: "empty_fail (liftE f) = empty_fail f" - by (fastforce simp: liftE_def empty_fail_def bind_def) + by (auto simp: liftE_def empty_fail_bindD1) lemma liftME_empty_fail_eq[simp]: "empty_fail (liftME f m) = empty_fail m" diff --git a/lib/Monads/trace/Trace_In_Monad.thy b/lib/Monads/trace/Trace_In_Monad.thy index 24769154c79..0078c66c445 100644 --- a/lib/Monads/trace/Trace_In_Monad.thy +++ b/lib/Monads/trace/Trace_In_Monad.thy @@ -55,8 +55,8 @@ lemma inl_whenE: by (auto simp add: in_whenE) lemma inr_in_unlessE_throwError[termination_simp]: - "(Inr (), s') \ fst (unlessE P (throwError E) s) = (P \ s'=s)" - by (simp add: unlessE_def returnOk_def throwError_def return_def) + "(Inr (), s') \ mres (unlessE P (throwError E) s) = (P \ s'=s)" + by (simp add: unlessE_def returnOk_def throwError_def in_return) lemma in_fail: "r \ mres (fail s) = False" @@ -90,6 +90,18 @@ 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_unless: + "(v, s') \ mres (unless P f s) = ((\ P \ (v, s') \ mres (f s)) \ (P \ v = () \ s' = s))" + by (simp add: unless_def in_when) + +lemma in_unlessE: + "(v, s') \ mres (unlessE P f s) = ((\ P \ (v, s') \ mres (f s)) \ (P \ v = Inr () \ s' = s))" + by (simp add: unlessE_def in_returnOk) + +lemma inl_unlessE: + "((Inl x, s') \ mres (unlessE P f s)) = (\ P \ (Inl x, s') \ mres (f s))" + by (auto simp add: in_unlessE) + 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) @@ -118,8 +130,8 @@ lemma in_bindE: 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_get in_gets in_put in_when inl_unlessE in_unlessE + in_unless in_modify gets_the_in_monad in_alternative in_liftM lemma bind_det_exec: diff --git a/lib/Monads/trace/Trace_Lemmas.thy b/lib/Monads/trace/Trace_Lemmas.thy index f6e7706f3cb..557c2a855de 100644 --- a/lib/Monads/trace/Trace_Lemmas.thy +++ b/lib/Monads/trace/Trace_Lemmas.thy @@ -31,15 +31,15 @@ lemma bind_apply_cong': lemmas bind_apply_cong = bind_apply_cong'[rule_format, fundef_cong] lemma bind_cong[fundef_cong]: - "\ f = f'; \v s s'. (v, s') \ fst (f' s) \ g v s' = g' v s' \ \ f >>= g = f' >>= g'" - by (auto simp: bind_def Let_def split_def intro: rev_image_eqI) + "\ f = f'; \v s s'. (v, s') \ mres (f' s) \ g v s' = g' v s' \ \ f >>= g = f' >>= g'" + by (auto intro!: bind_apply_cong) lemma bindE_cong[fundef_cong]: - "\ M = M' ; \v s s'. (Inr v, s') \ fst (M' s) \ N v s' = N' v s' \ \ bindE M N = bindE M' N'" + "\ M = M' ; \v s s'. (Inr v, s') \ mres (M' s) \ N v s' = N' v s' \ \ bindE M N = bindE M' N'" by (auto simp: bindE_def lift_def split: sum.splits intro!: bind_cong) lemma bindE_apply_cong[fundef_cong]: - "\ f s = f' s'; \rv st. (Inr rv, st) \ fst (f' s') \ g rv st = g' rv st \ + "\ f s = f' s'; \rv st. (Inr rv, st) \ mres (f' s') \ g rv st = g' rv st \ \ (f >>=E g) s = (f' >>=E g') s'" by (auto simp: bindE_def lift_def split: sum.splits intro!: bind_apply_cong) @@ -63,11 +63,12 @@ lemma unlessE_apply_cong[fundef_cong]: "\ C = C'; s = s'; \ C' \ m s' = m' s' \ \ unlessE C m s = unlessE C' m' s'" by (simp add: unlessE_def) + subsection \Simplifying Monads\ lemma nested_bind[simp]: "do x <- do y <- f; return (g y) od; h x od = do y <- f; h (g y) od" - by (clarsimp simp: bind_def Let_def split_def return_def) + by (fastforce simp: bind_def return_def split: tmres.splits) lemma bind_dummy_ret_val: "do y \ a; b od = do a; b od" diff --git a/lib/Monads/trace/Trace_Monad.thy b/lib/Monads/trace/Trace_Monad.thy index 37f7a70eab9..7ddffb245c2 100644 --- a/lib/Monads/trace/Trace_Monad.thy +++ b/lib/Monads/trace/Trace_Monad.thy @@ -47,21 +47,22 @@ text \ type_synonym ('s, 'a) tmonad = "'s \ ((tmid \ 's) list \ ('s, 'a) tmres) set" text \ - Print the type @{typ "('s,'a) nondet_monad"} instead of its unwieldy expansion. + Print the type @{typ "('s,'a) tmonad"} instead of its unwieldy expansion. Needs an AST translation in code, because it needs to check that the state variable - @{typ 's} occurs twice. This comparison is not guaranteed to always work as expected + @{typ 's} occurs three times. This comparison is not guaranteed to always work as expected (AST instances might have different decoration), but it does seem to work here.\ print_ast_translation \ let - fun monad_tr _ [t1, Ast.Appl [Ast.Constant @{type_syntax prod}, - Ast.Appl [Ast.Constant @{type_syntax set}, - Ast.Appl [Ast.Constant @{type_syntax prod}, t2, t3]], - Ast.Constant @{type_syntax bool}]] = - if t3 = t1 - then Ast.Appl [Ast.Constant @{type_syntax "nondet_monad"}, t1, t2] + fun tmonad_tr _ [t1, Ast.Appl [Ast.Constant @{type_syntax set}, + Ast.Appl [Ast.Constant @{type_syntax prod}, + Ast.Appl [Ast.Constant @{type_syntax list}, + Ast.Appl [Ast.Constant @{type_syntax prod}, + Ast.Constant @{type_syntax tmid}, t2]], + Ast.Appl [Ast.Constant @{type_syntax tmres}, t3, t4]]]] = + if t1 = t2 andalso t1 = t3 + then Ast.Appl [Ast.Constant @{type_syntax "tmonad"}, t1, t4] else raise Match - in [(@{type_syntax "fun"}, monad_tr)] end -\ + in [(@{type_syntax "fun"}, tmonad_tr)] end\ text \Returns monad results, ignoring failures and traces.\ definition mres :: "((tmid \ 's) list \ ('s, 'a) tmres) set \ ('a \ 's) set" where @@ -141,11 +142,16 @@ text \ FIXME: The @{text select_f} function was left out here until we figure out what variant we actually need.\ -text \@{text select_state} takes a relationship between - states, and outputs nondeterministically a state - related to the input state.\ -definition state_select :: "('s \ 's) set \ ('s, unit) nondet_monad" where - "state_select r \ \s. ((\x. ((), x)) ` {s'. (s, s') \ r}, \ (\s'. (s, s') \ r))" +definition + "default_elem dflt A \ if A = {} then {dflt} else A" + +text \ + @{text state_select} takes a relationship between states, and outputs + nondeterministically a state related to the input state. Fails if no such + state exists.\ +definition state_select :: "('s \ 's) set \ ('s, unit) tmonad" where + "state_select r \ + \s. (Pair [] ` default_elem Failed (Result ` (\x. ((), x)) ` {s'. (s, s') \ r}))" subsection "Failure" @@ -212,7 +218,7 @@ text \ Get a map (such as a heap) from the current state and apply an argument to the map. Fail if the map returns @{const None}, otherwise return the value.\ definition - gets_map :: "('s \ 'a \ 'b option) \ 'a \ ('s, 'b) nondet_monad" where + gets_map :: "('s \ 'a \ 'b option) \ 'a \ ('s, 'b) tmonad" where "gets_map f p \ gets f >>= (\m. assert_opt (m p))" @@ -520,8 +526,8 @@ text \The same for the exception monad:\ definition liftME :: "('a \ 'b) \ ('s,'e+'a) tmonad \ ('s,'e+'b) tmonad" where "liftME f m \ doE x \ m; returnOk (f x) odE" -text \ Execute @{term f} for @{term "Some x"}, otherwise do nothing. \ -definition maybeM :: "('a \ ('s, unit) nondet_monad) \ 'a option \ ('s, unit) nondet_monad" where +text \Execute @{term f} for @{term "Some x"}, otherwise do nothing.\ +definition maybeM :: "('a \ ('s, unit) tmonad) \ 'a option \ ('s, unit) tmonad" where "maybeM f y \ case y of Some x \ f x | None \ return ()" text \Run a sequence of monads from left to right, ignoring return values.\ @@ -589,10 +595,8 @@ primrec filterM :: "('a \ ('s, bool) tmonad) \ 'a list \ return (if b then (x # ys) else ys) od" -text \ - @{text select_state} takes a relationship between states, and outputs - nondeterministically a state related to the input state.\ -definition state_select :: "('s \ 's) set \ ('s, unit) tmonad" where +text \An alternative definition of @{term state_select}\ +lemma state_select_def2: "state_select r \ (do s \ get; S \ return {s'. (s, s') \ r}; @@ -600,6 +604,11 @@ definition state_select :: "('s \ 's) set \ ('s, unit) tmonad s' \ select S; put s' od)" + apply (clarsimp simp add: state_select_def get_def return_def assert_def fail_def select_def + put_def bind_def fun_eq_iff default_elem_def + intro!: eq_reflection) + apply fastforce + done section "Catching and Handling Exceptions" @@ -715,45 +724,46 @@ notation (output) section "Combinators that have conditions with side effects" -definition notM :: "('s, bool) nondet_monad \ ('s, bool) nondet_monad" where +definition notM :: "('s, bool) tmonad \ ('s, bool) tmonad" where "notM m = do c \ m; return (\ c) od" -definition - whileM :: "('s, bool) nondet_monad \ ('s, 'a) nondet_monad \ ('s, unit) nondet_monad" where +definition whileM :: + "('s, bool) tmonad \ ('s, 'a) tmonad \ ('s, unit) tmonad" where "whileM C B \ do c \ C; whileLoop (\c s. c) (\_. do B; C od) c; return () od" -definition - ifM :: "('s, bool) nondet_monad \ ('s, 'a) nondet_monad \ ('s, 'a) nondet_monad \ - ('s, 'a) nondet_monad" where +definition ifM :: + "('s, bool) tmonad \ ('s, 'a) tmonad \ ('s, 'a) tmonad \ + ('s, 'a) tmonad" where "ifM test t f = do c \ test; if c then t else f od" definition ifME :: - "('a, 'b + bool) nondet_monad \ ('a, 'b + 'c) nondet_monad \ ('a, 'b + 'c) nondet_monad - \ ('a, 'b + 'c) nondet_monad" where + "('a, 'b + bool) tmonad \ ('a, 'b + 'c) tmonad \ ('a, 'b + 'c) tmonad + \ ('a, 'b + 'c) tmonad" where "ifME test t f = doE c \ test; if c then t else f odE" -definition - whenM :: "('s, bool) nondet_monad \ ('s, unit) nondet_monad \ ('s, unit) nondet_monad" where +definition whenM :: + "('s, bool) tmonad \ ('s, unit) tmonad \ ('s, unit) tmonad" where "whenM t m = ifM t m (return ())" -definition - orM :: "('s, bool) nondet_monad \ ('s, bool) nondet_monad \ ('s, bool) nondet_monad" where +definition orM :: + "('s, bool) tmonad \ ('s, bool) tmonad \ ('s, bool) tmonad" where "orM a b = ifM a (return True) b" definition - andM :: "('s, bool) nondet_monad \ ('s, bool) nondet_monad \ ('s, bool) nondet_monad" where + andM :: "('s, bool) tmonad \ ('s, bool) tmonad \ ('s, bool) tmonad" where "andM a b = ifM a b (return False)" + subsection "Await command" text \@{term "Await c f"} blocks the execution until @{term "c"} is true, diff --git a/lib/Monads/trace/Trace_Monad_Equations.thy b/lib/Monads/trace/Trace_Monad_Equations.thy index 265b8c73c88..2e0815222df 100644 --- a/lib/Monads/trace/Trace_Monad_Equations.thy +++ b/lib/Monads/trace/Trace_Monad_Equations.thy @@ -29,11 +29,7 @@ lemma exec_modify: lemma bind_return_eq: "(a >>= return) = (b >>= return) \ a = b" - apply (clarsimp simp:bind_def) - apply (rule ext) - apply (drule_tac x= x in fun_cong) - apply (auto simp:return_def split_def) - done + by clarsimp lemmas bind_then_eq = arg_cong2[where f=bind, OF _ refl] @@ -51,7 +47,7 @@ lemma throwError_bind: lemma bind_bindE_assoc: "((f >>= g) >>=E h) - = f >>= (\rv. g rv >>=E h)" + = f >>= (\rv. g rv >>=E h)" by (simp add: bindE_def bind_assoc) lemma returnOk_bind: @@ -71,7 +67,7 @@ lemma cart_singleton_image: lemma liftE_bindE_handle: "((liftE f >>=E (\x. g x)) h) - = f >>= (\x. g x h)" + = f >>= (\x. g x h)" by (simp add: liftE_bindE handleE_def handleE'_def bind_assoc) @@ -93,13 +89,13 @@ lemma liftE_bindE_assoc: lemma unlessE_throw_catch_If: "catch (unlessE P (throwError e) >>=E f) g - = (if P then catch (f ()) g else g e)" + = (if P then catch (f ()) g else g e)" by (simp add: unlessE_def catch_throwError split: if_split) lemma whenE_bindE_throwError_to_if: "whenE P (throwError e) >>=E (\_. b) = (if P then (throwError e) else b)" unfolding whenE_def bindE_def - by (auto simp: Nondet_Monad.lift_def throwError_def returnOk_def) + by (auto simp: lift_def throwError_def returnOk_def) lemma alternative_liftE_returnOk: "(liftE m \ returnOk v) = liftE (m \ return v)" @@ -129,13 +125,13 @@ lemma all_rv_choice_fn_eq_pred: lemma all_rv_choice_fn_eq: "\ \rv. \fn. f rv = g fn \ - \ \fn. f = (\rv. g (fn rv))" + \ \fn. f = (\rv. g (fn rv))" using all_rv_choice_fn_eq_pred[where f=f and g=g and P=\] by (simp add: fun_eq_iff) lemma gets_the_eq_bind: "\ \fn. f = gets_the (fn o fn'); \rv. \fn. g rv = gets_the (fn o fn') \ - \ \fn. (f >>= g) = gets_the (fn o fn')" + \ \fn. (f >>= g) = gets_the (fn o fn')" apply (clarsimp dest!: all_rv_choice_fn_eq) apply (rule_tac x="\s. case (fn s) of None \ None | Some v \ fna v s" in exI) apply (simp add: gets_the_def bind_assoc exec_gets @@ -145,7 +141,7 @@ lemma gets_the_eq_bind: lemma gets_the_eq_bindE: "\ \fn. f = gets_the (fn o fn'); \rv. \fn. g rv = gets_the (fn o fn') \ - \ \fn. (f >>=E g) = gets_the (fn o fn')" + \ \fn. (f >>=E g) = gets_the (fn o fn')" apply (simp add: bindE_def) apply (erule gets_the_eq_bind) apply (simp add: lift_def gets_the_returns split: sum.split) @@ -171,9 +167,9 @@ lemma ex_const_function: lemma gets_the_condsE: "(\fn. whenE P f = gets_the (fn o fn')) - = (P \ (\fn. f = gets_the (fn o fn')))" + = (P \ (\fn. f = gets_the (fn o fn')))" "(\fn. unlessE P g = gets_the (fn o fn')) - = (\ P \ (\fn. g = gets_the (fn o fn')))" + = (\ P \ (\fn. g = gets_the (fn o fn')))" by (simp add: whenE_def unlessE_def gets_the_returns ex_const_function split: if_split)+ @@ -187,7 +183,7 @@ lemma liftME_return: lemma fold_bindE_into_list_case: "(doE v \ f; case_list (g v) (h v) x odE) - = (case_list (doE v \ f; g v odE) (\x xs. doE v \ f; h v x xs odE) x)" + = (case_list (doE v \ f; g v odE) (\x xs. doE v \ f; h v x xs odE) x)" by (simp split: list.split) lemma whenE_liftE: @@ -216,7 +212,7 @@ lemma maybe_fail_bind_fail: lemma select_singleton[simp]: "select {x} = return x" - by (fastforce simp add: fun_eq_iff select_def return_def) + by (simp add: select_def return_def) lemma return_modify: "return () = modify id" @@ -234,10 +230,9 @@ lemma modify_id_return: "modify id = return ()" by (simp add: simpler_modify_def return_def) - lemma liftE_bind_return_bindE_returnOk: "liftE (v >>= (\rv. return (f rv))) - = (liftE v >>=E (\rv. returnOk (f rv)))" + = (liftE v >>=E (\rv. returnOk (f rv)))" by (simp add: liftE_bindE, simp add: liftE_def returnOk_def) lemma bind_eqI: @@ -245,12 +240,12 @@ lemma bind_eqI: lemma unlessE_throwError_returnOk: "(if P then returnOk v else throwError x) - = (unlessE P (throwError x) >>=E (\_. returnOk v))" + = (unlessE P (throwError x) >>=E (\_. returnOk v))" by (cases P, simp_all add: unlessE_def) lemma gets_the_bind_eq: "\ f s = Some x; g x s = h s \ - \ (gets_the f >>= g) s = h s" + \ (gets_the f >>= g) s = h s" by (simp add: gets_the_def bind_assoc exec_gets assert_opt_def) lemma zipWithM_x_modify: @@ -265,7 +260,7 @@ lemma zipWithM_x_modify: lemma assert2: "(do v1 \ assert P; v2 \ assert Q; c od) - = (do v \ assert (P \ Q); c od)" + = (do v \ assert (P \ Q); c od)" by (simp add: assert_def split: if_split) lemma assert_opt_def2: @@ -274,20 +269,20 @@ lemma assert_opt_def2: lemma gets_assert: "(do v1 \ assert v; v2 \ gets f; c v1 v2 od) - = (do v2 \ gets f; v1 \ assert v; c v1 v2 od)" + = (do v2 \ gets f; v1 \ assert v; c v1 v2 od)" by (simp add: simpler_gets_def return_def assert_def fail_def bind_def split: if_split) lemma modify_assert: "(do v2 \ modify f; v1 \ assert v; c v1 od) - = (do v1 \ assert v; v2 \ modify f; c v1 od)" + = (do v1 \ assert v; v2 \ modify f; c v1 od)" by (simp add: simpler_modify_def return_def assert_def fail_def bind_def split: if_split) lemma gets_fold_into_modify: "do x \ gets f; modify (g x) od = modify (\s. g (f s) s)" "do x \ gets f; _ \ modify (g x); h od - = do modify (\s. g (f s) s); h od" + = do modify (\s. g (f s) s); h od" by (simp_all add: fun_eq_iff modify_def bind_assoc exec_gets exec_get exec_put) @@ -332,7 +327,7 @@ lemma catch_is_if: od" apply (simp add: bindE_def catch_def bind_assoc cong: if_cong) apply (rule bind_cong, rule refl) - apply (clarsimp simp: Nondet_Monad.lift_def throwError_def split: sum.splits) + apply (clarsimp simp: lift_def throwError_def split: sum.splits) done lemma liftE_K_bind: "liftE ((K_bind (\s. A s)) x) = K_bind (liftE (\s. A s)) x" @@ -354,36 +349,24 @@ lemma if_to_top_of_bindE: "(bindE (If P x y) z) = If P (bindE x z) (bindE y z)" by (simp split: if_split) -lemma modify_id: - "modify id = return ()" - by (simp add: modify_def get_def bind_def put_def return_def) - lemma modify_modify: "(do x \ modify f; modify (g x) od) = modify (g () o f)" by (simp add: bind_def simpler_modify_def) -lemmas modify_modify_bind = arg_cong2[where f=bind, - OF modify_modify refl, simplified bind_assoc] - -lemma select_single: - "select {x} = return x" - by (simp add: select_def return_def) +lemmas modify_modify_bind = + arg_cong2[where f=bind, OF modify_modify refl, simplified bind_assoc] lemma put_then_get[unfolded K_bind_def]: "do put s; get od = do put s; return s od" by (simp add: put_def bind_def get_def return_def) -lemmas put_then_get_then - = put_then_get[THEN bind_then_eq, simplified bind_assoc return_bind] +lemmas put_then_get_then = + put_then_get[THEN bind_then_eq, simplified bind_assoc return_bind] lemma select_empty_bind[simp]: "select {} >>= f = select {}" by (simp add: select_def bind_def) -lemma fail_bind[simp]: - "fail >>= f = fail" - by (simp add: bind_def fail_def) - subsection \Alternative env_steps with repeat\ diff --git a/lib/Monads/trace/Trace_More_VCG.thy b/lib/Monads/trace/Trace_More_VCG.thy index 27b5d9d34df..80f4ab5f7a7 100644 --- a/lib/Monads/trace/Trace_More_VCG.thy +++ b/lib/Monads/trace/Trace_More_VCG.thy @@ -11,11 +11,12 @@ theory Trace_More_VCG imports Trace_VCG + Trace_In_Monad begin lemma hoare_take_disjunct: "\P\ f \\rv s. P' rv s \ (False \ P'' rv s)\ - \ \P\ f \P''\" + \ \P\ f \P''\" by (erule hoare_strengthen_post, simp) lemma hoare_post_add: @@ -44,10 +45,6 @@ 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\" @@ -97,12 +94,12 @@ lemmas hoare_lift_Pf_pre_conj' = hoare_lift_Pf2_pre_conj[where Q=P and P=P for P 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)\" + = \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\" + "\ \\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 @@ -115,8 +112,8 @@ lemma hoare_vcg_ex_lift_R: 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\,-" + "\\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: @@ -129,12 +126,6 @@ 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) @@ -182,7 +173,7 @@ lemma gets_inv [simp]: lemma select_inv: "\ P \ select S \ \r. P \" - by (simp add: select_def valid_def) + by wpsimp lemmas return_inv = hoare_return_drop_var @@ -223,9 +214,10 @@ lemma list_cases_weak_wp: 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\" + case ts of + [] \ a + | x#xs \ b x xs + \Q\" apply (cases ts) apply (simp, rule hoare_weaken_pre, rule assms, simp)+ done @@ -234,18 +226,18 @@ 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. 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\" + \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. 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\, -" + \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 hoare_vcg_imp_liftE: @@ -303,7 +295,7 @@ 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 + f \\rv s. P (S s)\" apply (clarsimp simp: valid_def) apply (drule spec, erule mp) @@ -331,7 +323,7 @@ lemma shrinks_proof: by (metis use_valid w z) lemma use_validE_R: - "\ (Inr r, s') \ fst (f s); \P\ f \Q\,-; P s \ \ Q r s'" + "\ (Inr r, s') \ mres (f s); \P\ f \Q\,-; P s \ \ Q r s'" unfolding validE_R_def validE_def by (frule(2) use_valid, simp) @@ -345,8 +337,6 @@ lemma valid_preservation_ex: 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\" @@ -358,9 +348,12 @@ lemma whenE_throwError_wp: lemma ifM_throwError_returnOk: "\Q\ test \\c s. \ c \ P s\ \ \Q\ ifM test (throwError e) (returnOk ()) \\_. P\, -" - by (fastforce simp: ifM_def returnOk_def throwError_def return_def validE_R_def valid_def - validE_def bind_def - split: if_splits) + unfolding ifM_def + apply (fold liftE_bindE) + apply wpsimp + apply assumption + apply simp + done lemma ifME_liftE: "ifME (liftE test) a b = ifM test a b" @@ -368,14 +361,10 @@ lemma ifME_liftE: 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'" + assumes rl: "\s r s'. \ P s; (r, s') \ mres (S s) \ \ Q r s'" shows "\P\ S \Q\" unfolding valid_def using rl by safe @@ -386,23 +375,13 @@ lemma opt_return_pres_lift: 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) + by (auto simp: valid_def in_bind in_return Ball_def) -lemma static_imp_conj_wp: +lemma hoare_weak_lift_imp_conj: "\ \Q\ m \Q'\; \R\ m \R'\ \ - \ \\s. (P \ Q s) \ R s\ m \\rv s. (P \ Q' rv s) \ R' rv s\" + \ \\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 (rule hoare_weak_lift_imp) apply assumption+ done @@ -415,10 +394,6 @@ 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'\,-" @@ -429,9 +404,10 @@ lemma hoare_vcg_disj_lift_R: 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\" + "\\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: @@ -454,7 +430,7 @@ lemma gets_sp: "\P\ gets f \\rv. P and (\ \P\ f \Q\; (r, s') \ fst (f s); P s \ \ Q r s'" + "\ \P\ f \Q\; (r, s') \ mres (f s); P s \ \ Q r s'" by (rule post_by_hoare, assumption+) lemma hoare_Ball_helper: @@ -511,19 +487,19 @@ lemma hoare_ex_pre: (* safe, unlike hoare_vcg_ex_lift *) 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\" + "\\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 \ 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 : +lemma hoare_in_monad_post: assumes x: "\P. \P\ f \\x. P\" - shows "\\\ f \\rv s. (rv, s) \ fst (f s)\" + shows "\\\ f \\rv s. (rv, s) \ mres (f s)\" apply (clarsimp simp: valid_def) apply (subgoal_tac "s = b", simp) apply (simp add: state_unchanged [OF x]) @@ -544,7 +520,7 @@ lemma validE_R_sp: 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\" + \ \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 @@ -576,29 +552,13 @@ lemma wp_split_const_if_R: 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\" + \ \\s. (P \ R s) \ (Q \ T s)\ f \S\" apply safe apply (rule hoare_pre_imp) prefer 2 @@ -615,8 +575,8 @@ lemma hoare_grab_asm: by (cases G, simp+) lemma hoare_grab_asm2: - "(P' \ \\s. P s \ R s\ f \Q\) - \ \\s. P s \ P' \ R s\ f \Q\" + "\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: @@ -631,8 +591,8 @@ lemma hoare_prop_E: "\\rv. P\ f -,\\rv s 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\,-" + "\ \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) @@ -649,12 +609,12 @@ lemma hoare_walk_assmsE: done lemma univ_wp: - "\\s. \(rv, s') \ fst (f s). Q rv s'\ f \Q\" + "\\s. \(rv, s') \ mres (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\" + shows "\\s. \(rv, s') \ mres (f s). s = s' \ Q rv s'\ f \Q\" apply (rule hoare_pre_imp [OF _ univ_wp]) apply clarsimp apply (drule bspec, assumption, simp) @@ -662,16 +622,11 @@ lemma univ_get_wp: apply (simp add: state_unchanged [OF x]) done -lemma result_in_set_wp : +lemma other_hoare_in_monad_post: 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')\" + shows "\\s. \(v, s) \ mres (fn s). F v = v\ fn \\v s'. (F v, s') \ mres (fn s')\" proof - - have P: "\v s. (F v = v) \ (v, s) \ fst (fn s) \ (F v, s) \ fst (fn s)" + have P: "\v s. (F v = v) \ (v, s) \ mres (fn s) \ (F v, s) \ mres (fn s)" by simp show ?thesis apply (rule hoare_post_imp [OF P], assumption) @@ -679,7 +634,7 @@ lemma other_result_in_set_wp: defer apply (rule hoare_vcg_conj_lift) apply (rule univ_get_wp [OF x]) - apply (rule result_in_set_wp [OF x]) + apply (rule hoare_in_monad_post [OF x]) apply clarsimp apply (drule bspec, assumption, simp) done @@ -687,7 +642,7 @@ lemma other_result_in_set_wp: lemma weak_if_wp: "\ \P\ f \Q\; \P'\ f \Q'\ \ \ - \P and P'\ f \\r. if C r then Q r else Q' r\" + \P and P'\ f \\r. if C r then Q r else Q' r\" by (auto simp add: valid_def split_def) lemma weak_if_wp': @@ -696,12 +651,12 @@ lemma weak_if_wp': 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\" + assumes x: "\x s'. \ (Inr x, s') \ mres (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 (clarsimp simp: validE_def valid_def bindE_def in_bind 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 (case_tac x, simp_all add: in_throwError) apply (drule x) apply (clarsimp simp: validE_def valid_def) apply (drule(1) bspec, simp) @@ -713,7 +668,7 @@ lemma validE_R_abstract_rv: lemma validE_cases_valid: "\P\ f \\rv s. Q (Inr rv) s\,\\rv s. Q (Inl rv) s\ - \ \P\ f \Q\" + \ \P\ f \Q\" apply (simp add: validE_def) apply (erule hoare_strengthen_post) apply (simp split: sum.split_asm) @@ -738,12 +693,10 @@ 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) @@ -754,20 +707,19 @@ lemma valid_imp_ex: 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\" + \ \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\" + \ \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) \" +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)+ @@ -819,9 +771,9 @@ lemma hoare_name_pre_state2: 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) + by wpsimp lemma throwError_R': "\P\ throwError e \Q\,-" - by (clarsimp simp:throwError_def validE_R_def validE_def valid_def return_def) + by wpsimp end \ No newline at end of file diff --git a/lib/Monads/trace/Trace_No_Fail.thy b/lib/Monads/trace/Trace_No_Fail.thy index 4265dd0793d..3630aa911a7 100644 --- a/lib/Monads/trace/Trace_No_Fail.thy +++ b/lib/Monads/trace/Trace_No_Fail.thy @@ -144,13 +144,14 @@ lemma no_fail_assume_pre: "(\s. P s \ no_fail P f) \ no_fail P f" by (simp add: no_fail_def) -lemma no_fail_liftM_eq[simp]: +\ \lemma no_fail_liftM_eq[simp]: "no_fail P (liftM f m) = no_fail P m" - by (auto simp: liftM_def no_fail_def bind_def return_def) + by (auto simp: liftM_def no_fail_def bind_def return_def)\ lemma no_fail_liftM[wp]: "no_fail P m \ no_fail P (liftM f m)" - by simp + unfolding liftM_def + by wpsimp lemma no_fail_pre_and: "no_fail P f \ no_fail (P and Q) f" diff --git a/lib/Monads/trace/Trace_No_Throw.thy b/lib/Monads/trace/Trace_No_Throw.thy index 90d667b718d..f5174f1ecd7 100644 --- a/lib/Monads/trace/Trace_No_Throw.thy +++ b/lib/Monads/trace/Trace_No_Throw.thy @@ -27,10 +27,12 @@ definition no_return :: "('a \ bool) \ ('a, 'b + 'c) tmo (* Alternative definition of no_throw; easier to work with than unfolding validE. *) lemma no_throw_def': - "no_throw P A = (\s. P s \ (\(r, t) \ fst (A s). (\x. r = Inr x)))" + "no_throw P A = (\s. P s \ (\(r, t) \ mres (A s). (\x. r = Inr x)))" by (clarsimp simp: no_throw_def validE_def2 split_def split: sum.splits) +subsection \no_throw rules\ + lemma no_throw_returnOk[simp]: "no_throw P (returnOk a)" unfolding no_throw_def @@ -53,12 +55,14 @@ lemma no_throw_bindE_simple: lemma no_throw_handleE_simple: "\ \x. no_throw \ L \ no_throw \ (R x) \ \ no_throw \ (L R)" by (fastforce simp: no_throw_def' handleE_def handleE'_def validE_def valid_def bind_def return_def - split: sum.splits) + mres_def image_def + split: sum.splits tmres.splits) lemma no_throw_handle2: "\ \a. no_throw Y (B a); \ X \ A \ \_ _. True \,\ \_. Y \ \ \ no_throw X (A B)" - by (fastforce simp: no_throw_def' handleE'_def validE_def valid_def bind_def return_def - split: sum.splits) + by (fastforce simp: no_throw_def' handleE'_def validE_def valid_def bind_def return_def mres_def + image_def + split: sum.splits tmres.splits) lemma no_throw_handle: "\ \a. no_throw Y (B a); \ X \ A \ \_ _. True \,\ \_. Y \ \ \ no_throw X (A B)" @@ -92,7 +96,7 @@ lemma condition_nothrow: by (clarsimp simp: condition_def no_throw_def validE_def2) lemma no_throw_Inr: - "\ x \ fst (A s); no_throw P A; P s \ \ \y. fst x = Inr y" + "\ x \ mres (A s); no_throw P A; P s \ \ \y. fst x = Inr y" by (fastforce simp: no_throw_def' split: sum.splits) end \ No newline at end of file diff --git a/lib/Monads/trace/Trace_RG.thy b/lib/Monads/trace/Trace_RG.thy index fb844d0f181..f4d3164cca6 100644 --- a/lib/Monads/trace/Trace_RG.thy +++ b/lib/Monads/trace/Trace_RG.thy @@ -69,7 +69,7 @@ abbreviation(input) "\\\ \ \_ _ _. False" text \ - Test whether the enironment steps in @{text tr} satisfy the rely condition @{text R}, + Test whether the environment steps in @{text tr} satisfy the rely condition @{text R}, assuming that @{text s0s} was the initial state before the first step in the trace.\ definition rely_cond :: "'s rg_pred \ 's \ (tmid \ 's) list \ bool" where "rely_cond R s0s tr = (\(ident, s0, s) \ trace_steps (rev tr) s0s. ident = Env \ R s0 s)" diff --git a/lib/Monads/trace/Trace_Sat.thy b/lib/Monads/trace/Trace_Sat.thy index 20d68e584df..213303f21a2 100644 --- a/lib/Monads/trace/Trace_Sat.thy +++ b/lib/Monads/trace/Trace_Sat.thy @@ -29,7 +29,7 @@ definition ex_exs_validE :: text \ Seen as predicate transformer, @{const exs_valid} is the so-called conjugate wp in the literature, i.e. with - @{term "wp f Q \ \s. fst (f s) \ {(rv,s). Q rv s}"} and + @{term "wp f Q \ \s. mres (f s) \ {(rv,s). Q rv s}"} and @{term "cwp f Q \ not (wp f (not Q))"}, we get @{prop "valid P f Q = (\s. P s \ wp f Q s)"} and @{prop "exs_valid P f Q = (\s. P s \ cwp f Q s)"}. @@ -39,7 +39,7 @@ experiment begin definition - "wp f Q \ \s. fst (f s) \ {(rv,s). Q rv s}" + "wp f Q \ \s. mres (f s) \ {(rv,s). Q rv s}" definition "cwp f Q \ not (wp f (not Q))" @@ -100,11 +100,11 @@ lemma exs_valid_return[wp]: lemma exs_valid_select[wp]: "\\s. \r \ S. Q r s\ select S \\Q\" - by (clarsimp simp: exs_valid_def select_def) + by (auto simp: exs_valid_def select_def mres_def image_def) lemma exs_valid_alt[wp]: "\ \P\ f \\Q\; \P'\ g \\Q\ \ \ \P or P'\ f \ g \\Q\" - by (fastforce simp: exs_valid_def alternative_def) + by (fastforce simp: exs_valid_def alternative_def mres_def image_def) lemma exs_valid_get[wp]: "\\s. Q s s\ get \\ Q \" @@ -129,7 +129,7 @@ lemma exs_valid_assert[wp]: by (wpsimp | rule conjI)+ lemma exs_valid_state_assert[wp]: - "\ \s. Q () s \ G s \ state_assert G \\ Q \" + "\\s. Q () s \ G s\ state_assert G \\Q\" unfolding state_assert_def by wp @@ -145,7 +145,7 @@ lemma gets_exs_valid: lemma exs_valid_assert_opt[wp]: "\\s. \x. G = Some x \ Q x s\ assert_opt G \\Q\" - by (clarsimp simp: assert_opt_def exs_valid_def get_def assert_def bind_def' return_def) + by (clarsimp simp: assert_opt_def exs_valid_def return_def mres_def) lemma gets_the_exs_valid[wp]: "\\s. \x. h s = Some x \ Q x s\ gets_the h \\Q\" diff --git a/lib/Monads/trace/Trace_Strengthen_Setup.thy b/lib/Monads/trace/Trace_Strengthen_Setup.thy index c4b652fa001..4980330968f 100644 --- a/lib/Monads/trace/Trace_Strengthen_Setup.thy +++ b/lib/Monads/trace/Trace_Strengthen_Setup.thy @@ -42,33 +42,29 @@ lemma strengthen_validI[strg]: by (cases F, auto elim: validI_strengthen_post) lemma wpfix_strengthen_hoare: - "(\s. st (\ F) (\) (P s) (P' s)) - \ (\r s. st F (\) (Q r s) (Q' r s)) - \ st F (\) (\P\ f \Q\) (\P'\ f \Q'\)" + "\\s. st (\ F) (\) (P s) (P' s); \r s. st F (\) (Q r s) (Q' r s)\ + \ st F (\) (\P\ f \Q\) (\P'\ f \Q'\)" by (cases F, auto elim: hoare_chain) lemma wpfix_strengthen_validE_R_cong: - "(\s. st (\ F) (\) (P s) (P' s)) - \ (\r s. st F (\) (Q r s) (Q' r s)) - \ st F (\) (\P\ f \Q\, -) (\P'\ f \Q'\, -)" + "\\s. st (\ F) (\) (P s) (P' s); \r s. st F (\) (Q r s) (Q' r s)\ + \ st F (\) (\P\ f \Q\, -) (\P'\ f \Q'\, -)" by (cases F, auto elim: hoare_chainE simp: validE_R_def) lemma wpfix_strengthen_validE_cong: - "(\s. st (\ F) (\) (P s) (P' s)) - \ (\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\)" + "\\s. st (\ F) (\) (P s) (P' s); \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_chainE) lemma wpfix_strengthen_validE_E_cong: - "(\s. st (\ F) (\) (P s) (P' s)) - \ (\r s. st F (\) (S r s) (T r s)) - \ st F (\) (\P\ f -, \S\) (\P'\ f -, \T\)" + "\\s. st (\ F) (\) (P s) (P' s); \r s. st F (\) (S r s) (T r s)\ + \ st F (\) (\P\ f -, \S\) (\P'\ f -, \T\)" by (cases F, auto elim: hoare_chainE simp: validE_E_def) lemma wpfix_no_fail_cong: - "(\s. st (\ F) (\) (P s) (P' s)) - \ st F (\) (no_fail P f) (no_fail P' f)" + "\\s. st (\ F) (\) (P s) (P' s)\ + \ st F (\) (no_fail P f) (no_fail P' f)" by (cases F, auto elim: no_fail_pre) lemmas nondet_wpfix_strgs = diff --git a/lib/Monads/trace/Trace_Total.thy b/lib/Monads/trace/Trace_Total.thy index 7c89f267f21..1c08d8460c0 100644 --- a/lib/Monads/trace/Trace_Total.thy +++ b/lib/Monads/trace/Trace_Total.thy @@ -52,13 +52,15 @@ subsection \Basic @{const validNF} theorems\ lemma validNF_make_schematic_post: "(\s0. \ \s. P s0 s \ f \ \rv s. Q s0 rv s \!) \ \ \s. \s0. P s0 s \ (\rv s'. Q s0 rv s' \ Q' rv s') \ f \ Q' \!" - by (auto simp add: valid_def validNF_def no_fail_def split: prod.splits) + by (fastforce simp: valid_def validNF_def no_fail_def mres_def image_def + split: prod.splits) lemma validE_NF_make_schematic_post: "(\s0. \ \s. P s0 s \ f \ \rv s. Q s0 rv s \, \ \rv s. E s0 rv s \!) \ \ \s. \s0. P s0 s \ (\rv s'. Q s0 rv s' \ Q' rv s') \ (\rv s'. E s0 rv s' \ E' rv s') \ f \ Q' \, \ E' \!" - by (auto simp add: validE_NF_def validE_def valid_def no_fail_def split: prod.splits sum.splits) + by (fastforce simp: validE_NF_def validE_def valid_def no_fail_def mres_def image_def + split: prod.splits sum.splits) lemma validNF_conjD1: "\ P \ f \ \rv s. Q rv s \ Q' rv s \! \ \ P \ f \ Q \!" @@ -84,7 +86,7 @@ lemma validNF_no_fail: "\ \ P \ f \ Q \! \ \ no_fail P f" by (erule validNFE) -lemma snd_validNF: +lemma validNF_not_failed: "\ \ P \ f \ Q \!; P s \ \ Failed \ snd ` (f s)" by (clarsimp simp: validNF_def no_fail_def) @@ -344,6 +346,6 @@ lemma validE_NF_condition[wp]: lemma hoare_assume_preNF: "(\s. P s \ \P\ f \Q\!) \ \P\ f \Q\!" - by (metis validNF_alt_def) + by (simp add: validNF_alt_def) end \ No newline at end of file diff --git a/lib/Monads/trace/Trace_VCG.thy b/lib/Monads/trace/Trace_VCG.thy index f950d1b6e24..dd0a2f57a89 100644 --- a/lib/Monads/trace/Trace_VCG.thy +++ b/lib/Monads/trace/Trace_VCG.thy @@ -139,17 +139,6 @@ wpc_setup "\m. \P\ m \Q\,-" wpc_helper_v wpc_setup "\m. \P\ m -,\E\" wpc_helper_validR_R -subsection "Simplification Rules for Lifted And/Or" - -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 bind_wp[wp_split]: @@ -180,7 +169,7 @@ lemma seq_ext': lemma seq_ext: "\ \A\ f \B\; \x. \B x\ g x \C\ \ \ \A\ do x \ f; g x od \C\" - by (fastforce simp: valid_def bind_def) + by (rule bind_wp) lemma seqE': "\ \A\ f \B\,\E\; \x. \B x\ g x \C\,\E\ \ \ @@ -320,7 +309,7 @@ lemma use_valid: lemmas post_by_hoare = use_valid[rotated] lemma use_valid_inv: - assumes step: "(r, s') \ fst (f s)" + assumes step: "(r, s') \ mres (f s)" assumes pres: "\N. \\s. N (P s) \ E s\ f \\rv s. N (P s)\" shows "E s \ P s = P s'" using use_valid[where f=f, OF step pres[where N="\p. p = P s"]] by simp @@ -418,7 +407,7 @@ lemma hoare_case_option_wp2: (* Might be useful for forward reasoning, when P is known. *) lemma hoare_when_cases: "\\s. \\B; P s\ \ Q s; B \ \P\ f \\_. Q\\ \ \P\ when B f \\_. Q\" - by (cases B; simp add: valid_def return_def) + by (cases B; simp add: valid_def return_def mres_def) lemma hoare_vcg_prop: "\\s. P\ f \\rv s. P\" @@ -624,6 +613,14 @@ 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_weak_lift_impE: + "\Q\ m \R\,\E\ \ \\s. P \ Q s\ m \\rv s. P \ R rv s\,\\rv s. P \ E rv s\" + by (cases P; simp add: validE_def hoare_vcg_prop) + +lemma hoare_weak_lift_imp_R: + "\Q\ m \R\,- \ \\s. P \ Q s\ m \\rv s. P \ R rv s\,-" + by (cases P, simp_all) + lemmas hoare_vcg_weaken_imp = hoare_weaken_imp (* FIXME lib: eliminate *) lemma hoare_vcg_ex_lift: @@ -724,7 +721,7 @@ lemma return_wp: lemma get_wp: "\\s. P s s\ get \P\" - by(simp add: valid_def split_def get_def) + by (simp add: valid_def get_def mres_def) lemma gets_wp: "\\s. P (f s) s\ gets f \P\" @@ -835,12 +832,9 @@ lemma select_wp: by (simp add: select_def valid_def mres_def image_def) lemma state_select_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 put_wp select_wp hoare_vcg_if_split return_wp fail_wp get_wp) - apply simp - done + "\\s. \t. (s, t) \ f \ P () t\ state_select f \P\" + unfolding state_select_def2 + by (wpsimp wp: put_wp select_wp return_wp get_wp assert_wp) lemma condition_wp: "\ \Q\ A \P\; \R\ B \P\ \ \ \\s. if C s then Q s else R s\ condition C A B \P\" @@ -875,18 +869,18 @@ lemma unlessE_wp: lemma maybeM_wp: "(\x. y = Some x \ \P x\ m x \Q\) \ \\s. (\x. y = Some x \ P x s) \ (y = None \ Q () s)\ maybeM m y \Q\" - unfolding maybeM_def by (cases y; simp add: bind_def return_def valid_def) + unfolding maybeM_def by (wpsimp wp: return_wp) auto lemma notM_wp: "\P\ m \\c. Q (\ c)\ \ \P\ notM m \Q\" - unfolding notM_def by (fastforce simp: bind_def return_def valid_def) + unfolding notM_def by (wpsimp wp: return_wp) lemma ifM_wp: assumes [wp]: "\Q\ f \S\" "\R\ g \S\" assumes [wp]: "\A\ P \\c s. c \ Q s\" "\B\ P \\c s. \c \ R s\" shows "\A and B\ ifM P f g \S\" - unfolding ifM_def using assms - by (fastforce simp: bind_def valid_def split: if_splits) + unfolding ifM_def + by (wpsimp wp: hoare_vcg_if_split hoare_vcg_conj_lift) lemma andM_wp: assumes [wp]: "\Q'\ B \Q\"