hobbes
a language, embedded compiler, and runtime for efficient dynamic expression evaluation, data storage and analysis
unionfind.H
Go to the documentation of this file.
1 /****
2  * unionfind : a data structure for efficiently performing unification for n terms in effectively O(n) time
3  ****/
4 
5 #ifndef HOBBES_UTIL_UNIONFIND_HPP_INCLUDED
6 #define HOBBES_UTIL_UNIONFIND_HPP_INCLUDED
7 
8 #include <unordered_map>
9 #include <stdexcept>
10 #include <sstream>
11 #include <memory>
12 
13 namespace hobbes {
14 
15 template <typename K, typename V>
16  struct eqsetmem {
17  eqsetmem(const K& key, const V& value) : key(key), value(value), rank(0) {
18  representative = this;
19  }
20 
21  K key;
22  V value;
23  size_t rank;
25  };
26 
27 template <typename K, typename V, typename KVLift, typename VPlus>
29  public:
30  equivalence_mapping() : eqsz(0) {
31  }
32 
33  // how many equivalence constraints have been recorded?
34  size_t size() const {
35  return this->eqsz;
36  }
37 
38  // find the representative element for a set
39  V& find(const K& k) {
40  return findNode(k)->value;
41  }
42 
43  // declare two values equal
44  void join(const K& k0, const K& k1) {
45  node_t* lhs = findNode(k0);
46  node_t* rhs = findNode(k1);
47 
48  if (lhs->rank < rhs->rank) {
49  lhs->representative = rhs;
50  rhs->value = VPlus::apply(rhs->value, lhs->value);
51  } else if (lhs->rank > rhs->rank) {
52  rhs->representative = lhs;
53  lhs->value = VPlus::apply(lhs->value, rhs->value);
54  } else if (lhs == rhs) {
55  // these are the same thing, don't pretend that we've added information
56  return;
57  } else {
58  rhs->representative = lhs;
59  lhs->rank += 1;
60  lhs->value = VPlus::apply(lhs->value, rhs->value);
61  }
62 
63  ++this->eqsz;
64  }
65 
66  // merge another equivalence mapping with this one
68  // count the number of extra bindings that we add
69  size_t c = this->eqsz;
70 
71  // add new nodes to this set
72  for (const auto& kn : rhs.nodes) {
73  if (this->nodes.find(kn.first) == this->nodes.end()) {
74  this->nodes[kn.first] = nodep(new node_t(kn.first, KVLift::apply(kn.first)));
75  }
76  }
77 
78  // now for these new nodes, apply the equivalence bindings from the input set
79  for (const auto& kn : rhs.nodes) {
80  node_t* rrep = findRepresentative(kn.second.get());
81  if (kn.first != rrep->key) {
82  join(kn.first, rrep->key);
83  }
84  }
85 
86  return this->eqsz - c;
87  }
88 
89  // get the universe of values
90  std::vector<K> values() const {
91  std::vector<K> vs;
92  vs.reserve(nodes.size());
93  for (const auto& kn : this->nodes) {
94  vs.push_back(kn.first);
95  }
96  return vs;
97  }
98  private:
99  size_t eqsz;
100 
102  typedef std::unique_ptr<node_t> nodep; // allows multiple incremental extensions of unification sets
103  typedef std::unordered_map<K, nodep> nodes_t;
104  nodes_t nodes;
105 
106  static node_t* findRepresentative(node_t* n) {
107  if (n != n->representative) {
108  n->representative = findRepresentative(n->representative);
109  }
110  return n->representative;
111  }
112 
113  node_t* findNode(const K& k) {
114  typename nodes_t::const_iterator n = this->nodes.find(k);
115 
116  if (n != this->nodes.end()) {
117  return findRepresentative(n->second.get());
118  } else {
119  node_t* n = new node_t(k, KVLift::apply(k));
120  this->nodes[k] = nodep(n);
121  return n;
122  }
123  }
124  };
125 
126 }
127 
128 #endif
129 
std::unique_ptr< node_t > nodep
Definition: unionfind.H:102
void join(const K &k0, const K &k1)
Definition: unionfind.H:44
V value
Definition: unionfind.H:22
size_t merge(const equivalence_mapping< K, V, KVLift, VPlus > &rhs)
Definition: unionfind.H:67
std::vector< K > values() const
Definition: unionfind.H:90
size_t size() const
Definition: unionfind.H:34
void apply(const transition_lookahead &tl, parserdef *p)
Definition: lalr.C:564
eqsetmem< K, V > node_t
Definition: unionfind.H:101
size_t eqsz
Definition: unionfind.H:99
Definition: boot.H:7
node_t * findNode(const K &k)
Definition: unionfind.H:113
V & find(const K &k)
Definition: unionfind.H:39
Definition: unionfind.H:16
Definition: unionfind.H:28
eqsetmem< K, V > * representative
Definition: unionfind.H:24
K key
Definition: unionfind.H:21
eqsetmem(const K &key, const V &value)
Definition: unionfind.H:17
equivalence_mapping()
Definition: unionfind.H:30
std::unordered_map< K, nodep > nodes_t
Definition: unionfind.H:103
nodes_t nodes
Definition: unionfind.H:104
static node_t * findRepresentative(node_t *n)
Definition: unionfind.H:106
size_t rank
Definition: unionfind.H:23