15 #ifndef PAAL_STEINER_STRATEGY_HPP
16 #define PAAL_STEINER_STRATEGY_HPP
23 #include <boost/graph/connected_components.hpp>
24 #include <boost/graph/filtered_graph.hpp>
25 #include <boost/range/as_array.hpp>
26 #include <boost/range/algorithm_ext/erase.hpp>
27 #include <boost/range/algorithm/sort.hpp>
28 #include <boost/range/algorithm/unique.hpp>
29 #include <boost/random/discrete_distribution.hpp>
32 #include <unordered_set>
45 template<
typename Metric>
53 template<
typename Metric,
typename Terminals>
57 typename MTraits<Metric>::VertexType,
58 typename MTraits<Metric>::DistanceType>&
components) {
60 using Vertex =
typename MTraits<Metric>::VertexType;
61 using Dist =
typename MTraits<Metric>::DistanceType;
62 std::vector<Vertex> current_terminals;
63 gen_all_components<Vertex, Dist>(
components, 0, terminals.size(),
64 current_terminals, cost_map, terminals, steiner_vertices);
67 template<
typename Vertex,
typename Dist,
typename Metric,
typename Terminals>
69 int first_avail,
int last, std::vector<Vertex>& curr,
70 const Metric& cost_map,
const Terminals& terminals,
73 if (curr.size() > 1) {
75 components.
add(std::move(c));
77 if ((
int) curr.size() >= m_component_max_size)
79 for (
int i = first_avail; i < last; ++i) {
80 curr.push_back(terminals[i]);
81 gen_all_components(components, i + 1, last, curr, cost_map,
82 terminals, steiner_vertices);
87 int m_component_max_size;
92 template<
typename Vertex>
94 bool operator()(Vertex v)
const {
return vertices.find(v) == vertices.end(); }
95 std::unordered_set<Vertex> vertices;
104 template<
typename Graph,
typename Vertex,
typename Terminals>
107 template<
typename Metric>
113 const Terminals& terminals,
int K = 4) : m_component_max_size(K),
115 m_terminals_graph(m_index.size()) {
116 initialize_terminals_graph(graph, terminals);
120 template<
typename Metric>
124 typename MTraits<Metric>::VertexType,
125 typename MTraits<Metric>::DistanceType>& components) {
127 using Dist =
typename MTraits<Metric>::DistanceType;
128 merge_vertices<Dist>(cost_map);
129 std::vector<Vertex> current_terminals;
130 gen_all_components<Dist>(components, 0, terminals.
size(),
131 current_terminals, cost_map, terminals, steiner_vertices);
135 using AuxGraph = boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS>;
138 int m_component_max_size;
140 AuxGraph m_terminals_graph;
142 void initialize_terminals_graph(
const Graph& graph,
const Terminals& terminals) {
144 filter.vertices.insert(terminals.begin(), terminals.end());
145 auto index =
get(boost::vertex_index, graph);
146 std::vector<int> components(num_vertices(graph));
147 for (
auto u : terminals) {
148 for (
auto v : terminals) {
149 if (u == v)
continue;
150 filter.vertices.erase(u);
151 filter.vertices.erase(v);
152 boost::filtered_graph<Graph, boost::keep_all, decltype(filter)>
153 fg(graph, boost::keep_all{}, filter);
154 boost::connected_components(fg, &components[0]);
155 if (components[index[u]] == components[index[v]]) {
156 add_edge(get_idx(u), get_idx(v), m_terminals_graph);
158 filter.vertices.insert(u);
159 filter.vertices.insert(v);
164 template<
typename Dist,
typename Metric>
165 void merge_vertices(
const Metric& cost_map) {
166 auto range = vertices(m_terminals_graph);
167 for (
auto v_pair : data_structures::make_subsets_iterator_range<2>(
168 range.first, range.second)) {
169 auto i = std::get<0>(v_pair);
170 auto j = std::get<1>(v_pair);
171 if (cost_map(get_val(i), get_val(j)) == Dist{}) {
172 merge_vertices(i, j);
173 merge_vertices(j, i);
178 void merge_vertices(Vertex trg, Vertex src) {
179 for (
auto v : boost::as_array(adjacent_vertices(src,
180 m_terminals_graph))) {
181 if (trg != static_cast<Vertex>(v)) {
182 add_edge(trg, v, m_terminals_graph);
187 auto get_idx(Vertex v)
const -> decltype(m_index.get_idx(v)) {
191 auto get_val(
int idx)
const -> decltype(m_index.get_val(idx)) {
195 bool is_graph_component(
const std::vector<Vertex>& comp)
const {
196 for (
auto term_pair : data_structures::make_subsets_iterator_range<2>(
197 comp.begin(), comp.end())) {
199 get_idx(std::get<0>(term_pair)),
200 get_idx(std::get<1>(term_pair)),
201 m_terminals_graph).second) {
208 template<
typename Dist,
typename Metric>
209 void gen_all_components(steiner_components<Vertex, Dist>& components,
210 int first_avail,
int last, std::vector<Vertex>& curr,
211 const Metric& cost_map,
const Terminals& terminals,
217 if (curr.size() > 1) {
218 if (!is_graph_component(curr))
220 steiner_component<Vertex, Dist> c(cost_map, curr, steiner_vertices);
221 components.add(std::move(c));
223 if ((
int) curr.size() >= m_component_max_size)
225 for (
int i = first_avail; i < last; ++i) {
226 curr.push_back(terminals[i]);
227 gen_all_components(components, i + 1, last, curr, cost_map,
228 terminals, steiner_vertices);
237 template<
typename Vertex,
typename Graph,
typename Terminals>
238 steiner_tree_graph_all_generator<Graph, Vertex, Terminals>
242 graph, terminals, K);
252 m_iterations(N), m_component_max_size(K) {
256 template<
typename Metric,
typename Terminals>
260 typename data_structures::metric_traits<Metric>::VertexType,
263 using Vertex =
typename data_structures::metric_traits<Metric>::VertexType;
265 if (terminals.size() < 2) {
268 for (
int i = 0; i < m_iterations; ++i) {
269 std::set<Vertex> curr;
270 while ((
int)curr.size() < m_component_max_size) {
271 if (curr.size() > 1) {
274 m_component_max_size;
279 int r = (int)rand() % terminals.size();
280 curr.insert(terminals[r]);
282 std::vector<Vertex> elements(curr.begin(), curr.end());
284 components.add(std::move(c));
291 int m_component_max_size;
299 std::default_random_engine m_rng;
303 m_iterations(N), m_component_max_size(K) {
307 template<
typename Metric,
typename Terminals>
311 typename data_structures::metric_traits<Metric>::VertexType,
314 using Vertex =
typename data_structures::metric_traits<Metric>::VertexType;
316 std::vector<Vertex> elements;
317 std::vector<double> prob;
318 for (Vertex start : terminals) {
319 for (
int i = 0; i < m_iterations; ++i) {
321 elements.push_back(start);
322 int limit = 2 + rand() % (m_component_max_size - 1);
323 while ((
int)elements.size() < limit) {
324 prob.resize(terminals.size());
325 for (
int k = 0; k < (int)prob.size(); ++k) {
326 for (
auto e : elements) {
327 if (e == terminals[k]) {
331 int cost = cost_map(e, terminals[k]);
336 auto selected = boost::random::discrete_distribution<std::size_t>(prob)(m_rng);
337 if (selected == prob.size())
break;
338 elements.push_back(terminals[selected]);
340 boost::erase(elements, boost::unique<boost::return_found_end>(boost::sort(elements)));
343 components.add(std::move(c));
350 int m_component_max_size;
356 #endif // PAAL_STEINER_STRATEGY_HPP
Idx get_idx(const T &t) const
gets index of element t
const T & get_val(Idx i) const
get value for index i
Class represents k-components of Steiner Tree. Component is a subtree whose terminals coincide with l...
steiner_tree_graph_all_generator(const Graph &graph, const Terminals &terminals, int K=4)
Constructor.
void gen_components(const Metric &cost_map, const Terminals &terminals, const Terminals &steiner_vertices, steiner_components< typename MTraits< Metric >::VertexType, typename MTraits< Metric >::DistanceType > &components)
Generates all possible components.
void gen_components(const Metric &cost_map, const Terminals &terminals, const Terminals &steiner_vertices, steiner_components< typename data_structures::metric_traits< Metric >::VertexType, typename data_structures::metric_traits< Metric >::DistanceType > &components)
Generates a specified number of components by selecting random elements.
void gen_components(const Metric &cost_map, const Terminals &terminals, const Terminals &steiner_vertices, steiner_components< typename data_structures::metric_traits< Metric >::VertexType, typename data_structures::metric_traits< Metric >::DistanceType > &components)
Generates components.
void assign_max(T &t, const T &u)
steiner_tree_graph_all_generator< Graph, Vertex, Terminals > make_steiner_tree_graph_all_generator(const Graph &graph, const Terminals &terminals, int K=4)
steiner_tree_all_generator(int K=4)
Constructor.
void gen_components(const Metric &cost_map, const Terminals &terminals, const Terminals &steiner_vertices, steiner_components< typename MTraits< Metric >::VertexType, typename MTraits< Metric >::DistanceType > &components)
Generates all possible components.
Terminals
enum indicates if given color represents terminal or NONTERMINAL.
void add(const steiner_component< Vertex, Dist > &component)
steiner_tree_smart_generator(int N=100, int K=3, std::default_random_engine rng=std::default_random_engine{})
Constructor.
puretype(std::declval< Metric >()(std::declval< VertexType >(), std::declval< VertexType >())) DistanceType
Distance type.
steiner_tree_random_generator(int N=100, int K=3)
Constructor.