Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
random_tree.hpp
1// Copyright 2021 Arnaud Becheler <abechele@umich.edu>
2
10
11#ifndef RANDOM_TREE_H_INCLUDED
12#define RANDOM_TREE_H_INCLUDED
13
14#include <boost/graph/adjacency_list.hpp>
15#include <boost/graph/connected_components.hpp>
16#include <boost/graph/graph_utility.hpp>
17#include <boost/graph/graphviz.hpp>
18#include <boost/graph/random.hpp>
19#include <boost/graph/random_spanning_tree.hpp>
20#include <boost/property_map/function_property_map.hpp>
21#include <iomanip>
22#include <random>
23
24#include <quetzal/coalescence/graph/k_ary_tree.hpp>
25
26namespace quetzal
27{
28
29namespace detail
30{
31// Default, no type
32template <typename T> struct make_undirected
33{
34 using type = void;
35};
36
37// For boost adjacency list
38template <typename A, typename B, typename C, typename D, typename E, typename F>
39struct make_undirected<boost::adjacency_list<A, B, C, D, E, F>>
40{
41 using type = boost::adjacency_list<A, B, boost::undirectedS, D, E, F>;
42};
43
44// For quetzal trees
45template <typename V, typename E> struct make_undirected<quetzal::coalescence::k_ary_tree<V, E>>
46{
47 using type = boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS, V, E>;
48};
49
50template <typename T> using Undirect = typename make_undirected<T>::type;
51} // namespace detail
52
56template <class Graph = quetzal::coalescence::k_ary_tree<boost::no_property, boost::no_property>, class Generator>
57auto get_random_spanning_tree(int n_vertices, int n_edges, Generator &rng)
58{
59 using UG = detail::Undirect<Graph>;
60 using vertex_t = typename UG::vertex_descriptor;
61
62 // assuming integral vertex index for simplicity
63 static_assert(std::is_same_v<vertex_t, size_t>);
64 static_assert(std::is_same_v<typename UG::vertex_descriptor, typename Graph::vertex_descriptor>);
65
66 // Initialize a random undirected graph
67 UG ug;
68 generate_random_graph(ug, n_vertices, n_edges, rng);
69 vertex_t const root = random_vertex(ug, rng);
70
71 // make the graph fully connected
72 {
73 std::map<vertex_t, int> components;
74 auto from = [&](int component) { // just picking the first...
75 for (auto &[v, c] : components)
76 if (c == component)
77 return v;
78 throw std::range_error("component");
79 };
80
81 // records the component number in the component property map
82 auto cmap = boost::make_assoc_property_map(components);
83 // The algorithm computes how many connected components are in the graph
84 if (int n = connected_components(ug, cmap); n > 1)
85 {
86 for (int c = 1; c < n; ++c)
87 add_edge(from(c - 1), from(c), ug);
88 }
89 }
90
91 std::map<vertex_t, vertex_t> predecessors;
92 random_spanning_tree(ug, rng,
93 boost::root_vertex(root) //
94 .predecessor_map(boost::make_assoc_property_map(predecessors)));
95
96 Graph tree(num_vertices(ug)); // build a tree copy
97 for (auto v : boost::make_iterator_range(vertices(ug)))
98 if (predecessors.contains(v))
99 if (auto pred = predecessors.at(v); ug.null_vertex() != pred)
100 add_edge(predecessors.at(v), v, tree);
101
102 return std::tuple(std::move(tree), root);
103}
104
105} // end namespace quetzal
106
107#endif
Definition k_ary_tree.hpp:349
Definition cardinal_k_ary_tree.hpp:46
Simulation of coalescence-based models of molecular evolution.
Definition coalescence.hpp:21
auto get_random_spanning_tree(int n_vertices, int n_edges, Generator &rng)
Generates a random directed tree.
Definition random_tree.hpp:57
Definition random_tree.hpp:33