dtrees_rs/caching/
trie.rs1use crate::caching::entry::{CacheEntry, CacheEntryUpdater};
2use crate::caching::helpers::{CacheKey, Index};
3use crate::caching::Caching;
4use rustc_hash::FxHashMap;
5
6#[derive(Debug)]
7struct TrieNode {
8 index: usize,
9 entry: CacheEntry,
10 children: FxHashMap<usize, usize>,
11}
12
13impl Default for TrieNode {
14 fn default() -> Self {
15 Self {
16 index: usize::MAX,
17 children: FxHashMap::default(),
18 entry: CacheEntry::default(),
19 }
20 }
21}
22
23impl TrieNode {
24 pub fn new(item: usize) -> Self {
25 Self {
26 index: usize::MAX,
27 children: FxHashMap::default(),
28 entry: CacheEntry::new(item),
29 }
30 }
31}
32
33#[derive(Default)]
35pub struct Trie {
36 arena: Vec<TrieNode>,
37 root_index: usize,
38}
39
40impl Caching for Trie {
41 fn init(&mut self) -> Index {
42 if !self.arena.is_empty() {
43 self.arena.clear();
44 }
45 let index = self.add_default_root();
46 Index::new_at(index)
47 }
48
49 fn root_index(&mut self) -> Index {
50 Index::new_at(self.get_root_index())
51 }
52
53 fn root(&self) -> Option<&CacheEntry> {
54 self.get_node(self.get_root_index()).map(|node| &node.entry)
55 }
56
57 fn insert(&mut self, path: &[usize]) -> Index {
58 let mut current_index = self.root_index;
59 let mut is_new = false;
60 for &item in path {
61 if let Some(&child_index) = self
62 .get_node(current_index)
63 .and_then(|node| node.children.get(&item))
64 {
65 current_index = child_index;
66 } else {
67 is_new = true;
68 current_index = self.create_child(current_index, item);
69 }
70 }
71
72 let leaf_is_infinite = self
73 .get_node(current_index)
74 .map_or(true, |node| !node.entry.has_finite_leaf_error());
75
76 if is_new || leaf_is_infinite {
77 return Index::New(current_index);
78 }
79 Index::Existing(current_index)
80 }
81
82 fn node(&self, key: &CacheKey) -> Option<&CacheEntry> {
83 match key {
84 CacheKey::Index(index) => self.get_node(*index).map(|node| &node.entry),
85 CacheKey::Path(path) => self.find(path),
86 }
87 }
88
89 fn contains(&self, key: &CacheKey) -> bool {
90 self.node(key).is_some()
91 }
92
93 fn update_root(&mut self) -> Option<CacheEntryUpdater<'_>> {
94 self.get_node_mut(self.root_index)
95 .map(|node| CacheEntryUpdater::new(&mut node.entry))
96 }
97
98 fn update_node(&mut self, key: &CacheKey) -> Option<CacheEntryUpdater<'_>> {
99 match key {
100 CacheKey::Index(index) => self
101 .get_node_mut(*index)
102 .map(|node| CacheEntryUpdater::new(&mut node.entry)),
103 CacheKey::Path(path) => self.find_mut(path).map(CacheEntryUpdater::new),
104 }
105 }
106
107 fn size(&self) -> usize {
108 self.arena.len()
109 }
110
111 fn is_empty(&self) -> bool {
112 self.arena.is_empty()
113 }
114}
115
116impl Trie {
117 pub fn new() -> Self {
119 Self {
120 arena: Vec::new(),
121 root_index: 0,
122 }
123 }
124
125 fn add_node(&mut self, parent_index: usize, mut node: TrieNode) -> usize {
126 let new_index = self.arena.len();
127 node.index = new_index;
128 let item = node.entry.item();
129 self.arena.push(node);
130 if new_index != 0 {
131 if let Some(parent) = self.arena.get_mut(parent_index) {
132 parent.children.insert(item, new_index);
133 }
134 }
135
136 new_index
137 }
138
139 fn find(&self, itemset: &[usize]) -> Option<&CacheEntry> {
140 let mut current_index = self.root_index;
141 for &item in itemset {
142 let current_node = self.get_node(current_index)?;
143 current_index = *current_node.children.get(&item)?;
144 }
145 self.get_node(current_index).map(|node| &node.entry)
146 }
147
148 fn find_mut(&mut self, itemset: &[usize]) -> Option<&mut CacheEntry> {
149 let mut current_index = self.root_index;
150 for &item in itemset {
151 let current_node = self.get_node(current_index)?;
152 current_index = *current_node.children.get(&item)?;
153 }
154 self.get_node_mut(current_index).map(|node| &mut node.entry)
155 }
156
157 fn add_root(&mut self, root: TrieNode) -> usize {
158 self.root_index = self.add_node(0, root);
159 self.root_index
160 }
161
162 fn add_default_root(&mut self) -> usize {
163 self.root_index = self.add_root(TrieNode::default());
164 self.root_index
165 }
166
167 #[inline]
168 fn get_root_index(&self) -> usize {
169 self.root_index
170 }
171
172 #[inline]
173 fn get_node(&self, index: usize) -> Option<&TrieNode> {
174 self.arena.get(index)
175 }
176
177 #[inline]
178 fn get_node_mut(&mut self, index: usize) -> Option<&mut TrieNode> {
179 self.arena.get_mut(index)
180 }
181
182 fn create_child(&mut self, parent: usize, item: usize) -> usize {
183 let node = TrieNode::new(item);
184 self.add_node(parent, node)
185 }
186}
187
188#[cfg(test)]
189mod trie_test {
190 use crate::caching::helpers::Index;
191 use crate::caching::trie::{Trie, TrieNode};
192 use crate::caching::Caching;
193
194 #[test]
195 fn test_cache_init() {
196 let mut cache = Trie::new();
197 assert!(cache.is_empty());
198
199 let root_data = TrieNode::default();
200 cache.add_root(root_data);
201 cache.add_node(0, TrieNode::default());
202 println!("Cache 0 {:?}", cache.arena[0].children);
203
204 assert!(!cache.is_empty());
205
206 let mut itemset = Vec::new();
207 itemset.push(0);
208 itemset.push(1);
209 itemset.push(3);
210
211 let idx = cache.insert(&itemset);
212
213 match idx {
214 Index::NewUnknown => {}
215 Index::New(_) | Index::Existing(_) => {}
216 }
217
218 itemset.remove(1);
219 }
220}