Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
network.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 network_common
45{
46 protected:
50 tree_traits::directed_type, VertexProperty, EdgeProperty>;
51
52 base _graph;
53
54 public:
56 explicit network_common() : _graph()
57 {
58 }
59
61 explicit network_common(size_t n) : _graph(n)
62 {
63 }
64
66 using vertex_descriptor = typename base::vertex_descriptor;
67
69 using edge_descriptor = typename base::edge_descriptor;
70
72 using vertex_property = VertexProperty;
73
75 using edge_property = EdgeProperty;
76
78 using degree_size_type = typename base::degree_size_type;
79
81 using traversal_category = typename base::traversal_category;
82
84 using directed_category = typename base::directed_category;
85
87 using in_edge_iterator = typename base::in_edge_iterator;
88
90 using out_edge_iterator = typename base::out_edge_iterator;
91
92 using edge_parallel_category = typename base::edge_parallel_category;
93
96
101 bool is_isomorphic(network_common const &other) const
102 {
103 return boost::isomorphism(_graph, other._graph);
104 }
105
110 {
111 std::vector<vertex_descriptor> order;
112 topological_sort(this->_graph, back_inserter(order));
113 return order.back();
114 }
115
120 {
121 return boost::degree(u, _graph);
122 }
123
128 {
129 return has_predecessor(u);
130 }
131
134 {
135 return boost::out_degree(v, _graph);
136 }
137
142 {
143 auto range = boost::in_edges(u, _graph);
144 return std::distance(range.first, range.second) > 0;
145 }
146
151 {
152 auto range = boost::in_edges(u, _graph);
153 assert(std::distance(range.first, range.second) == 1);
154 return source(*range.first);
155 }
156
161 {
162 auto range = boost::out_edges(u, _graph);
163 assert(std::distance(range.first, range.second) != 1);
164 return std::distance(range.first, range.second) >= 2;
165 }
166
171 {
172 return boost::make_iterator_range(out_edges(u, _graph)) |
173 boost::adaptors::transformed([this](auto it) { return target(it); });
174 }
175
180 std::optional<edge_descriptor> edge(vertex_descriptor u, vertex_descriptor v) const
181 {
182 auto p = boost::edge(u, v, _graph);
183 return p.second ? std::make_optional(p.first) : std::nullopt;
184 }
185
190 {
191 return boost::source(e, _graph);
192 }
193
198 {
199 return boost::target(e, _graph);
200 }
201
203
206
208 vertex_descriptor add_vertex()
209 {
210 return boost::add_vertex(_graph);
211 }
212
216 {
217 return boost::clear_vertex(u, _graph);
218 }
219
223 {
224 clear_vertex(u);
225 return boost::remove_vertex(u, _graph);
226 }
227
233 {
234 return boost::add_edge(u, v, _graph).first;
235 }
236
241 {
242 return boost::remove_edge(u, v, _graph);
243 }
244
248 {
249 return boost::remove_edge(e, _graph);
250 }
251
253
256
261 {
262 return boost::make_iterator_range(boost::in_edges(u, _graph));
263 }
264
269 {
270 return boost::make_iterator_range(boost::out_edges(u, _graph));
271 }
272
275 auto vertices() const
276 {
277 return boost::make_iterator_range(boost::vertices(_graph));
278 }
279
281
284
289 template <typename DFSVisitor> void depth_first_search(vertex_descriptor start, DFSVisitor &vis)
290 {
291 // Give a BGL interface to a Quetzal visitor
292 struct wrapper : boost::default_dfs_visitor
293 {
294 network_common &_graph;
295 DFSVisitor &_visitor;
296
297 wrapper(network_common &graph, DFSVisitor &v) : _graph(graph), _visitor(v)
298 {
299 }
300 void discover_vertex(vertex_descriptor v, const base &g)
301 {
302 _visitor(boost::visit::pre, v);
303 }
304 void tree_edge(const edge_descriptor &e, const base &g)
305 {
306 _visitor(boost::visit::in, _graph.target(e));
307 }
308 void finish_vertex(vertex_descriptor v, const base &g)
309 {
310 _visitor(boost::visit::post, v);
311 }
312 } bgl_visitor(*this, vis);
313
314 std::vector<boost::default_color_type> colors(boost::num_vertices(_graph));
315 boost::iterator_property_map color_map(colors.begin(), boost::get(boost::vertex_index, _graph));
316 return boost::depth_first_search(_graph, boost::visitor(bgl_visitor).color_map(color_map).root_vertex(start));
317 }
318
323 template <typename DFSVisitor> void depth_first_search(vertex_descriptor start, DFSVisitor &vis) const
324 {
325 // Give a BGL interface to a Quetzal visitor
326 struct wrapper : boost::default_dfs_visitor
327 {
328 const network_common &_graph;
329 DFSVisitor &_visitor;
330
331 wrapper(const network_common &graph, DFSVisitor &v) : _graph(graph), _visitor(v)
332 {
333 }
334 void discover_vertex(vertex_descriptor v, const base &g)
335 {
336 _visitor(boost::visit::pre, v);
337 }
338 void tree_edge(const edge_descriptor &e, const base &g)
339 {
340 _visitor(boost::visit::in, _graph.target(e));
341 }
342 void finish_vertex(vertex_descriptor v, const base &g)
343 {
344 _visitor(boost::visit::post, v);
345 }
346 } bgl_visitor(*this, vis);
347
348 std::vector<boost::default_color_type> colors(boost::num_vertices(_graph));
349 boost::iterator_property_map color_map(colors.begin(), boost::get(boost::vertex_index, _graph));
350 return boost::depth_first_search(_graph, boost::visitor(bgl_visitor).color_map(color_map).root_vertex(start));
351 }
352
354
357
359 void to_graphviz(std::ostream &out) const
360 {
361 using namespace boost;
362 return boost::write_graphviz(out, *this, boost::make_label_writer(boost::get(vertex_bundle, *this)),
363 boost::make_label_writer(boost::get(edge_bundle, *this)));
364 }
365
367
370 static constexpr inline vertex_descriptor null_vertex()
371 {
372 return base::null_vertex();
373 }
374
375}; // end class network_common
376
377} // end namespace detail
378
379template <class VertexProperty, class EdgeProperty> class network
380{
381};
382
400template <>
401class network<no_property, no_property>
402 : public detail::network_common<no_property, no_property, network<no_property, no_property>>
403{
405
406 public:
409
411 explicit network() : base()
412 {
413 }
414
416 explicit network(size_t n) : base(n)
417 {
418 }
420
423
426 {
427 return boost::add_vertex(_graph);
428 }
429
431 std::vector<edge_descriptor> add_edges(vertex_descriptor parent, std::vector<vertex_descriptor> children)
432 {
433 assert(children.size() > 1);
434 for (auto const &c : children)
435 {
436 assert(parent != c);
437 }
438
439 std::vector<edge_descriptor> edges(children.size());
440 std::transform(children.cbegin(), children.cend(), edges.begin(),
441 [parent, this](auto c) { return boost::add_edge(parent, c, this->_graph).first; });
442 return edges;
443 }
444
446
447}; // end specialization network<boost::no::property, boost::no_property>
448
466template <class VertexProperty>
467 requires(!std::is_same_v<VertexProperty, no_property>)
469 : public detail::network_common<VertexProperty, no_property, network<VertexProperty, no_property>>
470{
471 private:
473
474 public:
477
480
483
485 explicit network() : base()
486 {
487 }
488
490 explicit network(size_t n) : base(n)
491 {
492 }
493
495
498
500 auto add_vertex(const VertexProperty &p)
501 {
502 return boost::add_vertex(p, this->_graph);
503 }
504
506 std::vector<edge_descriptor> add_edges(vertex_descriptor parent, std::vector<vertex_descriptor> children)
507 {
508 assert(children.size() > 1);
509 for (auto const &c : children)
510 {
511 assert(parent != c);
512 }
513
514 std::vector<edge_descriptor> edges(children.size());
515 std::transform(children.cbegin(), children.cend(), edges.begin(),
516 [parent, this](auto c) { return boost::add_edge(parent, c, this->_graph).first; });
517 return edges;
518 }
519
521
524
526 const VertexProperty &operator[](vertex_descriptor v) const
527 {
528 return this->_graph[v];
529 }
530
532 VertexProperty &operator[](vertex_descriptor v)
533 {
534 return this->_graph[v];
535 }
536
538
539}; // end specialization network<Vertex, boost::no_property>
540
558template <class EdgeProperty>
559 requires(!std::is_same_v<EdgeProperty, no_property>)
561 : public detail::network_common<no_property, EdgeProperty, network<no_property, EdgeProperty>>
562{
563 private:
565
566 public:
569
572
575
577 explicit network() : base()
578 {
579 }
580
582 explicit network(size_t n) : base(n)
583 {
584 }
585
587
590
592 vertex_descriptor add_vertex()
593 {
594 return boost::add_vertex(this->_graph);
595 }
596
598 std::vector<edge_descriptor> add_edges(vertex_descriptor parent,
599 const std::vector<std::pair<vertex_descriptor, EdgeProperty>> &children)
600 {
601 assert(children.size() > 1);
602 for (auto const &c : children)
603 {
604 assert(parent != c);
605 }
606
607 std::vector<edge_descriptor> edges(children.size());
608 std::transform(children.cbegin(), children.cend(), edges.begin(), [parent, this](const auto &c) {
609 return boost::add_edge(parent, c.first, c.second, this->_graph).first;
610 });
611 return edges;
612 }
613
615
618
620 const EdgeProperty &operator[](const edge_descriptor &edge) const
621 {
622 return this->_graph[edge];
623 }
624
626 EdgeProperty &operator[](const edge_descriptor &edge)
627 {
628 return this->_graph[edge];
629 }
630
632
633}; // end specialization network<boost::no_property, Edge>
634
653template <class VertexProperty, class EdgeProperty>
654 requires(!std::is_same_v<VertexProperty, no_property> && !std::is_same_v<EdgeProperty, no_property>)
656 : public detail::network_common<VertexProperty, EdgeProperty, network<no_property, EdgeProperty>>
657{
658 private:
660
661 public:
664
667
670
672
673 explicit network() : base()
674 {
675 }
676
678 explicit network(size_t n) : base(n)
679 {
680 }
681
683
686
688 vertex_descriptor add_vertex(const VertexProperty &p)
689 {
690 return boost::add_vertex(p, this->_graph);
691 }
692
694 std::vector<edge_descriptor> add_edges(vertex_descriptor parent,
695 std::vector<std::tuple<vertex_descriptor, EdgeProperty>> children)
696 {
697 assert(children.size() > 1);
698 for (auto const &[c, p] : children)
699 {
700 assert(parent != c);
701 }
702
703 std::vector<edge_descriptor> edges(children.size());
704 std::transform(children.cbegin(), children.cend(), edges.begin(), [parent, this](const auto &c) {
705 return boost::add_edge(parent, std::get<0>(c), std::get<1>(c), this->_graph).first;
706 });
707 return edges;
708 }
709
711
714
716 const VertexProperty &operator[](vertex_descriptor v) const
717 {
718 return this->_graph[v];
719 }
720
722 VertexProperty &operator[](vertex_descriptor v)
723 {
724 return this->_graph[v];
725 }
726
728 const EdgeProperty &operator[](const edge_descriptor &edge) const
729 {
730 return this->_graph[edge];
731 }
732
734 EdgeProperty &operator[](const edge_descriptor &edge)
735 {
736 return this->_graph[edge];
737 }
738
740};
741
742} // end namespace quetzal::coalescence
void remove_vertex(vertex_descriptor u)
Remove vertex u from the graph, also removing all edges to and from vertex .
Definition network.hpp:222
auto out_edges(vertex_descriptor u) const
Provides a range to iterate over the out-going edges of vertex .
Definition network.hpp:268
bool has_successors(vertex_descriptor u) const
Evaluates if vertex has successors.
Definition network.hpp:160
void remove_edge(edge_descriptor e)
Remove the edge from the graph.
Definition network.hpp:247
auto vertices() const
Provides a range to iterate over the vertices of the graph.
Definition network.hpp:275
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 network class.
Definition network.hpp:50
auto successors(vertex_descriptor u) const
The successors of vertex .
Definition network.hpp:170
bool is_isomorphic(network_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 network.hpp:101
vertex_descriptor predecessor(vertex_descriptor u) const
The predecessor of vertex .
Definition network.hpp:150
typename base::degree_size_type degree_size_type
Degree size type.
Definition network.hpp:78
void to_graphviz(std::ostream &out) const
Print the graph to the graphviz format.
Definition network.hpp:359
static constexpr vertex_descriptor null_vertex()
Null vertex identifier.
Definition network.hpp:370
degree_size_type degree(vertex_descriptor u) const
Returns the number of in-edges plus out-edges.
Definition network.hpp:119
network_common()
Default constructor.
Definition network.hpp:56
void remove_edge(vertex_descriptor u, vertex_descriptor v)
Remove the edge from the graph.
Definition network.hpp:240
edge_descriptor add_edge(vertex_descriptor u, vertex_descriptor v)
Inserts the edge into the graph if it does not exist, and returns an edge descriptor pointing to the...
Definition network.hpp:232
bool has_predecessor(vertex_descriptor u) const
Evaluates if vertex has a predecessor.
Definition network.hpp:141
vertex_descriptor source(edge_descriptor e) const
Returns the source vertex of a directed edge.
Definition network.hpp:189
auto in_edges(vertex_descriptor u) const
Provides a range to iterate over the in-going edges of vertex .
Definition network.hpp:260
void depth_first_search(vertex_descriptor start, DFSVisitor &vis)
Performs a read-and-write depth-first traversal of the vertices starting at vertex .
Definition network.hpp:289
degree_size_type in_degree(vertex_descriptor u) const
Returns the number of in-edges of vertex .
Definition network.hpp:127
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition network.hpp:69
void depth_first_search(vertex_descriptor start, DFSVisitor &vis) const
Performs a read-only depth-first traversal of the vertices starting at vertex .
Definition network.hpp:323
vertex_descriptor target(edge_descriptor e) const
Returns the target vertex of a directed edge.
Definition network.hpp:197
typename base::traversal_category traversal_category
The ways in which the vertices in the graph can be traversed.
Definition network.hpp:81
typename base::out_edge_iterator out_edge_iterator
Iterate through the out-edges.
Definition network.hpp:90
degree_size_type out_degree(vertex_descriptor v) const
Returns the number of out-edges of vertex .
Definition network.hpp:133
vertex_descriptor find_root_from(vertex_descriptor u) const
Finds the root of the network graph starting from a vertex .
Definition network.hpp:109
typename base::in_edge_iterator in_edge_iterator
Iterate through the in-edges.
Definition network.hpp:87
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 network.hpp:180
void clear_vertex(vertex_descriptor u)
Remove all edges to and from vertex from the graph.
Definition network.hpp:215
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor ("node ID" in other words).
Definition network.hpp:66
VertexProperty vertex_property
Vertex information.
Definition network.hpp:72
typename base::directed_category directed_category
The graph is bidirected.
Definition network.hpp:84
network_common(size_t n)
Constructs a network with vertices.
Definition network.hpp:61
EdgeProperty edge_property
Edge information.
Definition network.hpp:75
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition network.hpp:666
EdgeProperty & operator[](const edge_descriptor &edge)
Read and write access to the edge property.
Definition network.hpp:734
network()
Default constructor. Initializes a graph with 0 vertices.
Definition network.hpp:673
const EdgeProperty & operator[](const edge_descriptor &edge) const
Read only access to the edge property.
Definition network.hpp:728
network(size_t n)
Construct graph with vertices.
Definition network.hpp:678
const VertexProperty & operator[](vertex_descriptor v) const
Read only access to the vertex property.
Definition network.hpp:716
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition network.hpp:663
vertex_descriptor add_vertex(const VertexProperty &p)
Add a vertex and its properties to the graph.
Definition network.hpp:688
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 network.hpp:694
VertexProperty & operator[](vertex_descriptor v)
Read and write access to the vertex property.
Definition network.hpp:722
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition network.hpp:479
network(size_t n)
Construct graph with vertices.
Definition network.hpp:490
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition network.hpp:476
VertexProperty & operator[](vertex_descriptor v)
Read and write access to the vertex property.
Definition network.hpp:532
const VertexProperty & operator[](vertex_descriptor v) const
Read only access to the vertex property.
Definition network.hpp:526
network()
Default constructor. Initializes a graph with 0 vertices.
Definition network.hpp:485
auto add_vertex(const VertexProperty &p)
Add a vertex and its properties to the graph.
Definition network.hpp:500
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 network.hpp:506
EdgeProperty & operator[](const edge_descriptor &edge)
Read and write access to the edge property.
Definition network.hpp:626
typename base::edge_descriptor edge_descriptor
Edge descriptor.
Definition network.hpp:568
network(size_t n)
Construct graph with vertices.
Definition network.hpp:582
network()
Default constructor. Initializses a graph with 0 vertices.
Definition network.hpp:577
typename base::vertex_descriptor vertex_descriptor
Vertex descriptor.
Definition network.hpp:571
const EdgeProperty & operator[](const edge_descriptor &edge) const
Read only access to the edge property.
Definition network.hpp:620
network(size_t n)
Construct graph with vertices.
Definition network.hpp:416
vertex_descriptor add_vertex()
Add a vertex to the graph.
Definition network.hpp:425
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 network.hpp:431
network()
Default constructor. Initializes a graph with 0 vertices.
Definition network.hpp:411
Definition network.hpp:380
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
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