Fleet  0.0.9
Inference in the LOT
BaseNode.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include<vector>
4 #include<string>
5 
6 #include "Errors.h"
7 #include "IO.h"
8 
19 template<typename this_t>
20 class BaseNode {
21 
22 protected:
23  std::vector<this_t> children;
24 
25 public:
26  this_t* parent;
27  size_t pi; // what index am I in the parent?
28 
35  BaseNode(size_t n=0, this_t* p=nullptr, size_t i=0) : children(n), parent(p), pi(i) {
36  }
37 
38  BaseNode(const this_t& n) {
39  children = n.children;
40  parent = n.parent;
41  pi = n.pi;
43  }
44  BaseNode(this_t&& n) {
45  parent = n.parent;
46  pi = n.pi;
47  children = std::move(n.children);
49  }
50 
51  void operator=(const this_t& t) {
52  parent = t.parent;
53  pi = t.pi;
54  children = t.children;
56  }
57  void operator=(const this_t&& t) {
58  parent = t.parent;
59  pi = t.pi;
60  children = std::move(t.children);
62  }
63 
64 
68  void make_root() {
69  parent = nullptr;
70  pi = 0;
71  }
72 
73  virtual ~BaseNode() {}
74 
75  // Functions to be defined by subclasses
76  virtual std::string string(bool usedot=true) const {
77  throw YouShouldNotBeHereError("*** BaseNode subclass has no defined string()");
78  }
79  virtual std::string my_string() const {
80  throw YouShouldNotBeHereError("*** BaseNode subclass has no defined my_string()");
81  }
82  virtual bool operator==(const this_t& n) const {
83  throw YouShouldNotBeHereError("*** BaseNode subclass has no defined operator==");
84  }
85 
87 
95  class NodeIterator {
96  // Define an iterator class to make managing trees easier.
97  // This iterates in postfix order, which is standard in the library
98  // because it is the order of linearization
99 
100  // these are require din here for this to be an iterator
101  using iterator_category = std::forward_iterator_tag;
102  using value_type = this_t;
103  using difference_type = int;
104  using pointer = this_t*;
105  using reference = this_t&;
106 
107 
108  protected:
109  this_t* current;
110 
111  // we need to store the start because when we start at a subtree, we want to iteratre through its subnodes
112  // and so we need to know when to stop
113  const this_t* start;
114 
115  public:
116 
117  NodeIterator(const this_t* n) : current( n!= nullptr ? n->left_descend() : nullptr), start(n) { }
118  this_t& operator*() const {
119  assert(current != nullptr);
120  return *current;
121  }
122  this_t* operator->() const {
123  assert(current != nullptr);
124  return current;
125  }
126 
127  NodeIterator& operator++(int blah) { this->operator++(); return *this; }
129  assert(current != nullptr);
130  assert(not (*this == EndNodeIterator) && "Can't iterate past the end!");
131  if(current == nullptr or current == start or current->is_root()) {
132  current = nullptr;
133  return EndNodeIterator;
134  }
135 
136  // go through the children if we can
137  if(current->pi+1 < current->parent->children.size()) {
138  current = current->parent->children[current->pi+1].left_descend();
139  }
140  else { // now we call the parent (if we're out of children)
141  current = current->parent;
142  }
143  return *this;
144  }
145 
146  NodeIterator& operator+(size_t n) {
147  for(size_t i=0;i<n;i++) this->operator++();
148  return *this;
149  }
150 
151  bool operator==(const NodeIterator& rhs) const { return current == rhs.current; }
152  bool operator!=(const NodeIterator& rhs) const { return not(current == rhs.current); }
153  };
154  static NodeIterator EndNodeIterator; // defined below
156 
157  NodeIterator begin() const { return BaseNode<this_t>::NodeIterator(static_cast<const this_t*>(this)); }
159 
160  virtual bool operator!=(const this_t& n) const{
161  return not (*this == n);
162  }
163 
164  void reserve_children(const size_t n) {
165  children.reserve(n);
166  }
167 
168  decltype(children)& get_children() {
169  return children;
170  }
171  const decltype(children)& get_children() const {
172  return children;
173  }
174 
175  this_t& child(const size_t i) {
182  return children.at(i);
183  }
184 
185  const this_t& child(const size_t i) const {
192  return children.at(i);
193  }
194 
195  template<typename... Args>
196  void fill(size_t n, Args... args) {
201  // ensure that all of my children are empty nodes
202  for(size_t i=0;i<n;i++) {
203  set_child(i, this_t(args...));
204  }
205  }
206 
207 
208  size_t nchildren() const {
214  return children.size();
215  }
216 
217  this_t* left_descend() const {
223  this_t* k = const_cast<this_t*>(static_cast<const this_t*>(this));
224  while(k != nullptr and k->nchildren() > 0) {
225  k = &(k->child(0));
226  }
227  return k;
228  }
229 
230  size_t depth() const {
231  size_t d = 0;
232  for(const auto& c: children) {
233  d = std::max(d, c.depth()+1);
234  }
235  return d;
236  }
237 
238  void fix_child_info() {
243  // go through children and assign their parents to me
244  // and fix their pi's
245  size_t i = 0;
246  for(auto& c : children) {
247  c.pi = i;
248  c.parent = static_cast<this_t*>(this);
249  i++;
250  }
251  }
252 
253  void check_child_info() const {
258  size_t i = 0;
259  for(const auto& c : children) {
260 
261  // check that the kids point to the right things
262  assert(c.pi == i);
263  assert(c.parent == this);
264  i++;
265  }
266  }
267 
268 
269  this_t& operator[](const size_t i) {
276  return children.at(i); // at does bounds checking
277  }
278 
279  const this_t& operator[](const size_t i) const {
280  return children.at(i);
281  }
282 
283  void set_child(const size_t i, this_t& n) {
290  while(children.size() <= i) // make it big enough for i
291  children.push_back(this_t());
292 
293  children[i] = n;
294  children[i].pi = i;
295  children[i].parent = static_cast<this_t*>(this);
296  }
297  void set_child(const size_t i, this_t&& n) {
303  // NOTE: if you add anything fancy to this, be sure to update the copy and move constructors
304 
305  while(children.size() <= i) // make it big enough for i
306  children.push_back(this_t());
307 
308  children[i] = n;
309  children[i].pi = i;
310  children[i].parent = static_cast<this_t*>(this);
311  }
312 
313  void push_back(this_t& n) {
314  set_child(children.size(), n);
315  }
316  void push_back(this_t&& n) {
317  set_child(children.size(), n);
318  }
319 
324  virtual bool is_root() const {
325  return parent == nullptr;
326  }
327 
328 
333  this_t* root() {
334  this_t* x = static_cast<this_t*>(this);
335  while(x->parent != nullptr) {
336  x = x->parent;
337  }
338  return x;
339  }
340 
346  this_t* get_via(std::function<bool(this_t&)>& f ) {
347  for(auto& n : *this) {
348  if(f(n)) return &n;
349  }
350  return nullptr;
351  }
352 
358  virtual size_t count() const {
359 
360  size_t n=1; // me
361  for(auto& c : children) {
362  n += c.count();
363  }
364  return n;
365  }
366 
372  virtual size_t count(const this_t& n) const {
373  size_t cnt = (n == *static_cast<const this_t*>(this));
374  for(auto& c : children) {
375  cnt += c.count(n);
376  }
377  return cnt;
378  }
379 
384  virtual bool is_terminal() const {
385  return children.size() == 0;
386  }
387 
388  virtual size_t count_terminals() const {
394  size_t cnt = 0;
395  for(const auto& n : *this) {
396  if(n.is_terminal()) ++cnt;
397  }
398  return cnt;
399  }
400 
401  virtual this_t* get_nth(int n, std::function<int(const this_t&)>& f) {
409  for(auto& x : *this) {
410  if(f(x)) {
411  if(n == 0) return &x;
412  else --n;
413  }
414  }
415 
416  return nullptr; // not here, losers
417  }
418  virtual this_t* get_nth(int n) { // default true on every node
419  std::function<int(const this_t&)> f = [](const this_t& x) { return 1;};
420  return get_nth(n, f);
421  }
422 
423 
424  template<typename T>
425  T sum(std::function<T(const this_t&)>& f ) const {
432  T s = f(* dynamic_cast<const this_t*>(this)); // a little ugly here because it needs to be the subclass type
433  for(auto& c: this->children) {
434  s += c.sum(f);
435  }
436  return s;
437  }
438 
439  template<typename T>
440  T sum(T(*f)(const this_t&) ) const {
441  std::function ff = f;
442  return sum(ff);
443  }
444 
445 
446  bool all(std::function<bool(const this_t&)>& f ) const {
453  if(not f(* dynamic_cast<const this_t*>(this)))
454  return false;
455 
456  for(auto& c: this->children) {
457  if(not c.all(f))
458  return false;
459  }
460  return true;
461  }
462 
463  void map( const std::function<void(this_t&)>& f) {
469  f(* dynamic_cast<const this_t*>(this));
470  for(auto& c: this->children) {
471  c.map(f);
472  }
473  }
474 
475 
476  void show(size_t t=0) const {
477 
478  std::string tabs(t,'\t');
479 
480  COUT tabs << this->my_string() ENDL;
481  for(auto& c : children) {
482  c.show(t+1);
483  }
484  }
485 
486 };
487 
488 
489 template<typename this_t>
491 
492 
493 
494 template<typename this_t>
495 std::ostream& operator<<(std::ostream& o, const BaseNode<this_t>& t) {
496  o << t.string();
497  return o;
498 }
virtual bool operator==(const this_t &n) const
Definition: BaseNode.h:82
void show(size_t t=0) const
Definition: BaseNode.h:476
virtual this_t * get_nth(int n, std::function< int(const this_t &)> &f)
Definition: BaseNode.h:401
size_t pi
Definition: BaseNode.h:27
void reserve_children(const size_t n)
Definition: BaseNode.h:164
decltype(children) & get_children()
Definition: BaseNode.h:168
std::vector< this_t > children
Definition: BaseNode.h:23
virtual bool is_terminal() const
Am I a terminal? I am if I have no children.
Definition: BaseNode.h:384
NodeIterator & operator++(int blah)
Definition: BaseNode.h:127
this_t * root()
Find the root of this node by walking up the tree.
Definition: BaseNode.h:333
void fix_child_info()
Definition: BaseNode.h:238
bool operator==(const NodeIterator &rhs) const
Definition: BaseNode.h:151
void push_back(this_t &n)
Definition: BaseNode.h:313
virtual std::string my_string() const
Definition: BaseNode.h:79
T sum(T(*f)(const this_t &)) const
Definition: BaseNode.h:440
void set_child(const size_t i, this_t &n)
Definition: BaseNode.h:283
this_t & operator*() const
Definition: BaseNode.h:118
this_t * get_via(std::function< bool(this_t &)> &f)
Return a pointer to the first node satisfying predicate f, in standard traversal; nullptr otherwise...
Definition: BaseNode.h:346
Definition: Errors.h:18
NodeIterator end() const
Definition: BaseNode.h:158
this_t & operator[](const size_t i)
Definition: BaseNode.h:269
decltype(children) const & get_children() const
Definition: BaseNode.h:171
T sum(std::function< T(const this_t &)> &f) const
Definition: BaseNode.h:425
NodeIterator & operator++()
Definition: BaseNode.h:128
virtual size_t count_terminals() const
Definition: BaseNode.h:388
BaseNode(this_t &&n)
Definition: BaseNode.h:44
void check_child_info() const
Definition: BaseNode.h:253
void map(const std::function< void(this_t &)> &f)
Definition: BaseNode.h:463
static NodeIterator EndNodeIterator
Definition: BaseNode.h:154
virtual bool operator!=(const this_t &n) const
Definition: BaseNode.h:160
BaseNode(size_t n=0, this_t *p=nullptr, size_t i=0)
Constructor of basenode – sizes children to n.
Definition: BaseNode.h:35
Definition: BaseNode.h:20
const this_t & child(const size_t i) const
Definition: BaseNode.h:185
void fill(size_t n, Args... args)
Definition: BaseNode.h:196
this_t * left_descend() const
Definition: BaseNode.h:217
NodeIterator(const this_t *n)
Definition: BaseNode.h:117
this_t & child(const size_t i)
Definition: BaseNode.h:175
void make_root()
Make a node root – just nulls the parent.
Definition: BaseNode.h:68
virtual std::string string(bool usedot=true) const
Definition: BaseNode.h:76
this_t * parent
Definition: BaseNode.h:26
Definition: BaseNode.h:95
#define ENDL
Definition: IO.h:21
virtual size_t count(const this_t &n) const
How many nodes below me are equal to n?
Definition: BaseNode.h:372
bool all(std::function< bool(const this_t &)> &f) const
Definition: BaseNode.h:446
BaseNode(const this_t &n)
Definition: BaseNode.h:38
bool operator!=(const NodeIterator &rhs) const
Definition: BaseNode.h:152
virtual this_t * get_nth(int n)
Definition: BaseNode.h:418
this_t * current
Definition: BaseNode.h:109
void operator=(const this_t &t)
Definition: BaseNode.h:51
size_t depth() const
Definition: BaseNode.h:230
const this_t * start
Definition: BaseNode.h:113
const this_t & operator[](const size_t i) const
Definition: BaseNode.h:279
void operator=(const this_t &&t)
Definition: BaseNode.h:57
void set_child(const size_t i, this_t &&n)
Definition: BaseNode.h:297
this_t * operator->() const
Definition: BaseNode.h:122
virtual ~BaseNode()
Definition: BaseNode.h:73
virtual size_t count() const
How many nodes total are below me?
Definition: BaseNode.h:358
NodeIterator & operator+(size_t n)
Definition: BaseNode.h:146
#define COUT
Definition: IO.h:24
NodeIterator begin() const
Definition: BaseNode.h:157
virtual bool is_root() const
Am I a root node? I am if my parent is nullptr.
Definition: BaseNode.h:324
size_t nchildren() const
Definition: BaseNode.h:208
void push_back(this_t &&n)
Definition: BaseNode.h:316