src/HOL/Data_Structures/Trie_Ternary.thy
author nipkow
Wed, 31 Jul 2024 10:36:28 +0200
changeset 80628 161286c9d426
parent 80404 f34e62eda167
child 80629 06350a8745c9
permissions -rw-r--r--
tuned names
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
80404
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     1
section "Ternary Tries"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     2
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     3
theory Trie_Ternary
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     4
imports
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     5
  Tree_Map
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     6
  Trie_Fun
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     7
begin
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     8
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
     9
text \<open>An implementation of tries for an arbitrary alphabet \<open>'a\<close> where the mapping
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    10
from an element of type \<open>'a\<close> to the sub-trie is implemented by an (unbalanced) binary search tree.
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    11
In principle, other search trees (e.g. red-black trees) work just as well,
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    12
with some small adjustments (Exercise!).
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    13
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    14
This is an implementation of the ``ternary search trees'' by Bentley and Sedgewick
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    15
[SODA 1997, Dr. Dobbs 1998]. The name derives from the fact that a node in the BST can now
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    16
be drawn to have 3 children, where the middle child is the sub-trie that the node maps
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    17
its key to. Hence the name \<open>trie3\<close>.
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    18
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    19
Example from @{url "https://en.wikipedia.org/wiki/Ternary_search_tree#Description"}:
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    20
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    21
          c
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    22
        / | \
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    23
       a  u  h
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    24
       |  |  | \
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    25
       t. t  e. u
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    26
     /  / |   / |
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    27
    s. p. e. i. s.
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    28
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    29
Characters with a dot are final.
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    30
Thus the tree represents the set of strings "cute","cup","at","as","he","us" and "i".
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    31
\<close>
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    32
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    33
datatype 'a trie3 = Nd3 bool "('a * 'a trie3) tree"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    34
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    35
text \<open>The development below works almost verbatim for any search tree implementation, eg \<open>RBT_Map\<close>,
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    36
and not just \<open>Tree_Map\<close>, except for the termination lemma \<open>lookup_size\<close>.\<close>
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    37
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    38
term size_tree
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    39
lemma lookup_size[termination_simp]:
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    40
  fixes t :: "('a::linorder * 'a trie3) tree"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    41
  shows "lookup t a = Some b \<Longrightarrow> size b < Suc (size_tree (\<lambda>ab. Suc (size (snd( ab)))) t)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    42
apply(induction t a rule: lookup.induct)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    43
apply(auto split: if_splits)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    44
done
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    45
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    46
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    47
definition empty3 :: "'a trie3" where
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    48
[simp]: "empty3 = Nd3 False Leaf"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    49
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    50
fun isin3 :: "('a::linorder) trie3 \<Rightarrow> 'a list \<Rightarrow> bool" where
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    51
"isin3 (Nd3 b m) [] = b" |
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    52
"isin3 (Nd3 b m) (x # xs) = (case lookup m x of None \<Rightarrow> False | Some t \<Rightarrow> isin3 t xs)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    53
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    54
fun insert3 :: "('a::linorder) list \<Rightarrow> 'a trie3 \<Rightarrow> 'a trie3" where
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    55
"insert3 [] (Nd3 b m) = Nd3 True m" |
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    56
"insert3 (x#xs) (Nd3 b m) =
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    57
  Nd3 b (update x (insert3 xs (case lookup m x of None \<Rightarrow> empty3 | Some t \<Rightarrow> t)) m)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    58
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    59
fun delete3 :: "('a::linorder) list \<Rightarrow> 'a trie3 \<Rightarrow> 'a trie3" where
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    60
"delete3 [] (Nd3 b m) = Nd3 False m" |
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    61
"delete3 (x#xs) (Nd3 b m) = Nd3 b
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    62
   (case lookup m x of
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    63
      None \<Rightarrow> m |
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    64
      Some t \<Rightarrow> update x (delete3 xs t) m)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    65
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    66
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    67
subsection "Correctness"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    68
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    69
text \<open>Proof by stepwise refinement. First abs3tract to type @{typ "'a trie"}.\<close>
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    70
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    71
fun abs3 :: "'a::linorder trie3 \<Rightarrow> 'a trie" where
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    72
"abs3 (Nd3 b t) = Nd b (\<lambda>a. map_option abs3 (lookup t a))"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    73
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    74
fun invar3 :: "('a::linorder)trie3 \<Rightarrow> bool" where
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    75
"invar3 (Nd3 b m) = (M.invar m \<and> (\<forall>a t. lookup m a = Some t \<longrightarrow> invar3 t))"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    76
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    77
lemma isin_abs3: "isin3 t xs = isin (abs3 t) xs"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    78
apply(induction t xs rule: isin3.induct)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    79
apply(auto split: option.split)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    80
done
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    81
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    82
lemma abs3_insert3: "invar3 t \<Longrightarrow> abs3(insert3 xs t) = insert xs (abs3 t)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    83
apply(induction xs t rule: insert3.induct)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    84
apply(auto simp: M.map_specs Tree_Set.empty_def[symmetric] split: option.split)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    85
done
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    86
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    87
lemma abs3_delete3: "invar3 t \<Longrightarrow> abs3(delete3 xs t) = delete xs (abs3 t)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    88
apply(induction xs t rule: delete3.induct)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    89
apply(auto simp: M.map_specs split: option.split)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    90
done
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    91
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    92
lemma invar3_insert3: "invar3 t \<Longrightarrow> invar3 (insert3 xs t)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    93
apply(induction xs t rule: insert3.induct)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    94
apply(auto simp: M.map_specs Tree_Set.empty_def[symmetric] split: option.split)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    95
done
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    96
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    97
lemma invar3_delete3: "invar3 t \<Longrightarrow> invar3 (delete3 xs t)"
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    98
apply(induction xs t rule: delete3.induct)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
    99
apply(auto simp: M.map_specs split: option.split)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   100
done
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   101
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   102
text \<open>Overall correctness w.r.t. the \<open>Set\<close> ADT:\<close>
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   103
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   104
interpretation S2: Set
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   105
where empty = empty3 and isin = isin3 and insert = insert3 and delete = delete3
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   106
and set = "set o abs3" and invar = invar3
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   107
proof (standard, goal_cases)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   108
  case 1 show ?case by (simp add: isin_case split: list.split)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   109
next
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   110
  case 2 thus ?case by (simp add: isin_abs3)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   111
next
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   112
  case 3 thus ?case by (simp add: set_insert abs3_insert3 del: set_def)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   113
next
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   114
  case 4 thus ?case by (simp add: set_delete abs3_delete3 del: set_def)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   115
next
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   116
  case 5 thus ?case by (simp add: M.map_specs Tree_Set.empty_def[symmetric])
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   117
next
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   118
  case 6 thus ?case by (simp add: invar3_insert3)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   119
next
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   120
  case 7 thus ?case by (simp add: invar3_delete3)
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   121
qed
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   122
f34e62eda167 clarified ternary tries
nipkow
parents:
diff changeset
   123
end