Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
binary_tree.hpp
1// Copyright 2021 Arnaud Becheler <abechele@umich.edu>
2
10
11#pragma once
12
13#include <type_traits>
14
15#include <boost/range/iterator_range.hpp>
16#include <range/v3/all.hpp>
17#include <ranges>
18
19#include <boost/graph/graphviz.hpp>
20
21#include "detail/adl_resolution.hpp"
22#include "detail/cardinal_k_ary_tree.hpp"
23#include "detail/tree_traits.hpp"
24#include "detail/utils.hpp"
25
26#include <algorithm>
27#include <iterator>
28#include <tuple>
29#include <utility>
30
32{
33
34using no_property = boost::no_property;
35
36namespace detail
37{
38
39// Getting std::map::emplace to work with aggregate initialization for POD EdgeProperties
40template <typename T> struct tag
41{
42 using type = T;
43};
44
45template <typename F> struct initializer
46{
47 F f;
48 template <typename T> operator T() &&
49 {
50 return std::forward<F>(f)(tag<T>{});
51 }
52};
53
54template <typename F> initializer(F &&) -> initializer<F>;
55
56template <typename... Args> auto initpack(Args &&...args)
57{
58 return initializer{[&](auto t) {
59 using Ret = typename decltype(t)::type;
60 return Ret{std::forward<Args>(args)...};
61 }};
62}
63
64template <typename VertexDescriptor, typename VertexProperty> struct VertexManager
65{
66 using vertex_descriptor = VertexDescriptor;
67 using vertex_hashmap_type = std::map<vertex_descriptor, VertexProperty>;
68
69 vertex_hashmap_type _property_map;
70
71 template <typename... Args> void add_vertex_to_manager(vertex_descriptor v, Args &&...args)
72 {
73 _property_map[v] = {std::forward<Args>(args)...};
74 }
75
76 const VertexProperty &operator[](vertex_descriptor v) const
77 {
78 return _property_map.at(v);
79 }
80
81 VertexProperty &operator[](vertex_descriptor v)
82 {
83 return _property_map[v];
84 }
85};
86
87template <typename EdgeDescriptor, typename EdgeProperty> struct EdgeManager
88{
89 using edge_descriptor = EdgeDescriptor;
90 using vertex_descriptor = typename EdgeDescriptor::first_type;
91 using edge_hashmap_type = std::map<edge_descriptor, EdgeProperty>;
92
93 edge_hashmap_type _property_map;
94
95 void add_edges(EdgeDescriptor u, const EdgeProperty &left, EdgeDescriptor v, const EdgeProperty &right)
96 {
97 _property_map.insert({u, left});
98 _property_map.insert({v, right});
99 }
100
101 template <typename... Args>
102 void add_edges(EdgeDescriptor u, std::tuple<Args...> left, EdgeDescriptor v, std::tuple<Args...> right)
103 {
104 _property_map.emplace(
105 std::piecewise_construct, std::forward_as_tuple(u),
106 std::forward_as_tuple(std::apply([](auto &&...args) { return initpack(args...); }, left)));
107 _property_map.emplace(
108 std::piecewise_construct, std::forward_as_tuple(v),
109 std::forward_as_tuple(std::apply([](auto &&...args) { return initpack(args...); }, right)));
110 }
111
112 template <typename VertexDescriptor>
113 const EdgeProperty &operator[](const std::pair<VertexDescriptor, VertexDescriptor> &edge) const
114 {
115 return _property_map.at(edge);
116 }
117
118 template <typename VertexDescriptor>
119 EdgeProperty &operator[](const std::pair<VertexDescriptor, VertexDescriptor> &edge)
120 {
121 return _property_map.at(edge);
122 }
123};
124
125template <class VertexProperty, class EdgeProperty> class binary_tree_common
126{
127 protected:
130 base _graph;
131
132 public:
135 {
136 }
137
139 binary_tree_common(size_t n) : _graph(n)
140 {
141 }
142
144 using vertex_descriptor = typename base::vertex_descriptor;
145
147 using edge_descriptor = typename base::edge_descriptor;
148
150 using degree_size_type = typename base::degree_size_type;
151
153 using traversal_category = typename base::traversal_category;
154
156 using directed_category = typename base::directed_category;
157
159 using in_edge_iterator = typename base::in_edge_iterator;
160
161 using edge_parallel_category = typename base::edge_parallel_category;
162
165
170 bool is_isomorphic(binary_tree_common const &other) const
171 {
172 using detail::adl_resolution::isomorphism;
173 return isomorphism(_graph, other._graph);
174 }
175
181 {
182 using detail::adl_resolution::root;
183 return root(u, _graph);
184 }
185
190 {
191 using detail::adl_resolution::degree;
192 return degree(u, _graph);
193 }
194
199 {
200 return has_predecessor(u);
201 }
202
205 {
206 using detail::adl_resolution::out_degree;
207 return out_degree(v, _graph);
208 }
209
214 {
215 using detail::adl_resolution::has_predecessor;
216 return has_predecessor(u, _graph);
217 }
218
223 {
224 using detail::adl_resolution::predecessor;
225 return predecessor(u, _graph);
226 }
227
232 {
233 return out_degree(u) == 2;
234 }
235
240 {
241 return boost::make_iterator_range(out_edges(u, _graph)) |
242 boost::adaptors::transformed([this](auto it) { return target(it, _graph); });
243 }
244
249 {
250 using detail::adl_resolution::is_left_successor;
251 return is_left_successor(u, _graph);
252 }
253
258 {
259 using detail::adl_resolution::is_right_successor;
260 return is_right_successor(u, _graph);
261 }
262
264
267
271 std::pair<in_edge_iterator, in_edge_iterator> in_edges(vertex_descriptor u) const
272 {
273 using detail::adl_resolution::in_edges;
274 return in_edges(u, _graph);
275 }
276
278
281
286 template <typename DFSTreeVisitor> void depth_first_search(vertex_descriptor s, DFSTreeVisitor &vis)
287 {
288 // delete the member function void depth_first_search(vertex_descriptor s, DFSTreeVisitor &vis) const
289 // using detail::adl_resolution::depth_first_search;
290 // ADL is now enabled
291 return boost::depth_first_search(_graph, s, vis);
292 }
293
298 template <typename DFSTreeVisitor> void depth_first_search(vertex_descriptor s, DFSTreeVisitor &vis) const
299 {
300 // delete the member function void depth_first_search(vertex_descriptor s, DFSTreeVisitor &vis)
301 // using detail::adl_resolution::depth_first_search;
302 // ADL is now enabled
303 return boost::depth_first_search(_graph, s, vis);
304 }
305
307
310
312 void to_graphviz(std::ostream &out) const
313 {
314 using namespace boost;
315 return boost::write_graphviz(out, *this, boost::make_label_writer(boost::get(vertex_bundle, *this)),
316 boost::make_label_writer(boost::get(edge_bundle, *this)));
317 }
318
320
321 static constexpr inline vertex_descriptor null_vertex()
322 {
323 return base::null_vertex();
324 }
325};
326
327} // end namespace detail
328
329template <class VertexProperty, class EdgeProperty> class binary_tree
330{
331};
332
350template <> class binary_tree<no_property, no_property> : public detail::binary_tree_common<no_property, no_property>
351{
353
354 public:
357
359 explicit binary_tree() : base()
360 {
361 }
362
364 explicit binary_tree(size_t n) : base(n)
365 {
366 }
368
371
374 {
375 // ADL intended to happen on that name, somewhere in that scope.
376 using boost::add_vertex;
377 return add_vertex(_graph);
378 }
379
381 std::pair<edge_descriptor, edge_descriptor> add_edges(vertex_descriptor parent, vertex_descriptor left,
382 vertex_descriptor right)
383 {
384 assert(parent != left);
385 assert(parent != right);
386 assert(left != right);
387 return std::make_pair(add_left_edge(parent, left, _graph), add_right_edge(parent, right, _graph));
388 }
389
391
392}; // end specialization binary_tree<boost::no::property, boost::no_property>
393
412template <class VertexProperty>
413 requires(!std::is_same_v<VertexProperty, no_property>)
414class binary_tree<VertexProperty, no_property> : public detail::binary_tree_common<VertexProperty, no_property>
415{
416 private:
419
420 public:
423
426
429
431 explicit binary_tree() : base()
432 {
433 }
434
436 explicit binary_tree(size_t n) : base(n)
437 {
438 }
439
441
444
446 vertex_descriptor add_vertex(const VertexProperty &p)
447 {
448 // ADL intended to happen on that name, somewhere in that scope.
449 using boost::add_vertex;
450 vertex_descriptor v = add_vertex(this->_graph);
451 _vertex_manager.add_vertex_to_manager(v, p);
452 return v;
453 }
454
456 std::pair<edge_descriptor, edge_descriptor> add_edges(vertex_descriptor parent, vertex_descriptor left,
457 vertex_descriptor right)
458 {
459 assert(parent != left);
460 assert(parent != right);
461 assert(left != right);
462 return {add_left_edge(parent, left, this->_graph), add_right_edge(parent, right, this->_graph)};
463 }
464
466
469
471 const VertexProperty &operator[](vertex_descriptor v) const
472 {
473 return _vertex_manager[v];
474 }
475
477 VertexProperty &operator[](vertex_descriptor v)
478 {
479 return _vertex_manager[v];
480 }
481
483
484}; // end specialization binary_tree<Vertex, boost::no_property>
485
500template <class EdgeProperty>
501 requires(!std::is_same_v<EdgeProperty, no_property>)
502class binary_tree<no_property, EdgeProperty> : public detail::binary_tree_common<no_property, EdgeProperty>
503{
504 private:
507
508 public:
511
514
517
519 explicit binary_tree() : base()
520 {
521 }
522
524 explicit binary_tree(size_t n) : base(n)
525 {
526 }
527
529
532
534 vertex_descriptor add_vertex()
535 {
536 // ADL intended to happen on that name, somewhere in that scope.
537 using boost::add_vertex;
538 return add_vertex(this->_graph);
539 }
540
542 std::pair<edge_descriptor, edge_descriptor> add_edges(vertex_descriptor parent,
543 const std::pair<vertex_descriptor, EdgeProperty> &left,
544 const std::pair<vertex_descriptor, EdgeProperty> &right)
545 {
546 assert(parent != left.first);
547 assert(parent != right.first);
548 assert(left.first != right.first);
549
550 auto left_edge = add_left_edge(parent, left.first, this->_graph);
551 auto right_edge = add_right_edge(parent, right.first, this->_graph);
552
553 _edge_manager.add_edges(left_edge, left.second, right_edge, right.second);
554 return {left_edge, right_edge};
555 }
556
558
561
563 const EdgeProperty &operator[](const edge_descriptor &edge) const
564 {
565 return _edge_manager[edge];
566 }
567
569 EdgeProperty &operator[](const edge_descriptor &edge)
570 {
571 return _edge_manager[edge];
572 }
573
575
576}; // end specialization binary_tree<boost::no_property, Edge>
577
597template <class VertexProperty, class EdgeProperty>
598 requires(!std::is_same_v<VertexProperty, no_property> && !std::is_same_v<EdgeProperty, no_property>)
599class binary_tree<VertexProperty, EdgeProperty> : public detail::binary_tree_common<VertexProperty, EdgeProperty>
600{
601 private:
605
606 public:
609
612
615
617 explicit binary_tree() : base()
618 {
619 }
620
622 explicit binary_tree(size_t n) : base(n)
623 {
624 }
625
627
630
632 vertex_descriptor add_vertex(const VertexProperty &p)
633 {
634 // ADL intended to happen on that name, somewhere in that scope.
635 using boost::add_vertex;
636 vertex_descriptor v = add_vertex(this->_graph);
637 _vertex_manager.add_vertex_to_manager(v, p);
638 return v;
639 }
640
642 std::pair<edge_descriptor, edge_descriptor> add_edges(vertex_descriptor parent,
643 const std::pair<vertex_descriptor, EdgeProperty> &left,
644 const std::pair<vertex_descriptor, EdgeProperty> &right)
645 {
646 assert(parent != left.first);
647 assert(parent != right.first);
648 assert(left.first != right.first);
649
650 auto left_edge = add_left_edge(parent, left.first, this->_graph);
651 auto right_edge = add_right_edge(parent, right.first, this->_graph);
652
653 _edge_manager.add_edges(left_edge, left.second, right_edge, right.second);
654 return {left_edge, right_edge};
655 }
656
658
661
663 const VertexProperty &operator[](vertex_descriptor v) const
664 {
665 return _vertex_manager[v];
666 }
667
669 VertexProperty &operator[](vertex_descriptor v)
670 {
671 return _vertex_manager[v];
672 }
673
675 const EdgeProperty &operator[](const edge_descriptor &edge) const
676 {
677 return _edge_manager[edge];
678 }
679
681 EdgeProperty &operator[](const edge_descriptor &edge)
682 {
683 return _edge_manager[edge];
684 }
685
687};
688
689namespace detail
690{
691template <typename Vertex, typename Edge, typename Generator>
692auto update_tree(binary_tree<Vertex, Edge> &tree,
693 std::vector<typename binary_tree<Vertex, Edge>::vertex_descriptor> leaves, Generator &rng)
694{
695 using tree_type = binary_tree<Vertex, Edge>;
696 using vertex_descriptor = typename tree_type::vertex_descriptor;
697
698 if (leaves.size() == 1)
699 {
700 return leaves.front();
701 }
702 else
703 {
704 std::uniform_int_distribution<> distrib(1, leaves.size() - 1);
705 int split = distrib(rng);
706
707 std::vector<vertex_descriptor> left(leaves.begin(), leaves.begin() + split);
708 std::vector<vertex_descriptor> right(leaves.begin() + split, leaves.end());
709
710 vertex_descriptor parent;
711
712 if constexpr (std::is_same_v<Vertex, boost::no_property>)
713 parent = tree.add_vertex();
714 else
715 parent = tree.add_vertex(Vertex());
716
717 if constexpr (std::is_same_v<Edge, boost::no_property>)
718 tree.add_edges(parent, update_tree(tree, left, rng), update_tree(tree, right, rng));
719 else
720 tree.add_edges(parent, {update_tree(tree, left, rng), Edge()}, {update_tree(tree, right, rng), Edge()});
721 return parent;
722 }
723}
724} // namespace detail
725
731template <typename Vertex = boost::no_property, typename Edge = boost::no_property, typename Generator>
732std::pair<quetzal::coalescence::binary_tree<Vertex, Edge>,
734get_random_binary_tree(int n_leaves, Generator &rng)
735{
737 using vertex_descriptor = typename tree_type::vertex_descriptor;
738
739 tree_type tree;
740
741 std::vector<vertex_descriptor> leaves(n_leaves);
742
743 std::transform(leaves.cbegin(), leaves.cend(), leaves.begin(), [&tree](auto) {
744 if constexpr (std::is_same_v<Vertex, boost::no_property>)
745 return tree.add_vertex();
746 else
747 return tree.add_vertex(Vertex());
748 });
749
750 vertex_descriptor root = detail::update_tree(tree, leaves, rng);
751 return std::make_pair(std::move(tree), root);
752}
753} // namespace quetzal::coalescence
VertexProperty & operator[](vertex_descriptor v)
Read and write access to the vertex property.
Definition binary_tree.hpp:669
std::pair< edge_descriptor, edge_descriptor > add_edges(vertex_descriptor parent, const std::pair< vertex_descriptor, EdgeProperty > &left, const std::pair< vertex_descriptor, EdgeProperty > &right)
Add edges between the parent vertex and the two children.
Definition binary_tree.hpp:642
const VertexProperty & operator[](vertex_descriptor v) const
Read only access to the vertex property.
Definition binary_tree.hpp:663
binary_tree()
Default constructor. Initializes a graph with 0 vertices.
Definition binary_tree.hpp:617
EdgeProperty & operator[](const edge_descriptor &edge)
Read and write access to the edge property.
Definition binary_tree.hpp:681
const EdgeProperty & operator[](const edge_descriptor &edge) const
Read only access to the edge property.
Definition binary_tree.hpp:675
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition binary_tree.hpp:611
vertex_descriptor add_vertex(const VertexProperty &p)
Add a vertex and its properties to the graph.
Definition binary_tree.hpp:632
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition binary_tree.hpp:608
binary_tree(size_t n)
Construct graph with vertices.
Definition binary_tree.hpp:622
vertex_descriptor add_vertex(const VertexProperty &p)
Add a vertex and its properties to the graph.
Definition binary_tree.hpp:446
binary_tree()
Default constructor. Initializes a graph with 0 vertices.
Definition binary_tree.hpp:431
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition binary_tree.hpp:425
binary_tree(size_t n)
Construct graph with vertices.
Definition binary_tree.hpp:436
std::pair< edge_descriptor, edge_descriptor > add_edges(vertex_descriptor parent, vertex_descriptor left, vertex_descriptor right)
Add edges between the parent vertex and the two children.
Definition binary_tree.hpp:456
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition binary_tree.hpp:422
const VertexProperty & operator[](vertex_descriptor v) const
Read only access to the vertex property.
Definition binary_tree.hpp:471
VertexProperty & operator[](vertex_descriptor v)
Read and write access to the vertex property.
Definition binary_tree.hpp:477
const EdgeProperty & operator[](const edge_descriptor &edge) const
Read only access to the edge property.
Definition binary_tree.hpp:563
binary_tree(size_t n)
Construct graph with vertices.
Definition binary_tree.hpp:524
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition binary_tree.hpp:513
binary_tree()
Default constructor. Initializses a graph with 0 vertices.
Definition binary_tree.hpp:519
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition binary_tree.hpp:510
EdgeProperty & operator[](const edge_descriptor &edge)
Read and write access to the edge property.
Definition binary_tree.hpp:569
vertex_descriptor add_vertex()
Add a vertex to the graph.
Definition binary_tree.hpp:373
std::pair< edge_descriptor, edge_descriptor > add_edges(vertex_descriptor parent, vertex_descriptor left, vertex_descriptor right)
Add edges between the parent vertex and the two children.
Definition binary_tree.hpp:381
binary_tree(size_t n)
Construct graph with vertices.
Definition binary_tree.hpp:364
binary_tree()
Default constructor. Initializes a graph with 0 vertices.
Definition binary_tree.hpp:359
Definition binary_tree.hpp:330
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor ("node ID" in other words).
Definition binary_tree.hpp:144
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition binary_tree.hpp:147
bool has_predecessor(vertex_descriptor u) const
Evaluates if vertex has a predecessor.
Definition binary_tree.hpp:213
auto successors(vertex_descriptor u) const
The successors of vertex .
Definition binary_tree.hpp:239
bool is_right_successor(vertex_descriptor u) const
Evaluate if vertex is a right successor.
Definition binary_tree.hpp:257
binary_tree_common(size_t n)
Constructs a tree with vertices.
Definition binary_tree.hpp:139
bool is_left_successor(vertex_descriptor u) const
Evaluate if vertex is a left successor.
Definition binary_tree.hpp:248
vertex_descriptor predecessor(vertex_descriptor u) const
The predecessor of vertex .
Definition binary_tree.hpp:222
bool is_isomorphic(binary_tree_common const &other) const
Detects if there is a 1-to-1 mapping of the vertices in one graph to the vertices of another graph su...
Definition binary_tree.hpp:170
typename base::in_edge_iterator in_edge_iterator
Iterate through the in-edges.
Definition binary_tree.hpp:159
typename base::directed_category directed_category
The graph is bidirected.
Definition binary_tree.hpp:156
typename base::degree_size_type degree_size_type
Degree size type.
Definition binary_tree.hpp:150
void depth_first_search(vertex_descriptor s, DFSTreeVisitor &vis) const
Performs a read-only depth-first traversal of the vertices starting at vertex .
Definition binary_tree.hpp:298
void to_graphviz(std::ostream &out) const
Print the tree to the graphviz format.
Definition binary_tree.hpp:312
void depth_first_search(vertex_descriptor s, DFSTreeVisitor &vis)
Performs a read-and-write depth-first traversal of the vertices starting at vertex .
Definition binary_tree.hpp:286
degree_size_type in_degree(vertex_descriptor u) const
Returns the number of in-edges of vertex .
Definition binary_tree.hpp:198
bool has_successors(vertex_descriptor u) const
Evaluates if vertex has successors.
Definition binary_tree.hpp:231
degree_size_type degree(vertex_descriptor u) const
Returns the number of in-edges plus out-edges.
Definition binary_tree.hpp:189
binary_tree_common()
Default constructor.
Definition binary_tree.hpp:134
vertex_descriptor find_root_from(vertex_descriptor u) const
Finds the root of the tree graph starting from a vertex .
Definition binary_tree.hpp:180
typename base::traversal_category traversal_category
The ways in which the vertices in the graph can be traversed.
Definition binary_tree.hpp:153
std::pair< in_edge_iterator, in_edge_iterator > in_edges(vertex_descriptor u) const
Provides iterators to iterate over the in-going edges of vertex .
Definition binary_tree.hpp:271
degree_size_type out_degree(vertex_descriptor v) const
Returns the number of out-edges of vertex .
Definition binary_tree.hpp:204
Definition cardinal_k_ary_tree.hpp:46
void depth_first_search(binary_tree< false, Vertex > &g, vertex_descriptor_t< binary_tree< false, Vertex > > s, DFSTreeVisitor &vis)
performs a depth-first traversal of the vertices in a directed graph
Definition cardinal_k_ary_tree.hpp:573
Simulation of coalescent trees.
Definition coalescence.hpp:26
std::pair< quetzal::coalescence::binary_tree< Vertex, Edge >, typename quetzal::coalescence::binary_tree< Vertex, Edge >::vertex_descriptor > get_random_binary_tree(int n_leaves, Generator &rng)
Generate a random binary tree.
Definition binary_tree.hpp:734
Definition binary_tree.hpp:88
Definition binary_tree.hpp:65
Definition binary_tree.hpp:46
Definition binary_tree.hpp:41