All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
steiner_strategy.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
15 #ifndef PAAL_STEINER_STRATEGY_HPP
16 #define PAAL_STEINER_STRATEGY_HPP
17 
22 
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>
30 
31 #include <random>
32 #include <unordered_set>
33 #include <vector>
34 
35 
36 namespace paal {
37 namespace ir {
38 
44 private:
45  template<typename Metric>
46  using MTraits = typename data_structures::metric_traits<Metric>;
47 
48 public:
50  steiner_tree_all_generator(int K = 4) : m_component_max_size(K) {}
51 
53  template<typename Metric, typename Terminals>
54  void gen_components(const Metric& cost_map, const Terminals& terminals,
55  const Terminals& steiner_vertices,
57  typename MTraits<Metric>::VertexType,
58  typename MTraits<Metric>::DistanceType>& components) {
59 
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);
65  }
66 private:
67  template<typename Vertex, typename Dist, typename Metric, typename Terminals>
68  void gen_all_components(steiner_components<Vertex, Dist>& components,
69  int first_avail, int last, std::vector<Vertex>& curr,
70  const Metric& cost_map, const Terminals& terminals,
71  const Terminals& steiner_vertices) {
72 
73  if (curr.size() > 1) {
74  steiner_component<Vertex, Dist> c(cost_map, curr, steiner_vertices);
75  components.add(std::move(c));
76  }
77  if ((int) curr.size() >= m_component_max_size)
78  return;
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);
83  curr.pop_back();
84  }
85  }
86 
87  int m_component_max_size;
88 };
89 
90 namespace detail {
91 
92 template<typename Vertex>
93 struct vertex_filter {
94  bool operator()(Vertex v) const { return vertices.find(v) == vertices.end(); }
95  std::unordered_set<Vertex> vertices;
96 };
97 
98 }// detail
99 
104 template<typename Graph, typename Vertex, typename Terminals>
106 private:
107  template<typename Metric>
108  using MTraits = typename data_structures::metric_traits<Metric>;
109 
110 public:
113  const Terminals& terminals, int K = 4) : m_component_max_size(K),
114  m_index(terminals),
115  m_terminals_graph(m_index.size()) {
116  initialize_terminals_graph(graph, terminals);
117  }
118 
120  template<typename Metric>
121  void gen_components(const Metric& cost_map, const Terminals& terminals,
122  const Terminals& steiner_vertices,
124  typename MTraits<Metric>::VertexType,
125  typename MTraits<Metric>::DistanceType>& components) {
126 
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);
132  }
133 
134 private:
135  using AuxGraph = boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS>;
136  using VertexIndex = data_structures::bimap<Vertex>;
137 
138  int m_component_max_size;
139  VertexIndex m_index;
140  AuxGraph m_terminals_graph;
141 
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);
157  }
158  filter.vertices.insert(u);
159  filter.vertices.insert(v);
160  }
161  }
162  }
163 
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);
174  }
175  }
176  }
177 
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);
183  }
184  }
185  }
186 
187  auto get_idx(Vertex v) const -> decltype(m_index.get_idx(v)) {
188  return m_index.get_idx(v);
189  }
190 
191  auto get_val(int idx) const -> decltype(m_index.get_val(idx)) {
192  return m_index.get_val(idx);
193  }
194 
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())) {
198  if (!edge(
199  get_idx(std::get<0>(term_pair)),
200  get_idx(std::get<1>(term_pair)),
201  m_terminals_graph).second) {
202  return false;
203  }
204  }
205  return true;
206  }
207 
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,
212  const Terminals& steiner_vertices) {
213 
214  // TODO implement a subset_iterator with K passed as a parameter
215  // not as a template parameter (also in the gen_all_components method
216  // in steiner_tree_all_generator)
217  if (curr.size() > 1) {
218  if (!is_graph_component(curr))
219  return;
220  steiner_component<Vertex, Dist> c(cost_map, curr, steiner_vertices);
221  components.add(std::move(c));
222  }
223  if ((int) curr.size() >= m_component_max_size)
224  return;
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);
229  curr.pop_back();
230  }
231  }
232 };
233 
237 template<typename Vertex, typename Graph, typename Terminals>
238 steiner_tree_graph_all_generator<Graph, Vertex, Terminals>
240  const Terminals& terminals, int K = 4) {
242  graph, terminals, K);
243 }
244 
249 public:
251  steiner_tree_random_generator(int N = 100, int K = 3) :
252  m_iterations(N), m_component_max_size(K) {
253  }
254 
256  template<typename Metric, typename Terminals>
257  void gen_components(const Metric& cost_map, const Terminals & terminals,
258  const Terminals& steiner_vertices,
260  typename data_structures::metric_traits<Metric>::VertexType,
262 
263  using Vertex = typename data_structures::metric_traits<Metric>::VertexType;
265  if (terminals.size() < 2) {
266  return;
267  }
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) {
272  int c =
273  (int)rand() %
274  m_component_max_size; // TODO: Is this fair probability?
275  if (c == 0) {
276  break;
277  }
278  }
279  int r = (int)rand() % terminals.size();
280  curr.insert(terminals[r]);
281  }
282  std::vector<Vertex> elements(curr.begin(), curr.end());
283  steiner_component<Vertex, Dist> c(cost_map, elements, steiner_vertices);
284  components.add(std::move(c));
285  }
286  // TODO some terminals may not be in any component
287  }
288 
289  private:
290  int m_iterations;
291  int m_component_max_size;
292 };
293 
299  std::default_random_engine m_rng;
300 public:
302  steiner_tree_smart_generator(int N = 100, int K = 3, std::default_random_engine rng = std::default_random_engine{}) :
303  m_iterations(N), m_component_max_size(K) {
304  }
305 
307  template<typename Metric, typename Terminals>
308  void gen_components(const Metric& cost_map, const Terminals& terminals,
309  const Terminals& steiner_vertices,
311  typename data_structures::metric_traits<Metric>::VertexType,
313 
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) {
320  elements.clear();
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]) {
328  prob[k] = 0;
329  break;
330  }
331  int cost = cost_map(e, terminals[k]);
332  assert(cost > 0);
333  assign_max(prob[k], 1. / cost);
334  }
335  }
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]);
339  }
340  boost::erase(elements, boost::unique<boost::return_found_end>(boost::sort(elements)));
341 
342  steiner_component<Vertex, Dist> c(cost_map, elements, steiner_vertices);
343  components.add(std::move(c));
344  }
345  }
346  }
347 
348  private:
349  int m_iterations;
350  int m_component_max_size;
351 };
352 
353 } // ir
354 } // paal
355 
356 #endif // PAAL_STEINER_STRATEGY_HPP
Idx get_idx(const T &t) const
gets index of element t
Definition: bimap.hpp:153
const T & get_val(Idx i) const
get value for index i
Definition: bimap.hpp:166
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.