src/HOL/Library/Mapping.thy
author haftmann
Mon, 24 May 2010 13:48:57 +0200
changeset 37091 1535aa1c943a
parent 37036 80dd92673fca
child 37299 6315d1bd8388
permissions -rw-r--r--
more lemmas
     1 (* Author: Florian Haftmann, TU Muenchen *)
     2 
     3 header {* An abstract view on maps for code generation. *}
     4 
     5 theory Mapping
     6 imports Main
     7 begin
     8 
     9 subsection {* Type definition and primitive operations *}
    10 
    11 datatype ('a, 'b) mapping = Mapping "'a \<rightharpoonup> 'b"
    12 
    13 definition empty :: "('a, 'b) mapping" where
    14   "empty = Mapping (\<lambda>_. None)"
    15 
    16 primrec lookup :: "('a, 'b) mapping \<Rightarrow> 'a \<rightharpoonup> 'b" where
    17   "lookup (Mapping f) = f"
    18 
    19 primrec update :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" where
    20   "update k v (Mapping f) = Mapping (f (k \<mapsto> v))"
    21 
    22 primrec delete :: "'a \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" where
    23   "delete k (Mapping f) = Mapping (f (k := None))"
    24 
    25 
    26 subsection {* Derived operations *}
    27 
    28 definition keys :: "('a, 'b) mapping \<Rightarrow> 'a set" where
    29   "keys m = dom (lookup m)"
    30 
    31 definition ordered_keys :: "('a\<Colon>linorder, 'b) mapping \<Rightarrow> 'a list" where
    32   "ordered_keys m = (if finite (keys m) then sorted_list_of_set (keys m) else [])"
    33 
    34 definition is_empty :: "('a, 'b) mapping \<Rightarrow> bool" where
    35   "is_empty m \<longleftrightarrow> keys m = {}"
    36 
    37 definition size :: "('a, 'b) mapping \<Rightarrow> nat" where
    38   "size m = (if finite (keys m) then card (keys m) else 0)"
    39 
    40 definition replace :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" where
    41   "replace k v m = (if k \<in> keys m then update k v m else m)"
    42 
    43 definition default :: "'a \<Rightarrow> 'b \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" where
    44   "default k v m = (if k \<in> keys m then m else update k v m)"
    45 
    46 definition map_entry :: "'a \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" where
    47   "map_entry k f m = (case lookup m k of None \<Rightarrow> m
    48     | Some v \<Rightarrow> update k (f v) m)" 
    49 
    50 definition map_default :: "'a \<Rightarrow> 'b \<Rightarrow> ('b \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping \<Rightarrow> ('a, 'b) mapping" where
    51   "map_default k v f m = map_entry k f (default k v m)" 
    52 
    53 definition tabulate :: "'a list \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a, 'b) mapping" where
    54   "tabulate ks f = Mapping (map_of (map (\<lambda>k. (k, f k)) ks))"
    55 
    56 definition bulkload :: "'a list \<Rightarrow> (nat, 'a) mapping" where
    57   "bulkload xs = Mapping (\<lambda>k. if k < length xs then Some (xs ! k) else None)"
    58 
    59 
    60 subsection {* Properties *}
    61 
    62 lemma lookup_inject [simp]:
    63   "lookup m = lookup n \<longleftrightarrow> m = n"
    64   by (cases m, cases n) simp
    65 
    66 lemma mapping_eqI:
    67   assumes "lookup m = lookup n"
    68   shows "m = n"
    69   using assms by simp
    70 
    71 lemma keys_is_none_lookup [code_inline]:
    72   "k \<in> keys m \<longleftrightarrow> \<not> (Option.is_none (lookup m k))"
    73   by (auto simp add: keys_def is_none_def)
    74 
    75 lemma lookup_empty [simp]:
    76   "lookup empty = Map.empty"
    77   by (simp add: empty_def)
    78 
    79 lemma lookup_update [simp]:
    80   "lookup (update k v m) = (lookup m) (k \<mapsto> v)"
    81   by (cases m) simp
    82 
    83 lemma lookup_delete [simp]:
    84   "lookup (delete k m) = (lookup m) (k := None)"
    85   by (cases m) simp
    86 
    87 lemma lookup_map_entry [simp]:
    88   "lookup (map_entry k f m) = (lookup m) (k := Option.map f (lookup m k))"
    89   by (cases "lookup m k") (simp_all add: map_entry_def expand_fun_eq)
    90 
    91 lemma lookup_tabulate [simp]:
    92   "lookup (tabulate ks f) = (Some o f) |` set ks"
    93   by (induct ks) (auto simp add: tabulate_def restrict_map_def expand_fun_eq)
    94 
    95 lemma lookup_bulkload [simp]:
    96   "lookup (bulkload xs) = (\<lambda>k. if k < length xs then Some (xs ! k) else None)"
    97   by (simp add: bulkload_def)
    98 
    99 lemma update_update:
   100   "update k v (update k w m) = update k v m"
   101   "k \<noteq> l \<Longrightarrow> update k v (update l w m) = update l w (update k v m)"
   102   by (rule mapping_eqI, simp add: fun_upd_twist)+
   103 
   104 lemma update_delete [simp]:
   105   "update k v (delete k m) = update k v m"
   106   by (rule mapping_eqI) simp
   107 
   108 lemma delete_update:
   109   "delete k (update k v m) = delete k m"
   110   "k \<noteq> l \<Longrightarrow> delete k (update l v m) = update l v (delete k m)"
   111   by (rule mapping_eqI, simp add: fun_upd_twist)+
   112 
   113 lemma delete_empty [simp]:
   114   "delete k empty = empty"
   115   by (rule mapping_eqI) simp
   116 
   117 lemma replace_update:
   118   "k \<notin> keys m \<Longrightarrow> replace k v m = m"
   119   "k \<in> keys m \<Longrightarrow> replace k v m = update k v m"
   120   by (rule mapping_eqI) (auto simp add: replace_def fun_upd_twist)+
   121 
   122 lemma size_empty [simp]:
   123   "size empty = 0"
   124   by (simp add: size_def keys_def)
   125 
   126 lemma size_update:
   127   "finite (keys m) \<Longrightarrow> size (update k v m) =
   128     (if k \<in> keys m then size m else Suc (size m))"
   129   by (auto simp add: size_def insert_dom keys_def)
   130 
   131 lemma size_delete:
   132   "size (delete k m) = (if k \<in> keys m then size m - 1 else size m)"
   133   by (simp add: size_def keys_def)
   134 
   135 lemma size_tabulate [simp]:
   136   "size (tabulate ks f) = length (remdups ks)"
   137   by (simp add: size_def distinct_card [of "remdups ks", symmetric] comp_def keys_def)
   138 
   139 lemma bulkload_tabulate:
   140   "bulkload xs = tabulate [0..<length xs] (nth xs)"
   141   by (rule mapping_eqI) (simp add: expand_fun_eq)
   142 
   143 lemma is_empty_empty: (*FIXME*)
   144   "is_empty m \<longleftrightarrow> m = Mapping Map.empty"
   145   by (cases m) (simp add: is_empty_def keys_def)
   146 
   147 lemma is_empty_empty' [simp]:
   148   "is_empty empty"
   149   by (simp add: is_empty_empty empty_def) 
   150 
   151 lemma is_empty_update [simp]:
   152   "\<not> is_empty (update k v m)"
   153   by (cases m) (simp add: is_empty_empty)
   154 
   155 lemma is_empty_delete:
   156   "is_empty (delete k m) \<longleftrightarrow> is_empty m \<or> keys m = {k}"
   157   by (cases m) (auto simp add: is_empty_empty keys_def dom_eq_empty_conv [symmetric] simp del: dom_eq_empty_conv)
   158 
   159 lemma is_empty_replace [simp]:
   160   "is_empty (replace k v m) \<longleftrightarrow> is_empty m"
   161   by (auto simp add: replace_def) (simp add: is_empty_def)
   162 
   163 lemma is_empty_default [simp]:
   164   "\<not> is_empty (default k v m)"
   165   by (auto simp add: default_def) (simp add: is_empty_def)
   166 
   167 lemma is_empty_map_entry [simp]:
   168   "is_empty (map_entry k f m) \<longleftrightarrow> is_empty m"
   169   by (cases "lookup m k")
   170     (auto simp add: map_entry_def, simp add: is_empty_empty)
   171 
   172 lemma is_empty_map_default [simp]:
   173   "\<not> is_empty (map_default k v f m)"
   174   by (simp add: map_default_def)
   175 
   176 lemma keys_empty [simp]:
   177   "keys empty = {}"
   178   by (simp add: keys_def)
   179 
   180 lemma keys_update [simp]:
   181   "keys (update k v m) = insert k (keys m)"
   182   by (simp add: keys_def)
   183 
   184 lemma keys_delete [simp]:
   185   "keys (delete k m) = keys m - {k}"
   186   by (simp add: keys_def)
   187 
   188 lemma keys_replace [simp]:
   189   "keys (replace k v m) = keys m"
   190   by (auto simp add: keys_def replace_def)
   191 
   192 lemma keys_default [simp]:
   193   "keys (default k v m) = insert k (keys m)"
   194   by (auto simp add: keys_def default_def)
   195 
   196 lemma keys_map_entry [simp]:
   197   "keys (map_entry k f m) = keys m"
   198   by (auto simp add: keys_def)
   199 
   200 lemma keys_map_default [simp]:
   201   "keys (map_default k v f m) = insert k (keys m)"
   202   by (simp add: map_default_def)
   203 
   204 lemma keys_tabulate [simp]:
   205   "keys (tabulate ks f) = set ks"
   206   by (simp add: tabulate_def keys_def map_of_map_restrict o_def)
   207 
   208 lemma keys_bulkload [simp]:
   209   "keys (bulkload xs) = {0..<length xs}"
   210   by (simp add: keys_tabulate bulkload_tabulate)
   211 
   212 lemma distinct_ordered_keys [simp]:
   213   "distinct (ordered_keys m)"
   214   by (simp add: ordered_keys_def)
   215 
   216 lemma ordered_keys_infinite [simp]:
   217   "\<not> finite (keys m) \<Longrightarrow> ordered_keys m = []"
   218   by (simp add: ordered_keys_def)
   219 
   220 lemma ordered_keys_empty [simp]:
   221   "ordered_keys empty = []"
   222   by (simp add: ordered_keys_def)
   223 
   224 lemma ordered_keys_update [simp]:
   225   "k \<in> keys m \<Longrightarrow> ordered_keys (update k v m) = ordered_keys m"
   226   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (update k v m) = insort k (ordered_keys m)"
   227   by (simp_all add: ordered_keys_def) (auto simp only: sorted_list_of_set_insert [symmetric] insert_absorb)
   228 
   229 lemma ordered_keys_delete [simp]:
   230   "ordered_keys (delete k m) = remove1 k (ordered_keys m)"
   231 proof (cases "finite (keys m)")
   232   case False then show ?thesis by simp
   233 next
   234   case True note fin = True
   235   show ?thesis
   236   proof (cases "k \<in> keys m")
   237     case False with fin have "k \<notin> set (sorted_list_of_set (keys m))" by simp
   238     with False show ?thesis by (simp add: ordered_keys_def remove1_idem)
   239   next
   240     case True with fin show ?thesis by (simp add: ordered_keys_def sorted_list_of_set_remove)
   241   qed
   242 qed
   243 
   244 lemma ordered_keys_replace [simp]:
   245   "ordered_keys (replace k v m) = ordered_keys m"
   246   by (simp add: replace_def)
   247 
   248 lemma ordered_keys_default [simp]:
   249   "k \<in> keys m \<Longrightarrow> ordered_keys (default k v m) = ordered_keys m"
   250   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (default k v m) = insort k (ordered_keys m)"
   251   by (simp_all add: default_def)
   252 
   253 lemma ordered_keys_map_entry [simp]:
   254   "ordered_keys (map_entry k f m) = ordered_keys m"
   255   by (simp add: ordered_keys_def)
   256 
   257 lemma ordered_keys_map_default [simp]:
   258   "k \<in> keys m \<Longrightarrow> ordered_keys (map_default k v f m) = ordered_keys m"
   259   "finite (keys m) \<Longrightarrow> k \<notin> keys m \<Longrightarrow> ordered_keys (map_default k v f m) = insort k (ordered_keys m)"
   260   by (simp_all add: map_default_def)
   261 
   262 lemma ordered_keys_tabulate [simp]:
   263   "ordered_keys (tabulate ks f) = sort (remdups ks)"
   264   by (simp add: ordered_keys_def sorted_list_of_set_sort_remdups)
   265 
   266 lemma ordered_keys_bulkload [simp]:
   267   "ordered_keys (bulkload ks) = [0..<length ks]"
   268   by (simp add: ordered_keys_def)
   269 
   270 
   271 subsection {* Some technical code lemmas *}
   272 
   273 lemma [code]:
   274   "mapping_case f m = f (Mapping.lookup m)"
   275   by (cases m) simp
   276 
   277 lemma [code]:
   278   "mapping_rec f m = f (Mapping.lookup m)"
   279   by (cases m) simp
   280 
   281 lemma [code]:
   282   "Nat.size (m :: (_, _) mapping) = 0"
   283   by (cases m) simp
   284 
   285 lemma [code]:
   286   "mapping_size f g m = 0"
   287   by (cases m) simp
   288 
   289 
   290 hide_const (open) empty is_empty lookup update delete ordered_keys keys size replace tabulate bulkload
   291 
   292 end