| author | blanchet | 
| Fri, 05 Sep 2014 00:41:01 +0200 | |
| changeset 58187 | d2ddd401d74d | 
| parent 56327 | 3e62e68fb342 | 
| child 58881 | b9556a055632 | 
| permissions | -rw-r--r-- | 
| 46238 
9ace9e5b79be
renaming theory AList_Impl back to AList (reverting 1fec5b365f9b; AList with distinct key invariant is called DAList)
 bulwahn parents: 
46171diff
changeset | 1 | (* Title: HOL/Library/AList.thy | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 2 | Author: Norbert Schirmer, Tobias Nipkow, Martin Wildmoser, TU Muenchen | 
| 19234 | 3 | *) | 
| 4 | ||
| 44897 
787983a08bfb
moving connection of association lists to Mappings into a separate theory
 bulwahn parents: 
39921diff
changeset | 5 | header {* Implementation of Association Lists *}
 | 
| 19234 | 6 | |
| 46238 
9ace9e5b79be
renaming theory AList_Impl back to AList (reverting 1fec5b365f9b; AList with distinct key invariant is called DAList)
 bulwahn parents: 
46171diff
changeset | 7 | theory AList | 
| 45990 
b7b905b23b2a
incorporated More_Set and More_List into the Main body -- to be consolidated later
 haftmann parents: 
45884diff
changeset | 8 | imports Main | 
| 19234 | 9 | begin | 
| 10 | ||
| 22740 | 11 | text {*
 | 
| 56327 | 12 | The operations preserve distinctness of keys and | 
| 13 |   function @{term "clearjunk"} distributes over them. Since
 | |
| 22740 | 14 |   @{term clearjunk} enforces distinctness of keys it can be used
 | 
| 15 | to establish the invariant, e.g. for inductive proofs. | |
| 16 | *} | |
| 19234 | 17 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 18 | subsection {* @{text update} and @{text updates} *}
 | 
| 19323 | 19 | |
| 56327 | 20 | primrec update :: "'key \<Rightarrow> 'val \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | 
| 21 | where | |
| 22 | "update k v [] = [(k, v)]" | |
| 23 | | "update k v (p # ps) = (if fst p = k then (k, v) # ps else p # update k v ps)" | |
| 19234 | 24 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 25 | lemma update_conv': "map_of (update k v al) = (map_of al)(k\<mapsto>v)" | 
| 39302 
d7728f65b353
renamed lemmas: ext_iff -> fun_eq_iff, set_ext_iff -> set_eq_iff, set_ext -> set_eqI
 nipkow parents: 
39198diff
changeset | 26 | by (induct al) (auto simp add: fun_eq_iff) | 
| 23373 | 27 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 28 | corollary update_conv: "map_of (update k v al) k' = ((map_of al)(k\<mapsto>v)) k'" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 29 | by (simp add: update_conv') | 
| 19234 | 30 | |
| 31 | lemma dom_update: "fst ` set (update k v al) = {k} \<union> fst ` set al"
 | |
| 32 | by (induct al) auto | |
| 33 | ||
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 34 | lemma update_keys: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 35 | "map fst (update k v al) = | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 36 | (if k \<in> set (map fst al) then map fst al else map fst al @ [k])" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 37 | by (induct al) simp_all | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 38 | |
| 19234 | 39 | lemma distinct_update: | 
| 56327 | 40 | assumes "distinct (map fst al)" | 
| 19234 | 41 | shows "distinct (map fst (update k v al))" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 42 | using assms by (simp add: update_keys) | 
| 19234 | 43 | |
| 56327 | 44 | lemma update_filter: | 
| 45 | "a \<noteq> k \<Longrightarrow> update k v [q\<leftarrow>ps. fst q \<noteq> a] = [q\<leftarrow>update k v ps. fst q \<noteq> a]" | |
| 19234 | 46 | by (induct ps) auto | 
| 47 | ||
| 48 | lemma update_triv: "map_of al k = Some v \<Longrightarrow> update k v al = al" | |
| 49 | by (induct al) auto | |
| 50 | ||
| 51 | lemma update_nonempty [simp]: "update k v al \<noteq> []" | |
| 52 | by (induct al) auto | |
| 53 | ||
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 54 | lemma update_eqD: "update k v al = update k v' al' \<Longrightarrow> v = v'" | 
| 56327 | 55 | proof (induct al arbitrary: al') | 
| 56 | case Nil | |
| 57 | then show ?case | |
| 19234 | 58 | by (cases al') (auto split: split_if_asm) | 
| 59 | next | |
| 56327 | 60 | case Cons | 
| 61 | then show ?case | |
| 19234 | 62 | by (cases al') (auto split: split_if_asm) | 
| 63 | qed | |
| 64 | ||
| 65 | lemma update_last [simp]: "update k v (update k v' al) = update k v al" | |
| 66 | by (induct al) auto | |
| 67 | ||
| 68 | text {* Note that the lists are not necessarily the same:
 | |
| 56327 | 69 |         @{term "update k v (update k' v' []) = [(k', v'), (k, v)]"} and
 | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 70 |         @{term "update k' v' (update k v []) = [(k, v), (k', v')]"}.*}
 | 
| 56327 | 71 | |
| 72 | lemma update_swap: | |
| 73 | "k \<noteq> k' \<Longrightarrow> | |
| 74 | map_of (update k v (update k' v' al)) = map_of (update k' v' (update k v al))" | |
| 39302 
d7728f65b353
renamed lemmas: ext_iff -> fun_eq_iff, set_ext_iff -> set_eq_iff, set_ext -> set_eqI
 nipkow parents: 
39198diff
changeset | 75 | by (simp add: update_conv' fun_eq_iff) | 
| 19234 | 76 | |
| 56327 | 77 | lemma update_Some_unfold: | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 78 | "map_of (update k v al) x = Some y \<longleftrightarrow> | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 79 | x = k \<and> v = y \<or> x \<noteq> k \<and> map_of al x = Some y" | 
| 19234 | 80 | by (simp add: update_conv' map_upd_Some_unfold) | 
| 81 | ||
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 82 | lemma image_update [simp]: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 83 | "x \<notin> A \<Longrightarrow> map_of (update x y al) ` A = map_of al ` A" | 
| 46133 
d9fe85d3d2cd
incorporated canonical fold combinator on lists into body of List theory; refactored passages on List.fold(l/r)
 haftmann parents: 
45990diff
changeset | 84 | by (simp add: update_conv') | 
| 19234 | 85 | |
| 56327 | 86 | definition updates :: "'key list \<Rightarrow> 'val list \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | 
| 87 | where "updates ks vs = fold (case_prod update) (zip ks vs)" | |
| 19234 | 88 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 89 | lemma updates_simps [simp]: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 90 | "updates [] vs ps = ps" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 91 | "updates ks [] ps = ps" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 92 | "updates (k#ks) (v#vs) ps = updates ks vs (update k v ps)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 93 | by (simp_all add: updates_def) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 94 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 95 | lemma updates_key_simp [simp]: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 96 | "updates (k # ks) vs ps = | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 97 | (case vs of [] \<Rightarrow> ps | v # vs \<Rightarrow> updates ks vs (update k v ps))" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 98 | by (cases vs) simp_all | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 99 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 100 | lemma updates_conv': "map_of (updates ks vs al) = (map_of al)(ks[\<mapsto>]vs)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 101 | proof - | 
| 55414 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 102 | have "map_of \<circ> fold (case_prod update) (zip ks vs) = | 
| 56327 | 103 | fold (\<lambda>(k, v) f. f(k \<mapsto> v)) (zip ks vs) \<circ> map_of" | 
| 39921 | 104 | by (rule fold_commute) (auto simp add: fun_eq_iff update_conv') | 
| 56327 | 105 | then show ?thesis | 
| 106 | by (auto simp add: updates_def fun_eq_iff map_upds_fold_map_upd foldl_conv_fold split_def) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 107 | qed | 
| 19234 | 108 | |
| 109 | lemma updates_conv: "map_of (updates ks vs al) k = ((map_of al)(ks[\<mapsto>]vs)) k" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 110 | by (simp add: updates_conv') | 
| 19234 | 111 | |
| 112 | lemma distinct_updates: | |
| 113 | assumes "distinct (map fst al)" | |
| 114 | shows "distinct (map fst (updates ks vs al))" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 115 | proof - | 
| 46133 
d9fe85d3d2cd
incorporated canonical fold combinator on lists into body of List theory; refactored passages on List.fold(l/r)
 haftmann parents: 
45990diff
changeset | 116 | have "distinct (fold | 
| 37458 | 117 | (\<lambda>(k, v) al. if k \<in> set al then al else al @ [k]) | 
| 118 | (zip ks vs) (map fst al))" | |
| 119 | by (rule fold_invariant [of "zip ks vs" "\<lambda>_. True"]) (auto intro: assms) | |
| 55414 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 120 | moreover have "map fst \<circ> fold (case_prod update) (zip ks vs) = | 
| 56327 | 121 | fold (\<lambda>(k, v) al. if k \<in> set al then al else al @ [k]) (zip ks vs) \<circ> map fst" | 
| 55414 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 122 | by (rule fold_commute) (simp add: update_keys split_def case_prod_beta comp_def) | 
| 56327 | 123 | ultimately show ?thesis | 
| 124 | by (simp add: updates_def fun_eq_iff) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 125 | qed | 
| 19234 | 126 | |
| 127 | lemma updates_append1[simp]: "size ks < size vs \<Longrightarrow> | |
| 56327 | 128 | updates (ks@[k]) vs al = update k (vs!size ks) (updates ks vs al)" | 
| 20503 | 129 | by (induct ks arbitrary: vs al) (auto split: list.splits) | 
| 19234 | 130 | |
| 131 | lemma updates_list_update_drop[simp]: | |
| 56327 | 132 | "size ks \<le> i \<Longrightarrow> i < size vs \<Longrightarrow> | 
| 133 | updates ks (vs[i:=v]) al = updates ks vs al" | |
| 134 | by (induct ks arbitrary: al vs i) (auto split: list.splits nat.splits) | |
| 19234 | 135 | |
| 56327 | 136 | lemma update_updates_conv_if: | 
| 137 | "map_of (updates xs ys (update x y al)) = | |
| 138 | map_of | |
| 139 | (if x \<in> set (take (length ys) xs) | |
| 140 | then updates xs ys al | |
| 141 | else (update x y (updates xs ys al)))" | |
| 19234 | 142 | by (simp add: updates_conv' update_conv' map_upd_upds_conv_if) | 
| 143 | ||
| 144 | lemma updates_twist [simp]: | |
| 56327 | 145 | "k \<notin> set ks \<Longrightarrow> | 
| 146 | map_of (updates ks vs (update k v al)) = map_of (update k v (updates ks vs al))" | |
| 46507 | 147 | by (simp add: updates_conv' update_conv') | 
| 19234 | 148 | |
| 56327 | 149 | lemma updates_apply_notin [simp]: | 
| 150 | "k \<notin> set ks \<Longrightarrow> map_of (updates ks vs al) k = map_of al k" | |
| 19234 | 151 | by (simp add: updates_conv) | 
| 152 | ||
| 56327 | 153 | lemma updates_append_drop [simp]: | 
| 154 | "size xs = size ys \<Longrightarrow> updates (xs @ zs) ys al = updates xs ys al" | |
| 20503 | 155 | by (induct xs arbitrary: ys al) (auto split: list.splits) | 
| 19234 | 156 | |
| 56327 | 157 | lemma updates_append2_drop [simp]: | 
| 158 | "size xs = size ys \<Longrightarrow> updates xs (ys @ zs) al = updates xs ys al" | |
| 20503 | 159 | by (induct xs arbitrary: ys al) (auto split: list.splits) | 
| 19234 | 160 | |
| 23373 | 161 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 162 | subsection {* @{text delete} *}
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 163 | |
| 56327 | 164 | definition delete :: "'key \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | 
| 165 | where delete_eq: "delete k = filter (\<lambda>(k', _). k \<noteq> k')" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 166 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 167 | lemma delete_simps [simp]: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 168 | "delete k [] = []" | 
| 56327 | 169 | "delete k (p # ps) = (if fst p = k then delete k ps else p # delete k ps)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 170 | by (auto simp add: delete_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 171 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 172 | lemma delete_conv': "map_of (delete k al) = (map_of al)(k := None)" | 
| 39302 
d7728f65b353
renamed lemmas: ext_iff -> fun_eq_iff, set_ext_iff -> set_eq_iff, set_ext -> set_eqI
 nipkow parents: 
39198diff
changeset | 173 | by (induct al) (auto simp add: fun_eq_iff) | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 174 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 175 | corollary delete_conv: "map_of (delete k al) k' = ((map_of al)(k := None)) k'" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 176 | by (simp add: delete_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 177 | |
| 56327 | 178 | lemma delete_keys: "map fst (delete k al) = removeAll k (map fst al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 179 | by (simp add: delete_eq removeAll_filter_not_eq filter_map split_def comp_def) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 180 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 181 | lemma distinct_delete: | 
| 56327 | 182 | assumes "distinct (map fst al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 183 | shows "distinct (map fst (delete k al))" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 184 | using assms by (simp add: delete_keys distinct_removeAll) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 185 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 186 | lemma delete_id [simp]: "k \<notin> fst ` set al \<Longrightarrow> delete k al = al" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 187 | by (auto simp add: image_iff delete_eq filter_id_conv) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 188 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 189 | lemma delete_idem: "delete k (delete k al) = delete k al" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 190 | by (simp add: delete_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 191 | |
| 56327 | 192 | lemma map_of_delete [simp]: "k' \<noteq> k \<Longrightarrow> map_of (delete k al) k' = map_of al k'" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 193 | by (simp add: delete_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 194 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 195 | lemma delete_notin_dom: "k \<notin> fst ` set (delete k al)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 196 | by (auto simp add: delete_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 197 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 198 | lemma dom_delete_subset: "fst ` set (delete k al) \<subseteq> fst ` set al" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 199 | by (auto simp add: delete_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 200 | |
| 56327 | 201 | lemma delete_update_same: "delete k (update k v al) = delete k al" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 202 | by (induct al) simp_all | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 203 | |
| 56327 | 204 | lemma delete_update: "k \<noteq> l \<Longrightarrow> delete l (update k v al) = update k v (delete l al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 205 | by (induct al) simp_all | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 206 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 207 | lemma delete_twist: "delete x (delete y al) = delete y (delete x al)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 208 | by (simp add: delete_eq conj_commute) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 209 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 210 | lemma length_delete_le: "length (delete k al) \<le> length al" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 211 | by (simp add: delete_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 212 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 213 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 214 | subsection {* @{text restrict} *}
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 215 | |
| 56327 | 216 | definition restrict :: "'key set \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | 
| 217 | where restrict_eq: "restrict A = filter (\<lambda>(k, v). k \<in> A)" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 218 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 219 | lemma restr_simps [simp]: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 220 | "restrict A [] = []" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 221 | "restrict A (p#ps) = (if fst p \<in> A then p # restrict A ps else restrict A ps)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 222 | by (auto simp add: restrict_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 223 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 224 | lemma restr_conv': "map_of (restrict A al) = ((map_of al)|` A)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 225 | proof | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 226 | fix k | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 227 | show "map_of (restrict A al) k = ((map_of al)|` A) k" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 228 | by (induct al) (simp, cases "k \<in> A", auto) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 229 | qed | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 230 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 231 | corollary restr_conv: "map_of (restrict A al) k = ((map_of al)|` A) k" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 232 | by (simp add: restr_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 233 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 234 | lemma distinct_restr: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 235 | "distinct (map fst al) \<Longrightarrow> distinct (map fst (restrict A al))" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 236 | by (induct al) (auto simp add: restrict_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 237 | |
| 56327 | 238 | lemma restr_empty [simp]: | 
| 239 |   "restrict {} al = []"
 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 240 | "restrict A [] = []" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 241 | by (induct al) (auto simp add: restrict_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 242 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 243 | lemma restr_in [simp]: "x \<in> A \<Longrightarrow> map_of (restrict A al) x = map_of al x" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 244 | by (simp add: restr_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 245 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 246 | lemma restr_out [simp]: "x \<notin> A \<Longrightarrow> map_of (restrict A al) x = None" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 247 | by (simp add: restr_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 248 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 249 | lemma dom_restr [simp]: "fst ` set (restrict A al) = fst ` set al \<inter> A" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 250 | by (induct al) (auto simp add: restrict_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 251 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 252 | lemma restr_upd_same [simp]: "restrict (-{x}) (update x y al) = restrict (-{x}) al"
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 253 | by (induct al) (auto simp add: restrict_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 254 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 255 | lemma restr_restr [simp]: "restrict A (restrict B al) = restrict (A\<inter>B) al" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 256 | by (induct al) (auto simp add: restrict_eq) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 257 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 258 | lemma restr_update[simp]: | 
| 56327 | 259 | "map_of (restrict D (update x y al)) = | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 260 |   map_of ((if x \<in> D then (update x y (restrict (D-{x}) al)) else restrict D al))"
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 261 | by (simp add: restr_conv' update_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 262 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 263 | lemma restr_delete [simp]: | 
| 56327 | 264 |   "delete x (restrict D al) = (if x \<in> D then restrict (D - {x}) al else restrict D al)"
 | 
| 265 | apply (simp add: delete_eq restrict_eq) | |
| 266 | apply (auto simp add: split_def) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 267 | proof - | 
| 56327 | 268 | have "\<And>y. y \<noteq> x \<longleftrightarrow> x \<noteq> y" | 
| 269 | by auto | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 270 | then show "[p \<leftarrow> al. fst p \<in> D \<and> x \<noteq> fst p] = [p \<leftarrow> al. fst p \<in> D \<and> fst p \<noteq> x]" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 271 | by simp | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 272 | assume "x \<notin> D" | 
| 56327 | 273 | then have "\<And>y. y \<in> D \<longleftrightarrow> y \<in> D \<and> x \<noteq> y" | 
| 274 | by auto | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 275 | then show "[p \<leftarrow> al . fst p \<in> D \<and> x \<noteq> fst p] = [p \<leftarrow> al . fst p \<in> D]" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 276 | by simp | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 277 | qed | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 278 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 279 | lemma update_restr: | 
| 56327 | 280 |   "map_of (update x y (restrict D al)) = map_of (update x y (restrict (D - {x}) al))"
 | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 281 | by (simp add: update_conv' restr_conv') (rule fun_upd_restrict) | 
| 19234 | 282 | |
| 45867 | 283 | lemma update_restr_conv [simp]: | 
| 56327 | 284 | "x \<in> D \<Longrightarrow> | 
| 285 |     map_of (update x y (restrict D al)) = map_of (update x y (restrict (D - {x}) al))"
 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 286 | by (simp add: update_conv' restr_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 287 | |
| 56327 | 288 | lemma restr_updates [simp]: | 
| 289 | "length xs = length ys \<Longrightarrow> set xs \<subseteq> D \<Longrightarrow> | |
| 290 | map_of (restrict D (updates xs ys al)) = | |
| 291 | map_of (updates xs ys (restrict (D - set xs) al))" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 292 | by (simp add: updates_conv' restr_conv') | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 293 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 294 | lemma restr_delete_twist: "(restrict A (delete a ps)) = delete a (restrict A ps)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 295 | by (induct ps) auto | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 296 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 297 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 298 | subsection {* @{text clearjunk} *}
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 299 | |
| 56327 | 300 | function clearjunk  :: "('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | 
| 301 | where | |
| 302 | "clearjunk [] = []" | |
| 303 | | "clearjunk (p#ps) = p # clearjunk (delete (fst p) ps)" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 304 | by pat_completeness auto | 
| 56327 | 305 | termination | 
| 306 | by (relation "measure length") (simp_all add: less_Suc_eq_le length_delete_le) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 307 | |
| 56327 | 308 | lemma map_of_clearjunk: "map_of (clearjunk al) = map_of al" | 
| 309 | by (induct al rule: clearjunk.induct) (simp_all add: fun_eq_iff) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 310 | |
| 56327 | 311 | lemma clearjunk_keys_set: "set (map fst (clearjunk al)) = set (map fst al)" | 
| 312 | by (induct al rule: clearjunk.induct) (simp_all add: delete_keys) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 313 | |
| 56327 | 314 | lemma dom_clearjunk: "fst ` set (clearjunk al) = fst ` set al" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 315 | using clearjunk_keys_set by simp | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 316 | |
| 56327 | 317 | lemma distinct_clearjunk [simp]: "distinct (map fst (clearjunk al))" | 
| 318 | by (induct al rule: clearjunk.induct) (simp_all del: set_map add: clearjunk_keys_set delete_keys) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 319 | |
| 56327 | 320 | lemma ran_clearjunk: "ran (map_of (clearjunk al)) = ran (map_of al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 321 | by (simp add: map_of_clearjunk) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 322 | |
| 56327 | 323 | lemma ran_map_of: "ran (map_of al) = snd ` set (clearjunk al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 324 | proof - | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 325 | have "ran (map_of al) = ran (map_of (clearjunk al))" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 326 | by (simp add: ran_clearjunk) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 327 | also have "\<dots> = snd ` set (clearjunk al)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 328 | by (simp add: ran_distinct) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 329 | finally show ?thesis . | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 330 | qed | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 331 | |
| 56327 | 332 | lemma clearjunk_update: "clearjunk (update k v al) = update k v (clearjunk al)" | 
| 333 | by (induct al rule: clearjunk.induct) (simp_all add: delete_update) | |
| 19234 | 334 | |
| 56327 | 335 | lemma clearjunk_updates: "clearjunk (updates ks vs al) = updates ks vs (clearjunk al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 336 | proof - | 
| 55414 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 337 | have "clearjunk \<circ> fold (case_prod update) (zip ks vs) = | 
| 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 338 | fold (case_prod update) (zip ks vs) \<circ> clearjunk" | 
| 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 339 | by (rule fold_commute) (simp add: clearjunk_update case_prod_beta o_def) | 
| 56327 | 340 | then show ?thesis | 
| 341 | by (simp add: updates_def fun_eq_iff) | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 342 | qed | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 343 | |
| 56327 | 344 | lemma clearjunk_delete: "clearjunk (delete x al) = delete x (clearjunk al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 345 | by (induct al rule: clearjunk.induct) (auto simp add: delete_idem delete_twist) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 346 | |
| 56327 | 347 | lemma clearjunk_restrict: "clearjunk (restrict A al) = restrict A (clearjunk al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 348 | by (induct al rule: clearjunk.induct) (auto simp add: restr_delete_twist) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 349 | |
| 56327 | 350 | lemma distinct_clearjunk_id [simp]: "distinct (map fst al) \<Longrightarrow> clearjunk al = al" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 351 | by (induct al rule: clearjunk.induct) auto | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 352 | |
| 56327 | 353 | lemma clearjunk_idem: "clearjunk (clearjunk al) = clearjunk al" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 354 | by simp | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 355 | |
| 56327 | 356 | lemma length_clearjunk: "length (clearjunk al) \<le> length al" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 357 | proof (induct al rule: clearjunk.induct [case_names Nil Cons]) | 
| 56327 | 358 | case Nil | 
| 359 | then show ?case by simp | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 360 | next | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 361 | case (Cons kv al) | 
| 56327 | 362 | moreover have "length (delete (fst kv) al) \<le> length al" | 
| 363 | by (fact length_delete_le) | |
| 364 | ultimately have "length (clearjunk (delete (fst kv) al)) \<le> length al" | |
| 365 | by (rule order_trans) | |
| 366 | then show ?case | |
| 367 | by simp | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 368 | qed | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 369 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 370 | lemma delete_map: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 371 | assumes "\<And>kv. fst (f kv) = fst kv" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 372 | shows "delete k (map f ps) = map f (delete k ps)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 373 | by (simp add: delete_eq filter_map comp_def split_def assms) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 374 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 375 | lemma clearjunk_map: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 376 | assumes "\<And>kv. fst (f kv) = fst kv" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 377 | shows "clearjunk (map f ps) = map f (clearjunk ps)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 378 | by (induct ps rule: clearjunk.induct [case_names Nil Cons]) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 379 | (simp_all add: clearjunk_delete delete_map assms) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 380 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 381 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 382 | subsection {* @{text map_ran} *}
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 383 | |
| 56327 | 384 | definition map_ran :: "('key \<Rightarrow> 'val \<Rightarrow> 'val) \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | 
| 385 | where "map_ran f = map (\<lambda>(k, v). (k, f k v))" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 386 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 387 | lemma map_ran_simps [simp]: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 388 | "map_ran f [] = []" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 389 | "map_ran f ((k, v) # ps) = (k, f k v) # map_ran f ps" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 390 | by (simp_all add: map_ran_def) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 391 | |
| 56327 | 392 | lemma dom_map_ran: "fst ` set (map_ran f al) = fst ` set al" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 393 | by (simp add: map_ran_def image_image split_def) | 
| 56327 | 394 | |
| 395 | lemma map_ran_conv: "map_of (map_ran f al) k = map_option (f k) (map_of al k)" | |
| 19234 | 396 | by (induct al) auto | 
| 397 | ||
| 56327 | 398 | lemma distinct_map_ran: "distinct (map fst al) \<Longrightarrow> distinct (map fst (map_ran f al))" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 399 | by (simp add: map_ran_def split_def comp_def) | 
| 19234 | 400 | |
| 56327 | 401 | lemma map_ran_filter: "map_ran f [p\<leftarrow>ps. fst p \<noteq> a] = [p\<leftarrow>map_ran f ps. fst p \<noteq> a]" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 402 | by (simp add: map_ran_def filter_map split_def comp_def) | 
| 19234 | 403 | |
| 56327 | 404 | lemma clearjunk_map_ran: "clearjunk (map_ran f al) = map_ran f (clearjunk al)" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 405 | by (simp add: map_ran_def split_def clearjunk_map) | 
| 19234 | 406 | |
| 23373 | 407 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 408 | subsection {* @{text merge} *}
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 409 | |
| 56327 | 410 | definition merge :: "('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | 
| 411 | where "merge qs ps = foldr (\<lambda>(k, v). update k v) ps qs" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 412 | |
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 413 | lemma merge_simps [simp]: | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 414 | "merge qs [] = qs" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 415 | "merge qs (p#ps) = update (fst p) (snd p) (merge qs ps)" | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 416 | by (simp_all add: merge_def split_def) | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 417 | |
| 56327 | 418 | lemma merge_updates: "merge qs ps = updates (rev (map fst ps)) (rev (map snd ps)) qs" | 
| 47397 
d654c73e4b12
no preference wrt. fold(l/r); prefer fold rather than foldr for iterating over lists in generated code
 haftmann parents: 
46507diff
changeset | 419 | by (simp add: merge_def updates_def foldr_conv_fold zip_rev zip_map_fst_snd) | 
| 19234 | 420 | |
| 421 | lemma dom_merge: "fst ` set (merge xs ys) = fst ` set xs \<union> fst ` set ys" | |
| 20503 | 422 | by (induct ys arbitrary: xs) (auto simp add: dom_update) | 
| 19234 | 423 | |
| 424 | lemma distinct_merge: | |
| 425 | assumes "distinct (map fst xs)" | |
| 426 | shows "distinct (map fst (merge xs ys))" | |
| 56327 | 427 | using assms by (simp add: merge_updates distinct_updates) | 
| 19234 | 428 | |
| 56327 | 429 | lemma clearjunk_merge: "clearjunk (merge xs ys) = merge (clearjunk xs) ys" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 430 | by (simp add: merge_updates clearjunk_updates) | 
| 19234 | 431 | |
| 56327 | 432 | lemma merge_conv': "map_of (merge xs ys) = map_of xs ++ map_of ys" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 433 | proof - | 
| 55414 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 434 | have "map_of \<circ> fold (case_prod update) (rev ys) = | 
| 56327 | 435 | fold (\<lambda>(k, v) m. m(k \<mapsto> v)) (rev ys) \<circ> map_of" | 
| 55414 
eab03e9cee8a
renamed '{prod,sum,bool,unit}_case' to 'case_...'
 blanchet parents: 
47397diff
changeset | 436 | by (rule fold_commute) (simp add: update_conv' case_prod_beta split_def fun_eq_iff) | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 437 | then show ?thesis | 
| 47397 
d654c73e4b12
no preference wrt. fold(l/r); prefer fold rather than foldr for iterating over lists in generated code
 haftmann parents: 
46507diff
changeset | 438 | by (simp add: merge_def map_add_map_of_foldr foldr_conv_fold fun_eq_iff) | 
| 19234 | 439 | qed | 
| 440 | ||
| 56327 | 441 | corollary merge_conv: "map_of (merge xs ys) k = (map_of xs ++ map_of ys) k" | 
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 442 | by (simp add: merge_conv') | 
| 19234 | 443 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 444 | lemma merge_empty: "map_of (merge [] ys) = map_of ys" | 
| 19234 | 445 | by (simp add: merge_conv') | 
| 446 | ||
| 56327 | 447 | lemma merge_assoc [simp]: "map_of (merge m1 (merge m2 m3)) = map_of (merge (merge m1 m2) m3)" | 
| 19234 | 448 | by (simp add: merge_conv') | 
| 449 | ||
| 56327 | 450 | lemma merge_Some_iff: | 
| 451 | "map_of (merge m n) k = Some x \<longleftrightarrow> | |
| 452 | map_of n k = Some x \<or> map_of n k = None \<and> map_of m k = Some x" | |
| 19234 | 453 | by (simp add: merge_conv' map_add_Some_iff) | 
| 454 | ||
| 45605 | 455 | lemmas merge_SomeD [dest!] = merge_Some_iff [THEN iffD1] | 
| 19234 | 456 | |
| 56327 | 457 | lemma merge_find_right [simp]: "map_of n k = Some v \<Longrightarrow> map_of (merge m n) k = Some v" | 
| 19234 | 458 | by (simp add: merge_conv') | 
| 459 | ||
| 56327 | 460 | lemma merge_None [iff]: | 
| 19234 | 461 | "(map_of (merge m n) k = None) = (map_of n k = None \<and> map_of m k = None)" | 
| 462 | by (simp add: merge_conv') | |
| 463 | ||
| 56327 | 464 | lemma merge_upd [simp]: | 
| 19234 | 465 | "map_of (merge m (update k v n)) = map_of (update k v (merge m n))" | 
| 466 | by (simp add: update_conv' merge_conv') | |
| 467 | ||
| 56327 | 468 | lemma merge_updatess [simp]: | 
| 19234 | 469 | "map_of (merge m (updates xs ys n)) = map_of (updates xs ys (merge m n))" | 
| 470 | by (simp add: updates_conv' merge_conv') | |
| 471 | ||
| 56327 | 472 | lemma merge_append: "map_of (xs @ ys) = map_of (merge ys xs)" | 
| 19234 | 473 | by (simp add: merge_conv') | 
| 474 | ||
| 23373 | 475 | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 476 | subsection {* @{text compose} *}
 | 
| 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 477 | |
| 56327 | 478 | function compose :: "('key \<times> 'a) list \<Rightarrow> ('a \<times> 'b) list \<Rightarrow> ('key \<times> 'b) list"
 | 
| 479 | where | |
| 480 | "compose [] ys = []" | |
| 481 | | "compose (x # xs) ys = | |
| 482 | (case map_of ys (snd x) of | |
| 483 | None \<Rightarrow> compose (delete (fst x) xs) ys | |
| 484 | | Some v \<Rightarrow> (fst x, v) # compose xs ys)" | |
| 34975 
f099b0b20646
more correspondence lemmas between related operations; tuned some proofs
 haftmann parents: 
32960diff
changeset | 485 | by pat_completeness auto | 
| 56327 | 486 | termination | 
| 487 | by (relation "measure (length \<circ> fst)") (simp_all add: less_Suc_eq_le length_delete_le) | |
| 19234 | 488 | |
| 56327 | 489 | lemma compose_first_None [simp]: | 
| 490 | assumes "map_of xs k = None" | |
| 19234 | 491 | shows "map_of (compose xs ys) k = None" | 
| 56327 | 492 | using assms by (induct xs ys rule: compose.induct) (auto split: option.splits split_if_asm) | 
| 19234 | 493 | |
| 56327 | 494 | lemma compose_conv: "map_of (compose xs ys) k = (map_of ys \<circ>\<^sub>m map_of xs) k" | 
| 22916 | 495 | proof (induct xs ys rule: compose.induct) | 
| 56327 | 496 | case 1 | 
| 497 | then show ?case by simp | |
| 19234 | 498 | next | 
| 56327 | 499 | case (2 x xs ys) | 
| 500 | show ?case | |
| 19234 | 501 | proof (cases "map_of ys (snd x)") | 
| 56327 | 502 | case None | 
| 503 | with 2 have hyp: "map_of (compose (delete (fst x) xs) ys) k = | |
| 504 | (map_of ys \<circ>\<^sub>m map_of (delete (fst x) xs)) k" | |
| 19234 | 505 | by simp | 
| 506 | show ?thesis | |
| 507 | proof (cases "fst x = k") | |
| 508 | case True | |
| 509 | from True delete_notin_dom [of k xs] | |
| 510 | have "map_of (delete (fst x) xs) k = None" | |
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
30663diff
changeset | 511 | by (simp add: map_of_eq_None_iff) | 
| 19234 | 512 | with hyp show ?thesis | 
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
30663diff
changeset | 513 | using True None | 
| 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
30663diff
changeset | 514 | by simp | 
| 19234 | 515 | next | 
| 516 | case False | |
| 517 | from False have "map_of (delete (fst x) xs) k = map_of xs k" | |
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
30663diff
changeset | 518 | by simp | 
| 19234 | 519 | with hyp show ?thesis | 
| 56327 | 520 | using False None by (simp add: map_comp_def) | 
| 19234 | 521 | qed | 
| 522 | next | |
| 523 | case (Some v) | |
| 22916 | 524 | with 2 | 
| 19234 | 525 | have "map_of (compose xs ys) k = (map_of ys \<circ>\<^sub>m map_of xs) k" | 
| 526 | by simp | |
| 527 | with Some show ?thesis | |
| 528 | by (auto simp add: map_comp_def) | |
| 529 | qed | |
| 530 | qed | |
| 56327 | 531 | |
| 532 | lemma compose_conv': "map_of (compose xs ys) = (map_of ys \<circ>\<^sub>m map_of xs)" | |
| 19234 | 533 | by (rule ext) (rule compose_conv) | 
| 534 | ||
| 535 | lemma compose_first_Some [simp]: | |
| 56327 | 536 | assumes "map_of xs k = Some v" | 
| 19234 | 537 | shows "map_of (compose xs ys) k = map_of ys v" | 
| 56327 | 538 | using assms by (simp add: compose_conv) | 
| 19234 | 539 | |
| 540 | lemma dom_compose: "fst ` set (compose xs ys) \<subseteq> fst ` set xs" | |
| 22916 | 541 | proof (induct xs ys rule: compose.induct) | 
| 56327 | 542 | case 1 | 
| 543 | then show ?case by simp | |
| 19234 | 544 | next | 
| 22916 | 545 | case (2 x xs ys) | 
| 19234 | 546 | show ?case | 
| 547 | proof (cases "map_of ys (snd x)") | |
| 548 | case None | |
| 22916 | 549 | with "2.hyps" | 
| 19234 | 550 | have "fst ` set (compose (delete (fst x) xs) ys) \<subseteq> fst ` set (delete (fst x) xs)" | 
| 551 | by simp | |
| 552 | also | |
| 553 | have "\<dots> \<subseteq> fst ` set xs" | |
| 554 | by (rule dom_delete_subset) | |
| 555 | finally show ?thesis | |
| 556 | using None | |
| 557 | by auto | |
| 558 | next | |
| 559 | case (Some v) | |
| 22916 | 560 | with "2.hyps" | 
| 19234 | 561 | have "fst ` set (compose xs ys) \<subseteq> fst ` set xs" | 
| 562 | by simp | |
| 563 | with Some show ?thesis | |
| 564 | by auto | |
| 565 | qed | |
| 566 | qed | |
| 567 | ||
| 568 | lemma distinct_compose: | |
| 56327 | 569 | assumes "distinct (map fst xs)" | 
| 570 | shows "distinct (map fst (compose xs ys))" | |
| 571 | using assms | |
| 22916 | 572 | proof (induct xs ys rule: compose.induct) | 
| 56327 | 573 | case 1 | 
| 574 | then show ?case by simp | |
| 19234 | 575 | next | 
| 22916 | 576 | case (2 x xs ys) | 
| 19234 | 577 | show ?case | 
| 578 | proof (cases "map_of ys (snd x)") | |
| 579 | case None | |
| 22916 | 580 | with 2 show ?thesis by simp | 
| 19234 | 581 | next | 
| 582 | case (Some v) | |
| 56327 | 583 | with 2 dom_compose [of xs ys] show ?thesis | 
| 584 | by auto | |
| 19234 | 585 | qed | 
| 586 | qed | |
| 587 | ||
| 56327 | 588 | lemma compose_delete_twist: "compose (delete k xs) ys = delete k (compose xs ys)" | 
| 22916 | 589 | proof (induct xs ys rule: compose.induct) | 
| 56327 | 590 | case 1 | 
| 591 | then show ?case by simp | |
| 19234 | 592 | next | 
| 22916 | 593 | case (2 x xs ys) | 
| 19234 | 594 | show ?case | 
| 595 | proof (cases "map_of ys (snd x)") | |
| 596 | case None | |
| 56327 | 597 | with 2 have hyp: "compose (delete k (delete (fst x) xs)) ys = | 
| 598 | delete k (compose (delete (fst x) xs) ys)" | |
| 19234 | 599 | by simp | 
| 600 | show ?thesis | |
| 601 | proof (cases "fst x = k") | |
| 602 | case True | |
| 56327 | 603 | with None hyp show ?thesis | 
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
30663diff
changeset | 604 | by (simp add: delete_idem) | 
| 19234 | 605 | next | 
| 606 | case False | |
| 56327 | 607 | from None False hyp show ?thesis | 
| 32960 
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
 wenzelm parents: 
30663diff
changeset | 608 | by (simp add: delete_twist) | 
| 19234 | 609 | qed | 
| 610 | next | |
| 611 | case (Some v) | |
| 56327 | 612 | with 2 have hyp: "compose (delete k xs) ys = delete k (compose xs ys)" | 
| 613 | by simp | |
| 19234 | 614 | with Some show ?thesis | 
| 615 | by simp | |
| 616 | qed | |
| 617 | qed | |
| 618 | ||
| 619 | lemma compose_clearjunk: "compose xs (clearjunk ys) = compose xs ys" | |
| 56327 | 620 | by (induct xs ys rule: compose.induct) | 
| 621 | (auto simp add: map_of_clearjunk split: option.splits) | |
| 622 | ||
| 19234 | 623 | lemma clearjunk_compose: "clearjunk (compose xs ys) = compose (clearjunk xs) ys" | 
| 624 | by (induct xs rule: clearjunk.induct) | |
| 56327 | 625 | (auto split: option.splits simp add: clearjunk_delete delete_idem compose_delete_twist) | 
| 626 | ||
| 627 | lemma compose_empty [simp]: "compose xs [] = []" | |
| 22916 | 628 | by (induct xs) (auto simp add: compose_delete_twist) | 
| 19234 | 629 | |
| 630 | lemma compose_Some_iff: | |
| 56327 | 631 | "(map_of (compose xs ys) k = Some v) \<longleftrightarrow> | 
| 632 | (\<exists>k'. map_of xs k = Some k' \<and> map_of ys k' = Some v)" | |
| 19234 | 633 | by (simp add: compose_conv map_comp_Some_iff) | 
| 634 | ||
| 635 | lemma map_comp_None_iff: | |
| 56327 | 636 | "map_of (compose xs ys) k = None \<longleftrightarrow> | 
| 637 | (map_of xs k = None \<or> (\<exists>k'. map_of xs k = Some k' \<and> map_of ys k' = None))" | |
| 19234 | 638 | by (simp add: compose_conv map_comp_None_iff) | 
| 639 | ||
| 56327 | 640 | |
| 45869 | 641 | subsection {* @{text map_entry} *}
 | 
| 642 | ||
| 643 | fun map_entry :: "'key \<Rightarrow> ('val \<Rightarrow> 'val) \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | |
| 644 | where | |
| 645 | "map_entry k f [] = []" | |
| 56327 | 646 | | "map_entry k f (p # ps) = | 
| 647 | (if fst p = k then (k, f (snd p)) # ps else p # map_entry k f ps)" | |
| 45869 | 648 | |
| 649 | lemma map_of_map_entry: | |
| 56327 | 650 | "map_of (map_entry k f xs) = | 
| 651 | (map_of xs)(k := case map_of xs k of None \<Rightarrow> None | Some v' \<Rightarrow> Some (f v'))" | |
| 652 | by (induct xs) auto | |
| 45869 | 653 | |
| 56327 | 654 | lemma dom_map_entry: "fst ` set (map_entry k f xs) = fst ` set xs" | 
| 655 | by (induct xs) auto | |
| 45869 | 656 | |
| 657 | lemma distinct_map_entry: | |
| 658 | assumes "distinct (map fst xs)" | |
| 659 | shows "distinct (map fst (map_entry k f xs))" | |
| 56327 | 660 | using assms by (induct xs) (auto simp add: dom_map_entry) | 
| 661 | ||
| 45869 | 662 | |
| 45868 | 663 | subsection {* @{text map_default} *}
 | 
| 664 | ||
| 665 | fun map_default :: "'key \<Rightarrow> 'val \<Rightarrow> ('val \<Rightarrow> 'val) \<Rightarrow> ('key \<times> 'val) list \<Rightarrow> ('key \<times> 'val) list"
 | |
| 666 | where | |
| 667 | "map_default k v f [] = [(k, v)]" | |
| 56327 | 668 | | "map_default k v f (p # ps) = | 
| 669 | (if fst p = k then (k, f (snd p)) # ps else p # map_default k v f ps)" | |
| 45868 | 670 | |
| 671 | lemma map_of_map_default: | |
| 56327 | 672 | "map_of (map_default k v f xs) = | 
| 673 | (map_of xs)(k := case map_of xs k of None \<Rightarrow> Some v | Some v' \<Rightarrow> Some (f v'))" | |
| 674 | by (induct xs) auto | |
| 45868 | 675 | |
| 56327 | 676 | lemma dom_map_default: "fst ` set (map_default k v f xs) = insert k (fst ` set xs)" | 
| 677 | by (induct xs) auto | |
| 45868 | 678 | |
| 679 | lemma distinct_map_default: | |
| 680 | assumes "distinct (map fst xs)" | |
| 681 | shows "distinct (map fst (map_default k v f xs))" | |
| 56327 | 682 | using assms by (induct xs) (auto simp add: dom_map_default) | 
| 45868 | 683 | |
| 46171 
19f68d7671f0
proper hiding of facts and constants in AList_Impl and AList theory
 bulwahn parents: 
46133diff
changeset | 684 | hide_const (open) update updates delete restrict clearjunk merge compose map_entry | 
| 45884 | 685 | |
| 19234 | 686 | end |