Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
k_ary_tree.hpp
1// Copyright 2021 Arnaud Becheler <abechele@umich.edu>
2
10
11#pragma once
12
13#include "detail/tree_traits.hpp"
14#include "detail/visit.hpp"
15
16#include <boost/range/adaptor/transformed.hpp>
17#include <boost/range/iterator_range.hpp>
18
19#include <boost/graph/adjacency_list.hpp>
20#include <boost/graph/graphviz.hpp>
21#include <boost/graph/isomorphism.hpp>
22#include <boost/graph/topological_sort.hpp>
23
24#include <boost/graph/connected_components.hpp>
25#include <boost/graph/random.hpp>
26#include <boost/graph/random_spanning_tree.hpp>
27
28#include "detail/adl_resolution.hpp"
29#include "detail/utils.hpp"
30
31#include <algorithm>
32#include <iostream>
33
34#include <range/v3/all.hpp>
35
37{
38using no_property = boost::no_property;
39
40namespace detail
41{
42
43// Base class and common implementation
44template <class VertexProperty, class EdgeProperty, class CRTP> class k_ary_tree_common
45{
46 protected:
49 tree_traits::directed_type, VertexProperty, EdgeProperty>;
50
51 base _graph;
52
53 public:
55 explicit k_ary_tree_common() : _graph()
56 {
57 }
58
60 explicit k_ary_tree_common(size_t n) : _graph(n)
61 {
62 }
63
65 using vertex_descriptor = typename base::vertex_descriptor;
66
68 using edge_descriptor = typename base::edge_descriptor;
69
71 using vertex_property = VertexProperty;
72
74 using edge_property = EdgeProperty;
75
77 using degree_size_type = typename base::degree_size_type;
78
80 using traversal_category = typename base::traversal_category;
81
83 using directed_category = typename base::directed_category;
84
86 using in_edge_iterator = typename base::in_edge_iterator;
87
89 using out_edge_iterator = typename base::out_edge_iterator;
90
91 using edge_parallel_category = typename base::edge_parallel_category;
92
95
100 bool is_isomorphic(k_ary_tree_common const &other) const
101 {
102 return boost::isomorphism(_graph, other._graph);
103 }
104
113
118 {
119 return boost::degree(u, _graph);
120 }
121
126 {
127 return has_predecessor(u);
128 }
129
132 {
133 return boost::out_degree(v, _graph);
134 }
135
140 {
141 auto range = boost::in_edges(u, _graph);
142 return std::distance(range.first, range.second) > 0;
143 }
144
149 {
150 auto range = boost::in_edges(u, _graph);
151 assert(std::distance(range.first, range.second) == 1);
152 return source(*range.first);
153 }
154
159 {
160 auto range = boost::out_edges(u, _graph);
161 assert(std::distance(range.first, range.second) != 1);
162 return std::distance(range.first, range.second) >= 2;
163 }
164
169 {
170 return boost::make_iterator_range(out_edges(u, _graph)) |
171 boost::adaptors::transformed([this](auto it) { return target(it); });
172 }
173
178 std::optional<edge_descriptor> edge(vertex_descriptor u, vertex_descriptor v) const
179 {
180 auto p = boost::edge(u, v, _graph);
181 return p.second ? std::make_optional(p.first) : std::nullopt;
182 }
183
188 {
189 return boost::source(e, _graph);
190 }
191
196 {
197 return boost::target(e, _graph);
198 }
199
201
204
208 std::pair<in_edge_iterator, in_edge_iterator> in_edges(vertex_descriptor u) const
209 {
210 using detail::adl_resolution::in_edges;
211 return in_edges(u, _graph);
212 }
213
215
218
223 template <typename DFSTreeVisitor> void depth_first_search(vertex_descriptor start, DFSTreeVisitor &vis)
224 {
225 // convert tree visitor to graph visitor
226 struct VisWrap : boost::default_dfs_visitor
227 {
228 k_ary_tree_common &_tree;
229 DFSTreeVisitor &_tree_visitor;
230 VisWrap(k_ary_tree_common &tree, DFSTreeVisitor &v) : _tree(tree), _tree_visitor(v)
231 {
232 }
233 void discover_vertex(vertex_descriptor v, const base &g)
234 {
235 _tree_visitor(boost::visit::pre, v);
236 }
237 void tree_edge(const edge_descriptor &e, const base &g)
238 {
239 _tree_visitor(boost::visit::in, _tree.target(e));
240 }
241 void finish_vertex(vertex_descriptor v, const base &g)
242 {
243 _tree_visitor(boost::visit::post, v);
244 }
245 } graph_visitor(*this, vis);
246 std::vector<boost::default_color_type> colors(boost::num_vertices(_graph));
247 boost::iterator_property_map color_map(colors.begin(), boost::get(boost::vertex_index, _graph));
248 return boost::depth_first_search(_graph, boost::visitor(graph_visitor).color_map(color_map).root_vertex(start));
249 }
250
255 template <typename DFSTreeVisitor> void depth_first_search(vertex_descriptor start, DFSTreeVisitor &vis) const
256 {
257 // convert tree visitor to graph visitor
258 struct VisWrap : boost::default_dfs_visitor
259 {
260 const k_ary_tree_common &_tree;
261 DFSTreeVisitor &_tree_visitor;
262 VisWrap(const k_ary_tree_common &tree, DFSTreeVisitor &v) : _tree(tree), _tree_visitor(v)
263 {
264 }
265 void discover_vertex(vertex_descriptor v, const base &g)
266 {
267 _tree_visitor(boost::visit::pre, v);
268 }
269 void tree_edge(const edge_descriptor &e, const base &g)
270 {
271 _tree_visitor(boost::visit::in, _tree.target(e));
272 }
273 void finish_vertex(vertex_descriptor v, const base &g)
274 {
275 _tree_visitor(boost::visit::post, v);
276 }
277 } graph_visitor(*this, vis);
278 std::vector<boost::default_color_type> colors(boost::num_vertices(_graph));
279 boost::iterator_property_map color_map(colors.begin(), boost::get(boost::vertex_index, _graph));
280 return boost::depth_first_search(_graph, boost::visitor(graph_visitor).color_map(color_map).root_vertex(start));
281 }
282
284
287
289 void to_graphviz(std::ostream &out) const
290 {
291 using namespace boost;
292 return boost::write_graphviz(out, *this, boost::make_label_writer(boost::get(vertex_bundle, *this)),
293 boost::make_label_writer(boost::get(edge_bundle, *this)));
294 }
295
297
300 static constexpr inline vertex_descriptor null_vertex()
301 {
302 return base::null_vertex();
303 }
304
305 private:
306 template <typename Generator>
307 static auto update_tree(CRTP &tree, std::vector<vertex_descriptor> leaves, Generator &rng)
308 {
309 using tree_type = CRTP;
310
311 if (leaves.size() == 1)
312 {
313 return leaves.front();
314 }
315 else
316 {
317 std::uniform_int_distribution<> distrib(1, leaves.size() - 1);
318 int split = distrib(rng);
319
320 std::vector<vertex_descriptor> left(leaves.begin(), leaves.begin() + split);
321 std::vector<vertex_descriptor> right(leaves.begin() + split, leaves.end());
322
323 auto parent = boost::add_vertex(tree._graph);
324 if constexpr (std::is_same_v<EdgeProperty, boost::no_property>)
325 tree.add_edges(parent, {update_tree(tree, left, rng), update_tree(tree, right, rng)});
326 else
327 tree.add_edges(parent, {std::make_tuple(update_tree(tree, left, rng), EdgeProperty()),
328 std::make_tuple(update_tree(tree, right, rng), EdgeProperty())});
329 return parent;
330 }
331 }
332
333 public:
334 template <typename Generator>
335 static std::tuple<CRTP, vertex_descriptor> make_random_tree(int n_leaves, int k_max, Generator &rng)
336 {
337 CRTP tree;
338 std::vector<vertex_descriptor> leaves(n_leaves);
339 std::transform(leaves.cbegin(), leaves.cend(), leaves.begin(), [&tree](auto) { return tree.add_vertex(); });
340 vertex_descriptor root = update_tree(tree, leaves, rng);
341 return std::tuple(std::move(tree), root);
342 }
343
344}; // end class k_ary_tree_common
345
346} // end namespace detail
347
348template <class VertexProperty, class EdgeProperty> class k_ary_tree
349{
350};
351
369template <>
370class k_ary_tree<no_property, no_property>
371 : public detail::k_ary_tree_common<no_property, no_property, k_ary_tree<no_property, no_property>>
372{
374
375 public:
378
380 explicit k_ary_tree() : base()
381 {
382 }
383
385 explicit k_ary_tree(size_t n) : base(n)
386 {
387 }
389
392
395 {
396 return boost::add_vertex(_graph);
397 }
398
400 std::vector<edge_descriptor> add_edges(vertex_descriptor parent, std::vector<vertex_descriptor> children)
401 {
402 // std::cout << children.size() << std::endl;
403 assert(children.size() != 0);
404 // for(auto const& c : children){ std::cout << parent << " -> " << c << std::endl; }
405
406 assert(children.size() > 1);
407 for (auto const &c : children)
408 {
409 assert(parent != c);
410 }
411 std::vector<edge_descriptor> edges(children.size());
412 std::transform(children.cbegin(), children.cend(), edges.begin(),
413 [parent, this](auto c) { return boost::add_edge(parent, c, this->_graph).first; });
414 return edges;
415 }
416
418
419}; // end specialization k_ary_tree<boost::no::property, boost::no_property>
420
438template <class VertexProperty>
439 requires(!std::is_same_v<VertexProperty, no_property>)
441 : public detail::k_ary_tree_common<VertexProperty, no_property, k_ary_tree<VertexProperty, no_property>>
442{
443 private:
445
446 public:
449
452
455
457 explicit k_ary_tree() : base()
458 {
459 }
460
462 explicit k_ary_tree(size_t n) : base(n)
463 {
464 }
465
467
470
472 auto add_vertex(const VertexProperty &p)
473 {
474 return boost::add_vertex(p, this->_graph);
475 }
476
478 std::vector<edge_descriptor> add_edges(vertex_descriptor parent, std::vector<vertex_descriptor> children)
479 {
480 assert(children.size() > 1);
481 for (auto const &c : children)
482 {
483 assert(parent != c);
484 }
485
486 std::vector<edge_descriptor> edges(children.size());
487 std::transform(children.cbegin(), children.cend(), edges.begin(),
488 [parent, this](auto c) { return boost::add_edge(parent, c, this->_graph).first; });
489 return edges;
490 }
491
493
496
498 const VertexProperty &operator[](vertex_descriptor v) const
499 {
500 return this->_graph[v];
501 }
502
504 VertexProperty &operator[](vertex_descriptor v)
505 {
506 return this->_graph[v];
507 }
508
510
511}; // end specialization k_ary_tree<Vertex, boost::no_property>
512
530template <class EdgeProperty>
531 requires(!std::is_same_v<EdgeProperty, no_property>)
533 : public detail::k_ary_tree_common<no_property, EdgeProperty, k_ary_tree<no_property, EdgeProperty>>
534{
535 private:
537
538 public:
541
544
547
549 explicit k_ary_tree() : base()
550 {
551 }
552
554 explicit k_ary_tree(size_t n) : base(n)
555 {
556 }
557
559
562
564 vertex_descriptor add_vertex()
565 {
566 return boost::add_vertex(this->_graph);
567 }
568
570 std::vector<edge_descriptor> add_edges(vertex_descriptor parent,
571 const std::vector<std::pair<vertex_descriptor, EdgeProperty>> &children)
572 {
573 assert(children.size() > 1);
574 for (auto const &[c, p] : children)
575 {
576 assert(parent != c);
577 }
578
579 std::vector<edge_descriptor> edges(children.size());
580 std::transform(children.cbegin(), children.cend(), edges.begin(), [parent, this](const auto &c) {
581 return boost::add_edge(parent, c.first, c.second, this->_graph).first;
582 });
583 return edges;
584 }
585
587
590
592 const EdgeProperty &operator[](const edge_descriptor &edge) const
593 {
594 return this->_graph[edge];
595 }
596
598 EdgeProperty &operator[](const edge_descriptor &edge)
599 {
600 return this->_graph[edge];
601 }
602
604
605}; // end specialization k_ary_tree<boost::no_property, Edge>
606
626template <class VertexProperty, class EdgeProperty>
627 requires(!std::is_same_v<VertexProperty, no_property> && !std::is_same_v<EdgeProperty, no_property>)
629 : public detail::k_ary_tree_common<VertexProperty, EdgeProperty, k_ary_tree<no_property, EdgeProperty>>
630{
631 private:
633
634 public:
637
640
643
645
646 explicit k_ary_tree() : base()
647 {
648 }
649
651 explicit k_ary_tree(size_t n) : base(n)
652 {
653 }
654
656
659
661 vertex_descriptor add_vertex(const VertexProperty &p)
662 {
663 return boost::add_vertex(p, this->_graph);
664 }
665
667 std::vector<edge_descriptor> add_edges(vertex_descriptor parent,
668 std::vector<std::tuple<vertex_descriptor, EdgeProperty>> children)
669 {
670 std::cout << children.size() << std::endl;
671 assert(children.size() > 1);
672 for (auto const &[c, p] : children)
673 {
674 assert(parent != c);
675 }
676
677 std::vector<edge_descriptor> edges(children.size());
678 std::transform(children.cbegin(), children.cend(), edges.begin(), [parent, this](const auto &c) {
679 return boost::add_edge(parent, std::get<0>(c), std::get<1>(c), this->_graph).first;
680 });
681 return edges;
682 }
683
685
688
690 const VertexProperty &operator[](vertex_descriptor v) const
691 {
692 return this->_graph[v];
693 }
694
696 VertexProperty &operator[](vertex_descriptor v)
697 {
698 return this->_graph[v];
699 }
700
702 const EdgeProperty &operator[](const edge_descriptor &edge) const
703 {
704 return this->_graph[edge];
705 }
706
708 EdgeProperty &operator[](const edge_descriptor &edge)
709 {
710 return this->_graph[edge];
711 }
712
714};
715
716namespace detail
717{
718template <typename Vertex, typename Edge, typename Generator>
719auto update_tree(k_ary_tree<Vertex, Edge> &tree,
720 std::vector<typename k_ary_tree<Vertex, Edge>::vertex_descriptor> leaves, Generator &rng)
721{
722 using tree_type = k_ary_tree<Vertex, Edge>;
723 using vertex_descriptor = typename tree_type::vertex_descriptor;
724
725 if (leaves.size() == 1)
726 {
727 return leaves.front();
728 }
729 else
730 {
731 std::uniform_int_distribution<> distrib(1, leaves.size() - 1);
732 int split = distrib(rng);
733
734 std::vector<vertex_descriptor> left(leaves.begin(), leaves.begin() + split);
735 std::vector<vertex_descriptor> right(leaves.begin() + split, leaves.end());
736
737 vertex_descriptor parent;
738
739 if constexpr (std::is_same_v<Vertex, boost::no_property>)
740 parent = tree.add_vertex();
741 else
742 parent = tree.add_vertex(Vertex());
743
744 if constexpr (std::is_same_v<Edge, boost::no_property>)
745 tree.add_edges(parent, {update_tree(tree, left, rng), update_tree(tree, right, rng)});
746 else
747 tree.add_edges(parent, {{update_tree(tree, left, rng), Edge()}, {update_tree(tree, right, rng), Edge()}});
748 return parent;
749 }
750}
751} // end namespace detail
752
758template <typename Vertex = boost::no_property, typename Edge = boost::no_property, typename Generator>
759std::pair<quetzal::coalescence::k_ary_tree<Vertex, Edge>,
761get_random_k_ary_tree(int n_leaves, Generator &rng)
762{
764 using vertex_descriptor = typename tree_type::vertex_descriptor;
765
766 tree_type tree;
767
768 std::vector<vertex_descriptor> leaves(n_leaves);
769
770 std::transform(leaves.cbegin(), leaves.cend(), leaves.begin(), [&tree](auto) {
771 if constexpr (std::is_same_v<Vertex, boost::no_property>)
772 return tree.add_vertex();
773 else
774 return tree.add_vertex(Vertex());
775 });
776
777 vertex_descriptor root = detail::update_tree(tree, leaves, rng);
778 return std::make_pair(std::move(tree), root);
779}
780
781} // end namespace quetzal::coalescence
typename base::degree_size_type degree_size_type
Degree size type.
Definition k_ary_tree.hpp:77
typename base::traversal_category traversal_category
The ways in which the vertices in the graph can be traversed.
Definition k_ary_tree.hpp:80
typename base::directed_category directed_category
The graph is bidirected.
Definition k_ary_tree.hpp:83
vertex_descriptor predecessor(vertex_descriptor u) const
The predecessor of vertex .
Definition k_ary_tree.hpp:148
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition k_ary_tree.hpp:68
std::optional< edge_descriptor > edge(vertex_descriptor u, vertex_descriptor v) const
Returns the edge between two vertices of the graph if the edge exists.
Definition k_ary_tree.hpp:178
k_ary_tree_common()
Default constructor.
Definition k_ary_tree.hpp:55
degree_size_type degree(vertex_descriptor u) const
Returns the number of in-edges plus out-edges.
Definition k_ary_tree.hpp:117
VertexProperty vertex_property
Vertex information.
Definition k_ary_tree.hpp:71
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 k_ary_tree.hpp:208
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor ("node ID" in other words).
Definition k_ary_tree.hpp:65
typename base::in_edge_iterator in_edge_iterator
Iterate through the in-edges.
Definition k_ary_tree.hpp:86
EdgeProperty edge_property
Edge information.
Definition k_ary_tree.hpp:74
auto successors(vertex_descriptor u) const
The successors of vertex .
Definition k_ary_tree.hpp:168
bool has_successors(vertex_descriptor u) const
Evaluates if vertex has successors.
Definition k_ary_tree.hpp:158
vertex_descriptor target(edge_descriptor e) const
Returns the target vertex of a directed edge.
Definition k_ary_tree.hpp:195
k_ary_tree_common(size_t n)
Constructs a tree with vertices.
Definition k_ary_tree.hpp:60
void to_graphviz(std::ostream &out) const
Print the tree to the graphviz format.
Definition k_ary_tree.hpp:289
tree_traits::model< tree_traits::out_edge_list_type, tree_traits::vertex_list_type, tree_traits::directed_type, VertexProperty, EdgeProperty > base
The type of graph hold by the tree class.
Definition k_ary_tree.hpp:49
void depth_first_search(vertex_descriptor start, DFSTreeVisitor &vis)
Performs a read-and-write depth-first traversal of the vertices starting at vertex .
Definition k_ary_tree.hpp:223
degree_size_type in_degree(vertex_descriptor u) const
Returns the number of in-edges of vertex .
Definition k_ary_tree.hpp:125
degree_size_type out_degree(vertex_descriptor v) const
Returns the number of out-edges of vertex .
Definition k_ary_tree.hpp:131
vertex_descriptor source(edge_descriptor e) const
Returns the source vertex of a directed edge.
Definition k_ary_tree.hpp:187
void depth_first_search(vertex_descriptor start, DFSTreeVisitor &vis) const
Performs a read-only depth-first traversal of the vertices starting at vertex .
Definition k_ary_tree.hpp:255
bool has_predecessor(vertex_descriptor u) const
Evaluates if vertex has a predecessor.
Definition k_ary_tree.hpp:139
static constexpr vertex_descriptor null_vertex()
Null vertex identifier.
Definition k_ary_tree.hpp:300
typename base::out_edge_iterator out_edge_iterator
Iterate through the out-edges.
Definition k_ary_tree.hpp:89
vertex_descriptor find_root_from(vertex_descriptor u) const
Finds the root of the tree graph starting from a vertex .
Definition k_ary_tree.hpp:109
bool is_isomorphic(k_ary_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 k_ary_tree.hpp:100
k_ary_tree()
Default constructor. Initializes a graph with 0 vertices.
Definition k_ary_tree.hpp:646
VertexProperty & operator[](vertex_descriptor v)
Read and write access to the vertex property.
Definition k_ary_tree.hpp:696
const EdgeProperty & operator[](const edge_descriptor &edge) const
Read only access to the edge property.
Definition k_ary_tree.hpp:702
EdgeProperty & operator[](const edge_descriptor &edge)
Read and write access to the edge property.
Definition k_ary_tree.hpp:708
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition k_ary_tree.hpp:639
k_ary_tree(size_t n)
Construct graph with vertices.
Definition k_ary_tree.hpp:651
std::vector< edge_descriptor > add_edges(vertex_descriptor parent, std::vector< std::tuple< vertex_descriptor, EdgeProperty > > children)
Add edges from the parent vertex (source) to the children (target)
Definition k_ary_tree.hpp:667
const VertexProperty & operator[](vertex_descriptor v) const
Read only access to the vertex property.
Definition k_ary_tree.hpp:690
vertex_descriptor add_vertex(const VertexProperty &p)
Add a vertex and its properties to the graph.
Definition k_ary_tree.hpp:661
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition k_ary_tree.hpp:636
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition k_ary_tree.hpp:451
k_ary_tree()
Default constructor. Initializes a graph with 0 vertices.
Definition k_ary_tree.hpp:457
auto add_vertex(const VertexProperty &p)
Add a vertex and its properties to the graph.
Definition k_ary_tree.hpp:472
const VertexProperty & operator[](vertex_descriptor v) const
Read only access to the vertex property.
Definition k_ary_tree.hpp:498
VertexProperty & operator[](vertex_descriptor v)
Read and write access to the vertex property.
Definition k_ary_tree.hpp:504
std::vector< edge_descriptor > add_edges(vertex_descriptor parent, std::vector< vertex_descriptor > children)
Add edges from the parent vertex (source) to the children (target)
Definition k_ary_tree.hpp:478
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition k_ary_tree.hpp:448
k_ary_tree(size_t n)
Construct graph with vertices.
Definition k_ary_tree.hpp:462
const EdgeProperty & operator[](const edge_descriptor &edge) const
Read only access to the edge property.
Definition k_ary_tree.hpp:592
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition k_ary_tree.hpp:543
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition k_ary_tree.hpp:540
k_ary_tree()
Default constructor. Initializses a graph with 0 vertices.
Definition k_ary_tree.hpp:549
EdgeProperty & operator[](const edge_descriptor &edge)
Read and write access to the edge property.
Definition k_ary_tree.hpp:598
k_ary_tree(size_t n)
Construct graph with vertices.
Definition k_ary_tree.hpp:554
vertex_descriptor add_vertex()
Add a vertex to the graph.
Definition k_ary_tree.hpp:394
k_ary_tree(size_t n)
Construct graph with vertices.
Definition k_ary_tree.hpp:385
std::vector< edge_descriptor > add_edges(vertex_descriptor parent, std::vector< vertex_descriptor > children)
Add edges from the parent vertex (source) to the children (target)
Definition k_ary_tree.hpp:400
k_ary_tree()
Default constructor. Initializes a graph with 0 vertices.
Definition k_ary_tree.hpp:380
Definition k_ary_tree.hpp:349
Definition cardinal_k_ary_tree.hpp:46
bool isomorphism(binary_tree< false, Vertex0 > const &g, binary_tree< false, Vertex1 > const &h)
Detects if there is a 1-to-1 mapping of the vertices in one graph to the vertices of another graph su...
Definition cardinal_k_ary_tree.hpp:616
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::k_ary_tree< Vertex, Edge >, typename quetzal::coalescence::k_ary_tree< Vertex, Edge >::vertex_descriptor > get_random_k_ary_tree(int n_leaves, Generator &rng)
Generate a random k-ary tree.
Definition k_ary_tree.hpp:761
boost::vecS vertex_list_type
We don't allow for inserting vertices except at the end and we don't remove vertices....
Definition tree_traits.hpp:31
boost::bidirectionalS directed_type
Coalescent trees are directed acyclic graphs but we need bidirectionality for in-edges access.
Definition tree_traits.hpp:36
boost::setS out_edge_list_type
We want to enforce avoiding multi-graphs (edges with same end nodes)
Definition tree_traits.hpp:27
boost::adjacency_list< Types... > model
Trees are sparse graph in nature, adjacency_matrix would not be justified here.
Definition tree_traits.hpp:24