All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
voronoi.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
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_VORONOI_HPP
16 #define PAAL_VORONOI_HPP
17 
18 #include "voronoi_traits.hpp"
19 
21 #include "paal/utils/functors.hpp"
22 
23 #include <boost/range/as_array.hpp>
24 #include <boost/range/adaptor/map.hpp>
25 #include <boost/functional/hash.hpp>
26 
27 #include <unordered_set>
28 #include <unordered_map>
29 #include <map>
30 #include <cassert>
31 #include <climits>
32 
33 namespace paal {
34 namespace data_structures {
35 
42 template <typename Metric> class voronoi {
43  public:
44  typedef typename metric_traits<Metric>::VertexType VertexType;
45  typedef std::multimap<VertexType, VertexType> GeneratorsToVertices;
46  typedef std::unordered_set<VertexType, boost::hash<VertexType>>
47  GeneratorsSet;
48  typedef typename metric_traits<Metric>::DistanceType Dist;
49  // TODO change to vector
50  typedef GeneratorsSet Vertices;
51  private:
52  typedef std::unordered_map<VertexType,
53  typename GeneratorsToVertices::iterator,
54  boost::hash<VertexType>> VerticesToGenerators;
55 
56  VerticesToGenerators m_vertices_to_generators;
57  GeneratorsToVertices m_generators_to_vertices;
58  Vertices m_vertices;
59  GeneratorsSet m_generators;
60 
61  const Metric &m_metric;
62  const Dist m_cost_of_no_generator;
63 public:
64 
73  voronoi(const GeneratorsSet &generators, Vertices vertices, const Metric &m,
74  Dist costOfNoGenerator = std::numeric_limits<Dist>::max())
75  : m_vertices(std::move(vertices)), m_metric(m),
76  m_cost_of_no_generator(costOfNoGenerator) {
77  for (VertexType f : generators) {
78  add_generator(f);
79  }
80  }
81 
87  voronoi(const voronoi &v)
88  : m_generators_to_vertices(v.m_generators_to_vertices),
89  m_vertices(v.m_vertices), m_generators(v.m_generators),
90  m_metric(v.m_metric),
91  m_cost_of_no_generator(v.m_cost_of_no_generator) {
92  auto b = m_generators_to_vertices.begin();
93  auto e = m_generators_to_vertices.end();
94  for (; b != e; ++b) {
95  m_vertices_to_generators.insert(std::make_pair(b->second, b));
96  }
97  }
98 
105  : m_vertices_to_generators(std::move(v.m_vertices_to_generators)),
106  m_generators_to_vertices(std::move(v.m_generators_to_vertices)),
107  m_vertices(std::move(v.m_vertices)),
108  m_generators(std::move(v.m_generators)), m_metric(v.m_metric),
109  m_cost_of_no_generator(v.m_cost_of_no_generator) {}
110 
112  Dist add_generator(VertexType f) {
113  Dist cost = Dist();
114  m_generators.insert(f);
115 
116  // first generatorsility
117  if (m_generators.size() == 1) {
118  m_vertices_to_generators.clear();
119  m_generators_to_vertices.clear();
120  for (VertexType v : m_vertices) {
121  m_vertices_to_generators[v] =
122  m_generators_to_vertices.insert(std::make_pair(f, v));
123  cost += m_metric(v, f);
124  }
125 
126  cost = cost - m_cost_of_no_generator;
127 
128  } else {
129  for (VertexType v : m_vertices) {
130  Dist d = m_metric(v, f) - dist(v);
131  if (d < 0) {
132  cost += d;
133  assign(v, f);
134  }
135  }
136  }
137  return cost;
138  }
139 
141  Dist rem_generator(VertexType f) {
142  Dist cost = Dist();
143  if (m_generators.size() == 1) {
144  cost = m_cost_of_no_generator;
145  for (VertexType v : m_vertices) {
146  cost -= dist(v);
147  }
148  m_vertices_to_generators.clear();
149  m_generators_to_vertices.clear();
150  } else {
151  auto op =
152  std::bind(utils::not_equal_to(), f, std::placeholders::_1);
153  auto begin = m_generators_to_vertices.lower_bound(f);
154  auto end = m_generators_to_vertices.upper_bound(f);
155  for (; begin != end;) {
156  auto v = begin->second;
157  // using the fact that generators is a map
158  //(with other containers you have to be careful cause of iter
159  // invalidation)
160  ++begin;
161  cost -= dist(v);
162  cost += adjust_vertex(v, op);
163  }
164  }
165  m_generators.erase(f);
166  return cost;
167  }
168 
174  const GeneratorsSet &get_generators() const { return m_generators; }
175 
181  const Vertices &get_vertices() const { return m_vertices; }
182 
188  auto get_vertices_for_generator(VertexType g) const ->
189  decltype(boost::as_array(m_generators_to_vertices.equal_range(g) |
190  boost::adaptors::map_values))
191  {
192  return boost::as_array(m_generators_to_vertices.equal_range(g) |
193  boost::adaptors::map_values);
194  }
195 
197  bool operator==(const voronoi & vor) const {
198  return boost::equal(m_generators_to_vertices, vor.m_generators_to_vertices) &&
199  m_cost_of_no_generator == vor.m_cost_of_no_generator &&
200  m_metric == vor.m_metric;
201  }
202 
203  private:
204 
212  Dist dist(VertexType v) { return m_metric(v, vertex_to_generators(v)); }
213 
224  template <typename Filter = utils::always_true>
225  Dist adjust_vertex(VertexType v, Filter filter = Filter()) {
226  bool init = true;
227  Dist d = Dist();
228  VertexType f_best = VertexType();
229  for (VertexType f : m_generators) {
230  if (filter(f)) {
231  Dist td = m_metric(v, f);
232  if (init || td < d) {
233  f_best = f;
234  d = td;
235  init = false;
236  }
237  }
238  }
239  assert(!init);
240  assign(v, f_best);
241  return d;
242  }
243 
251  VertexType vertex_to_generators(VertexType v) const {
252  auto i = m_vertices_to_generators.find(v);
253  assert(i != m_vertices_to_generators.end());
254  return i->second->first;
255  }
256 
263  void assign(VertexType v, VertexType f) {
264  auto prev = m_vertices_to_generators.at(v);
265  m_generators_to_vertices.erase(prev);
266  m_vertices_to_generators[v] =
267  m_generators_to_vertices.insert(std::make_pair(f, v));
268  }
269 
270 };
271 
272 
273 namespace detail {
274  template <typename Metric>
275  using v_t = typename metric_traits<Metric>::VertexType;
276 
277  template <typename Metric>
278  using generators_set_t = std::unordered_set<v_t<Metric>, boost::hash<v_t<Metric>>>;
279 
280  template <typename Metric>
281  using dist_t = typename metric_traits<Metric>::DistanceType;
282 }
283 
285 template <typename Metric>
287  const detail::generators_set_t<Metric> & generators,
288  detail::generators_set_t<Metric> vertices,
289  const Metric & metric,
290  detail::dist_t<Metric> costOfNoGenerator = std::numeric_limits<detail::dist_t<Metric>>::max())
291 {
292  return voronoi<Metric>(generators, std::move(vertices), metric, costOfNoGenerator);
293 }
294 
300 template <typename Metric>
301 struct voronoi_traits<voronoi<Metric>> : public _voronoi_traits<
302  voronoi<Metric>, typename metric_traits<Metric>::VertexType> {};
303 };
304 };
305 
306 #endif // PAAL_VORONOI_HPP
voronoi traits
voronoi(voronoi &&v)
Move constructor.
Definition: voronoi.hpp:104
voronoi< Metric > make_voronoi(const detail::generators_set_t< Metric > &generators, detail::generators_set_t< Metric > vertices, const Metric &metric, detail::dist_t< Metric > costOfNoGenerator=std::numeric_limits< detail::dist_t< Metric >>::max())
make for voronoi
Definition: voronoi.hpp:286
Dist add_generator(VertexType f)
returns diff between new cost and old cost
Definition: voronoi.hpp:112
const GeneratorsSet & get_generators() const
getter for generators
Definition: voronoi.hpp:174
default VertexType is int.
auto get_vertices_for_generator(VertexType g) const -> decltype(boost::as_array(m_generators_to_vertices.equal_range(g)|boost::adaptors::map_values))
getter for vertices assigned to specific generator
Definition: voronoi.hpp:188
bool operator==(const voronoi &vor) const
operator==
Definition: voronoi.hpp:197
voronoi(const voronoi &v)
Copy constructor.
Definition: voronoi.hpp:87
not_equal_to functor
Definition: functors.hpp:593
const Vertices & get_vertices() const
getter for vertices
Definition: voronoi.hpp:181
This file contains set of simple useful functors or functor adapters.
Dist rem_generator(VertexType f)
returns diff between new cost and old cost
Definition: voronoi.hpp:141
simple implementation of the Voronoi concept.
Definition: voronoi.hpp:42
voronoi(const GeneratorsSet &generators, Vertices vertices, const Metric &m, Dist costOfNoGenerator=std::numeric_limits< Dist >::max())
Constructor.
Definition: voronoi.hpp:73
puretype(std::declval< Metric >()(std::declval< VertexType >(), std::declval< VertexType >())) DistanceType
Distance type.