Skip to main content

adapton/catalog/
trie.rs

1use std::fmt::Debug;
2use std::hash::{Hash, Hasher};
3use std::collections::hash_map::DefaultHasher;
4use std::rc::Rc;
5use std::cmp::min;
6
7use crate::adapton::catalog::collections::{ListIntro, ListElim, list_fold};
8use crate::adapton::catalog::bitstring::*;
9use crate::adapton::engine::*;
10use crate::macros::*;
11
12/// Probablistically Balanced Trie
13/// Rough implementation of probabilistic tries from OOPSLA 2015 paper.
14///
15/// See also: [Tries in OCaml](http://github.com/plum-umd/adapton.ocaml)
16#[derive(Debug,PartialEq,Eq,Clone)]
17pub enum Trie<X> {
18    Nil(BS),
19    Leaf(BS, X),
20    Bin(BS, Box<Trie<X>>, Box<Trie<X>>),
21    Root(Meta, Box<Trie<X>>),
22    Name(Name, Box<Trie<X>>),
23    Art(Art<Trie<X>>),
24}
25
26pub const PLACEMENT_SEED: u64 = 42;
27
28/// Metadata held by the root node.
29#[derive(Debug,PartialEq,Eq,Hash,Clone)]
30pub struct Meta {
31    pub min_depth: i64,
32}
33
34pub trait MetaT {
35    fn hash_seeded(&self, _: u64);
36}
37
38impl MetaT for Meta {
39    fn hash_seeded(&self, seed: u64) {
40        let mut hasher = DefaultHasher::new();
41        seed.hash(&mut hasher);
42        "Adapton.Trie.Meta".hash(&mut hasher);
43        self.min_depth.hash(&mut hasher);
44    }
45}
46
47// impl<X: Debug + Hash + PartialEq + Eq + Clone + 'static> PartialEq for Trie<X> {
48//     fn eq(&self, other: &Trie<X>) -> bool {
49//         match (self, other) {
50//             (&Trie::Nil(ref bs_self), &Trie::Nil(ref bs_other)) => bs_self == bs_other,
51//             (&Trie::Leaf(ref bs_self, ref e_self), &Trie::Leaf(ref bs_other, ref e_other)) => {
52//                 let bs_equal = bs_self == bs_other;
53//                 let b = bs_equal && e_self == e_other;
54//                 // println!("{:?}\n{}\n{:?}", self, b, other);
55//                 b
56//             }
57//             (&Trie::Bin(ref bs, ref left, ref right),
58//              &Trie::Bin(ref bs_other, ref left_other, ref right_other)) => {
59//                 let b = bs == bs_other && left == left_other && right == right_other;
60//                 // println!("{:?}\n{}\n{:?}", self, b, other);
61//                 b
62//             }
63//             (&Trie::Root(ref md, ref t), &Trie::Root(ref md_other, ref t_other)) => {
64//                 let b = md == md_other && t == t_other;
65//                 // println!("{:?}\n{}\n{:?}", t, b, t_other);
66//                 b
67//             }
68//             (&Trie::Name(ref nm, ref t), &Trie::Name(ref nm_other, ref t_other)) => {
69//                 let b = nm == nm_other && t == t_other;
70//                 // println!("{:?}\n{}\n{:?}", t, b, t_other);
71//                 b
72//             }
73//             (&Trie::Art(ref a), &Trie::Art(ref a_other)) => {
74//                 let b = a == a_other;
75//                 // println!("{:?}\n{}\n{:?}", a, b, a_other);
76//                 b
77//             }
78//             (t, t_other) => {
79//                 // println!("{:?}\n!=\n{:?}", t, t_other);
80//                 false
81//             }
82//         }
83//     }
84// }
85
86// impl<X: Debug + Hash + PartialEq + Eq + Clone + 'static> Eq for Trie<X> {}
87
88pub trait TrieIntro<X>: Debug + Hash + PartialEq + Eq + Clone + 'static {
89    fn nil(_: BS) -> Self;
90    fn leaf(_: BS, _: X) -> Self;
91    fn bin(_: BS, _: Self, _: Self) -> Self;
92    fn root(_: Meta, _: Self) -> Self;
93
94    // requisite "adaptonic" constructors: `name` and `art`:
95    fn name(_: Name, _: Self) -> Self;
96    fn art(_: Art<Self>) -> Self;
97
98    fn empty(_: Meta) -> Self;
99    fn singleton(_: Meta, _: Name, _: X) -> Self;
100    fn extend(_: Name, _: Self, _: X) -> Self;
101}
102
103pub trait TrieElim<X>: Debug + Hash + PartialEq + Eq + Clone + 'static {
104    fn find(_: &Self, _: &X, _: i64) -> Option<X>;
105    fn is_empty(_: &Self) -> bool;
106    fn split_atomic(_: Self) -> Self;
107
108    fn elim<Res, NilC, LeafC, BinC, RootC, NameC>(_: Self, _: NilC, _: LeafC, _: BinC, _: RootC, _: NameC) -> Res
109        where NilC: FnOnce(BS) -> Res,
110              LeafC: FnOnce(BS, X) -> Res,
111              BinC: FnOnce(BS, Self, Self) -> Res,
112              RootC: FnOnce(Meta, Self) -> Res,
113              NameC: FnOnce(Name, Self) -> Res;
114
115    fn elim_arg<Arg, Res, NilC, LeafC, BinC, RootC, NameC>(_: Self,
116                                                           _: Arg,
117                                                           _: NilC,
118                                                           _: LeafC,
119                                                           _: BinC,
120                                                           _: RootC,
121                                                           _: NameC)
122                                                           -> Res
123        where NilC: FnOnce(BS, Arg) -> Res,
124              LeafC: FnOnce(BS, X, Arg) -> Res,
125              BinC: FnOnce(BS, Self, Self, Arg) -> Res,
126              RootC: FnOnce(Meta, Self, Arg) -> Res,
127              NameC: FnOnce(Name, Self, Arg) -> Res;
128
129    fn elim_ref<Res, NilC, LeafC, BinC, RootC, NameC>(_: &Self,
130                                                      _: NilC,
131                                                      _: LeafC,
132                                                      _: BinC,
133                                                      _: RootC,
134                                                      _: NameC)
135                                                      -> Res
136        where NilC: FnOnce(&BS) -> Res,
137              LeafC: FnOnce(&BS, &X) -> Res,
138              BinC: FnOnce(&BS, &Self, &Self) -> Res,
139              RootC: FnOnce(&Meta, &Self) -> Res,
140              NameC: FnOnce(&Name, &Self) -> Res;
141}
142
143/*
14420121221-- requires box_syntax feature
145
146impl<X: Debug + Hash + PartialEq + Eq + Clone + 'static> Trie<X> {
147    fn mfn(nm: Name, meta: Meta, trie: Self, bs: BS, elt: X, hash: u64) -> Self {
148        match trie {
149            Trie::Nil(_) if BS::length(bs) < meta.min_depth => {
150                let h_ = hash >> 1;
151                let bs0 = BS::prepend(0, bs);
152                let bs1 = BS::prepend(1, bs);
153                let mt0 = Self::nil(bs0);
154                let mt1 = Self::nil(bs1);
155                if hash % 2 == 0 {
156                    Self::bin(bs, Self::mfn(nm, meta, mt0, bs0, elt, h_), mt1)
157                } else {
158                    Self::bin(bs, mt0, Self::mfn(nm, meta, mt1, bs1, elt, h_))
159                }
160            }
161            Trie::Nil(_) => Trie::Leaf(bs, elt),
162            Trie::Leaf(_, e) => {
163                let depth = BS::length(bs);
164                if depth >= BS::MAX_LEN || e == elt {
165                    Self::leaf(bs, e)
166                } else if depth < BS::MAX_LEN {
167                    Self::mfn(nm,
168                              meta,
169                              Self::split_atomic(Self::leaf(bs, e)),
170                              bs,
171                              elt,
172                              hash)
173                } else {
174                    panic!("Bad value found in nadd:\nLeaf(bs, e)\n{:?}",
175                           Self::leaf(bs, e));
176                }
177            }
178            Trie::Bin(bs, left, right) => {
179                let h_ = hash >> 1;
180                if hash % 2 == 0 {
181                    let l = Self::mfn(nm, meta, *left, BS::prepend(0, bs), elt, h_);
182                    Self::bin(bs, l, *right)
183                } else {
184                    let r = Self::mfn(nm, meta, *right, BS::prepend(1, bs), elt, h_);
185                    Self::bin(bs, *left, r)
186                }
187            }
188            Trie::Name(_, box Trie::Art(a)) => Self::mfn(nm, meta, force(&a), bs, elt, hash),
189            t => panic!("Bad value found in nadd:\n{:?}\n", t),
190        }
191    }
192
193    fn root_mfn(_: Name, nm: Name, trie: Self, elt: X) -> Self {
194        match trie {
195            Trie::Name(_, box Trie::Art(a)) => {
196                match force(&a) {
197                    Trie::Root(meta, t) => {
198                        let (nm, nm_) = name_fork(nm);
199                        let mut hasher = DefaultHasher::new();
200                        elt.hash(&mut hasher);
201                        let a = Self::mfn(nm_,
202                                          meta.clone(),
203                                          *t,
204                                          BS {
205                                              length: 0,
206                                              value: 0,
207                                          },
208                                          elt,
209                                          hasher.finish());
210                        Self::root(meta, Self::name(nm, Self::art(put(a))))
211                    }
212                    t @ Trie::Name(_, box Trie::Art(_)) => Self::root_mfn(nm.clone(), nm, t, elt),
213                    t => panic!("Non-root node entry to `Trie.extend': {:?}", t),
214                }
215            }
216            _ => panic!("None-name node at entry to `Trie.extend'"),
217        }
218    }
219}
220*/
221
222impl<X: Debug + Hash + PartialEq + Eq + Clone + 'static> TrieIntro<X> for Trie<X> {
223    fn nil(bs: BS) -> Self {
224        Trie::Nil(bs)
225    }
226    fn leaf(bs: BS, x: X) -> Self {
227        Trie::Leaf(bs, x)
228    }
229    fn bin(bs: BS, l: Self, r: Self) -> Self {
230        Trie::Bin(bs, Box::new(l), Box::new(r))
231    }
232    fn root(meta: Meta, trie: Self) -> Self {
233        Trie::Root(meta, Box::new(trie))
234    }
235    fn name(nm: Name, trie: Self) -> Self {
236        Trie::Name(nm, Box::new(trie))
237    }
238    fn art(art: Art<Self>) -> Self {
239        Trie::Art(art)
240    }
241
242    fn empty(meta: Meta) -> Self {
243        if meta.min_depth > BS::MAX_LEN {
244            println!("Cannot make Adapton.Trie with min_depth > {} (given {})",
245                     BS::MAX_LEN,
246                     meta.min_depth);
247        }
248        let min = min(meta.min_depth, BS::MAX_LEN);
249        let meta = Meta { min_depth: min };
250        let nm = name_of_str("empty");
251        let (nm1, nm2) = name_fork(nm);
252        let mtbs = BS {
253            length: 0,
254            value: 0,
255        };
256        let nil_art = thunk!(nm2.clone() =>> Self::nil, bs:mtbs);
257        let root_art = thunk!(nm1.clone() =>> Self::root, meta:meta,
258                              trie:Self::name(nm2, Self::art(nil_art)));
259        Self::name(nm1.clone(), Self::art(root_art))
260    }
261
262    fn singleton(meta: Meta, nm: Name, elt: X) -> Self {
263        Self::extend(nm, TrieIntro::empty(meta), elt)
264    }
265
266    fn extend(nm: Name, trie: Self, elt: X) -> Self {
267        let (nm, nm_) = name_fork(nm);
268        // let a = Self::root_mfn(nm.clone(), nm_, trie, elt);
269        let root_mfn_art = panic!("todo"); //put(Self::root_mfn(nm.clone(), nm_, trie, elt));
270        Self::name(nm, Self::art(root_mfn_art))
271    }
272}
273
274impl<X: Debug + Hash + PartialEq + Eq + Clone + 'static> Hash for Trie<X> {
275    fn hash<H: Hasher>(&self, state: &mut H) {
276        match *self {
277            Trie::Nil(bs) => bs.hash(state),
278            Trie::Leaf(bs, ref x) => {
279                x.hash(state);
280                bs.hash(state)
281            }
282            Trie::Bin(bs, ref left, ref right) => {
283                right.hash(state);
284                left.hash(state);
285                bs.hash(state)
286            }
287            Trie::Root(ref md, ref t) => {
288                t.hash(state);
289                md.hash_seeded(state.finish());
290            }
291            Trie::Name(ref nm, ref t) => {
292                t.hash(state);
293                nm.hash(state)
294            }
295            Trie::Art(ref art_t) => art_t.hash(state),
296        }
297    }
298}
299
300impl<X: Debug + Hash + PartialEq + Eq + Clone + 'static> TrieElim<X> for Trie<X> {
301    fn find(trie: &Self, elt: &X, i: i64) -> Option<X> {
302        Self::elim_ref(trie,
303                       |_| None,
304                       |_, x| if *elt == *x { Some(x.clone()) } else { None },
305                       |_, left, right| if i % 2 == 0 {
306                           Self::find(left, elt, i >> 1)
307                       } else {
308                           Self::find(right, elt, i >> 1)
309                       },
310                       |_, t| Self::find(t, elt, i),
311                       |_, t| Self::find(t, elt, i))
312    }
313
314    fn is_empty(trie: &Self) -> bool {
315        Self::elim_ref(trie,
316                       |_| true,
317                       |_, _| false,
318                       |_, _, _| false,
319                       |_, t| Self::is_empty(t),
320                       |_, t| Self::is_empty(t))
321    }
322
323    fn split_atomic(trie: Self) -> Self {
324        fn suffix(bs: BS, k: i64) -> bool {
325            bs.value & k == bs.value
326        }
327        match trie {
328            t @ Trie::Nil(_) |
329            t @ Trie::Bin(_, _, _) => t,
330            Trie::Leaf(bs, e) => {
331                let bs0 = BS::prepend(0, bs);
332                let bs1 = BS::prepend(1, bs);
333                let mut hasher = DefaultHasher::new();
334                e.hash(&mut hasher);
335                if suffix(bs1, hasher.finish() as i64) {
336                    Self::bin(bs, Self::nil(bs0), Self::leaf(bs1, e))
337                } else {
338                    Self::bin(bs, Self::leaf(bs0, e), Self::nil(bs1))
339                }
340            }
341            _ => panic!("Bad split_atomic(t)"),
342        }
343    }
344
345    fn elim<Res, NilC, LeafC, BinC, RootC, NameC>(trie: Self,
346                                                  nil: NilC,
347                                                  leaf: LeafC,
348                                                  bin: BinC,
349                                                  root: RootC,
350                                                  name: NameC)
351                                                  -> Res
352        where NilC: FnOnce(BS) -> Res,
353              LeafC: FnOnce(BS, X) -> Res,
354              BinC: FnOnce(BS, Self, Self) -> Res,
355              RootC: FnOnce(Meta, Self) -> Res,
356              NameC: FnOnce(Name, Self) -> Res
357    {
358        match trie {
359            Trie::Nil(bs) => nil(bs),
360            Trie::Leaf(bs, x) => leaf(bs, x),
361            Trie::Bin(bs, l, r) => bin(bs, *l, *r),
362            Trie::Name(nm, t) => name(nm, *t),
363            Trie::Root(meta, t) => root(meta, *t),
364            Trie::Art(art) => {
365                let trie = force(&art);
366                Self::elim(trie, nil, leaf, bin, root, name)
367            }
368        }
369    }
370
371    fn elim_arg<Arg, Res, NilC, LeafC, BinC, RootC, NameC>(trie: Self,
372                                                           arg: Arg,
373                                                           nil: NilC,
374                                                           leaf: LeafC,
375                                                           bin: BinC,
376                                                           root: RootC,
377                                                           name: NameC)
378                                                           -> Res
379        where NilC: FnOnce(BS, Arg) -> Res,
380              LeafC: FnOnce(BS, X, Arg) -> Res,
381              BinC: FnOnce(BS, Self, Self, Arg) -> Res,
382              RootC: FnOnce(Meta, Self, Arg) -> Res,
383              NameC: FnOnce(Name, Self, Arg) -> Res
384    {
385        match trie {
386            Trie::Nil(bs) => nil(bs, arg),
387            Trie::Leaf(bs, x) => leaf(bs, x, arg),
388            Trie::Bin(bs, l, r) => bin(bs, *l, *r, arg),
389            Trie::Name(nm, t) => name(nm, *t, arg),
390            Trie::Root(meta, t) => root(meta, *t, arg),
391            Trie::Art(art) => {
392                let trie = force(&art);
393                Self::elim_arg(trie, arg, nil, leaf, bin, root, name)
394            }
395        }
396    }
397
398    fn elim_ref<Res, NilC, LeafC, BinC, RootC, NameC>(trie: &Self,
399                                                      nil: NilC,
400                                                      leaf: LeafC,
401                                                      bin: BinC,
402                                                      root: RootC,
403                                                      name: NameC)
404                                                      -> Res
405        where NilC: FnOnce(&BS) -> Res,
406              LeafC: FnOnce(&BS, &X) -> Res,
407              BinC: FnOnce(&BS, &Self, &Self) -> Res,
408              RootC: FnOnce(&Meta, &Self) -> Res,
409              NameC: FnOnce(&Name, &Self) -> Res
410    {
411        match *trie {
412            Trie::Nil(ref bs) => nil(bs),
413            Trie::Leaf(ref bs, ref x) => leaf(bs, x),
414            Trie::Bin(ref bs, ref l, ref r) => bin(bs, &*l, &*r),
415            Trie::Name(ref nm, ref t) => name(nm, &*t),
416            Trie::Root(ref meta, ref t) => root(meta, &*t),
417            Trie::Art(ref art) => {
418                let trie = force(art);
419                Self::elim_ref(&trie, nil, leaf, bin, root, name)
420            }
421        }
422    }
423}
424
425pub trait SetIntro<X>: Debug + Hash + PartialEq + Eq + Clone + 'static {
426    fn empty() -> Self;
427    fn add(_: Self, e: X) -> Self;
428    // fn remove(Self, e: &X) -> Self;
429    // fn union(Self, Self) -> Self;
430    // fn inter(Self, Self) -> Self;
431    // fn diff(Self, Self) -> Self;
432}
433
434pub trait SetElim<X>: Debug + Hash + PartialEq + Eq + Clone + 'static {
435    fn mem(_: &Self, _: &X) -> bool;
436    fn fold<Res, F>(_: Self, _: Res, _: Rc<F>) -> Res where F: Fn(X, Res) -> Res;
437}
438
439impl<X, Set: TrieIntro<X> + TrieElim<X>> SetIntro<X> for Set {
440    fn empty() -> Self {
441        let meta = Meta { min_depth: 1 };
442        Self::empty(meta)
443    }
444
445    fn add(set: Self, elt: X) -> Self {
446        Self::extend(name_unit(), set, elt)
447    }
448}
449
450impl<X: Hash, Set: TrieIntro<X> + TrieElim<X>> SetElim<X> for Set {
451    fn mem(set: &Self, elt: &X) -> bool {
452        let mut hasher = DefaultHasher::new();
453        elt.hash(&mut hasher);
454        match Set::find(set, elt, hasher.finish() as i64) {
455            Some(_) => true,
456            None => false,
457        }
458    }
459
460    fn fold<Res, F>(set: Self, res: Res, f: Rc<F>) -> Res
461        where F: Fn(X, Res) -> Res
462    {
463        Self::elim_arg(set,
464                       res,
465                       |_, arg| arg,
466                       |_, x, arg| f(x, arg),
467                       |_, left, right, arg| {
468                           Self::fold(right, Self::fold(left, arg, f.clone()), f.clone())
469                       },
470                       |_, t, arg| Self::fold(t, arg, f.clone()),
471                       |_, t, arg| Self::fold(t, arg, f.clone()))
472    }
473}
474
475pub type Set<X> = Trie<X>;
476pub fn trie_fold
477    <X, T:TrieElim<X>, Res:Hash+Debug+Eq+Clone+'static, F:'static>
478    (t: T, res:Res, f: Rc<F>) -> Res
479    where F: Fn(X, Res) -> Res {
480    T::elim_arg(t,
481                (res, f),
482                |_, (arg, _)| arg,
483                |_, x, (arg, f)| f(x, arg),
484                |_, left, right, (arg, f)| trie_fold(right, trie_fold(left, arg, f.clone()), f),
485                |_, t, (arg, f)| trie_fold(t, arg, f),
486                |nm, t, (arg, f)| memo!(nm =>> trie_fold, t:t, res:arg ;; f:f))
487}
488
489pub fn trie_of_list<X: Hash + Clone + Debug + 'static,
490                    T: TrieIntro<X> + 'static,
491                    L: ListElim<X> + ListIntro<X> + 'static>
492    (list: L)
493     -> T {
494    list_fold(list,
495              T::empty(Meta { min_depth: 1 }),
496              Rc::new(|x, trie_acc| T::extend(name_unit(), trie_acc, x)))
497}