5 |
5 |
6 header {* Red-Black Trees *} |
6 header {* Red-Black Trees *} |
7 |
7 |
8 (*<*) |
8 (*<*) |
9 theory RBT |
9 theory RBT |
10 imports Main AssocList |
10 imports Main |
11 begin |
11 begin |
|
12 |
|
13 lemma map_sorted_distinct_set_unique: (*FIXME move*) |
|
14 assumes "inj_on f (set xs \<union> set ys)" |
|
15 assumes "sorted (map f xs)" "distinct (map f xs)" |
|
16 "sorted (map f ys)" "distinct (map f ys)" |
|
17 assumes "set xs = set ys" |
|
18 shows "xs = ys" |
|
19 proof - |
|
20 from assms have "map f xs = map f ys" |
|
21 by (simp add: sorted_distinct_set_unique) |
|
22 moreover with `inj_on f (set xs \<union> set ys)` show "xs = ys" |
|
23 by (blast intro: map_inj_on) |
|
24 qed |
12 |
25 |
13 subsection {* Datatype of RB trees *} |
26 subsection {* Datatype of RB trees *} |
14 |
27 |
15 datatype color = R | B |
28 datatype color = R | B |
16 datatype ('a, 'b) rbt = Empty | Branch color "('a, 'b) rbt" 'a 'b "('a, 'b) rbt" |
29 datatype ('a, 'b) rbt = Empty | Branch color "('a, 'b) rbt" 'a 'b "('a, 'b) rbt" |
51 shows "k \<in> set (keys t)" |
64 shows "k \<in> set (keys t)" |
52 proof - |
65 proof - |
53 from assms have "fst (k, v) \<in> fst ` set (entries t)" by (rule imageI) |
66 from assms have "fst (k, v) \<in> fst ` set (entries t)" by (rule imageI) |
54 then show ?thesis by (simp add: keys_def) |
67 then show ?thesis by (simp add: keys_def) |
55 qed |
68 qed |
|
69 |
|
70 lemma keys_entries: |
|
71 "k \<in> set (keys t) \<longleftrightarrow> (\<exists>v. (k, v) \<in> set (entries t))" |
|
72 by (auto intro: entry_in_tree_keys) (auto simp add: keys_def) |
56 |
73 |
57 |
74 |
58 subsubsection {* Search tree properties *} |
75 subsubsection {* Search tree properties *} |
59 |
76 |
60 definition tree_less :: "'a\<Colon>order \<Rightarrow> ('a, 'b) rbt \<Rightarrow> bool" |
77 definition tree_less :: "'a\<Colon>order \<Rightarrow> ('a, 'b) rbt \<Rightarrow> bool" |
213 qed |
227 qed |
214 also from Branch have "lookup t2 ++ [k \<mapsto> v] ++ lookup t1 = map_of (entries (Branch c t1 k v t2))" by simp |
228 also from Branch have "lookup t2 ++ [k \<mapsto> v] ++ lookup t1 = map_of (entries (Branch c t1 k v t2))" by simp |
215 finally show ?case . |
229 finally show ?case . |
216 qed |
230 qed |
217 |
231 |
218 (*lemma map_of_inject: |
232 lemma lookup_in_tree: "sorted t \<Longrightarrow> lookup t k = Some v \<longleftrightarrow> (k, v) \<in> set (entries t)" |
219 assumes distinct: "distinct (map fst xs)" "distinct (map fst ys)" |
233 by (simp_all add: lookup_map_of_entries distinct_entries) |
220 shows "map_of xs = map_of ys \<longleftrightarrow> set xs = set ys" |
234 |
|
235 lemma set_entries_inject: |
|
236 assumes sorted: "sorted t1" "sorted t2" |
|
237 shows "set (entries t1) = set (entries t2) \<longleftrightarrow> entries t1 = entries t2" |
|
238 proof - |
|
239 from sorted have "distinct (map fst (entries t1))" |
|
240 "distinct (map fst (entries t2))" |
|
241 by (auto intro: distinct_entries) |
|
242 with sorted show ?thesis |
|
243 by (auto intro: map_sorted_distinct_set_unique sorted_entries simp add: distinct_map) |
|
244 qed |
221 |
245 |
222 lemma entries_eqI: |
246 lemma entries_eqI: |
223 assumes sorted: "sorted t1" "sorted t2" |
247 assumes sorted: "sorted t1" "sorted t2" |
224 assumes lookup: "lookup t1 = lookup t2" |
248 assumes lookup: "lookup t1 = lookup t2" |
225 shows entries: "entries t1 = entries t2" |
249 shows "entries t1 = entries t2" |
226 proof - |
250 proof - |
227 from sorted lookup have "map_of (entries t1) = map_of (entries t2)" |
251 from sorted lookup have "map_of (entries t1) = map_of (entries t2)" |
228 by (simp_all add: lookup_map_of_entries) |
252 by (simp add: lookup_map_of_entries) |
229 qed*) |
253 with sorted have "set (entries t1) = set (entries t2)" |
230 |
254 by (simp add: map_of_inject_set distinct_entries) |
231 (* a kind of extensionality *) |
255 with sorted show ?thesis by (simp add: set_entries_inject) |
|
256 qed |
|
257 |
|
258 lemma entries_lookup: |
|
259 assumes "sorted t1" "sorted t2" |
|
260 shows "entries t1 = entries t2 \<longleftrightarrow> lookup t1 = lookup t2" |
|
261 using assms by (auto intro: entries_eqI simp add: lookup_map_of_entries) |
|
262 |
232 lemma lookup_from_in_tree: |
263 lemma lookup_from_in_tree: |
233 assumes sorted: "sorted t1" "sorted t2" |
264 assumes "sorted t1" "sorted t2" |
234 and eq: "\<And>v. entry_in_tree (k\<Colon>'a\<Colon>linorder) v t1 = entry_in_tree k v t2" |
265 and "\<And>v. (k\<Colon>'a\<Colon>linorder, v) \<in> set (entries t1) \<longleftrightarrow> (k, v) \<in> set (entries t2)" |
235 shows "lookup t1 k = lookup t2 k" |
266 shows "lookup t1 k = lookup t2 k" |
236 proof (cases "lookup t1 k") |
267 proof - |
237 case None |
268 from assms have "k \<in> dom (lookup t1) \<longleftrightarrow> k \<in> dom (lookup t2)" |
238 then have "\<And>v. \<not> entry_in_tree k v t1" |
269 by (simp add: keys_entries lookup_keys) |
239 by (simp add: lookup_in_tree[symmetric] sorted) |
270 with assms show ?thesis by (auto simp add: lookup_in_tree [symmetric]) |
240 with None show ?thesis |
|
241 by (cases "lookup t2 k") (auto simp: lookup_in_tree sorted eq) |
|
242 next |
|
243 case (Some a) |
|
244 then show ?thesis |
|
245 apply (cases "lookup t2 k") |
|
246 apply (auto simp: lookup_in_tree sorted eq) |
|
247 by (auto simp add: lookup_in_tree[symmetric] sorted Some) |
|
248 qed |
271 qed |
249 |
272 |
250 |
273 |
251 subsubsection {* Red-black properties *} |
274 subsubsection {* Red-black properties *} |
252 |
275 |
982 |
1005 |
983 |
1006 |
984 subsection {* Modifying existing entries *} |
1007 subsection {* Modifying existing entries *} |
985 |
1008 |
986 primrec |
1009 primrec |
987 map_entry :: "('a \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a\<Colon>linorder) \<Rightarrow> ('a,'b) rbt \<Rightarrow> ('a,'b) rbt" |
1010 map_entry :: "'a\<Colon>linorder \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt" |
988 where |
1011 where |
989 "map_entry f k Empty = Empty" |
1012 "map_entry k f Empty = Empty" |
990 | "map_entry f k (Branch c lt x v rt) = (if k < x then (Branch c (map_entry f k lt) x v rt) else if k > x then (Branch c lt x v (map_entry f k rt)) else (Branch c lt x (f x v) rt))" |
1013 | "map_entry k f (Branch c lt x v rt) = |
991 |
1014 (if k < x then Branch c (map_entry k f lt) x v rt |
992 lemma map_entrywk_color_of: "color_of (map_entry f k t) = color_of t" by (induct t) simp+ |
1015 else if k > x then (Branch c lt x v (map_entry k f rt)) |
993 lemma map_entrywk_inv1: "inv1 (map_entry f k t) = inv1 t" by (induct t) (simp add: map_entrywk_color_of)+ |
1016 else Branch c lt x (f v) rt)" |
994 lemma map_entrywk_inv2: "inv2 (map_entry f k t) = inv2 t" "bheight (map_entry f k t) = bheight t" by (induct t) simp+ |
1017 |
995 lemma map_entrywk_tree_greater: "tree_greater k (map_entry f kk t) = tree_greater k t" by (induct t) simp+ |
1018 lemma map_entry_color_of: "color_of (map_entry k f t) = color_of t" by (induct t) simp+ |
996 lemma map_entrywk_tree_less: "tree_less k (map_entry f kk t) = tree_less k t" by (induct t) simp+ |
1019 lemma map_entry_inv1: "inv1 (map_entry k f t) = inv1 t" by (induct t) (simp add: map_entry_color_of)+ |
997 lemma map_entrywk_sorted: "sorted (map_entry f k t) = sorted t" by (induct t) (simp add: map_entrywk_tree_less map_entrywk_tree_greater)+ |
1020 lemma map_entry_inv2: "inv2 (map_entry k f t) = inv2 t" "bheight (map_entry k f t) = bheight t" by (induct t) simp+ |
998 |
1021 lemma map_entry_tree_greater: "tree_greater a (map_entry k f t) = tree_greater a t" by (induct t) simp+ |
999 theorem map_entrywk_is_rbt [simp]: "is_rbt (map_entry f k t) = is_rbt t" |
1022 lemma map_entry_tree_less: "tree_less a (map_entry k f t) = tree_less a t" by (induct t) simp+ |
1000 unfolding is_rbt_def by (simp add: map_entrywk_inv2 map_entrywk_color_of map_entrywk_sorted map_entrywk_inv1 ) |
1023 lemma map_entry_sorted: "sorted (map_entry k f t) = sorted t" |
|
1024 by (induct t) (simp_all add: map_entry_tree_less map_entry_tree_greater) |
|
1025 |
|
1026 theorem map_entry_is_rbt [simp]: "is_rbt (map_entry k f t) = is_rbt t" |
|
1027 unfolding is_rbt_def by (simp add: map_entry_inv2 map_entry_color_of map_entry_sorted map_entry_inv1 ) |
1001 |
1028 |
1002 theorem map_entry_map [simp]: |
1029 theorem map_entry_map [simp]: |
1003 "lookup (map_entry f k t) x = |
1030 "lookup (map_entry k f t) x = |
1004 (if x = k then case lookup t x of None \<Rightarrow> None | Some y \<Rightarrow> Some (f k y) |
1031 (if x = k then case lookup t x of None \<Rightarrow> None | Some y \<Rightarrow> Some (f y) |
1005 else lookup t x)" |
1032 else lookup t x)" |
1006 by (induct t arbitrary: x) (auto split:option.splits) |
1033 by (induct t arbitrary: x) (auto split:option.splits) |
1007 |
1034 |
1008 |
1035 |
1009 subsection {* Mapping all entries *} |
1036 subsection {* Mapping all entries *} |
1010 |
1037 |
1011 primrec |
1038 primrec |
1012 map :: "('a::linorder \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> ('a,'b) rbt \<Rightarrow> ('a,'c) rbt" |
1039 map :: "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'c) rbt" |
1013 where |
1040 where |
1014 "map f Empty = Empty" |
1041 "map f Empty = Empty" |
1015 | "map f (Branch c lt k v rt) = Branch c (map f lt) k (f k v) (map f rt)" |
1042 | "map f (Branch c lt k v rt) = Branch c (map f lt) k (f k v) (map f rt)" |
1016 |
1043 |
1017 lemma map_entries [simp]: "entries (map f t) = List.map (\<lambda>(k, v). (k, f k v)) (entries t)" |
1044 lemma map_entries [simp]: "entries (map f t) = List.map (\<lambda>(k, v). (k, f k v)) (entries t)" |