pruner  0.0-99
tree_meat.hpp
1 #ifndef H_PRUNER
2 #include <vector>
3 #include "typedefs.hpp"
4 #include "tree_bones.hpp"
5 #include "treeiterator_bones.hpp"
6 #include "treeiterator_meat.hpp"
7 // #include <memory> // For the std::shared_ptr
8 #endif
9 
10 #ifndef H_PRUNER_TREE_MEAT
11 #define H_PRUNER_TREE_MEAT
12 
13 // Pruning ---------------------------------------------------------------------
14 
15 // Function to get the pre and post order
16 template <typename Data_Type>
17 inline void Tree<Data_Type>::postorder() {
18 
19  // If it is not initialized
20  if (this->POSTORDER.size() == 0u)
21  POSTORDER.reserve(this->N_NODES);
22 
23  // We can start the algorithm from any place
24  postorder_(0u);
25  POSTORDER.shrink_to_fit();
26 
27  this->reset_visited();
28 
29  return;
30 }
31 
32 template <typename Data_Type>
33 inline void Tree<Data_Type>::postorder_(uint i) {
34 
35  // Setting the state to visited
36  this->visited[i] = true;
37 
38  // First, check the offspring
39  for (uint j = 0u; j < this->offspring[i].size(); ++j) {
40 
41  // Nothing to do here
42  if (this->visited[this->offspring[i][j]])
43  continue;
44 
45  postorder_(this->offspring[i][j]);
46 
47  }
48 
49  // After visiting all of its childs, we need to add this node to the pruning
50  // sequence and continue with its parent(s).
51  POSTORDER.push_back(i);
52  for (uint j = 0u; j < this->parents[i].size(); ++j) {
53 
54  // Nothing to do here
55  if (this->visited[this->parents[i][j]])
56  continue;
57 
58  postorder_(this->parents[i][j]);
59 
60  }
61 
62  return;
63 }
64 
65 // Returns an edgelist in the form a vector of two uint vectors.
66 template <typename Data_Type>
67 inline vv_uint Tree<Data_Type>::get_edgelist() const {
68 
69  vv_uint res(2u);
70 
71  // We know the number of edges before hand, so we better save the space
72  // up-front.
73  res[0u].reserve(this->N_EDGES);
74  res[1u].reserve(this->N_EDGES);
75 
76  for (uint i = 0u; i < this->N_NODES; ++i) {
77  for (uint j = 0u; j < this->offspring[i].size(); ++j) {
78  res[0u].push_back(i);
79  res[1u].push_back(this->offspring[i][j]);
80  }
81  }
82 
83  return res;
84 
85 }
86 
87 template <typename Data_Type>
88 inline void Tree<Data_Type>::print(bool details) const {
89 
90  // Basic information
91  printf(
92  "tree structure with %i nodes and %i edges.\n",
93  this->n_nodes(), this->n_edges()
94  );
95 
96  // When details are true, information regarding the offspring and parents
97  // is shown.
98  if (!details)
99  return;
100 
101  // What is sais below (just divide the sections :P)
102  printf("List of offspring:\n");
103  for (uint i = 0u; i < this->offspring.size(); ++i) {
104 
105  printf("%4i: [", i);
106 
107  if (this->offspring[i].size() == 0u)
108  printf(" -");
109  else {
110  v_uint::const_iterator iter;
111  for (iter = this->offspring[i].begin(); iter != this->offspring[i].end(); ++iter)
112  printf(" %i", *iter);
113  }
114 
115  printf(" ]\n");
116 
117  }
118 
119  // What is sais below (just divide the sections :P)
120  printf("List of parents:\n");
121  for (uint i = 0u; i < this->parents.size(); ++i) {
122 
123  printf("%4i: [", i);
124 
125  if (this->parents[i].size() == 0u)
126  printf(" -");
127  else {
128  v_uint::const_iterator iter;
129  for (iter = this->parents[i].begin(); iter != this->parents[i].end(); ++iter)
130  printf(" %i", *iter);
131  }
132 
133  printf(" ]\n");
134 
135  }
136 
137  return;
138 
139 }
140 
141 // Return codes:
142 // 0: OK
143 // 1: Sizes of parent and offspring differ
144 // 2: MAX_TREE_SIZE reached.
145 // 3: Disconnected tree
146 // 4: Not a Dag.
147 template <typename Data_Type>
148 inline Tree<Data_Type>::Tree(const v_uint & parents_, const v_uint & offspring_, uint & out) {
149 
150  // If different sizes, then it shouldn't work
151  if (parents_.size() != offspring_.size()) {
152  out = 1u;
153  return;
154  }
155 
156  // Checking ranges
157  uint maxid = 0u, m = parents_.size();
158  for (uint i = 0u; i < m; ++i) {
159  if ((parents_[i] > MAX_TREE_SIZE) || (offspring_[i] > MAX_TREE_SIZE)) {
160  out = 2u;
161  return;
162  }
163 
164  if (maxid < parents_[i])
165  maxid = parents_[i];
166  if (maxid < offspring_[i])
167  maxid = offspring_[i];
168  }
169 
170  // Resizing the vectors
171  this->parents.resize(maxid + 1u);
172  this->offspring.resize(maxid + 1u);
173 
174  this->visited.resize(maxid + 1u, false);
175  this->visit_counts.resize(maxid + 1u, 0u);
176 
177  // Adding the data
178  for (uint i = 0u; i < m; ++i) {
179  this->offspring[parents_[i]].push_back(offspring_[i]);
180  this->parents[offspring_[i]].push_back(parents_[i]);
181  }
182 
183 
184  // Constants
185  this->N_NODES = (uint) maxid + 1u;
186  this->N_EDGES = m;
187 
188  // Generating the postorder sequence
189  this->postorder();
190 
191  // Initializing iterator
192  this->iter = TreeIterator<Data_Type>(this);
193 
194  // Some checks
195  if (!this->is_connected()) {
196 
197  out = 3u;
198  return;
199 
200  } else if (!this->is_dag()) {
201 
202  out = 4u;
203  return;
204 
205  }
206 
207  // Marking tip nodes
208  int status = 0;
209  this->iter.bottom();
210  this->TIPS.reserve(this->n_tips());
211  while ( status == 0 ) {
212  if (this->iter.is_tip())
213  this->TIPS.push_back(*this->iter);
214  status = this->iter.up();
215  }
216  this->iter.bottom();
217 
218 
219  out = 0u;
220  return;
221 
222 }
223 
224 // A recursive function to check whether the tree is a DAG or not. -------------
225 typedef v_uint::const_iterator v_uint_iter;
226 
227 template <typename Data_Type>
228 inline bool Tree<Data_Type>::is_dag() {
229 
230  bool res = this->is_dag_();
231  this->reset_visited();
232 
233  return res;
234 
235 }
236 
237 template <typename Data_Type>
238 inline bool Tree<Data_Type>::is_dag_(int i, int caller, bool up_search) {
239 
240  // For the first iteration
241  if (i < 0)
242  i = 0u, caller = -1;
243 
244  // Yes, this is not a dag (came here multiple times)
245  if (this->visited[i])
246  return false;
247  this->visited[i] = true;
248 
249  // Iterating through parents
250  for (v_uint_iter n = this->parents[i].begin(); n != this->parents[i].end(); ++n) {
251 
252 #ifdef DEBUG_TREE
253  std::printf(
254  "Tree<Data_Type>::is_dag() @ parents (i, caller, *n, up_search): (%i, %i, %i, %i)\n",
255  i, caller, *n, up_search
256  );
257 #endif
258 
259  // Checking 1:1 cycles
260  if ((int) *n == caller) {
261 #ifdef DEBUG_TREE
262  std::printf("\tChecking 1:1 cycles.\n");
263 #endif
264  if (up_search) return false;
265  else continue;
266  }
267 
268  if (!(this->is_dag_((int) *n, i, true)))
269  return false;
270  }
271 
272  // Iterating through offspring
273  for (v_uint_iter n = this->offspring[i].begin(); n != this->offspring[i].end(); ++n) {
274 
275 #ifdef DEBUG_TREE
276  std::printf(
277  "Tree<Data_Type>::is_dag() @ offspring (i, caller, *n, up_search): (%i, %i, %i, %i)\n",
278  i, caller, *n, up_search
279  );
280 #endif
281 
282  // Checking 1:1 cycles
283  if ((int) *n == caller) {
284 #ifdef DEBUG_TREE
285  std::printf("\tChecking 1:1 cycles.\n");
286 #endif
287  if (!up_search) return false;
288  else continue;
289  }
290 
291  if (!(this->is_dag_((int) *n, i, false)))
292  return false;
293  }
294 
295  return true;
296 
297 }
298 
299 // The preorder is just the post order reversed
300 template <typename Data_Type>
301 inline v_uint Tree<Data_Type>::get_preorder() const {
302 
303  v_uint res = this->get_postorder();
304  std::reverse(res.begin(), res.end());
305  return res;
306 
307 }
308 
309 template <typename Data_Type>
310 inline uint Tree<Data_Type>::get_dist_tip2root_(uint i, uint count) {
311 
312  // If we are already in a root node, then return with the reached count
313  if (parents[i].size() == 0u)
314  return count;
315 
316  // We start by adding one step (since we are not at the root!)
317  ++count;
318 
319  // Otherwise, let's see at its parents (who is closests to the root)
320  v_uint counts(parents[i].size());
321  uint j = 0;
322  for (auto iter = parents[i].begin(); iter != parents[i].end(); ++iter) {
323 
324  // Looking how far do we reach
325  counts[j] = get_dist_tip2root_(*iter, count);
326 
327  // If we reached to root in the next step. Otherwise we need to keep looking
328  // until we get to that is closests.
329  if (counts[j++] == count)
330  return count;
331 
332  }
333 
334  // We keep the smallest one
335  count = counts[0];
336  for (auto iter = counts.begin() + 1; iter != counts.end(); ++iter)
337  if (*iter < count)
338  count = *iter;
339 
340  return count;
341 }
342 
343 template <typename Data_Type>
345 
346  if (this->DIST_TIPS2ROOT.size() == 0u) {
347 
348  // Making space available
349  this->DIST_TIPS2ROOT.resize(this->n_tips());
350 
351  for (uint i = 0u; i < TIPS.size(); ++i)
352  DIST_TIPS2ROOT[i] = get_dist_tip2root_(TIPS[i], 0u);
353 
354  }
355 
356  return this->DIST_TIPS2ROOT;
357 
358 }
359 
360 #define TOTAL(a) (a)->offspring.size()
361 
362 template <typename Data_Type>
363 inline uint Tree<Data_Type>::set_postorder(const v_uint & POSTORDER_, bool check) {
364 
365  // Checking the range of the data
366  if (check) {
367  uint min_idx = 999999u, max_idx = 0u;
368  for (auto i = POSTORDER_.begin(); i != POSTORDER_.end(); ++i) {
369 
370  if (*i > max_idx) max_idx = *i;
371  if (*i < min_idx) min_idx = *i;
372 
373  }
374 
375  if ((min_idx > max_idx) | (min_idx > TOTAL(this)) | (max_idx > TOTAL(this)))
376  return 1u;
377  }
378 
379  this->POSTORDER = POSTORDER_;
380 
381  return 0u;
382 }
383 
384 template <typename Data_Type>
386 
387  // Set the head in the first node of the sequence
388  this->iter.bottom();
389  int status = 0;
390  while (status == 0) {
391 
392  this->eval_fun();
393  status = this->iter.up();
394 
395  }
396 
397  return;
398 
399 }
400 
401 template <typename Data_Type>
402 inline void Tree<Data_Type>::prune_postorder(v_uint & seq) {
403 
404  // Let's reset the sequence
405  v_uint OLDPOSTORDER = POSTORDER;
406  POSTORDER.swap(seq);
407 
408  // Set the head in the first node of the sequence
409  this->iter.bottom();
410  int status = 0;
411  while (status == 0) {
412 
413  this->eval_fun();
414  status = this->iter.up();
415 
416  }
417 
418  // Going back to the previous order
419  POSTORDER.swap(OLDPOSTORDER);
420 
421  return;
422 
423 }
424 
425 template <typename Data_Type>
427 
428  // Set the head in the first node of the sequence
429  this->iter.top();
430  int status = 0;
431  while (status == 0) {
432 
433  this->eval_fun();
434  status = this->iter.down();
435 
436  }
437 
438  return;
439 
440 }
441 
442 template <typename Data_Type>
443 inline void Tree<Data_Type>::prune_preorder(v_uint & seq) {
444 
445  // Let's reset the sequence
446  v_uint OLDPOSTORDER = POSTORDER;
447  POSTORDER.swap(seq);
448 
449  // Set the head in the first node of the sequence
450  this->iter.top();
451  int status = 0;
452  while (status == 0) {
453 
454  this->eval_fun();
455  status = this->iter.down();
456 
457  }
458 
459  // Going back to the previous order
460  POSTORDER.swap(OLDPOSTORDER);
461 
462  return;
463 
464 }
465 
466 template <typename Data_Type>
467 inline uint Tree<Data_Type>::n_tips() const {
468 
469  uint count = 0u;
470  for (auto i = this->offspring.begin(); i != offspring.end(); ++i)
471  if (i->size() == 0u)
472  ++count;
473 
474  return count;
475 
476 }
477 
478 template <typename Data_Type>
479 inline int Tree<Data_Type>::n_offspring(uint i) const {
480 
481  if (i < this->offspring.size()) {
482  return this->offspring.at(i).size();
483  }
484  return -1;
485 }
486 
487 template <typename Data_Type>
488 inline int Tree<Data_Type>::n_parents(uint i) const {
489 
490  if (i < this->parents.size()) {
491  return this->parents.at(i).size();
492  }
493  return -1;
494 }
495 
496 #endif
497 
void prune_postorder()
Do the tree-traversal using the postorder.
Definition: tree_meat.hpp:385
uint n_tips() const
Return the number of tips defined as nodes with no offspring.
Definition: tree_meat.hpp:467
int n_parents(uint i) const
Return the number of parents a given node has.
Definition: tree_meat.hpp:488
void prune_preorder()
Do the tree-traversal using the preorder.
Definition: tree_meat.hpp:426
Tree class.
Definition: tree_bones.hpp:36
int n_offspring(uint i) const
Return the number of offsprings a given node has.
Definition: tree_meat.hpp:479
Definition: treeiterator_bones.hpp:12
v_uint get_dist_tip2root()
Distance of tips to the closest root.
Definition: tree_meat.hpp:344