src/HOL/Library/RBT.thy
changeset 63194 0b7bdb75f451
parent 61260 e6f03fae14d5
child 63219 a5697f7a3322
equal deleted inserted replaced
63190:3e79279c10ca 63194:0b7bdb75f451
    65 lift_definition union :: "('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt" is "rbt_union"
    65 lift_definition union :: "('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt" is "rbt_union"
    66 by (simp add: rbt_union_is_rbt)
    66 by (simp add: rbt_union_is_rbt)
    67 
    67 
    68 lift_definition foldi :: "('c \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'b \<Rightarrow> 'c \<Rightarrow> 'c) \<Rightarrow> ('a :: linorder, 'b) rbt \<Rightarrow> 'c \<Rightarrow> 'c"
    68 lift_definition foldi :: "('c \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'b \<Rightarrow> 'c \<Rightarrow> 'c) \<Rightarrow> ('a :: linorder, 'b) rbt \<Rightarrow> 'c \<Rightarrow> 'c"
    69   is RBT_Impl.foldi .
    69   is RBT_Impl.foldi .
       
    70   
       
    71 lift_definition combine_with_key :: "('a \<Rightarrow> 'b \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt"
       
    72   is RBT_Impl.rbt_union_with_key by (rule is_rbt_rbt_unionwk)
       
    73 
       
    74 lift_definition combine :: "('b \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt \<Rightarrow> ('a, 'b) rbt"
       
    75   is RBT_Impl.rbt_union_with by (rule rbt_unionw_is_rbt)
    70 
    76 
    71 subsection \<open>Derived operations\<close>
    77 subsection \<open>Derived operations\<close>
    72 
    78 
    73 definition is_empty :: "('a::linorder, 'b) rbt \<Rightarrow> bool" where
    79 definition is_empty :: "('a::linorder, 'b) rbt \<Rightarrow> bool" where
    74   [code]: "is_empty t = (case impl_of t of RBT_Impl.Empty \<Rightarrow> True | _ \<Rightarrow> False)"
    80   [code]: "is_empty t = (case impl_of t of RBT_Impl.Empty \<Rightarrow> True | _ \<Rightarrow> False)"
    75 
    81 
       
    82 (* TODO: Is deleting more efficient than re-building the tree? 
       
    83    (Probably more difficult to prove though *)
       
    84 definition filter :: "('a \<Rightarrow> 'b \<Rightarrow> bool) \<Rightarrow> ('a::linorder, 'b) rbt \<Rightarrow> ('a, 'b) rbt" where
       
    85   [code]: "filter P t = fold (\<lambda>k v t. if P k v then insert k v t else t) t empty" 
    76 
    86 
    77 subsection \<open>Abstract lookup properties\<close>
    87 subsection \<open>Abstract lookup properties\<close>
    78 
    88 
    79 lemma lookup_RBT:
    89 lemma lookup_RBT:
    80   "is_rbt t \<Longrightarrow> lookup (RBT t) = rbt_lookup t"
    90   "is_rbt t \<Longrightarrow> lookup (RBT t) = rbt_lookup t"
   126 
   136 
   127 lemma lookup_map [simp]:
   137 lemma lookup_map [simp]:
   128   "lookup (map f t) k = map_option (f k) (lookup t k)"
   138   "lookup (map f t) k = map_option (f k) (lookup t k)"
   129   by transfer (rule rbt_lookup_map)
   139   by transfer (rule rbt_lookup_map)
   130 
   140 
       
   141 lemma lookup_combine_with_key [simp]:
       
   142   "lookup (combine_with_key f t1 t2) k = combine_options (f k) (lookup t1 k) (lookup t2 k)"
       
   143   by transfer (simp_all add: combine_options_def rbt_lookup_rbt_unionwk)
       
   144 
       
   145 lemma combine_altdef: "combine f t1 t2 = combine_with_key (\<lambda>_. f) t1 t2"
       
   146   by transfer (simp add: rbt_union_with_def)
       
   147 
       
   148 lemma lookup_combine [simp]:
       
   149   "lookup (combine f t1 t2) k = combine_options f (lookup t1 k) (lookup t2 k)"
       
   150   by (simp add: combine_altdef)
       
   151 
   131 lemma fold_fold:
   152 lemma fold_fold:
   132   "fold f t = List.fold (case_prod f) (entries t)"
   153   "fold f t = List.fold (case_prod f) (entries t)"
   133   by transfer (rule RBT_Impl.fold_def)
   154   by transfer (rule RBT_Impl.fold_def)
   134 
   155 
   135 lemma impl_of_empty:
   156 lemma impl_of_empty:
   179   by transfer (simp add: non_empty_rbt_keys)
   200   by transfer (simp add: non_empty_rbt_keys)
   180 
   201 
   181 lemma keys_def_alt:
   202 lemma keys_def_alt:
   182   "keys t = List.map fst (entries t)"
   203   "keys t = List.map fst (entries t)"
   183   by transfer (simp add: RBT_Impl.keys_def)
   204   by transfer (simp add: RBT_Impl.keys_def)
       
   205 
       
   206 context
       
   207 begin
       
   208 
       
   209 private lemma lookup_filter_aux:
       
   210   assumes "distinct (List.map fst xs)"
       
   211   shows   "lookup (List.fold (\<lambda>(k, v) t. if P k v then insert k v t else t) xs t) k =
       
   212              (case map_of xs k of 
       
   213                 None \<Rightarrow> lookup t k
       
   214               | Some v \<Rightarrow> if P k v then Some v else lookup t k)"
       
   215   using assms by (induction xs arbitrary: t) (force split: option.splits)+
       
   216 
       
   217 lemma lookup_filter: 
       
   218   "lookup (filter P t) k = 
       
   219      (case lookup t k of None \<Rightarrow> None | Some v \<Rightarrow> if P k v then Some v else None)"
       
   220   unfolding filter_def using lookup_filter_aux[of "entries t" P empty k]
       
   221   by (simp add: fold_fold distinct_entries split: option.splits)
       
   222   
       
   223 end
       
   224 
   184 
   225 
   185 subsection \<open>Quickcheck generators\<close>
   226 subsection \<open>Quickcheck generators\<close>
   186 
   227 
   187 quickcheck_generator rbt predicate: is_rbt constructors: empty, insert
   228 quickcheck_generator rbt predicate: is_rbt constructors: empty, insert
   188 
   229