src/HOL/Library/RBT.thy
changeset 35602 e814157560e8
parent 35550 e2bc7f8d8d51
child 35603 c0db094d0d80
equal deleted inserted replaced
35565:56b070cd7ab3 35602:e814157560e8
     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"
   141 lemma lookup_tree_less[simp]: "t |\<guillemotleft> k \<Longrightarrow> lookup t k = None" 
   158 lemma lookup_tree_less[simp]: "t |\<guillemotleft> k \<Longrightarrow> lookup t k = None" 
   142 by (induct t) auto
   159 by (induct t) auto
   143 
   160 
   144 lemma lookup_tree_greater[simp]: "k \<guillemotleft>| t \<Longrightarrow> lookup t k = None"
   161 lemma lookup_tree_greater[simp]: "k \<guillemotleft>| t \<Longrightarrow> lookup t k = None"
   145 by (induct t) auto
   162 by (induct t) auto
   146 
       
   147 lemma lookup_in_tree: "sorted t \<Longrightarrow> (lookup t k = Some v) = entry_in_tree k v t"
       
   148 by (induct t) (auto simp: tree_less_prop tree_greater_prop entry_in_tree_keys)
       
   149 
   163 
   150 lemma lookup_Empty: "lookup Empty = empty"
   164 lemma lookup_Empty: "lookup Empty = empty"
   151 by (rule ext) simp
   165 by (rule ext) simp
   152 
   166 
   153 lemma lookup_map_of_entries:
   167 lemma lookup_map_of_entries:
   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)"