(* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) theory BCorres_UL imports Monads.Nondet_VCG Crunch_Instances_NonDet begin definition s_bcorres_underlying where "s_bcorres_underlying t f g s \ (\(x,y). (x, t y)) ` (fst (f s)) \ (fst (g (t s)))" definition bcorres_underlying where "bcorres_underlying t f g \ \s. s_bcorres_underlying t f g s" lemma wpc_helper_bcorres: "bcorres_underlying t f g \ wpc_helper P Q (bcorres_underlying t f g)" by (simp add: wpc_helper_def split: prod.split) lemma wpc_helper_s_bcorres: "s_bcorres_underlying t f g s \ wpc_helper P Q (s_bcorres_underlying t f g s)" by (simp add: wpc_helper_def split: prod.split) wpc_setup "\f. bcorres_underlying t f g" wpc_helper_bcorres wpc_setup "\f. s_bcorres_underlying t f g s" wpc_helper_bcorres lemma s_bcorres_underlying_split[wp_split]: "(\r s'. (r,s') \ fst (f s) \ (s_bcorres_underlying t (g r) (g' r) s')) \ s_bcorres_underlying t f f' s \ s_bcorres_underlying t (f >>= g) (f' >>= g') s" by (clarsimp simp: s_bcorres_underlying_def bind_def) force lemma bcorres_underlying_split[wp_split]: "(\r. (bcorres_underlying t (g r) (g' r))) \ bcorres_underlying t f f' \ bcorres_underlying t (f >>= g) (f' >>= g')" by (simp add: bcorres_underlying_def s_bcorres_underlying_split) lemma get_s_bcorres_underlying[wp]: "s_bcorres_underlying t (f s) (f' (t s)) s \ s_bcorres_underlying t (get >>= f) (get >>= f') s" by (simp add: gets_def s_bcorres_underlying_def get_def bind_def return_def) lemma get_bcorres[wp]: "(\x. bcorres_underlying t (f x) (f' (t x))) \ bcorres_underlying t (get >>= f) (get >>= f')" by (simp add: bcorres_underlying_def get_s_bcorres_underlying) lemma gets_s_bcorres_underlying[wp]: "x' (t s) = x s \ s_bcorres_underlying t (gets x) (gets x') s" by (simp add: s_bcorres_underlying_def gets_def get_def bind_def return_def) lemma gets_bcorres_underlying[wp]: "(\s. x' (t s) = x s) \ bcorres_underlying t (gets x) (gets x')" by (simp add: bcorres_underlying_def gets_s_bcorres_underlying) lemma gets_map_bcorres_underlying[wp]: "(\s. f' (t s) p = f s p) \ bcorres_underlying t (gets_map f p) (gets_map f' p)" by (simp add: gets_map_def bcorres_underlying_def s_bcorres_underlying_def simpler_gets_def bind_def assert_opt_def fail_def return_def split: option.splits) lemma gets_bcorres_underlying': "(\xa. bcorres_underlying t (f (x xa)) (f' (x' (t xa)))) \ bcorres_underlying t (gets x >>= f) (gets x' >>= f')" by (wpsimp simp: gets_def) lemma assert_bcorres_underlying[wp]: "f = f' \ bcorres_underlying t (assert f) (assert f')" by (simp add: assert_def bcorres_underlying_def return_def s_bcorres_underlying_def fail_def) lemma return_bcorres[wp]: "bcorres_underlying t (return x) (return x)" by (simp add:return_def bcorres_underlying_def s_bcorres_underlying_def) lemma drop_sbcorres_underlying: "bcorres_underlying t f g \ s_bcorres_underlying t f g s" by (simp add: bcorres_underlying_def) lemma use_sbcorres_underlying: "(\s. s_bcorres_underlying t f g s) \ bcorres_underlying t f g" by (simp add: bcorres_underlying_def) lemma bcorres_underlying_throwError[wp]: "bcorres_underlying t (throwError a) (throwError a)" by (wpsimp simp: throwError_def) lemma s_bcorres_underlying_splitE[wp_split]: "(\r s'. (Inr r,s') \ fst (f s) \ s_bcorres_underlying t (g r) (g' r) s') \ s_bcorres_underlying t f f' s \ s_bcorres_underlying t (f >>=E g) (f' >>=E g') s" by (wpsimp simp: bindE_def lift_def split: sum.splits | rule conjI drop_sbcorres_underlying)+ lemma get_s_bcorres_underlyingE[wp]: "s_bcorres_underlying t (f s) (f' (t s)) s \ s_bcorres_underlying t (liftE get >>=E f) (liftE get >>=E f') s" by (simp add: gets_def s_bcorres_underlying_def get_def bindE_def bind_def return_def liftE_def lift_def) lemma bcorres_underlying_splitE[wp_split]: "(\r. bcorres_underlying t (g r) (g' r)) \ bcorres_underlying t f f' \ bcorres_underlying t (f >>=E g) (f' >>=E g')" by (simp add: bcorres_underlying_def s_bcorres_underlying_splitE) lemmas return_s_bcorres_underlying[wp] = drop_sbcorres_underlying[OF return_bcorres] lemma liftE_s_bcorres_underlying[wp]: "s_bcorres_underlying t f f' s \ s_bcorres_underlying t (liftE f) (liftE f') s" by (wpsimp simp: liftE_def) lemma liftE_bcorres_underlying[wp]: "bcorres_underlying t f f' \ bcorres_underlying t (liftE f) (liftE f')" by (simp add: bcorres_underlying_def liftE_s_bcorres_underlying) lemma returnOk_bcorres_underlying[wp]: "bcorres_underlying t (returnOk x) (returnOk x)" by (wpsimp simp: returnOk_def) lemma whenE_s_bcorres_underlying[wp]: "\ \P = P'; P\ \ s_bcorres_underlying t f f' s; P = P' \ \ s_bcorres_underlying t (whenE P f) (whenE P' f') s" by (wpsimp simp: whenE_def|rule drop_sbcorres_underlying)+ lemma select_s_bcorres_underlying[wp]: "A \ B \ s_bcorres_underlying t (select A) (select B) s" by (simp add: s_bcorres_underlying_def select_def image_def) blast lemma fail_s_bcorres_underlying[wp]: "s_bcorres_underlying t fail fail s" by (simp add: s_bcorres_underlying_def fail_def) lemma fail_bcorres_underlying[wp]: "bcorres_underlying t fail fail" by (simp add: bcorres_underlying_def fail_s_bcorres_underlying) lemma assertE_bcorres_underlying[wp]: "bcorres_underlying t (assertE P) (assertE P)" by (wpsimp simp: assertE_def returnOk_def|rule conjI)+ lemmas assertE_s_bcorres_underlying[wp] = drop_sbcorres_underlying[OF assertE_bcorres_underlying] lemma when_s_bcorres_underlying[wp]: "(P \ s_bcorres_underlying t f f' s) \ s_bcorres_underlying t (when P f) (when P f') s" by (simp add: return_s_bcorres_underlying when_def) lemma when_bcorres_underlying[wp]: "(P \ bcorres_underlying t f f') \ bcorres_underlying t (when P f) (when P f')" by (simp add: bcorres_underlying_def when_s_bcorres_underlying) lemma put_bcorres_underlying[wp]: "t f = f' \ bcorres_underlying t (put f) (put f')" by (simp add: bcorres_underlying_def s_bcorres_underlying_def put_def) lemma modify_bcorres_underlying[wp]: "(\x. t (f x) = f' (t x)) \ bcorres_underlying t (modify f) (modify f')" by (wpsimp simp: modify_def) lemma liftM_bcorres_underlying[wp]: "bcorres_underlying t m m' \ bcorres_underlying t (liftM f m) (liftM f m')" by (wpsimp simp: liftM_def) lemma sequence_x_bcorres_underlying[wp]: "(\x. bcorres_underlying t (f x) (f' x)) \ bcorres_underlying t (sequence_x (map f xs)) (sequence_x (map f' xs))" by (induct xs; wpsimp simp: sequence_x_def) lemma sequence_bcorres_underlying[wp]: "(\x. bcorres_underlying t (f x) (f' x)) \ bcorres_underlying t (sequence (map f xs)) (sequence (map f' xs))" by (induct xs; wpsimp simp: sequence_def) lemma mapM_x_bcorres_underlying[wp]: "(\x. bcorres_underlying t (f x) (f' x)) \ bcorres_underlying t (mapM_x f xs) (mapM_x f' xs)" by (wpsimp simp: mapM_x_def) lemma mapM_bcorres_underlying[wp]: "(\x. bcorres_underlying t (f x) (f' x)) \ bcorres_underlying t (mapM f xs) (mapM f' xs)" by (simp add: mapM_def | wp)+ lemma gets_s_bcorres_underlyingE': "s_bcorres_underlying t (f (x s)) (f' (x' (t s))) s \ s_bcorres_underlying t (liftE (gets x) >>=E f) (liftE (gets x') >>=E f') s" by (simp add: gets_def liftE_def lift_def bindE_def) wp lemma bcorres_underlying_filterM[wp]: "(\x. bcorres_underlying t (a x) (a' x)) \ bcorres_underlying t (filterM a b) (filterM a' b)" by (induct b; wpsimp simp: filterM_def) lemma option_rec_bcorres_underlying[wp_split]: "(\x y. bcorres_underlying t (g x y) (g' x y)) \ (\x. bcorres_underlying t (f x) (f' x)) \ bcorres_underlying t (rec_option f g a b) (rec_option f' g' a b)" by (cases a, simp+) lemma bcorres_underlying_mapME[wp]: "(\x. bcorres_underlying t (f x) (f' x)) \ bcorres_underlying t (mapME f r) (mapME f' r)" by (induct r; wpsimp simp: mapME_def sequenceE_def) lemma handle2_bcorres_underlying[wp]: "bcorres_underlying t f f' \ (\x. bcorres_underlying t (g x) (g' x)) \ bcorres_underlying t (f g) (f' g')" by (wpsimp simp: handleE'_def) lemma liftME_bcorres_underlying[wp]: "bcorres_underlying t f f' \ bcorres_underlying t (liftME a f) (liftME a f')" by (wpsimp simp: liftME_def) lemma zipWithM_x_bcorres[wp]: "(\x y. bcorres_underlying t (f x y) (f' x y) ) \ bcorres_underlying t (zipWithM_x f xs ys) (zipWithM_x f' xs ys)" by (wpsimp simp: zipWithM_x_def zipWith_def split_def) lemma mapME_x_bcorres_underlying[wp]: "(\x. bcorres_underlying t (f x) (f' x)) \ bcorres_underlying t (mapME_x f xs) (mapME_x f' xs)" by (induct xs; wpsimp simp: mapME_x_def sequenceE_x_def) lemma liftE_bind_bcorres[wp]: "bcorres_underlying t (f >>= g) (f' >>= g') \ bcorres_underlying t (liftE f >>=E g) (liftE f' >>=E g')" by (simp add: gets_def bcorres_underlying_def s_bcorres_underlying_def get_def bind_def return_def split_def liftE_def bindE_def lift_def) lemma select_f_bcorres[wp]: "bcorres_underlying t (select_f f) (select_f f)" by (fastforce simp: select_f_def bcorres_underlying_def s_bcorres_underlying_def) lemma bcorres_underlying_if[wp]: "(b \ bcorres_underlying t f f') \ (\b \ bcorres_underlying t g g') \ bcorres_underlying t (if b then f else g) (if b then f' else g')" by (case_tac b; simp) lemma assert_opt_bcorres_underlying[wp]: "bcorres_underlying t (assert_opt f) (assert_opt f)" by (wpsimp simp: assert_opt_def) lemma unlessb_corres_underlying[wp]: "bcorres_underlying t f f' \ bcorres_underlying t (unless a f) (unless a f')" by (wpsimp simp: unless_def) lemma select_bcorres_underlying[wp]: "A \ B \ bcorres_underlying t (select A) (select B)" by (fastforce simp: bcorres_underlying_def select_def s_bcorres_underlying_def) lemma catch_bcorres[wp]: "bcorres_underlying t f f' \ (\x. bcorres_underlying t (g x) (g' x)) \ bcorres_underlying t (f g) (f' g')" unfolding catch_def by wpsimp lemma whenE_bcorres_underlying[wp]: "\ \P = P'; P\ \ bcorres_underlying t f f'; P = P' \ \ bcorres_underlying t (whenE P f) (whenE P' f')" unfolding whenE_def by wpsimp lemma unlessE_bcorres[wp]: "bcorres_underlying t f f' \ bcorres_underlying t (unlessE P f) (unlessE P f')" by (wpsimp simp: unlessE_def) lemma alternative_bcorres[wp]: "\ bcorres_underlying t f f'; bcorres_underlying t g g' \ \ bcorres_underlying t (f \ g) (f' \ g')" by (fastforce simp: alternative_def bcorres_underlying_def s_bcorres_underlying_def) lemma gets_the_bcorres_underlying[wp]: "(\s. f' (t s) = f s) \ bcorres_underlying t (gets_the f) (gets_the f')" by (wpsimp simp: gets_the_def) ML \ structure CrunchBCorresInstance : CrunchInstance = struct val name = "bcorres"; val prefix_name_scheme = false; type extra = term; val eq_extra = ae_conv; fun parse_extra ctxt extra = case extra of "" => error "bcorres needs truncate function" | e =>(Syntax.parse_term ctxt "%_. True", Syntax.parse_term ctxt e); val has_preconds = false; fun mk_term _ body extra = (Syntax.parse_term @{context} "bcorres_underlying") $ extra $ body $ body; fun dest_term (Const (@{const_name "bcorres_underlying"}, _) $ extra $ body $ _) = SOME (Term.dummy, body, extra) | dest_term _ = NONE; fun put_precond _ ((v as Const (@{const_name "bcorres_underlying"}, _)) $ extra $ body $ body') = v $ extra $ body $ body' | put_precond _ _ = error "put_precond: not an bcorres term"; val pre_thms = []; val wpc_tactic = WeakestPreCases.wp_cases_tac @{thms wpc_processors}; fun wps_tactic _ _ _ = no_tac; val magic = Syntax.parse_term @{context} "\mapp_lambda_ignore. bcorres_underlying t_free_ignore mapp_lambda_ignore g_free_ignore"; val get_monad_state_type = get_nondet_monad_state_type; end; structure CrunchBCorres : CRUNCH = Crunch(CrunchBCorresInstance); \ setup \ add_crunch_instance "bcorres" (CrunchBCorres.crunch_x, CrunchBCorres.crunch_ignore_add_dels) \ end