Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
detail_k_ary_tree.hpp
1//=======================================================================
2// Copyright 2018 Jeremy William Murphy
3//
4// Distributed under the Boost Software License, Version 1.0. (See
5// accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//=======================================================================
8
9#ifndef BOOST_GRAPH_DETAIL_K_ARY_TREE
10#define BOOST_GRAPH_DETAIL_K_ARY_TREE
11
12#include <boost/config.hpp>
13
14#include <boost/array.hpp>
15
16#include <boost/graph/graph_traits.hpp>
17
18#include <boost/iterator/filter_iterator.hpp>
19#include <boost/iterator/iterator_adaptor.hpp>
20
21#include <boost/range.hpp>
22#include <boost/range/adaptors.hpp>
23#include <boost/range/algorithm.hpp>
24#include <boost/range/algorithm_ext/is_sorted.hpp>
25
26#include <algorithm>
27#include <cstddef>
28#include <stack>
29#include <utility>
30#include <vector>
31
32namespace boost
33{
34template <typename Graph> using vertex_descriptor_t = typename graph_traits<Graph>::vertex_descriptor;
35
36namespace detail
37{
38
39template <typename BinaryTree> struct binary_tree_forward_node
40{
41 using vertex_descriptor = vertex_descriptor_t<BinaryTree>;
42
44 {
45 boost::fill(successors, graph_traits<BinaryTree>::null_vertex());
46 }
47
48 array<vertex_descriptor, 2> successors;
49};
50
51template <typename BinaryTree> struct binary_tree_bidirectional_node : binary_tree_forward_node<BinaryTree>
52{
53 using vertex_descriptor = vertex_descriptor_t<BinaryTree>;
54
55 binary_tree_bidirectional_node(vertex_descriptor predecessor = graph_traits<BinaryTree>::null_vertex())
56 : predecessor(predecessor)
57 {
58 }
59
60 vertex_descriptor predecessor;
61};
62
63template <typename Vertex, typename Node> class binary_tree_base
64{
65 protected:
66 std::vector<Node> nodes;
67 std::vector<Vertex> free_list;
68
69 public:
70 typedef Vertex vertex_descriptor;
71 typedef std::pair<vertex_descriptor, vertex_descriptor> edge_descriptor;
72 typedef disallow_parallel_edge_tag edge_parallel_category;
73 typedef std::size_t degree_size_type;
74 typedef std::size_t vertices_size_type;
75
76 BOOST_STATIC_CONSTEXPR
77 vertex_descriptor null_vertex()
78 {
79 return vertex_descriptor(-1);
80 }
81
82 binary_tree_base(Vertex n) : nodes(n), free_list{{n}}
83 {
84 }
85
86 std::size_t num_vertices() const
87 {
88 BOOST_ASSERT(!free_list.empty());
89 BOOST_ASSERT(free_list[0] == nodes.size());
90 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
91
92 return nodes.size() - free_list.size() + 1;
93 }
94
95 Node const &operator[](vertex_descriptor u) const
96 {
97 BOOST_ASSERT(!free_list.empty());
98 BOOST_ASSERT(free_list[0] == nodes.size());
99 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
100 BOOST_ASSERT(u < nodes.size());
101 BOOST_ASSERT(boost::find(free_list, u) == boost::end(free_list));
102
103 return nodes[u];
104 }
105
106 template <std::size_t N> bool has_successor(vertex_descriptor u) const
107 {
108 BOOST_ASSERT(!free_list.empty());
109 BOOST_ASSERT(free_list[0] == nodes.size());
110 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
111 BOOST_ASSERT(u < nodes.size());
112 BOOST_ASSERT(boost::find(free_list, u) == boost::end(free_list));
113
114 return nodes[u].successors[N] != null_vertex();
115 }
116
118 {
119 free_list.push_back(0);
120
121 BOOST_ASSERT(!free_list.empty());
122 BOOST_ASSERT(free_list[0] == nodes.size());
123 }
124
125 // *** IncidenceGraph ***
126
127 class out_edge_iterator : public boost::iterator_adaptor<out_edge_iterator, vertex_descriptor const *,
128 edge_descriptor, forward_traversal_tag, edge_descriptor>
129 {
130 vertex_descriptor const *last;
131 vertex_descriptor source;
132
133 public:
134 out_edge_iterator(Vertex const *first, Vertex const *last, Vertex source)
135 : out_edge_iterator::iterator_adaptor_(first), last(last), source(source)
136 {
137 BOOST_ASSERT(source != null_vertex());
138 post_increment();
139 }
140
141 private:
142 edge_descriptor dereference() const
143 {
144 return edge_descriptor(source, *this->base_reference());
145 }
146
147 void post_increment()
148 {
149 while (this->base_reference() != last && *this->base_reference() == null_vertex())
150 {
151 this->base_reference()++;
152 }
153 }
154
155 void increment()
156 {
157 this->base_reference()++;
158 post_increment();
159 }
160
161 friend class boost::iterator_core_access;
162 };
163
164 friend vertex_descriptor source(edge_descriptor e, binary_tree_base const &)
165 {
166 return e.first;
167 }
168
169 friend vertex_descriptor target(edge_descriptor e, binary_tree_base const &)
170 {
171 return e.second;
172 }
173
174 friend std::pair<out_edge_iterator, out_edge_iterator> out_edges(vertex_descriptor u, binary_tree_base const &g)
175 {
176 auto const &successors = g.nodes[u].successors;
177
178 return std::make_pair(out_edge_iterator(boost::begin(successors), boost::end(successors), u),
179 out_edge_iterator(boost::end(successors), boost::end(successors), u));
180 }
181
182 friend degree_size_type out_degree(vertex_descriptor v, binary_tree_base const &g)
183 {
184 return 2 - count(g.nodes[v].successors, null_vertex());
185 }
186
187 // *** VertexListGraph interface ***
188
189 struct vertex_iterator : public iterator_facade<vertex_iterator, vertex_descriptor, multi_pass_input_iterator_tag,
190 vertex_descriptor const &>
191 {
192 typedef iterator_facade<vertex_iterator, vertex_descriptor, multi_pass_input_iterator_tag,
193 vertex_descriptor const &>
194 super_t;
195 typedef typename super_t::value_type value_type;
196 typedef typename super_t::reference reference;
197
198 vertex_descriptor last;
199 std::stack<vertex_descriptor> traversal;
200 binary_tree_base const *g;
201
202 public:
203 vertex_iterator(binary_tree_base const &g) : g(&g)
204 {
205 }
206
207 vertex_iterator(vertex_descriptor start, binary_tree_base const &g) : last(g.null_vertex()), g(&g)
208 {
209 traversal.push(start);
210 while (has_left_successor(traversal.top(), g))
211 traversal.push(left_successor(traversal.top(), g));
212 }
213
214 private:
215 friend class boost::iterator_core_access;
216
217 reference dereference() const
218 {
219 return traversal.top();
220 }
221
222 void increment()
223 {
224 if (has_right_successor(traversal.top(), *g))
225 {
226 if (right_successor(traversal.top(), *g) != last)
227 {
228 traversal.push(right_successor(traversal.top(), *g));
229 while (has_left_successor(traversal.top(), *g))
230 traversal.push(left_successor(traversal.top(), *g));
231 return;
232 }
233 }
234
235 do
236 {
237 last = traversal.top();
238 traversal.pop();
239 } while (!traversal.empty() &&
240 (!has_right_successor(traversal.top(), *g) || right_successor(traversal.top(), *g) == last));
241 }
242
243 bool equal(vertex_iterator const &other) const
244 {
245 BOOST_ASSERT(g == other.g);
246
247 if (traversal.empty())
248 return other.traversal.empty();
249
250 if (other.traversal.empty())
251 return false;
252
253 return traversal.top() == other.traversal.top();
254 }
255 };
256
257 friend std::size_t num_vertices(binary_tree_base const &g)
258 {
259 return g.num_vertices();
260 }
261
262 friend std::pair<vertex_iterator, vertex_iterator> vertices(binary_tree_base const &g)
263 {
264 if (g.num_vertices() == 0)
265 return std::make_pair(vertex_iterator(g), vertex_iterator(g));
266 auto const start = default_starting_vertex(g);
267 return std::make_pair(vertex_iterator(start, g), vertex_iterator(g));
268 }
269
270 // *** MutableGraph interface ***
271
272 friend vertex_descriptor add_vertex(binary_tree_base &g)
273 {
274 return g.add_vertex();
275 }
276
277 friend void remove_vertex(vertex_descriptor u, binary_tree_base &g)
278 {
279 g.remove_vertex(u);
280 }
281
282 friend bool has_left_successor(Vertex u, binary_tree_base const &g)
283 {
284 return g.template has_successor<0>(u);
285 }
286
287 friend bool has_right_successor(Vertex u, binary_tree_base const &g)
288 {
289 return g.template has_successor<1>(u);
290 }
291
292 friend Vertex left_successor(Vertex u, binary_tree_base const &g)
293 {
294 return g.nodes[u].successors[0];
295 }
296
297 friend Vertex right_successor(Vertex u, binary_tree_base const &g)
298 {
299 return g.nodes[u].successors[1];
300 }
301
302 void clear()
303 {
304 nodes.clear();
305 free_list.resize(1);
306 free_list[0] = 0;
307 }
308
309 void shrink_to_fit()
310 {
311 nodes.shrink_to_fit();
312 free_list.shrink_to_fit();
313 }
314
315 friend Vertex default_starting_vertex(binary_tree_base const &g)
316 {
317 Vertex start = 0;
318 if (g.free_list.size() != 1)
319 {
320 auto const not_successors = [](auto x, auto y) { return ++x != y; };
321 auto const q = boost::adjacent_find(adaptors::reverse(g.free_list), not_successors);
322 start = *q + 1;
323 }
324 return start;
325 }
326
327 protected:
328 /**************************
329 * MutableGraph interface *
330 **************************/
331
332 // Adds an edge between vertices, adding them if necessary.
333 std::pair<edge_descriptor, bool> add_edge(vertex_descriptor u, vertex_descriptor v)
334 {
335 BOOST_ASSERT(u != v);
336
337 BOOST_ASSERT(!free_list.empty());
338 BOOST_ASSERT(free_list[0] == nodes.size());
339 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
340
341 add_vertex(u);
342 add_vertex(v);
343 auto const result = add_edge_strict(u, v);
344 BOOST_ASSERT(!free_list.empty());
345 BOOST_ASSERT(free_list[0] == nodes.size());
346 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
347 return result;
348 }
349
350 // Adds an edge between existing vertices.
351 std::pair<edge_descriptor, bool> add_edge_strict(vertex_descriptor u, vertex_descriptor v)
352 {
353 BOOST_ASSERT(u != v);
354 BOOST_ASSERT(u < nodes.size());
355 BOOST_ASSERT(v < nodes.size());
356 BOOST_ASSERT(find(free_list, u) == find(free_list, v));
357
358 BOOST_ASSERT(!free_list.empty());
359 BOOST_ASSERT(free_list[0] == nodes.size());
360 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
361
362 array<vertex_descriptor, 2> const keys{{null_vertex(), v}};
363 auto const p = find_first_of(nodes[u].successors, keys); // O(k)
364 edge_descriptor const result(u, v);
365
366 if (p == boost::end(nodes[u].successors) or *p == v)
367 return std::make_pair(result, false);
368 else
369 {
370 *p = v;
371 return std::make_pair(result, true);
372 }
373 }
374
375 void remove_edge(vertex_descriptor u, vertex_descriptor v)
376 {
377 BOOST_ASSERT(u != v);
378 BOOST_ASSERT(u < nodes.size() && v < nodes.size());
379 BOOST_ASSERT(find(free_list, u) == find(free_list, v)); // i.e., end.
380
381 BOOST_ASSERT(!free_list.empty());
382 BOOST_ASSERT(free_list[0] == nodes.size());
383 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
384
385 auto const p = find(nodes[u].successors, v);
386 BOOST_ASSERT(p != boost::end(nodes[u].successors));
387 *p = null_vertex();
388 }
389
390 vertex_descriptor add_vertex()
391 {
392 BOOST_ASSERT(!free_list.empty());
393 BOOST_ASSERT(free_list[0] == nodes.size());
394 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
395 BOOST_ASSERT(nodes.size() >= free_list.back() + 1 || free_list.size() == 1);
396
397 vertex_descriptor const result = free_list.back();
398 if (free_list.size() == 1)
399 {
400 nodes.resize(result + 1);
401 free_list.back() = nodes.size();
402 }
403 else
404 free_list.pop_back();
405 BOOST_ASSERT(!free_list.empty());
406 BOOST_ASSERT(free_list[0] == nodes.size());
407 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
408 return result;
409 }
410
411 // Internal use.
412 bool add_vertex(vertex_descriptor u)
413 {
414 BOOST_ASSERT(!free_list.empty());
415 BOOST_ASSERT(free_list[0] == nodes.size());
416 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
417
418 // First handle the case where it's not on the free list.
419 if (nodes.size() < u)
420 {
421 free_list.reserve(free_list.size() + u - nodes.size());
422 for (auto i = u - 1; i != nodes.size() - 1; i--)
423 free_list.push_back(i);
424 nodes.resize(u + 1);
425 free_list[0] = nodes.size();
426 BOOST_ASSERT(!free_list.empty());
427 BOOST_ASSERT(free_list[0] == nodes.size());
428 return true;
429 }
430
431 auto const which = find(free_list, u);
432 if (which == boost::begin(free_list))
433 {
434 (*which)++;
435 nodes.resize(*which);
436 }
437 else
438 {
439 if (which == boost::end(free_list))
440 return false;
441 free_list.erase(which);
442 }
443
444 BOOST_ASSERT(!free_list.empty());
445 BOOST_ASSERT(free_list[0] == nodes.size());
446 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
447 return true;
448 }
449
450 void remove_vertex(vertex_descriptor u)
451 {
452 BOOST_ASSERT(u || nodes.size() == 1); // FIXME: Kludge for now.
453
454 BOOST_ASSERT(num_vertices() > 0);
455 BOOST_ASSERT(!free_list.empty());
456 BOOST_ASSERT(free_list[0] == nodes.size());
457 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
458 BOOST_ASSERT(find(free_list, u) == boost::end(free_list));
459 BOOST_ASSERT(out_degree(u, *this) == 0);
460
461 if (u == nodes.size() - 1)
462 {
463 // happens to be the last node
464 if (free_list.size() == 1)
465 {
466 // simple case, no other nodes to consider
467 free_list[0]--;
468 nodes.pop_back();
469 }
470 else
471 {
472 // might be a run of nodes to erase
473 auto const not_successors = [](auto x, auto y) { return x != ++y; };
474 auto const least = boost::adjacent_find(free_list, not_successors);
475 auto const n = least - boost::begin(free_list);
476 nodes.erase(boost::end(nodes) - n, boost::end(nodes)); // pop_back(n)
477 free_list.erase(boost::begin(free_list), least); // pop_front(n) :/
478 }
479 }
480 else
481 {
482 auto const here = boost::lower_bound(free_list, u, std::greater<>());
483 free_list.insert(here, u);
484 }
485
486 BOOST_ASSERT(find(free_list, u) != boost::end(free_list));
487 BOOST_ASSERT(!free_list.empty());
488 BOOST_ASSERT(free_list[0] == nodes.size());
489 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
490 }
491
492 void clear_vertex(vertex_descriptor u)
493 {
494 BOOST_ASSERT(num_vertices() > 0);
495 BOOST_ASSERT(!free_list.empty());
496 BOOST_ASSERT(free_list[0] == nodes.size());
497 BOOST_ASSERT(free_list[0] == nodes.size());
498 BOOST_ASSERT(find(free_list, u) == boost::end(free_list));
499
500 boost::fill(nodes[u].successors, null_vertex());
501 }
502
503 /*******************************
504 * MutableBinaryTree interface *
505 *******************************/
506
507 edge_descriptor add_left_edge(vertex_descriptor parent, vertex_descriptor child)
508 {
509 BOOST_ASSERT(parent != child);
510 BOOST_ASSERT(parent < nodes.size());
511 BOOST_ASSERT(child < nodes.size());
512 BOOST_ASSERT(find(free_list, parent) == find(free_list, child));
513
514 BOOST_ASSERT(!free_list.empty());
515 BOOST_ASSERT(free_list[0] == nodes.size());
516 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
517
518 BOOST_ASSERT(!has_left_successor(parent, *this));
519
520 nodes[parent].successors[0] = child;
521
522 BOOST_ASSERT(has_left_successor(parent, *this));
523 BOOST_ASSERT(left_successor(parent, *this) == child);
524
525 return {parent, child};
526 }
527
528 edge_descriptor add_right_edge(vertex_descriptor parent, vertex_descriptor child)
529 {
530 BOOST_ASSERT(parent != child);
531 BOOST_ASSERT(parent < nodes.size());
532 BOOST_ASSERT(child < nodes.size());
533 BOOST_ASSERT(find(free_list, parent) == find(free_list, child));
534
535 BOOST_ASSERT(!free_list.empty());
536 BOOST_ASSERT(free_list[0] == nodes.size());
537 BOOST_ASSERT(boost::is_sorted(free_list, std::greater<>()));
538
539 BOOST_ASSERT(!has_right_successor(parent, *this));
540
541 nodes[parent].successors[1] = child;
542
543 BOOST_ASSERT(has_right_successor(parent, *this));
544 BOOST_ASSERT(right_successor(parent, *this) == child);
545
546 return {parent, child};
547 }
548};
549} // namespace detail
550} // namespace boost
551
552#endif
Definition detail_k_ary_tree.hpp:129
Definition detail_k_ary_tree.hpp:64
Definition cardinal_k_ary_tree.hpp:46
Definition newick_generator_5.cpp:7
Definition detail_k_ary_tree.hpp:191
Definition detail_k_ary_tree.hpp:52
Definition detail_k_ary_tree.hpp:40