src/HOL/Library/Tree.thy
author haftmann
Fri, 10 Jul 2009 07:59:27 +0200
changeset 31986 a68f88d264f7
parent 31459 ae39b7b2a68a
child 35158 63d0ed5a027c
permissions -rw-r--r--
dropped find_index_eq
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
31459
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     1
(* Author: Florian Haftmann, TU Muenchen *)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     2
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     3
header {* Trees implementing mappings. *}
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     4
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     5
theory Tree
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     6
imports Mapping
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     7
begin
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     8
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
     9
subsection {* Type definition and operations *}
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    10
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    11
datatype ('a, 'b) tree = Empty
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    12
  | Branch 'b 'a "('a, 'b) tree" "('a, 'b) tree"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    13
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    14
primrec lookup :: "('a\<Colon>linorder, 'b) tree \<Rightarrow> 'a \<rightharpoonup> 'b" where
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    15
  "lookup Empty = (\<lambda>_. None)"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    16
  | "lookup (Branch v k l r) = (\<lambda>k'. if k' = k then Some v
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    17
       else if k' \<le> k then lookup l k' else lookup r k')"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    18
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    19
primrec update :: "'a\<Colon>linorder \<Rightarrow> 'b \<Rightarrow> ('a, 'b) tree \<Rightarrow> ('a, 'b) tree" where
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    20
  "update k v Empty = Branch v k Empty Empty"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    21
  | "update k' v' (Branch v k l r) = (if k' = k then
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    22
      Branch v' k l r else if k' \<le> k
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    23
      then Branch v k (update k' v' l) r
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    24
      else Branch v k l (update k' v' r))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    25
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    26
primrec keys :: "('a\<Colon>linorder, 'b) tree \<Rightarrow> 'a list" where
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    27
  "keys Empty = []"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    28
  | "keys (Branch _ k l r) = k # keys l @ keys r"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    29
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    30
definition size :: "('a\<Colon>linorder, 'b) tree \<Rightarrow> nat" where
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    31
  "size t = length (filter (\<lambda>x. x \<noteq> None) (map (lookup t) (remdups (keys t))))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    32
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    33
fun bulkload :: "'a list \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> ('a\<Colon>linorder, 'b) tree" where
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    34
  [simp del]: "bulkload ks f = (case ks of [] \<Rightarrow> Empty | _ \<Rightarrow> let
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    35
     mid = length ks div 2;
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    36
     ys = take mid ks;
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    37
     x = ks ! mid;
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    38
     zs = drop (Suc mid) ks
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    39
   in Branch (f x) x (bulkload ys f) (bulkload zs f))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    40
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    41
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    42
subsection {* Properties *}
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    43
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    44
lemma dom_lookup:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    45
  "dom (Tree.lookup t) = set (filter (\<lambda>k. lookup t k \<noteq> None) (remdups (keys t)))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    46
proof -
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    47
  have "dom (Tree.lookup t) = set (filter (\<lambda>k. lookup t k \<noteq> None) (keys t))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    48
  by (induct t) (auto simp add: dom_if)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    49
  also have "\<dots> = set (filter (\<lambda>k. lookup t k \<noteq> None) (remdups (keys t)))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    50
    by simp
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    51
  finally show ?thesis .
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    52
qed
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    53
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    54
lemma lookup_finite:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    55
  "finite (dom (lookup t))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    56
  unfolding dom_lookup by simp
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    57
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    58
lemma lookup_update:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    59
  "lookup (update k v t) = (lookup t)(k \<mapsto> v)"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    60
  by (induct t) (simp_all add: expand_fun_eq)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    61
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    62
lemma lookup_bulkload:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    63
  "sorted ks \<Longrightarrow> lookup (bulkload ks f) = (Some o f) |` set ks"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    64
proof (induct ks f rule: bulkload.induct)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    65
  case (1 ks f) show ?case proof (cases ks)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    66
    case Nil then show ?thesis by (simp add: bulkload.simps)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    67
  next
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    68
    case (Cons w ws)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    69
    then have case_simp: "\<And>w v::('a, 'b) tree. (case ks of [] \<Rightarrow> v | _ \<Rightarrow> w) = w"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    70
      by (cases ks) auto
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    71
    from Cons have "ks \<noteq> []" by simp
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    72
    then have "0 < length ks" by simp
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    73
    let ?mid = "length ks div 2"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    74
    let ?ys = "take ?mid ks"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    75
    let ?x = "ks ! ?mid"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    76
    let ?zs = "drop (Suc ?mid) ks"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    77
    from `ks \<noteq> []` have ks_split: "ks = ?ys @ [?x] @ ?zs"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    78
      by (simp add: id_take_nth_drop)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    79
    then have in_ks: "\<And>x. x \<in> set ks \<longleftrightarrow> x \<in> set (?ys @ [?x] @ ?zs)"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    80
      by simp
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    81
    with ks_split have ys_x: "\<And>y. y \<in> set ?ys \<Longrightarrow> y \<le> ?x"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    82
      and x_zs: "\<And>z. z \<in> set ?zs \<Longrightarrow> ?x \<le> z"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    83
    using `sorted ks` sorted_append [of "?ys" "[?x] @ ?zs"] sorted_append [of "[?x]" "?zs"]
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    84
      by simp_all
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    85
    have ys: "lookup (bulkload ?ys f) = (Some o f) |` set ?ys"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    86
      by (rule "1.hyps"(1)) (auto intro: Cons sorted_take `sorted ks`)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    87
    have zs: "lookup (bulkload ?zs f) = (Some o f) |` set ?zs"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    88
      by (rule "1.hyps"(2)) (auto intro: Cons sorted_drop `sorted ks`)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    89
    show ?thesis using `0 < length ks`
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    90
      by (simp add: bulkload.simps)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    91
        (auto simp add: restrict_map_def in_ks case_simp Let_def ys zs expand_fun_eq
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    92
           dest: in_set_takeD in_set_dropD ys_x x_zs)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    93
  qed
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    94
qed
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    95
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    96
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    97
subsection {* Trees as mappings *}
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    98
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
    99
definition Tree :: "('a\<Colon>linorder, 'b) tree \<Rightarrow> ('a, 'b) map" where
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   100
  "Tree t = Map (Tree.lookup t)"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   101
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   102
lemma [code, code del]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   103
  "(eq_class.eq :: (_, _) map \<Rightarrow> _) = eq_class.eq" ..
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   104
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   105
lemma [code, code del]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   106
  "Mapping.delete k m = Mapping.delete k m" ..
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   107
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   108
code_datatype Tree
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   109
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   110
lemma empty_Tree [code]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   111
  "Mapping.empty = Tree Empty"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   112
  by (simp add: Tree_def Mapping.empty_def)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   113
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   114
lemma lookup_Tree [code]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   115
  "Mapping.lookup (Tree t) = lookup t"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   116
  by (simp add: Tree_def)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   117
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   118
lemma update_Tree [code]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   119
  "Mapping.update k v (Tree t) = Tree (update k v t)"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   120
  by (simp add: Tree_def lookup_update)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   121
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   122
lemma keys_Tree [code]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   123
  "Mapping.keys (Tree t) = set (filter (\<lambda>k. lookup t k \<noteq> None) (remdups (keys t)))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   124
  by (simp add: Tree_def dom_lookup)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   125
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   126
lemma size_Tree [code]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   127
  "Mapping.size (Tree t) = size t"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   128
proof -
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   129
  have "card (dom (Tree.lookup t)) = length (filter (\<lambda>x. x \<noteq> None) (map (lookup t) (remdups (keys t))))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   130
    unfolding dom_lookup by (subst distinct_card) (auto simp add: comp_def)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   131
  then show ?thesis by (auto simp add: Tree_def Mapping.size_def size_def)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   132
qed
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   133
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   134
lemma tabulate_Tree [code]:
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   135
  "Mapping.tabulate ks f = Tree (bulkload (sort ks) f)"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   136
proof -
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   137
  have "Mapping.lookup (Mapping.tabulate ks f) = Mapping.lookup (Tree (bulkload (sort ks) f))"
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   138
    by (simp add: lookup_Tree lookup_bulkload lookup_tabulate)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   139
  then show ?thesis by (simp add: lookup_inject)
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   140
qed
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   141
ae39b7b2a68a added trees implementing mappings
haftmann
parents:
diff changeset
   142
end