nipkow@3981: (* Title: HOL/Map.thy nipkow@3981: Author: Tobias Nipkow, based on a theory by David von Oheimb webertj@13908: Copyright 1997-2003 TU Muenchen nipkow@3981: nipkow@3981: The datatype of `maps' (written ~=>); strongly resembles maps in VDM. nipkow@3981: *) nipkow@3981: nipkow@13914: header {* Maps *} nipkow@13914: nipkow@15131: theory Map nipkow@15140: imports List nipkow@15131: begin nipkow@3981: bulwahn@42163: type_synonym ('a,'b) "map" = "'a => 'b option" (infixr "~=>" 0) nipkow@3981: wenzelm@35427: type_notation (xsymbols) haftmann@35565: "map" (infixr "\" 0) wenzelm@19656: nipkow@19378: abbreviation wenzelm@21404: empty :: "'a ~=> 'b" where nipkow@19378: "empty == %x. None" nipkow@19378: wenzelm@19656: definition haftmann@25670: map_comp :: "('b ~=> 'c) => ('a ~=> 'b) => ('a ~=> 'c)" (infixl "o'_m" 55) where wenzelm@20800: "f o_m g = (\k. case g k of None \ None | Some v \ f v)" nipkow@19378: wenzelm@21210: notation (xsymbols) wenzelm@19656: map_comp (infixl "\\<^sub>m" 55) wenzelm@19656: wenzelm@20800: definition wenzelm@21404: map_add :: "('a ~=> 'b) => ('a ~=> 'b) => ('a ~=> 'b)" (infixl "++" 100) where wenzelm@20800: "m1 ++ m2 = (\x. case m2 x of None => m1 x | Some y => Some y)" wenzelm@20800: wenzelm@21404: definition wenzelm@21404: restrict_map :: "('a ~=> 'b) => 'a set => ('a ~=> 'b)" (infixl "|`" 110) where wenzelm@20800: "m|`A = (\x. if x : A then m x else None)" nipkow@13910: wenzelm@21210: notation (latex output) wenzelm@19656: restrict_map ("_\\<^bsub>_\<^esub>" [111,110] 110) wenzelm@19656: wenzelm@20800: definition wenzelm@21404: dom :: "('a ~=> 'b) => 'a set" where wenzelm@20800: "dom m = {a. m a ~= None}" wenzelm@20800: wenzelm@21404: definition wenzelm@21404: ran :: "('a ~=> 'b) => 'b set" where wenzelm@20800: "ran m = {b. EX a. m a = Some b}" wenzelm@20800: wenzelm@21404: definition wenzelm@21404: map_le :: "('a ~=> 'b) => ('a ~=> 'b) => bool" (infix "\\<^sub>m" 50) where wenzelm@53015: "(m\<^sub>1 \\<^sub>m m\<^sub>2) = (\a \ dom m\<^sub>1. m\<^sub>1 a = m\<^sub>2 a)" wenzelm@20800: wenzelm@41229: nonterminal maplets and maplet nipkow@14180: oheimb@5300: syntax nipkow@14180: "_maplet" :: "['a, 'a] => maplet" ("_ /|->/ _") nipkow@14180: "_maplets" :: "['a, 'a] => maplet" ("_ /[|->]/ _") nipkow@14180: "" :: "maplet => maplets" ("_") nipkow@14180: "_Maplets" :: "[maplet, maplets] => maplets" ("_,/ _") nipkow@14180: "_MapUpd" :: "['a ~=> 'b, maplets] => 'a ~=> 'b" ("_/'(_')" [900,0]900) nipkow@14180: "_Map" :: "maplets => 'a ~=> 'b" ("(1[_])") nipkow@3981: wenzelm@12114: syntax (xsymbols) nipkow@14180: "_maplet" :: "['a, 'a] => maplet" ("_ /\/ _") nipkow@14180: "_maplets" :: "['a, 'a] => maplet" ("_ /[\]/ _") nipkow@14180: oheimb@5300: translations nipkow@14180: "_MapUpd m (_Maplets xy ms)" == "_MapUpd (_MapUpd m xy) ms" wenzelm@35115: "_MapUpd m (_maplet x y)" == "m(x := CONST Some y)" wenzelm@19947: "_Map ms" == "_MapUpd (CONST empty) ms" nipkow@14180: "_Map (_Maplets ms1 ms2)" <= "_MapUpd (_Map ms1) ms2" nipkow@14180: "_Maplets ms1 (_Maplets ms2 ms3)" <= "_Maplets (_Maplets ms1 ms2) ms3" nipkow@14180: berghofe@5183: primrec haftmann@34941: map_of :: "('a \ 'b) list \ 'a \ 'b" where haftmann@34941: "map_of [] = empty" haftmann@34941: | "map_of (p # ps) = (map_of ps)(fst p \ snd p)" oheimb@5300: haftmann@34941: definition haftmann@34941: map_upds :: "('a \ 'b) \ 'a list \ 'b list \ 'a \ 'b" where haftmann@34941: "map_upds m xs ys = m ++ map_of (rev (zip xs ys))" haftmann@34941: haftmann@34941: translations haftmann@34941: "_MapUpd m (_maplets x y)" == "CONST map_upds m x y" haftmann@25965: haftmann@25965: lemma map_of_Cons_code [code]: haftmann@25965: "map_of [] k = None" haftmann@25965: "map_of ((l, v) # ps) k = (if l = k then Some v else map_of ps k)" haftmann@25965: by simp_all haftmann@25965: wenzelm@20800: wenzelm@17399: subsection {* @{term [source] empty} *} webertj@13908: wenzelm@20800: lemma empty_upd_none [simp]: "empty(x := None) = empty" nipkow@24331: by (rule ext) simp webertj@13908: webertj@13908: wenzelm@17399: subsection {* @{term [source] map_upd} *} webertj@13908: webertj@13908: lemma map_upd_triv: "t k = Some x ==> t(k|->x) = t" nipkow@24331: by (rule ext) simp webertj@13908: wenzelm@20800: lemma map_upd_nonempty [simp]: "t(k|->x) ~= empty" wenzelm@20800: proof wenzelm@20800: assume "t(k \ x) = empty" wenzelm@20800: then have "(t(k \ x)) k = None" by simp wenzelm@20800: then show False by simp wenzelm@20800: qed webertj@13908: wenzelm@20800: lemma map_upd_eqD1: wenzelm@20800: assumes "m(a\x) = n(a\y)" wenzelm@20800: shows "x = y" wenzelm@20800: proof - wenzelm@41550: from assms have "(m(a\x)) a = (n(a\y)) a" by simp wenzelm@20800: then show ?thesis by simp wenzelm@20800: qed oheimb@14100: wenzelm@20800: lemma map_upd_Some_unfold: nipkow@24331: "((m(a|->b)) x = Some y) = (x = a \ b = y \ x \ a \ m x = Some y)" nipkow@24331: by auto oheimb@14100: wenzelm@20800: lemma image_map_upd [simp]: "x \ A \ m(x \ y) ` A = m ` A" nipkow@24331: by auto nipkow@15303: webertj@13908: lemma finite_range_updI: "finite (range f) ==> finite (range (f(a|->b)))" nipkow@24331: unfolding image_def nipkow@24331: apply (simp (no_asm_use) add:full_SetCompr_eq) nipkow@24331: apply (rule finite_subset) nipkow@24331: prefer 2 apply assumption nipkow@24331: apply (auto) nipkow@24331: done webertj@13908: webertj@13908: wenzelm@17399: subsection {* @{term [source] map_of} *} webertj@13908: nipkow@15304: lemma map_of_eq_None_iff: nipkow@24331: "(map_of xys x = None) = (x \ fst ` (set xys))" nipkow@24331: by (induct xys) simp_all nipkow@15304: nipkow@24331: lemma map_of_is_SomeD: "map_of xys x = Some y \ (x,y) \ set xys" nipkow@24331: apply (induct xys) nipkow@24331: apply simp nipkow@24331: apply (clarsimp split: if_splits) nipkow@24331: done nipkow@15304: wenzelm@20800: lemma map_of_eq_Some_iff [simp]: nipkow@24331: "distinct(map fst xys) \ (map_of xys x = Some y) = ((x,y) \ set xys)" nipkow@24331: apply (induct xys) nipkow@24331: apply simp nipkow@24331: apply (auto simp: map_of_eq_None_iff [symmetric]) nipkow@24331: done nipkow@15304: wenzelm@20800: lemma Some_eq_map_of_iff [simp]: nipkow@24331: "distinct(map fst xys) \ (Some y = map_of xys x) = ((x,y) \ set xys)" nipkow@24331: by (auto simp del:map_of_eq_Some_iff simp add: map_of_eq_Some_iff [symmetric]) nipkow@15304: paulson@17724: lemma map_of_is_SomeI [simp]: "\ distinct(map fst xys); (x,y) \ set xys \ wenzelm@20800: \ map_of xys x = Some y" nipkow@24331: apply (induct xys) nipkow@24331: apply simp nipkow@24331: apply force nipkow@24331: done nipkow@15304: wenzelm@20800: lemma map_of_zip_is_None [simp]: nipkow@24331: "length xs = length ys \ (map_of (zip xs ys) x = None) = (x \ set xs)" nipkow@24331: by (induct rule: list_induct2) simp_all nipkow@15110: haftmann@26443: lemma map_of_zip_is_Some: haftmann@26443: assumes "length xs = length ys" haftmann@26443: shows "x \ set xs \ (\y. map_of (zip xs ys) x = Some y)" haftmann@26443: using assms by (induct rule: list_induct2) simp_all haftmann@26443: haftmann@26443: lemma map_of_zip_upd: haftmann@26443: fixes x :: 'a and xs :: "'a list" and ys zs :: "'b list" haftmann@26443: assumes "length ys = length xs" haftmann@26443: and "length zs = length xs" haftmann@26443: and "x \ set xs" haftmann@26443: and "map_of (zip xs ys)(x \ y) = map_of (zip xs zs)(x \ z)" haftmann@26443: shows "map_of (zip xs ys) = map_of (zip xs zs)" haftmann@26443: proof haftmann@26443: fix x' :: 'a haftmann@26443: show "map_of (zip xs ys) x' = map_of (zip xs zs) x'" haftmann@26443: proof (cases "x = x'") haftmann@26443: case True haftmann@26443: from assms True map_of_zip_is_None [of xs ys x'] haftmann@26443: have "map_of (zip xs ys) x' = None" by simp haftmann@26443: moreover from assms True map_of_zip_is_None [of xs zs x'] haftmann@26443: have "map_of (zip xs zs) x' = None" by simp haftmann@26443: ultimately show ?thesis by simp haftmann@26443: next haftmann@26443: case False from assms haftmann@26443: have "(map_of (zip xs ys)(x \ y)) x' = (map_of (zip xs zs)(x \ z)) x'" by auto haftmann@26443: with False show ?thesis by simp haftmann@26443: qed haftmann@26443: qed haftmann@26443: haftmann@26443: lemma map_of_zip_inject: haftmann@26443: assumes "length ys = length xs" haftmann@26443: and "length zs = length xs" haftmann@26443: and dist: "distinct xs" haftmann@26443: and map_of: "map_of (zip xs ys) = map_of (zip xs zs)" haftmann@26443: shows "ys = zs" haftmann@26443: using assms(1) assms(2)[symmetric] using dist map_of proof (induct ys xs zs rule: list_induct3) haftmann@26443: case Nil show ?case by simp haftmann@26443: next haftmann@26443: case (Cons y ys x xs z zs) haftmann@26443: from `map_of (zip (x#xs) (y#ys)) = map_of (zip (x#xs) (z#zs))` haftmann@26443: have map_of: "map_of (zip xs ys)(x \ y) = map_of (zip xs zs)(x \ z)" by simp haftmann@26443: from Cons have "length ys = length xs" and "length zs = length xs" haftmann@26443: and "x \ set xs" by simp_all haftmann@26443: then have "map_of (zip xs ys) = map_of (zip xs zs)" using map_of by (rule map_of_zip_upd) haftmann@26443: with Cons.hyps `distinct (x # xs)` have "ys = zs" by simp haftmann@26443: moreover from map_of have "y = z" by (rule map_upd_eqD1) haftmann@26443: ultimately show ?case by simp haftmann@26443: qed haftmann@26443: haftmann@33635: lemma map_of_zip_map: haftmann@33635: "map_of (zip xs (map f xs)) = (\x. if x \ set xs then Some (f x) else None)" nipkow@39302: by (induct xs) (simp_all add: fun_eq_iff) haftmann@33635: nipkow@15110: lemma finite_range_map_of: "finite (range (map_of xys))" nipkow@24331: apply (induct xys) nipkow@24331: apply (simp_all add: image_constant) nipkow@24331: apply (rule finite_subset) nipkow@24331: prefer 2 apply assumption nipkow@24331: apply auto nipkow@24331: done nipkow@15110: wenzelm@20800: lemma map_of_SomeD: "map_of xs k = Some y \ (k, y) \ set xs" nipkow@24331: by (induct xs) (simp, atomize (full), auto) webertj@13908: wenzelm@20800: lemma map_of_mapk_SomeI: nipkow@24331: "inj f ==> map_of t k = Some x ==> nipkow@24331: map_of (map (split (%k. Pair (f k))) t) (f k) = Some x" nipkow@24331: by (induct t) (auto simp add: inj_eq) webertj@13908: wenzelm@20800: lemma weak_map_of_SomeI: "(k, x) : set l ==> \x. map_of l k = Some x" nipkow@24331: by (induct l) auto webertj@13908: wenzelm@20800: lemma map_of_filter_in: nipkow@24331: "map_of xs k = Some z \ P k z \ map_of (filter (split P) xs) k = Some z" nipkow@24331: by (induct xs) auto webertj@13908: haftmann@35607: lemma map_of_map: blanchet@55466: "map_of (map (\(k, v). (k, f v)) xs) = map_option f \ map_of xs" nipkow@39302: by (induct xs) (auto simp add: fun_eq_iff) haftmann@35607: blanchet@55466: lemma dom_map_option: blanchet@55466: "dom (\k. map_option (f k) (m k)) = dom m" haftmann@35607: by (simp add: dom_def) webertj@13908: haftmann@56545: lemma dom_map_option_comp [simp]: haftmann@56545: "dom (map_option g \ m) = dom m" haftmann@56545: using dom_map_option [of "\_. g" m] by (simp add: comp_def) haftmann@56545: webertj@13908: blanchet@55466: subsection {* @{const map_option} related *} webertj@13908: blanchet@55466: lemma map_option_o_empty [simp]: "map_option f o empty = empty" nipkow@24331: by (rule ext) simp webertj@13908: blanchet@55466: lemma map_option_o_map_upd [simp]: blanchet@55466: "map_option f o m(a|->b) = (map_option f o m)(a|->f b)" nipkow@24331: by (rule ext) simp wenzelm@20800: webertj@13908: wenzelm@17399: subsection {* @{term [source] map_comp} related *} schirmer@17391: wenzelm@20800: lemma map_comp_empty [simp]: nipkow@24331: "m \\<^sub>m empty = empty" nipkow@24331: "empty \\<^sub>m m = empty" huffman@44921: by (auto simp add: map_comp_def split: option.splits) schirmer@17391: wenzelm@20800: lemma map_comp_simps [simp]: nipkow@24331: "m2 k = None \ (m1 \\<^sub>m m2) k = None" nipkow@24331: "m2 k = Some k' \ (m1 \\<^sub>m m2) k = m1 k'" nipkow@24331: by (auto simp add: map_comp_def) schirmer@17391: schirmer@17391: lemma map_comp_Some_iff: nipkow@24331: "((m1 \\<^sub>m m2) k = Some v) = (\k'. m2 k = Some k' \ m1 k' = Some v)" nipkow@24331: by (auto simp add: map_comp_def split: option.splits) schirmer@17391: schirmer@17391: lemma map_comp_None_iff: nipkow@24331: "((m1 \\<^sub>m m2) k = None) = (m2 k = None \ (\k'. m2 k = Some k' \ m1 k' = None)) " nipkow@24331: by (auto simp add: map_comp_def split: option.splits) webertj@13908: wenzelm@20800: oheimb@14100: subsection {* @{text "++"} *} webertj@13908: nipkow@14025: lemma map_add_empty[simp]: "m ++ empty = m" nipkow@24331: by(simp add: map_add_def) webertj@13908: nipkow@14025: lemma empty_map_add[simp]: "empty ++ m = m" nipkow@24331: by (rule ext) (simp add: map_add_def split: option.split) webertj@13908: nipkow@14025: lemma map_add_assoc[simp]: "m1 ++ (m2 ++ m3) = (m1 ++ m2) ++ m3" nipkow@24331: by (rule ext) (simp add: map_add_def split: option.split) wenzelm@20800: wenzelm@20800: lemma map_add_Some_iff: nipkow@24331: "((m ++ n) k = Some x) = (n k = Some x | n k = None & m k = Some x)" nipkow@24331: by (simp add: map_add_def split: option.split) nipkow@14025: wenzelm@20800: lemma map_add_SomeD [dest!]: nipkow@24331: "(m ++ n) k = Some x \ n k = Some x \ n k = None \ m k = Some x" nipkow@24331: by (rule map_add_Some_iff [THEN iffD1]) webertj@13908: wenzelm@20800: lemma map_add_find_right [simp]: "!!xx. n k = Some xx ==> (m ++ n) k = Some xx" nipkow@24331: by (subst map_add_Some_iff) fast webertj@13908: nipkow@14025: lemma map_add_None [iff]: "((m ++ n) k = None) = (n k = None & m k = None)" nipkow@24331: by (simp add: map_add_def split: option.split) webertj@13908: nipkow@14025: lemma map_add_upd[simp]: "f ++ g(x|->y) = (f ++ g)(x|->y)" nipkow@24331: by (rule ext) (simp add: map_add_def) webertj@13908: nipkow@14186: lemma map_add_upds[simp]: "m1 ++ (m2(xs[\]ys)) = (m1++m2)(xs[\]ys)" nipkow@24331: by (simp add: map_upds_def) nipkow@14186: krauss@32236: lemma map_add_upd_left: "m\dom e2 \ e1(m \ u1) ++ e2 = (e1 ++ e2)(m \ u1)" krauss@32236: by (rule ext) (auto simp: map_add_def dom_def split: option.split) krauss@32236: wenzelm@20800: lemma map_of_append[simp]: "map_of (xs @ ys) = map_of ys ++ map_of xs" nipkow@24331: unfolding map_add_def nipkow@24331: apply (induct xs) nipkow@24331: apply simp nipkow@24331: apply (rule ext) nipkow@24331: apply (simp split add: option.split) nipkow@24331: done webertj@13908: nipkow@14025: lemma finite_range_map_of_map_add: wenzelm@20800: "finite (range f) ==> finite (range (f ++ map_of l))" nipkow@24331: apply (induct l) nipkow@24331: apply (auto simp del: fun_upd_apply) nipkow@24331: apply (erule finite_range_updI) nipkow@24331: done webertj@13908: wenzelm@20800: lemma inj_on_map_add_dom [iff]: nipkow@24331: "inj_on (m ++ m') (dom m') = inj_on m' (dom m')" nipkow@44890: by (fastforce simp: map_add_def dom_def inj_on_def split: option.splits) wenzelm@20800: haftmann@34979: lemma map_upds_fold_map_upd: haftmann@35552: "m(ks[\]vs) = foldl (\m (k, v). m(k \ v)) m (zip ks vs)" haftmann@34979: unfolding map_upds_def proof (rule sym, rule zip_obtain_same_length) haftmann@34979: fix ks :: "'a list" and vs :: "'b list" haftmann@34979: assume "length ks = length vs" haftmann@35552: then show "foldl (\m (k, v). m(k\v)) m (zip ks vs) = m ++ map_of (rev (zip ks vs))" haftmann@35552: by(induct arbitrary: m rule: list_induct2) simp_all haftmann@34979: qed haftmann@34979: haftmann@34979: lemma map_add_map_of_foldr: haftmann@34979: "m ++ map_of ps = foldr (\(k, v) m. m(k \ v)) ps m" nipkow@39302: by (induct ps) (auto simp add: fun_eq_iff map_add_def) haftmann@34979: nipkow@15304: wenzelm@17399: subsection {* @{term [source] restrict_map} *} oheimb@14100: wenzelm@20800: lemma restrict_map_to_empty [simp]: "m|`{} = empty" nipkow@24331: by (simp add: restrict_map_def) nipkow@14186: haftmann@31380: lemma restrict_map_insert: "f |` (insert a A) = (f |` A)(a := f a)" huffman@44921: by (auto simp add: restrict_map_def) haftmann@31380: wenzelm@20800: lemma restrict_map_empty [simp]: "empty|`D = empty" nipkow@24331: by (simp add: restrict_map_def) nipkow@14186: nipkow@15693: lemma restrict_in [simp]: "x \ A \ (m|`A) x = m x" nipkow@24331: by (simp add: restrict_map_def) oheimb@14100: nipkow@15693: lemma restrict_out [simp]: "x \ A \ (m|`A) x = None" nipkow@24331: by (simp add: restrict_map_def) oheimb@14100: nipkow@15693: lemma ran_restrictD: "y \ ran (m|`A) \ \x\A. m x = Some y" nipkow@24331: by (auto simp: restrict_map_def ran_def split: split_if_asm) oheimb@14100: nipkow@15693: lemma dom_restrict [simp]: "dom (m|`A) = dom m \ A" nipkow@24331: by (auto simp: restrict_map_def dom_def split: split_if_asm) oheimb@14100: nipkow@15693: lemma restrict_upd_same [simp]: "m(x\y)|`(-{x}) = m|`(-{x})" nipkow@24331: by (rule ext) (auto simp: restrict_map_def) oheimb@14100: nipkow@15693: lemma restrict_restrict [simp]: "m|`A|`B = m|`(A\B)" nipkow@24331: by (rule ext) (auto simp: restrict_map_def) oheimb@14100: wenzelm@20800: lemma restrict_fun_upd [simp]: nipkow@24331: "m(x := y)|`D = (if x \ D then (m|`(D-{x}))(x := y) else m|`D)" nipkow@39302: by (simp add: restrict_map_def fun_eq_iff) nipkow@14186: wenzelm@20800: lemma fun_upd_None_restrict [simp]: nipkow@24331: "(m|`D)(x := None) = (if x:D then m|`(D - {x}) else m|`D)" nipkow@39302: by (simp add: restrict_map_def fun_eq_iff) nipkow@14186: wenzelm@20800: lemma fun_upd_restrict: "(m|`D)(x := y) = (m|`(D-{x}))(x := y)" nipkow@39302: by (simp add: restrict_map_def fun_eq_iff) nipkow@14186: wenzelm@20800: lemma fun_upd_restrict_conv [simp]: nipkow@24331: "x \ D \ (m|`D)(x := y) = (m|`(D-{x}))(x := y)" nipkow@39302: by (simp add: restrict_map_def fun_eq_iff) nipkow@14186: haftmann@35159: lemma map_of_map_restrict: haftmann@35159: "map_of (map (\k. (k, f k)) ks) = (Some \ f) |` set ks" nipkow@39302: by (induct ks) (simp_all add: fun_eq_iff restrict_map_insert) haftmann@35159: haftmann@35619: lemma restrict_complement_singleton_eq: haftmann@35619: "f |` (- {x}) = f(x := None)" nipkow@39302: by (simp add: restrict_map_def fun_eq_iff) haftmann@35619: oheimb@14100: wenzelm@17399: subsection {* @{term [source] map_upds} *} nipkow@14025: wenzelm@20800: lemma map_upds_Nil1 [simp]: "m([] [|->] bs) = m" nipkow@24331: by (simp add: map_upds_def) nipkow@14025: wenzelm@20800: lemma map_upds_Nil2 [simp]: "m(as [|->] []) = m" nipkow@24331: by (simp add:map_upds_def) wenzelm@20800: wenzelm@20800: lemma map_upds_Cons [simp]: "m(a#as [|->] b#bs) = (m(a|->b))(as[|->]bs)" nipkow@24331: by (simp add:map_upds_def) nipkow@14025: wenzelm@20800: lemma map_upds_append1 [simp]: "\ys m. size xs < size ys \ nipkow@24331: m(xs@[x] [\] ys) = m(xs [\] ys)(x \ ys!size xs)" nipkow@24331: apply(induct xs) nipkow@24331: apply (clarsimp simp add: neq_Nil_conv) nipkow@24331: apply (case_tac ys) nipkow@24331: apply simp nipkow@24331: apply simp nipkow@24331: done nipkow@14187: wenzelm@20800: lemma map_upds_list_update2_drop [simp]: bulwahn@46588: "size xs \ i \ m(xs[\]ys[i:=y]) = m(xs[\]ys)" nipkow@24331: apply (induct xs arbitrary: m ys i) nipkow@24331: apply simp nipkow@24331: apply (case_tac ys) nipkow@24331: apply simp nipkow@24331: apply (simp split: nat.split) nipkow@24331: done nipkow@14025: wenzelm@20800: lemma map_upd_upds_conv_if: wenzelm@20800: "(f(x|->y))(xs [|->] ys) = wenzelm@20800: (if x : set(take (length ys) xs) then f(xs [|->] ys) wenzelm@20800: else (f(xs [|->] ys))(x|->y))" nipkow@24331: apply (induct xs arbitrary: x y ys f) nipkow@24331: apply simp nipkow@24331: apply (case_tac ys) nipkow@24331: apply (auto split: split_if simp: fun_upd_twist) nipkow@24331: done nipkow@14025: nipkow@14025: lemma map_upds_twist [simp]: nipkow@24331: "a ~: set as ==> m(a|->b)(as[|->]bs) = m(as[|->]bs)(a|->b)" nipkow@44890: using set_take_subset by (fastforce simp add: map_upd_upds_conv_if) nipkow@14025: wenzelm@20800: lemma map_upds_apply_nontin [simp]: nipkow@24331: "x ~: set xs ==> (f(xs[|->]ys)) x = f x" nipkow@24331: apply (induct xs arbitrary: ys) nipkow@24331: apply simp nipkow@24331: apply (case_tac ys) nipkow@24331: apply (auto simp: map_upd_upds_conv_if) nipkow@24331: done nipkow@14025: wenzelm@20800: lemma fun_upds_append_drop [simp]: nipkow@24331: "size xs = size ys \ m(xs@zs[\]ys) = m(xs[\]ys)" nipkow@24331: apply (induct xs arbitrary: m ys) nipkow@24331: apply simp nipkow@24331: apply (case_tac ys) nipkow@24331: apply simp_all nipkow@24331: done nipkow@14300: wenzelm@20800: lemma fun_upds_append2_drop [simp]: nipkow@24331: "size xs = size ys \ m(xs[\]ys@zs) = m(xs[\]ys)" nipkow@24331: apply (induct xs arbitrary: m ys) nipkow@24331: apply simp nipkow@24331: apply (case_tac ys) nipkow@24331: apply simp_all nipkow@24331: done nipkow@14300: nipkow@14300: wenzelm@20800: lemma restrict_map_upds[simp]: wenzelm@20800: "\ length xs = length ys; set xs \ D \ wenzelm@20800: \ m(xs [\] ys)|`D = (m|`(D - set xs))(xs [\] ys)" nipkow@24331: apply (induct xs arbitrary: m ys) nipkow@24331: apply simp nipkow@24331: apply (case_tac ys) nipkow@24331: apply simp nipkow@24331: apply (simp add: Diff_insert [symmetric] insert_absorb) nipkow@24331: apply (simp add: map_upd_upds_conv_if) nipkow@24331: done nipkow@14186: nipkow@14186: wenzelm@17399: subsection {* @{term [source] dom} *} webertj@13908: nipkow@31080: lemma dom_eq_empty_conv [simp]: "dom f = {} \ f = empty" huffman@44921: by (auto simp: dom_def) nipkow@31080: webertj@13908: lemma domI: "m a = Some b ==> a : dom m" nipkow@24331: by(simp add:dom_def) oheimb@14100: (* declare domI [intro]? *) webertj@13908: paulson@15369: lemma domD: "a : dom m ==> \b. m a = Some b" nipkow@24331: by (cases "m a") (auto simp add: dom_def) webertj@13908: wenzelm@20800: lemma domIff [iff, simp del]: "(a : dom m) = (m a ~= None)" nipkow@24331: by(simp add:dom_def) webertj@13908: wenzelm@20800: lemma dom_empty [simp]: "dom empty = {}" nipkow@24331: by(simp add:dom_def) webertj@13908: wenzelm@20800: lemma dom_fun_upd [simp]: nipkow@24331: "dom(f(x := y)) = (if y=None then dom f - {x} else insert x (dom f))" nipkow@24331: by(auto simp add:dom_def) webertj@13908: haftmann@34979: lemma dom_if: haftmann@34979: "dom (\x. if P x then f x else g x) = dom f \ {x. P x} \ dom g \ {x. \ P x}" haftmann@34979: by (auto split: if_splits) nipkow@13937: nipkow@15304: lemma dom_map_of_conv_image_fst: haftmann@34979: "dom (map_of xys) = fst ` set xys" haftmann@34979: by (induct xys) (auto simp add: dom_if) nipkow@15304: bulwahn@46588: lemma dom_map_of_zip [simp]: "length xs = length ys ==> dom (map_of (zip xs ys)) = set xs" bulwahn@46588: by (induct rule: list_induct2) (auto simp add: dom_if) nipkow@15110: webertj@13908: lemma finite_dom_map_of: "finite (dom (map_of l))" nipkow@24331: by (induct l) (auto simp add: dom_def insert_Collect [symmetric]) webertj@13908: wenzelm@20800: lemma dom_map_upds [simp]: nipkow@24331: "dom(m(xs[|->]ys)) = set(take (length ys) xs) Un dom m" nipkow@24331: apply (induct xs arbitrary: m ys) nipkow@24331: apply simp nipkow@24331: apply (case_tac ys) nipkow@24331: apply auto nipkow@24331: done nipkow@13910: wenzelm@20800: lemma dom_map_add [simp]: "dom(m++n) = dom n Un dom m" nipkow@24331: by(auto simp:dom_def) nipkow@13910: wenzelm@20800: lemma dom_override_on [simp]: wenzelm@20800: "dom(override_on f g A) = wenzelm@20800: (dom f - {a. a : A - dom g}) Un {a. a : A Int dom g}" nipkow@24331: by(auto simp: dom_def override_on_def) webertj@13908: nipkow@14027: lemma map_add_comm: "dom m1 \ dom m2 = {} \ m1++m2 = m2++m1" nipkow@24331: by (rule ext) (force simp: map_add_def dom_def split: option.split) wenzelm@20800: krauss@32236: lemma map_add_dom_app_simps: krauss@32236: "\ m\dom l2 \ \ (l1++l2) m = l2 m" krauss@32236: "\ m\dom l1 \ \ (l1++l2) m = l2 m" krauss@32236: "\ m\dom l2 \ \ (l1++l2) m = l1 m" krauss@32236: by (auto simp add: map_add_def split: option.split_asm) krauss@32236: haftmann@29622: lemma dom_const [simp]: haftmann@35159: "dom (\x. Some (f x)) = UNIV" haftmann@29622: by auto haftmann@29622: nipkow@22230: (* Due to John Matthews - could be rephrased with dom *) nipkow@22230: lemma finite_map_freshness: nipkow@22230: "finite (dom (f :: 'a \ 'b)) \ \ finite (UNIV :: 'a set) \ nipkow@22230: \x. f x = None" nipkow@22230: by(bestsimp dest:ex_new_if_finite) nipkow@14027: haftmann@28790: lemma dom_minus: haftmann@28790: "f x = None \ dom f - insert x A = dom f - A" haftmann@28790: unfolding dom_def by simp haftmann@28790: haftmann@28790: lemma insert_dom: haftmann@28790: "f x = Some y \ insert x (dom f) = dom f" haftmann@28790: unfolding dom_def by auto haftmann@28790: haftmann@35607: lemma map_of_map_keys: haftmann@35607: "set xs = dom m \ map_of (map (\k. (k, the (m k))) xs) = m" haftmann@35607: by (rule ext) (auto simp add: map_of_map_restrict restrict_map_def) haftmann@35607: haftmann@39379: lemma map_of_eqI: haftmann@39379: assumes set_eq: "set (map fst xs) = set (map fst ys)" haftmann@39379: assumes map_eq: "\k\set (map fst xs). map_of xs k = map_of ys k" haftmann@39379: shows "map_of xs = map_of ys" haftmann@39379: proof (rule ext) haftmann@39379: fix k show "map_of xs k = map_of ys k" haftmann@39379: proof (cases "map_of xs k") haftmann@39379: case None then have "k \ set (map fst xs)" by (simp add: map_of_eq_None_iff) haftmann@39379: with set_eq have "k \ set (map fst ys)" by simp haftmann@39379: then have "map_of ys k = None" by (simp add: map_of_eq_None_iff) haftmann@39379: with None show ?thesis by simp haftmann@39379: next haftmann@39379: case (Some v) then have "k \ set (map fst xs)" by (auto simp add: dom_map_of_conv_image_fst [symmetric]) haftmann@39379: with map_eq show ?thesis by auto haftmann@39379: qed haftmann@39379: qed haftmann@39379: haftmann@39379: lemma map_of_eq_dom: haftmann@39379: assumes "map_of xs = map_of ys" haftmann@39379: shows "fst ` set xs = fst ` set ys" haftmann@39379: proof - haftmann@39379: from assms have "dom (map_of xs) = dom (map_of ys)" by simp haftmann@39379: then show ?thesis by (simp add: dom_map_of_conv_image_fst) haftmann@39379: qed haftmann@39379: nipkow@53820: lemma finite_set_of_finite_maps: nipkow@53820: assumes "finite A" "finite B" nipkow@53820: shows "finite {m. dom m = A \ ran m \ B}" (is "finite ?S") nipkow@53820: proof - nipkow@53820: let ?S' = "{m. \x. (x \ A \ m x \ Some ` B) \ (x \ A \ m x = None)}" nipkow@53820: have "?S = ?S'" nipkow@53820: proof nipkow@53820: show "?S \ ?S'" by(auto simp: dom_def ran_def image_def) nipkow@53820: show "?S' \ ?S" nipkow@53820: proof nipkow@53820: fix m assume "m \ ?S'" nipkow@53820: hence 1: "dom m = A" by force nipkow@53820: hence 2: "ran m \ B" using `m \ ?S'` by(auto simp: dom_def ran_def) nipkow@53820: from 1 2 show "m \ ?S" by blast nipkow@53820: qed nipkow@53820: qed nipkow@53820: with assms show ?thesis by(simp add: finite_set_of_finite_funs) nipkow@53820: qed haftmann@28790: wenzelm@17399: subsection {* @{term [source] ran} *} oheimb@14100: wenzelm@20800: lemma ranI: "m a = Some b ==> b : ran m" nipkow@24331: by(auto simp: ran_def) oheimb@14100: (* declare ranI [intro]? *) webertj@13908: wenzelm@20800: lemma ran_empty [simp]: "ran empty = {}" nipkow@24331: by(auto simp: ran_def) webertj@13908: wenzelm@20800: lemma ran_map_upd [simp]: "m a = None ==> ran(m(a|->b)) = insert b (ran m)" nipkow@24331: unfolding ran_def nipkow@24331: apply auto nipkow@24331: apply (subgoal_tac "aa ~= a") nipkow@24331: apply auto nipkow@24331: done wenzelm@20800: haftmann@34979: lemma ran_distinct: haftmann@34979: assumes dist: "distinct (map fst al)" haftmann@34979: shows "ran (map_of al) = snd ` set al" haftmann@34979: using assms proof (induct al) haftmann@34979: case Nil then show ?case by simp haftmann@34979: next haftmann@34979: case (Cons kv al) haftmann@34979: then have "ran (map_of al) = snd ` set al" by simp haftmann@34979: moreover from Cons.prems have "map_of al (fst kv) = None" haftmann@34979: by (simp add: map_of_eq_None_iff) haftmann@34979: ultimately show ?case by (simp only: map_of.simps ran_map_upd) simp haftmann@34979: qed haftmann@34979: nipkow@13910: oheimb@14100: subsection {* @{text "map_le"} *} nipkow@13910: kleing@13912: lemma map_le_empty [simp]: "empty \\<^sub>m g" nipkow@24331: by (simp add: map_le_def) nipkow@13910: paulson@17724: lemma upd_None_map_le [simp]: "f(x := None) \\<^sub>m f" nipkow@24331: by (force simp add: map_le_def) nipkow@14187: nipkow@13910: lemma map_le_upd[simp]: "f \\<^sub>m g ==> f(a := b) \\<^sub>m g(a := b)" nipkow@44890: by (fastforce simp add: map_le_def) nipkow@13910: paulson@17724: lemma map_le_imp_upd_le [simp]: "m1 \\<^sub>m m2 \ m1(x := None) \\<^sub>m m2(x \ y)" nipkow@24331: by (force simp add: map_le_def) nipkow@14187: wenzelm@20800: lemma map_le_upds [simp]: nipkow@24331: "f \\<^sub>m g ==> f(as [|->] bs) \\<^sub>m g(as [|->] bs)" nipkow@24331: apply (induct as arbitrary: f g bs) nipkow@24331: apply simp nipkow@24331: apply (case_tac bs) nipkow@24331: apply auto nipkow@24331: done webertj@13908: webertj@14033: lemma map_le_implies_dom_le: "(f \\<^sub>m g) \ (dom f \ dom g)" nipkow@44890: by (fastforce simp add: map_le_def dom_def) webertj@14033: webertj@14033: lemma map_le_refl [simp]: "f \\<^sub>m f" nipkow@24331: by (simp add: map_le_def) webertj@14033: nipkow@14187: lemma map_le_trans[trans]: "\ m1 \\<^sub>m m2; m2 \\<^sub>m m3\ \ m1 \\<^sub>m m3" nipkow@24331: by (auto simp add: map_le_def dom_def) webertj@14033: webertj@14033: lemma map_le_antisym: "\ f \\<^sub>m g; g \\<^sub>m f \ \ f = g" nipkow@24331: unfolding map_le_def nipkow@24331: apply (rule ext) nipkow@24331: apply (case_tac "x \ dom f", simp) nipkow@44890: apply (case_tac "x \ dom g", simp, fastforce) nipkow@24331: done webertj@14033: webertj@14033: lemma map_le_map_add [simp]: "f \\<^sub>m (g ++ f)" nipkow@44890: by (fastforce simp add: map_le_def) webertj@14033: nipkow@15304: lemma map_le_iff_map_add_commute: "(f \\<^sub>m f ++ g) = (f++g = g++f)" nipkow@44890: by(fastforce simp: map_add_def map_le_def fun_eq_iff split: option.splits) nipkow@15304: nipkow@15303: lemma map_add_le_mapE: "f++g \\<^sub>m h \ g \\<^sub>m h" nipkow@44890: by (fastforce simp add: map_le_def map_add_def dom_def) nipkow@15303: bulwahn@46588: lemma map_add_le_mapI: "\ f \\<^sub>m h; g \\<^sub>m h \ \ f++g \\<^sub>m h" nipkow@24331: by (clarsimp simp add: map_le_def map_add_def dom_def split: option.splits) nipkow@15303: nipkow@31080: lemma dom_eq_singleton_conv: "dom f = {x} \ (\v. f = [x \ v])" nipkow@31080: proof(rule iffI) nipkow@31080: assume "\v. f = [x \ v]" nipkow@31080: thus "dom f = {x}" by(auto split: split_if_asm) nipkow@31080: next nipkow@31080: assume "dom f = {x}" nipkow@31080: then obtain v where "f x = Some v" by auto nipkow@31080: hence "[x \ v] \\<^sub>m f" by(auto simp add: map_le_def) nipkow@31080: moreover have "f \\<^sub>m [x \ v]" using `dom f = {x}` `f x = Some v` nipkow@31080: by(auto simp add: map_le_def) nipkow@31080: ultimately have "f = [x \ v]" by-(rule map_le_antisym) nipkow@31080: thus "\v. f = [x \ v]" by blast nipkow@31080: qed nipkow@31080: haftmann@35565: haftmann@35565: subsection {* Various *} haftmann@35565: haftmann@35565: lemma set_map_of_compr: haftmann@35565: assumes distinct: "distinct (map fst xs)" haftmann@35565: shows "set xs = {(k, v). map_of xs k = Some v}" haftmann@35565: using assms proof (induct xs) haftmann@35565: case Nil then show ?case by simp haftmann@35565: next haftmann@35565: case (Cons x xs) haftmann@35565: obtain k v where "x = (k, v)" by (cases x) blast haftmann@35565: with Cons.prems have "k \ dom (map_of xs)" haftmann@35565: by (simp add: dom_map_of_conv_image_fst) haftmann@35565: then have *: "insert (k, v) {(k, v). map_of xs k = Some v} = haftmann@35565: {(k', v'). (map_of xs(k \ v)) k' = Some v'}" haftmann@35565: by (auto split: if_splits) haftmann@35565: from Cons have "set xs = {(k, v). map_of xs k = Some v}" by simp haftmann@35565: with * `x = (k, v)` show ?case by simp haftmann@35565: qed haftmann@35565: haftmann@35565: lemma map_of_inject_set: haftmann@35565: assumes distinct: "distinct (map fst xs)" "distinct (map fst ys)" haftmann@35565: shows "map_of xs = map_of ys \ set xs = set ys" (is "?lhs \ ?rhs") haftmann@35565: proof haftmann@35565: assume ?lhs haftmann@35565: moreover from `distinct (map fst xs)` have "set xs = {(k, v). map_of xs k = Some v}" haftmann@35565: by (rule set_map_of_compr) haftmann@35565: moreover from `distinct (map fst ys)` have "set ys = {(k, v). map_of ys k = Some v}" haftmann@35565: by (rule set_map_of_compr) haftmann@35565: ultimately show ?rhs by simp haftmann@35565: next wenzelm@53374: assume ?rhs show ?lhs wenzelm@53374: proof haftmann@35565: fix k haftmann@35565: show "map_of xs k = map_of ys k" proof (cases "map_of xs k") haftmann@35565: case None wenzelm@53374: with `?rhs` have "map_of ys k = None" haftmann@35565: by (simp add: map_of_eq_None_iff) wenzelm@53374: with None show ?thesis by simp haftmann@35565: next haftmann@35565: case (Some v) wenzelm@53374: with distinct `?rhs` have "map_of ys k = Some v" haftmann@35565: by simp wenzelm@53374: with Some show ?thesis by simp haftmann@35565: qed haftmann@35565: qed haftmann@35565: qed haftmann@35565: nipkow@3981: end