diff -r aab26a65e80f -r ebcd69a00872 src/HOL/Library/Relational.thy --- a/src/HOL/Library/Relational.thy Thu Jan 08 10:53:48 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,700 +0,0 @@ -theory Relational -imports Array Ref -begin - -section{* Definition of the Relational framework *} - -text {* The crel predicate states that when a computation c runs with the heap h - will result in return value r and a heap h' (if no exception occurs). *} - -definition crel :: "'a Heap \ heap \ heap \ 'a \ bool" -where - crel_def': "crel c h h' r \ Heap_Monad.execute c h = (Inl r, h')" - -lemma crel_def: -- FIXME - "crel c h h' r \ (Inl r, h') = Heap_Monad.execute c h" - unfolding crel_def' by auto - -lemma crel_deterministic: "\ crel f h h' a; crel f h h'' b \ \ (a = b) \ (h' = h'')" -unfolding crel_def' by auto - -section {* Elimination rules *} - -text {* For all commands, we define simple elimination rules. *} -(* FIXME: consumes 1 necessary ?? *) - -subsection {* Elimination rules for basic monadic commands *} - -lemma crelE[consumes 1]: - assumes "crel (f >>= g) h h'' r'" - obtains h' r where "crel f h h' r" "crel (g r) h' h'' r'" - using assms - by (auto simp add: crel_def bindM_def Let_def prod_case_beta split_def Pair_fst_snd_eq split add: sum.split_asm) - -lemma crelE'[consumes 1]: - assumes "crel (f >> g) h h'' r'" - obtains h' r where "crel f h h' r" "crel g h' h'' r'" - using assms - by (elim crelE) auto - -lemma crel_return[consumes 1]: - assumes "crel (return x) h h' r" - obtains "r = x" "h = h'" - using assms - unfolding crel_def return_def by simp - -lemma crel_raise[consumes 1]: - assumes "crel (raise x) h h' r" - obtains "False" - using assms - unfolding crel_def raise_def by simp - -lemma crel_if: - assumes "crel (if c then t else e) h h' r" - obtains "c" "crel t h h' r" - | "\c" "crel e h h' r" - using assms - unfolding crel_def by auto - -lemma crel_option_case: - assumes "crel (case x of None \ n | Some y \ s y) h h' r" - obtains "x = None" "crel n h h' r" - | y where "x = Some y" "crel (s y) h h' r" - using assms - unfolding crel_def by auto - -lemma crel_mapM: - assumes "crel (mapM f xs) h h' r" - assumes "\h h'. P f [] h h' []" - assumes "\h h1 h' x xs y ys. \ crel (f x) h h1 y; crel (mapM f xs) h1 h' ys; P f xs h1 h' ys \ \ P f (x#xs) h h' (y#ys)" - shows "P f xs h h' r" -using assms(1) -proof (induct xs arbitrary: h h' r) - case Nil with assms(2) show ?case - by (auto elim: crel_return) -next - case (Cons x xs) - from Cons(2) obtain h1 y ys where crel_f: "crel (f x) h h1 y" - and crel_mapM: "crel (mapM f xs) h1 h' ys" - and r_def: "r = y#ys" - unfolding mapM.simps - by (auto elim!: crelE crel_return) - from Cons(1)[OF crel_mapM] crel_mapM crel_f assms(3) r_def - show ?case by auto -qed - -lemma crel_heap: - assumes "crel (Heap_Monad.heap f) h h' r" - obtains "h' = snd (f h)" "r = fst (f h)" - using assms - unfolding heap_def crel_def apfst_def split_def prod_fun_def by simp_all - -subsection {* Elimination rules for array commands *} - -lemma crel_length: - assumes "crel (length a) h h' r" - obtains "h = h'" "r = Heap.length a h'" - using assms - unfolding length_def - by (elim crel_heap) simp - -(* Strong version of the lemma for this operation is missing *) -lemma crel_new_weak: - assumes "crel (Array.new n v) h h' r" - obtains "get_array r h' = List.replicate n v" - using assms unfolding Array.new_def - by (elim crel_heap) (auto simp:Heap.array_def Let_def split_def) - -lemma crel_nth[consumes 1]: - assumes "crel (nth a i) h h' r" - obtains "r = (get_array a h) ! i" "h = h'" "i < Heap.length a h" - using assms - unfolding nth_def - by (auto elim!: crelE crel_if crel_raise crel_length crel_heap) - -lemma crel_upd[consumes 1]: - assumes "crel (upd i v a) h h' r" - obtains "r = a" "h' = Heap.upd a i v h" - using assms - unfolding upd_def - by (elim crelE crel_if crel_return crel_raise - crel_length crel_heap) auto - -(* Strong version of the lemma for this operation is missing *) -lemma crel_of_list_weak: - assumes "crel (Array.of_list xs) h h' r" - obtains "get_array r h' = xs" - using assms - unfolding of_list_def - by (elim crel_heap) (simp add:get_array_init_array_list) - -lemma crel_map_entry: - assumes "crel (Array.map_entry i f a) h h' r" - obtains "r = a" "h' = Heap.upd a i (f (get_array a h ! i)) h" - using assms - unfolding Array.map_entry_def - by (elim crelE crel_upd crel_nth) auto - -lemma crel_swap: - assumes "crel (Array.swap i x a) h h' r" - obtains "r = get_array a h ! i" "h' = Heap.upd a i x h" - using assms - unfolding Array.swap_def - by (elim crelE crel_upd crel_nth crel_return) auto - -(* Strong version of the lemma for this operation is missing *) -lemma crel_make_weak: - assumes "crel (Array.make n f) h h' r" - obtains "i < n \ get_array r h' ! i = f i" - using assms - unfolding Array.make_def - by (elim crel_of_list_weak) auto - -lemma upt_conv_Cons': - assumes "Suc a \ b" - shows "[b - Suc a.. Heap.length a h" - shows "h = h' \ xs = drop (Heap.length a h - n) (get_array a h)" -using assms -proof (induct n arbitrary: xs h h') - case 0 thus ?case - by (auto elim!: crel_return simp add: Heap.length_def) -next - case (Suc n) - from Suc(3) have "[Heap.length a h - Suc n..n. map_entry n f a) [Heap.length a h - n..n. map_entry n f a) [Heap.length a h - n..n. map_entry n f a) [Heap.length a ?h1 - n..n. map_entry n f a) [Heap.length a h - n.. Heap.length a h" - assumes "i \ Heap.length a h - n" - assumes "i < Heap.length a h" - shows "get_array a h' ! i = f (get_array a h ! i)" -using assms -proof (induct n arbitrary: h h' r) - case 0 - thus ?case - by (auto elim!: crel_return) -next - case (Suc n) - let ?h1 = "Heap.upd a (Heap.length a h - Suc n) (f (get_array a h ! (Heap.length a h - Suc n))) h" - from Suc(3) have "[Heap.length a h - Suc n..n. map_entry n f a) [Heap.length a h - n.. i \ Heap.length a ?h1 - n" by arith - from crel_mapM have crel_mapM': "crel (mapM (\n. map_entry n f a) [Heap.length a ?h1 - n..n. map_entry n f a) [Heap.length a h - n.. Heap.length a h" - shows "Heap.length a h' = Heap.length a h" -using assms -proof (induct n arbitrary: h h' r) - case 0 - thus ?case by (auto elim!: crel_return) -next - case (Suc n) - let ?h1 = "Heap.upd a (Heap.length a h - Suc n) (f (get_array a h ! (Heap.length a h - Suc n))) h" - from Suc(3) have "[Heap.length a h - Suc n..n. map_entry n f a) [Heap.length a h - n..n. map_entry n f a) [Heap.length a ?h1 - n..n. map_entry n f a) [0..n. map_entry n f a) [Heap.length a h - Heap.length a h.. \ ref_present x h -extends h' h x \ ref_present x h' -extends h' h x \ ref_present y h \ ref_present y h' -extends h' h x \ ref_present y h \ get_ref y h = get_ref y h' -extends h' h x \ lim h' = Suc (lim h) -*) - -lemma crel_Ref_new: - assumes "crel (Ref.new v) h h' x" - obtains "get_ref x h' = v" - and "\ ref_present x h" - and "ref_present x h'" - and "\y. ref_present y h \ get_ref y h = get_ref y h'" - (* and "lim h' = Suc (lim h)" *) - and "\y. ref_present y h \ ref_present y h'" - using assms - unfolding Ref.new_def - apply (elim crel_heap) - unfolding Heap.ref_def - apply (simp add: Let_def) - unfolding Heap.new_ref_def - apply (simp add: Let_def) - unfolding ref_present_def - apply auto - unfolding get_ref_def set_ref_def - apply auto - done - -lemma crel_lookup: - assumes "crel (!ref) h h' r" - obtains "h = h'" "r = get_ref ref h" -using assms -unfolding Ref.lookup_def -by (auto elim: crel_heap) - -lemma crel_update: - assumes "crel (ref := v) h h' r" - obtains "h' = set_ref ref v h" "r = ()" -using assms -unfolding Ref.update_def -by (auto elim: crel_heap) - -lemma crel_change: - assumes "crel (Ref.change f ref) h h' r" - obtains "h' = set_ref ref (f (get_ref ref h)) h" "r = f (get_ref ref h)" -using assms -unfolding Ref.change_def Let_def -by (auto elim!: crelE crel_lookup crel_update crel_return) - -subsection {* Elimination rules for the assert command *} - -lemma crel_assert[consumes 1]: - assumes "crel (assert P x) h h' r" - obtains "P x" "r = x" "h = h'" - using assms - unfolding assert_def - by (elim crel_if crel_return crel_raise) auto - -lemma crel_assert_eq: "(\h h' r. crel f h h' r \ P r) \ f \= assert P = f" -unfolding crel_def bindM_def Let_def assert_def - raise_def return_def prod_case_beta -apply (cases f) -apply simp -apply (simp add: expand_fun_eq split_def) -apply auto -apply (case_tac "fst (fun x)") -apply (simp_all add: Pair_fst_snd_eq) -apply (erule_tac x="x" in meta_allE) -apply fastsimp -done - -section {* Introduction rules *} - -subsection {* Introduction rules for basic monadic commands *} - -lemma crelI: - assumes "crel f h h' r" "crel (g r) h' h'' r'" - shows "crel (f >>= g) h h'' r'" - using assms by (simp add: crel_def' bindM_def) - -lemma crelI': - assumes "crel f h h' r" "crel g h' h'' r'" - shows "crel (f >> g) h h'' r'" - using assms by (intro crelI) auto - -lemma crel_returnI: - shows "crel (return x) h h x" - unfolding crel_def return_def by simp - -lemma crel_raiseI: - shows "\ (crel (raise x) h h' r)" - unfolding crel_def raise_def by simp - -lemma crel_ifI: - assumes "c \ crel t h h' r" - "\c \ crel e h h' r" - shows "crel (if c then t else e) h h' r" - using assms - unfolding crel_def by auto - -lemma crel_option_caseI: - assumes "\y. x = Some y \ crel (s y) h h' r" - assumes "x = None \ crel n h h' r" - shows "crel (case x of None \ n | Some y \ s y) h h' r" -using assms -by (auto split: option.split) - -lemma crel_heapI: - shows "crel (Heap_Monad.heap f) h (snd (f h)) (fst (f h))" - by (simp add: crel_def apfst_def split_def prod_fun_def) - -lemma crel_heapI': - assumes "h' = snd (f h)" "r = fst (f h)" - shows "crel (Heap_Monad.heap f) h h' r" - using assms - by (simp add: crel_def split_def apfst_def prod_fun_def) - -lemma crelI2: - assumes "\h' rs'. crel f h h' rs' \ (\h'' rs. crel (g rs') h' h'' rs)" - shows "\h'' rs. crel (f\= g) h h'' rs" - oops - -lemma crel_ifI2: - assumes "c \ \h' r. crel t h h' r" - "\ c \ \h' r. crel e h h' r" - shows "\ h' r. crel (if c then t else e) h h' r" - oops - -subsection {* Introduction rules for array commands *} - -lemma crel_lengthI: - shows "crel (length a) h h (Heap.length a h)" - unfolding length_def - by (rule crel_heapI') auto - -(* thm crel_newI for Array.new is missing *) - -lemma crel_nthI: - assumes "i < Heap.length a h" - shows "crel (nth a i) h h ((get_array a h) ! i)" - using assms - unfolding nth_def - by (auto intro!: crelI crel_ifI crel_raiseI crel_lengthI crel_heapI') - -lemma crel_updI: - assumes "i < Heap.length a h" - shows "crel (upd i v a) h (Heap.upd a i v h) a" - using assms - unfolding upd_def - by (auto intro!: crelI crel_ifI crel_returnI crel_raiseI - crel_lengthI crel_heapI') - -(* thm crel_of_listI is missing *) - -(* thm crel_map_entryI is missing *) - -(* thm crel_swapI is missing *) - -(* thm crel_makeI is missing *) - -(* thm crel_freezeI is missing *) - -(* thm crel_mapI is missing *) - -subsection {* Introduction rules for reference commands *} - -lemma crel_lookupI: - shows "crel (!ref) h h (get_ref ref h)" - unfolding lookup_def by (auto intro!: crel_heapI') - -lemma crel_updateI: - shows "crel (ref := v) h (set_ref ref v h) ()" - unfolding update_def by (auto intro!: crel_heapI') - -lemma crel_changeI: - shows "crel (Ref.change f ref) h (set_ref ref (f (get_ref ref h)) h) (f (get_ref ref h))" -unfolding change_def Let_def by (auto intro!: crelI crel_returnI crel_lookupI crel_updateI) - -subsection {* Introduction rules for the assert command *} - -lemma crel_assertI: - assumes "P x" - shows "crel (assert P x) h h x" - using assms - unfolding assert_def - by (auto intro!: crel_ifI crel_returnI crel_raiseI) - -section {* Defintion of the noError predicate *} - -text {* We add a simple definitional setting for crel intro rules - where we only would like to show that the computation does not result in a exception for heap h, - but we do not care about statements about the resulting heap and return value.*} - -definition noError :: "'a Heap \ heap \ bool" -where - "noError c h \ (\r h'. (Inl r, h') = Heap_Monad.execute c h)" - -lemma noError_def': -- FIXME - "noError c h \ (\r h'. Heap_Monad.execute c h = (Inl r, h'))" - unfolding noError_def apply auto proof - - fix r h' - assume "(Inl r, h') = Heap_Monad.execute c h" - then have "Heap_Monad.execute c h = (Inl r, h')" .. - then show "\r h'. Heap_Monad.execute c h = (Inl r, h')" by blast -qed - -subsection {* Introduction rules for basic monadic commands *} - -lemma noErrorI: - assumes "noError f h" - assumes "\h' r. crel f h h' r \ noError (g r) h'" - shows "noError (f \= g) h" - using assms - by (auto simp add: noError_def' crel_def' bindM_def) - -lemma noErrorI': - assumes "noError f h" - assumes "\h' r. crel f h h' r \ noError g h'" - shows "noError (f \ g) h" - using assms - by (auto simp add: noError_def' crel_def' bindM_def) - -lemma noErrorI2: -"\crel f h h' r ; noError f h; noError (g r) h'\ -\ noError (f \= g) h" -by (auto simp add: noError_def' crel_def' bindM_def) - -lemma noError_return: - shows "noError (return x) h" - unfolding noError_def return_def - by auto - -lemma noError_if: - assumes "c \ noError t h" "\ c \ noError e h" - shows "noError (if c then t else e) h" - using assms - unfolding noError_def - by auto - -lemma noError_option_case: - assumes "\y. x = Some y \ noError (s y) h" - assumes "noError n h" - shows "noError (case x of None \ n | Some y \ s y) h" -using assms -by (auto split: option.split) - -lemma noError_mapM: -assumes "\x \ set xs. noError (f x) h \ crel (f x) h h (r x)" -shows "noError (mapM f xs) h" -using assms -proof (induct xs) - case Nil - thus ?case - unfolding mapM.simps by (intro noError_return) -next - case (Cons x xs) - thus ?case - unfolding mapM.simps - by (auto intro: noErrorI2[of "f x"] noErrorI noError_return) -qed - -lemma noError_heap: - shows "noError (Heap_Monad.heap f) h" - by (simp add: noError_def' apfst_def prod_fun_def split_def) - -subsection {* Introduction rules for array commands *} - -lemma noError_length: - shows "noError (Array.length a) h" - unfolding length_def - by (intro noError_heap) - -lemma noError_new: - shows "noError (Array.new n v) h" -unfolding Array.new_def by (intro noError_heap) - -lemma noError_upd: - assumes "i < Heap.length a h" - shows "noError (Array.upd i v a) h" - using assms - unfolding upd_def - by (auto intro!: noErrorI noError_if noError_return noError_length noError_heap) (auto elim: crel_length) - -lemma noError_nth: -assumes "i < Heap.length a h" - shows "noError (Array.nth a i) h" - using assms - unfolding nth_def - by (auto intro!: noErrorI noError_if noError_return noError_length noError_heap) (auto elim: crel_length) - -lemma noError_of_list: - shows "noError (of_list ls) h" - unfolding of_list_def by (rule noError_heap) - -lemma noError_map_entry: - assumes "i < Heap.length a h" - shows "noError (map_entry i f a) h" - using assms - unfolding map_entry_def - by (auto elim: crel_nth intro!: noErrorI noError_nth noError_upd) - -lemma noError_swap: - assumes "i < Heap.length a h" - shows "noError (swap i x a) h" - using assms - unfolding swap_def - by (auto elim: crel_nth intro!: noErrorI noError_return noError_nth noError_upd) - -lemma noError_make: - shows "noError (make n f) h" - unfolding make_def - by (auto intro: noError_of_list) - -(*TODO: move to HeapMonad *) -lemma mapM_append: - "mapM f (xs @ ys) = mapM f xs \= (\xs. mapM f ys \= (\ys. return (xs @ ys)))" - by (induct xs) (simp_all add: monad_simp) - -lemma noError_freeze: - shows "noError (freeze a) h" -unfolding freeze_def -by (auto intro!: noErrorI noError_length noError_mapM[of _ _ _ "\x. get_array a h ! x"] - noError_nth crel_nthI elim: crel_length) - -lemma noError_mapM_map_entry: - assumes "n \ Heap.length a h" - shows "noError (mapM (\n. map_entry n f a) [Heap.length a h - n..