15 #ifndef PAAL_CAPACITATED_VORONOI_HPP
16 #define PAAL_CAPACITATED_VORONOI_HPP
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>
28 #include <unordered_map>
31 namespace data_structures {
45 template <
typename Metric,
typename GeneratorsCapacieties,
46 typename VerticesDemands>
66 Dist(DistI real, DistI distToFullAssign)
67 : m_real_dist(real), m_dist_to_full_assignment(distToFullAssign) {}
76 m_real_dist - d.m_real_dist,
77 m_dist_to_full_assignment - d.m_dist_to_full_assignment);
84 return m_dist_to_full_assignment;
98 return m_real_dist == d.m_real_dist &&
99 m_dist_to_full_assignment == d.m_dist_to_full_assignment;
108 if (m_dist_to_full_assignment > d.m_dist_to_full_assignment) {
110 }
else if (m_dist_to_full_assignment < d.m_dist_to_full_assignment) {
113 return m_real_dist > d.m_real_dist;
122 m_real_dist += d.m_real_dist;
123 m_dist_to_full_assignment += d.m_dist_to_full_assignment;
144 return Dist(-m_real_dist, -m_dist_to_full_assignment);
156 return Dist(d.m_real_dist + di, d.m_dist_to_full_assignment);
168 template <
typename Stream>
170 return s << d.m_dist_to_full_assignment <<
" " << d.m_real_dist;
175 DistI m_dist_to_full_assignment;
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;
183 typedef boost::adjacency_list<
184 boost::listS, boost::vecS, boost::bidirectionalS,
185 boost::property<boost::vertex_name_t, VertexType>,
187 boost::edge_capacity_t, DistI,
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>>>>>
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>>
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));
218 typedef boost::transform_iterator<Trans, IEI, std::pair<VertexType, DistI>>
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));
247 for (VertexType g : gen) {
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);
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());
285 add_edge_to_graph(genGraph, m_t, 0, m_generators_cap(gen));
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]));
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);
304 boost::as_array(in_edges(genGraph, m_g))) {
306 VD v = source(e, m_g);
310 DistI cap = residual_capacity[rev[e]];
312 std::tie(edgeFromStart, b) = edge(m_s, v, m_g);
314 residual_capacity[edgeFromStart] += cap;
315 residual_capacity[rev[edgeFromStart]] -= cap;
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);
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]));
351 boost::iterator_range<VForGenerator>
354 VD v = m_g_to_graph_v.at(gen);
355 auto r = in_edges(v, m_g);
358 return boost::make_iterator_range(VForGenerator(r.first, t),
359 VForGenerator(r.second, t));
368 auto residual_capacity =
get(boost::edge_residual_capacity, m_g);
370 boost::accumulate(out_edges(m_s, m_g), DistI(0), [&](DistI d,
const ED & e) {
371 return d + residual_capacity[e];
374 DistI cost = boost::find_flow_cost(m_g);
375 return Dist(cost, resCap);
387 template <
typename OStream>
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] <<
", ";
400 for (
auto e : boost::as_array(edgesToDisplay)) {
401 s << e <<
"-> " << residual_capacity[e] <<
"-> " << capacity[e]
405 for (
int g : v.m_generators) {
409 for (
int g : v.m_vertices) {
413 s << v.m_first_generator_id <<
"\n";
414 s << v.m_cost_of_no_generator <<
"\n";
416 for (std::pair<int, int> g : v.m_v_to_graph_v) {
417 s << g.first <<
", " << g.second <<
"\n";
420 for (std::pair<int, int> g : v.m_g_to_graph_v) {
421 s << g.first <<
", " << g.second <<
"\n";
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;
448 VD add_vertex_to_graph(VertexType v = VertexType()) {
449 VD vG = add_vertex(boost::property<boost::vertex_name_t, VertexType>(v),
451 int N = num_vertices(m_g);
454 m_dist_prev.resize(N);
467 void add_edge_to_graph(VD v, VD w, DistI weight, DistI capacity) {
468 auto rev =
get(boost::edge_reverse, m_g);
470 e = add_dir_edge(v, w, weight, capacity);
471 f = add_dir_edge(w, v, -weight, 0);
486 ED add_dir_edge(VD v, VD w, DistI weight, DistI capacity) {
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);
494 capacityMap[e] = capacity;
495 residual_capacity[e] = capacity;
496 weightMap[e] = weight;
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];
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)];
525 typedef std::vector<DistI> VPropMap;
527 VPropMap m_dist_prev;
528 std::vector<ED> m_pred;
533 Generators m_generators;
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;
545 #endif // PAAL_CAPACITATED_VORONOI_HPP
Dist operator-(Dist d)
operator-
const Dist & operator+=(Dist d)
operator+=
Dist operator-()
unary -operator
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)
bool operator>(Dist d) const
operator>
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
capacitated_voronoi(const capacitated_voronoi &other)
copy constructor is not default because of rev graph property
bool operator==(Dist d) const
operator==
friend Stream & operator<<(Stream &s, Dist d)
operator<<
Dist get_cost() const
get total cost of the assignment
Dist rem_generator(VertexType gen)
returns diff between new cost and old cost
this class store as a distance:
Dist operator+(Dist d)
operator+
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<<
DistI get_real_dist() const
sum of distances from vertices to facilities