All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
steiner_component.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Maciej Andrejczuk
3 // 2014 Piotr Wygocki
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //=======================================================================
16 #ifndef PAAL_STEINER_COMPONENT_HPP
17 #define PAAL_STEINER_COMPONENT_HPP
18 
21 #include "paal/utils/irange.hpp"
22 
23 #include <boost/range/algorithm/transform.hpp>
24 #include <boost/range/join.hpp>
25 
26 #include <iosfwd>
27 #include <set>
28 
29 namespace paal {
30 namespace ir {
31 
37 template <typename Vertex, typename Dist>
39 public:
40  using Edge = typename std::pair<Vertex, Vertex>;
41  using Vertices = typename std::vector<Vertex>;
42 
44  template<typename Metric, typename Terminals>
45  steiner_component(const Metric & cost_map, Vertices terminals, const Terminals& steiner_vertices) :
46  m_terminals(std::move(terminals)), m_size(m_terminals.size()) {
47 
48  auto all_elements = boost::join(m_terminals, steiner_vertices);
50  fast_metric(cost_map, all_elements);
51  auto term_nr = boost::distance(m_terminals);
52  auto all_elements_nr = boost::distance(all_elements);
53  auto dw = paal::make_dreyfus_wagner(fast_metric,
54  irange(term_nr),
55  irange(int(term_nr), int(all_elements_nr)));
56  dw.solve();
57  m_cost = dw.get_cost();
58  auto &steiner = dw.get_steiner_elements();
59  m_steiner_elements.resize(steiner.size());
60  auto id_to_elem = [&](int i){
61  if(i < term_nr) {
62  return m_terminals[i];
63  } else {
64  return steiner_vertices[i - term_nr];
65  }
66  };
67  boost::transform(steiner, m_steiner_elements.begin(), id_to_elem);
68  m_edges.resize(dw.get_edges().size());
69  boost::transform(dw.get_edges(), m_edges.begin(), [=](std::pair<int, int> e) {
70  return std::make_pair(id_to_elem(e.first), id_to_elem(e.second));
71  });
72  }
73 
78  Vertex get_sink(int version) const {
79  assert(version < count_terminals());
80  return m_terminals[version];
81  }
82 
86  const Vertices &get_terminals() const { return m_terminals; }
87 
92  const Vertices &get_steiner_elements() const {
93  return m_steiner_elements;
94  }
95 
99  const std::vector<Edge> &get_edges() const { return m_edges; }
100 
104  int count_terminals() const { return m_size; }
105 
109  Dist get_cost() const { return m_cost; }
110 
114  friend std::ostream &operator<<(std::ostream &stream,
115  const steiner_component &component) {
116  for (int i = 0; i < component.m_size; i++) {
117  stream << component.m_terminals[i] << " ";
118  }
119  stream << ": ";
120  for (auto edge : component.m_edges) {
121  stream << "(" << edge.first << "," << edge.second << ") ";
122  }
123  stream << component.m_cost;
124  return stream;
125  }
126 
127  private:
128  const Vertices m_terminals; // terminals of the component
129  int m_size; // m_terminals.size()
130  Dist m_cost; // minimal cost of spanning the component
131  Vertices m_steiner_elements; // non-terminals selected for
132  // spanning tree
133  std::vector<Edge> m_edges; // edges spanning the component
134 };
135 
136 } // ir
137 } // paal
138 
139 #endif // PAAL_STEINER_COMPONENT_HPP
dreyfus_wagner< Metric, Terminals, NonTerminals, TerminalsLimit > make_dreyfus_wagner(const Metric &metric, const Terminals &terminals, const NonTerminals &non_terminals)
Creates a dreyfus_wagner object.
Class represents k-components of Steiner Tree. Component is a subtree whose terminals coincide with l...
Finds optimal Steiner Tree in exponential time.
steiner_component(const Metric &cost_map, Vertices terminals, const Terminals &steiner_vertices)
constructor
const Vertices & get_terminals() const
auto irange(T begin, T end)
irange
Definition: irange.hpp:22
friend std::ostream & operator<<(std::ostream &stream, const steiner_component &component)
Vertex get_sink(int version) const
Each component has versions, where sink is chosen from its terminals.
this metric is rectangle_array_metric with N == M.
Terminals
enum indicates if given color represents terminal or NONTERMINAL.
const Vertices & get_steiner_elements() const
const std::vector< Edge > & get_edges() const