All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
capacitated_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_CAPACITATED_VORONOI_HPP
16 #define PAAL_CAPACITATED_VORONOI_HPP
17 
19 #include "paal/utils/irange.hpp"
20 
21 #include <boost/graph/adjacency_list.hpp>
22 #include <boost/range/as_array.hpp>
23 #include <boost/range/numeric.hpp>
24 #include <boost/iterator/transform_iterator.hpp>
25 #include <boost/graph/successive_shortest_path_nonnegative_weights.hpp>
26 #include <boost/graph/find_flow_cost.hpp>
27 
28 #include <unordered_map>
29 
30 namespace paal {
31 namespace data_structures {
32 
45 template <typename Metric, typename GeneratorsCapacieties,
46  typename VerticesDemands>
48  public:
55  class Dist {
56  public:
57  typedef typename metric_traits<Metric>::DistanceType DistI;
58  Dist() = default;
59 
66  Dist(DistI real, DistI distToFullAssign)
67  : m_real_dist(real), m_dist_to_full_assignment(distToFullAssign) {}
68 
75  return Dist(
76  m_real_dist - d.m_real_dist,
77  m_dist_to_full_assignment - d.m_dist_to_full_assignment);
78  }
79 
84  return m_dist_to_full_assignment;
85  }
86 
90  DistI get_real_dist() const { return m_real_dist; }
91 
97  bool operator==(Dist d) const {
98  return m_real_dist == d.m_real_dist &&
99  m_dist_to_full_assignment == d.m_dist_to_full_assignment;
100  }
101 
107  bool operator>(Dist d) const {
108  if (m_dist_to_full_assignment > d.m_dist_to_full_assignment) {
109  return true;
110  } else if (m_dist_to_full_assignment < d.m_dist_to_full_assignment) {
111  return false;
112  }
113  return m_real_dist > d.m_real_dist;
114  }
115 
121  const Dist &operator+=(Dist d) {
122  m_real_dist += d.m_real_dist;
123  m_dist_to_full_assignment += d.m_dist_to_full_assignment;
124  return *this;
125  }
126 
133  Dist ret(d);
134  ret += *this;
135  return ret;
136  }
137 
144  return Dist(-m_real_dist, -m_dist_to_full_assignment);
145  }
146 
155  friend Dist operator+(DistI di, Dist d) {
156  return Dist(d.m_real_dist + di, d.m_dist_to_full_assignment);
157  }
158 
168  template <typename Stream>
169  friend Stream &operator<<(Stream &s, Dist d) {
170  return s << d.m_dist_to_full_assignment << " " << d.m_real_dist;
171  }
172 
173  private:
174  DistI m_real_dist;
175  DistI m_dist_to_full_assignment;
176  };
177  typedef typename Dist::DistI DistI;
178  typedef typename metric_traits<Metric>::VertexType VertexType;
179  typedef std::set<VertexType> Generators;
180  typedef std::vector<VertexType> Vertices;
181 
182  private:
183  typedef boost::adjacency_list<
184  boost::listS, boost::vecS, boost::bidirectionalS,
185  boost::property<boost::vertex_name_t, VertexType>,
186  boost::property<
187  boost::edge_capacity_t, DistI,
188  boost::property<
189  boost::edge_residual_capacity_t, DistI,
190  boost::property<boost::edge_reverse_t,
191  boost::adjacency_list_traits<
192  boost::listS, boost::vecS,
193  boost::bidirectionalS>::edge_descriptor,
194  boost::property<boost::edge_weight_t, DistI>>>>>
195  Graph;
196  typedef boost::graph_traits<Graph> GTraits;
197  typedef typename GTraits::edge_descriptor ED;
198  typedef typename GTraits::edge_iterator EI;
199  typedef typename GTraits::in_edge_iterator IEI;
200  typedef typename GTraits::vertex_descriptor VD;
201  typedef typename boost::property_map<
202  Graph, boost::edge_residual_capacity_t>::type ResidualCapacity;
203  typedef typename std::unordered_map<VertexType, VD, boost::hash<VertexType>>
204  VertexToGraphVertex;
205 
210  struct Trans {
211  std::pair<VertexType, DistI> operator()(const ED &e) const {
212  return std::make_pair(m_v->get_vertex_for_edge(e),
213  m_v->get_flow_on_edge(e));
214  }
215  const capacitated_voronoi *m_v;
216  };
217 
218  typedef boost::transform_iterator<Trans, IEI, std::pair<VertexType, DistI>>
219  VForGenerator;
220 
221  public:
222 
233  capacitated_voronoi(const Generators &gen, Vertices ver, const Metric &m,
234  const GeneratorsCapacieties &gc,
235  const VerticesDemands &vd,
236  DistI costOfNoGenerator =
237  std::numeric_limits<DistI>::max())
238  : m_s(add_vertex_to_graph()), m_t(add_vertex_to_graph()),
239  m_vertices(std::move(ver)), m_metric(m), m_generators_cap(gc),
240  m_first_generator_id(m_vertices.size() + 2),
241  m_cost_of_no_generator(costOfNoGenerator) {
242  for (VertexType v : m_vertices) {
243  VD vGraph = add_vertex_to_graph(v);
244  m_v_to_graph_v.insert(std::make_pair(v, vGraph));
245  add_edge_to_graph(m_s, vGraph, 0, vd(v));
246  }
247  for (VertexType g : gen) {
248  add_generator(g);
249  }
250  }
251 
258  : m_dist(other.m_dist), m_dist_prev(other.m_dist_prev),
259  m_pred(other.m_pred), m_g(other.m_g), m_s(other.m_s), m_t(other.m_t),
260  m_generators(other.m_generators), m_vertices(other.m_vertices),
261  m_metric(other.m_metric), m_generators_cap(other.m_generators_cap),
262  m_first_generator_id(other.m_first_generator_id),
263  m_cost_of_no_generator(other.m_cost_of_no_generator),
264  m_v_to_graph_v(other.m_v_to_graph_v),
265  m_g_to_graph_v(other.m_g_to_graph_v) {
266  auto rev = get(boost::edge_reverse, m_g);
267  for (auto e : boost::as_array(edges(m_g))) {
268  auto eb = edge(target(e, m_g), source(e, m_g), m_g);
269  assert(eb.second);
270  rev[e] = eb.first;
271  }
272  }
273 
275  Dist add_generator(VertexType gen) {
276  Dist costStart = get_cost();
277  m_generators.insert(gen);
278  VD genGraph = add_vertex_to_graph(gen);
279  m_g_to_graph_v.insert(std::make_pair(gen, genGraph));
280  for (const std::pair<VertexType, VD> &v : m_v_to_graph_v) {
281  add_edge_to_graph(v.second, genGraph, m_metric(v.first, gen),
282  std::numeric_limits<DistI>::max());
283  }
284 
285  add_edge_to_graph(genGraph, m_t, 0, m_generators_cap(gen));
286 
287  boost::successive_shortest_path_nonnegative_weights(
288  m_g, m_s, m_t, predecessor_map(&m_pred[0]).distance_map(&m_dist[0])
289  .distance_map2(&m_dist_prev[0]));
290 
291  return get_cost() - costStart;
292  }
293 
295  Dist rem_generator(VertexType gen) {
296  Dist costStart = get_cost();
297  m_generators.erase(gen);
298  auto genGraph = m_g_to_graph_v.at(gen);
299  auto rev = get(boost::edge_reverse, m_g);
300  auto residual_capacity = get(boost::edge_residual_capacity, m_g);
301 
302  // removing flow from the net
303  for (const ED &e :
304  boost::as_array(in_edges(genGraph, m_g))) {
305  bool b;
306  VD v = source(e, m_g);
307  if (v == m_t) {
308  continue;
309  }
310  DistI cap = residual_capacity[rev[e]];
311  ED edgeFromStart;
312  std::tie(edgeFromStart, b) = edge(m_s, v, m_g);
313  assert(b);
314  residual_capacity[edgeFromStart] += cap;
315  residual_capacity[rev[edgeFromStart]] -= cap;
316  }
317  clear_vertex(genGraph, m_g);
318  assert(!edge(m_t, genGraph, m_g).second);
319  assert(!edge(genGraph, m_t, m_g).second);
320  remove_vertex(genGraph, m_g);
321  restore_index();
322 
323  boost::successive_shortest_path_nonnegative_weights(
324  m_g, m_s, m_t, predecessor_map(&m_pred[0]).distance_map(&m_dist[0])
325  .distance_map2(&m_dist_prev[0]));
326 
327  return get_cost() - costStart;
328  }
329 
335  const Generators &get_generators() const { return m_generators; }
336 
342  const Vertices &get_vertices() const { return m_vertices; }
343 
351  boost::iterator_range<VForGenerator>
352  get_vertices_for_generator(VertexType gen) const {
353  IEI ei, end;
354  VD v = m_g_to_graph_v.at(gen);
355  auto r = in_edges(v, m_g);
356  Trans t;
357  t.m_v = this;
358  return boost::make_iterator_range(VForGenerator(r.first, t),
359  VForGenerator(r.second, t));
360  }
361 
367  Dist get_cost() const {
368  auto residual_capacity = get(boost::edge_residual_capacity, m_g);
369  DistI resCap =
370  boost::accumulate(out_edges(m_s, m_g), DistI(0), [&](DistI d, const ED & e) {
371  return d + residual_capacity[e];
372  });
373 
374  DistI cost = boost::find_flow_cost(m_g);
375  return Dist(cost, resCap);
376  }
377 
387  template <typename OStream>
388  friend OStream &operator<<(OStream &s, capacitated_voronoi &v) {
389  s << num_vertices(v.m_g) << ", ";
390  s << v.m_s << ", " << v.m_t << "\n";
391  auto verticesToDisplay = vertices(v.m_g);
392  auto edgesToDisplay = edges(v.m_g);
393  auto capacity = get(boost::edge_capacity, v.m_g);
394  auto residual_capacity = get(boost::edge_residual_capacity, v.m_g);
395  auto name = get(boost::vertex_name, v.m_g);
396  for (auto v : boost::as_array(verticesToDisplay)) {
397  s << v << "-> " << name[v] << ", ";
398  }
399  s << "\n";
400  for (auto e : boost::as_array(edgesToDisplay)) {
401  s << e << "-> " << residual_capacity[e] << "-> " << capacity[e]
402  << ", ";
403  }
404  s << "\n";
405  for (int g : v.m_generators) {
406  s << g << "\n";
407  }
408  s << "\n";
409  for (int g : v.m_vertices) {
410  s << g << "\n";
411  }
412  s << "\n";
413  s << v.m_first_generator_id << "\n";
414  s << v.m_cost_of_no_generator << "\n";
415  s << "\n";
416  for (std::pair<int, int> g : v.m_v_to_graph_v) {
417  s << g.first << ", " << g.second << "\n";
418  }
419  s << "\n";
420  for (std::pair<int, int> g : v.m_g_to_graph_v) {
421  s << g.first << ", " << g.second << "\n";
422  }
423  s << "\n";
424  return s;
425  }
426 
427  private:
428 
432  void restore_index() {
433  const unsigned N = num_vertices(m_g);
434  m_g_to_graph_v.clear();
435  auto name = get(boost::vertex_name, m_g);
436  for (unsigned i : irange(unsigned(m_first_generator_id), N)) {
437  m_g_to_graph_v[name[i]] = i;
438  }
439  }
440 
448  VD add_vertex_to_graph(VertexType v = VertexType()) {
449  VD vG = add_vertex(boost::property<boost::vertex_name_t, VertexType>(v),
450  m_g);
451  int N = num_vertices(m_g);
452 
453  m_dist.resize(N);
454  m_dist_prev.resize(N);
455  m_pred.resize(N);
456  return vG;
457  }
458 
467  void add_edge_to_graph(VD v, VD w, DistI weight, DistI capacity) {
468  auto rev = get(boost::edge_reverse, m_g);
469  ED e, f;
470  e = add_dir_edge(v, w, weight, capacity);
471  f = add_dir_edge(w, v, -weight, 0);
472  rev[e] = f;
473  rev[f] = e;
474  }
475 
486  ED add_dir_edge(VD v, VD w, DistI weight, DistI capacity) {
487  bool b;
488  ED e;
489  auto weightMap = get(boost::edge_weight, m_g);
490  auto capacityMap = get(boost::edge_capacity, m_g);
491  auto residual_capacity = get(boost::edge_residual_capacity, m_g);
492  std::tie(e, b) = add_edge(v, w, m_g);
493  assert(b);
494  capacityMap[e] = capacity;
495  residual_capacity[e] = capacity;
496  weightMap[e] = weight;
497  return e;
498  }
499 
507  DistI get_flow_on_edge(const ED &e) const {
508  auto capacityMap = get(boost::edge_capacity, m_g);
509  auto residual_capacity = get(boost::edge_residual_capacity, m_g);
510  return capacityMap[e] - residual_capacity[e];
511  }
512 
520  VertexType get_vertex_for_edge(const ED &e) const {
521  auto name = get(boost::vertex_name, m_g);
522  return name[source(e, m_g)];
523  }
524 
525  typedef std::vector<DistI> VPropMap;
526  VPropMap m_dist;
527  VPropMap m_dist_prev;
528  std::vector<ED> m_pred;
529 
530  Graph m_g;
531  VD m_s, m_t;
532 
533  Generators m_generators;
534  Vertices m_vertices;
535  const Metric &m_metric;
536  const GeneratorsCapacieties &m_generators_cap;
537  const VD m_first_generator_id;
538  DistI m_cost_of_no_generator;
539  VertexToGraphVertex m_v_to_graph_v;
540  VertexToGraphVertex m_g_to_graph_v;
541 };
542 
543 }
544 }
545 #endif // PAAL_CAPACITATED_VORONOI_HPP
const Vertices & get_vertices() const
getter for vertices
Dist add_generator(VertexType gen)
returns diff between new cost and old cost
DistI get_dist_to_full_assignment() const
how many vertices are not covered
Computes size of TypesVector.
Dist(DistI real, DistI distToFullAssign)
constructor
friend Dist operator+(DistI di, Dist d)
Dist + scalar (interpreted as real distance)
capacitated_voronoi(const Generators &gen, Vertices ver, const Metric &m, const GeneratorsCapacieties &gc, const VerticesDemands &vd, DistI costOfNoGenerator=std::numeric_limits< DistI >::max())
constructor
auto irange(T begin, T end)
irange
Definition: irange.hpp:22
capacitated_voronoi(const capacitated_voronoi &other)
copy constructor is not default because of rev graph property
friend Stream & operator<<(Stream &s, Dist d)
operator&lt;&lt;
Dist get_cost() const
get total cost of the assignment
Dist rem_generator(VertexType gen)
returns diff between new cost and old cost
puretype(std::declval< Metric >()(std::declval< VertexType >(), std::declval< VertexType >())) DistanceType
Distance type.
This class is assigning vertices demands to capacitated generators in such a way that the total cost ...
const Generators & get_generators() const
getter for generators
boost::iterator_range< VForGenerator > get_vertices_for_generator(VertexType gen) const
member function for getting assignment, for generator.
friend OStream & operator<<(OStream &s, capacitated_voronoi &v)
operator&lt;&lt;
DistI get_real_dist() const
sum of distances from vertices to facilities