Aleph-w  1.9
General library for algorithms and data structures
tpl_netcost.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 # ifndef TPL_MAXFLOW_MINCOST_H
28 # define TPL_MAXFLOW_MINCOST_H
29 
30 # include <Bellman_Ford.H>
31 # include <tpl_net.H>
32 # include <generate_graph.H>
33 
34 using namespace Aleph;
35 
36 namespace Aleph {
37 
38 template <typename Node_Info = Empty_Class>
40 
55  template <typename Arc_Info = Empty_Class, typename F_Type = double>
56 struct Net_Cost_Arc : public Net_Arc<Arc_Info, F_Type>
57 {
59 
60  using Base::Base; // hereda constructores
61 
63  using Flow_Type = F_Type;
64 
66  Flow_Type cost = 0;
67 
69  Flow_Type flow_cost() const noexcept { return this->flow*cost; }
70 
71  Net_Cost_Arc(const Net_Cost_Arc & a) noexcept(noexcept(Base(a)))
72  : Base(a), cost(a->cost) {}
73 
74  Net_Cost_Arc & operator = (const Net_Cost_Arc & a)
75  noexcept(std::is_nothrow_copy_assignable<Arc_Info>::value)
76  {
77  if (&a == this)
78  return *this;
79  *(Base*) this = a;
80  cost = a.cost;
81  return *this;
82  }
83 };
84 
103  template <class NodeT = Net_Cost_Node<Empty_Class>,
104  class ArcT = Net_Cost_Arc<Empty_Class, double>>
105 struct Net_Cost_Graph : public Net_Graph<NodeT, ArcT>
106 {
107  using Base = Net_Graph<NodeT, ArcT>;
108 
109  Net_Cost_Graph(const Net_Cost_Graph & net) : Base(net)
110  {
111  zip(this->arcs(), net.arcs()).for_each([] (const auto & p)
112  {
113  auto atgt = p.first;
114  auto asrc = p.second;
115  atgt->cost = asrc->cost;
116  });
117  }
118 
119  Net_Cost_Graph() {}
120 
124 
126 
128  using Arc = ArcT;
129 
131  using Node = NodeT;
132 
134  using Flow_Type = typename Arc::Flow_Type;
135 
137  using Node_Type = typename Node::Node_Type;
138 
140  using Arc_Type = typename Arc::Arc_Type;
141 
143  Flow_Type & get_cost(Arc * a) noexcept { return a->cost; }
144 
146  const Flow_Type & flow_cost(Arc * a) const noexcept { return a->flow_cost(); }
147 
158  virtual Arc * insert_arc(Node * src_node, Node * tgt_node,
159  const Flow_Type & cap, const Flow_Type & cost)
160  {
161  Arc * a = Net::insert_arc(src_node, tgt_node, cap, 0, Arc_Type());
162  a->cost = cost;
163  return a;
164  }
165 
166  template <typename ... Args>
167  Arc * emplace_arc(Node * src_node, Node * tgt_node,
168  const Flow_Type & cap, const Flow_Type & cost,
169  Args && ... args)
170  {
171  auto a = Net::insert_arc(src_node, tgt_node, cap, cost, Arc_Type(args...));
172  a->cost = cost;
173  return a;
174  }
175 
177  virtual Arc * insert_arc(Node * src_node, Node * tgt_node)
178  {
179  Arc * a = Net::insert_arc(src_node, tgt_node, Arc_Type());
180  a->cost = 0;
181  return a;
182  }
183 
185  // virtual Arc * insert_arc(Node * src_node, Node * tgt_node,
186  // const Arc_Type & arc_info)
187  // {
188  // Arc * a = Net::insert_arc(src_node, tgt_node, arc_info);
189  // a->cost = 0;
190  // return a;
191  // }
192 
194  Flow_Type flow_cost() const noexcept
195  {
196  Flow_Type total = 0;
197  for (Arc_Iterator<Net_MFMC> it(*this); it.has_curr(); it.next_ne())
198  {
199  Arc * a = it.get_curr_ne();
200  total += a->flow_cost();
201  }
202 
203  return total;
204  }
205 
207  auto out_pars(Node * p) noexcept
208  {
209  Flow_Type cap_sum = 0, flow_sum = 0, cost_sum = 0;
210  for (__Out_Iterator<Net> it(p); it.has_curr(); it.next_ne())
211  {
212  Arc * a = it.get_curr_ne();
213  cap_sum += a->cap;
214  flow_sum += a->flow;
215  cost_sum += a->cost;
216  }
217  return make_tuple(cap_sum, flow_sum, cost_sum);
218  }
219 
221  auto in_pars(Node * p) noexcept
222  {
223  Flow_Type cap_sum = 0, flow_sum = 0, cost_sum = 0;
224  for (__In_Iterator<Net> it(p); it.has_curr(); it.next_ne())
225  {
226  Arc * a = it.get_curr_ne();
227  cap_sum += a->cap;
228  flow_sum += a->flow;
229  cost_sum += a->cost;
230  }
231  return make_tuple(cap_sum, flow_sum, cost_sum);
232  }
233 };
234 
235 
236 // Filtro de arcos para una red residual
237  template <class Net>
238 struct Res_Filt
239 {
240  Res_Filt(typename Net::Node *) noexcept {}
241 
242  Res_Filt() noexcept {}
243 
244  bool operator () (typename Net::Arc * a) const noexcept
245  {
246  return a->cap > a->flow;
247  }
248 };
249 
250  template <class Net>
251 struct Rcost
252 {
253  Rcost () noexcept {}
254 
255  using Distance_Type = typename Net::Flow_Type;
256 
257  // Este es el operador que se llamaría cuando se ejecuta Distance()(a)
258  typename Net::Flow_Type operator () (typename Net::Arc * a) const noexcept
259  {
260  return a->cost;
261  }
262 
263  static void set_zero(typename Net::Arc * a) noexcept
264  {
265  a->cap = numeric_limits<Distance_Type>::max();
266  a->flow = 0;
267  a->cost = 0;
268  }
269 };
270 
271 
272  template <typename Ftype>
273 struct Res_Arc : public Net_Cost_Arc<Empty_Class, Ftype>
274 {
276  using Base::Base;
277 
278  bool is_residual = false;
279  Res_Arc * img = nullptr;
280 };
281 
282 
283 template <typename Ftype>
284 using Residual_Net = Net_Cost_Graph<Net_Node<Empty_Class>, Res_Arc<Ftype>>;
285 
286 // Inserta en la red residual residual_net los arcos residuales
287 // correspondientes al arco a. src y tgt son los nodos origen y destino
288 // respectivamente de la red residual. Retorna el arco residual reflejo
289 // de a
290 template <class Res_Net> typename Res_Net::Arc *
291 create_residual_arc(Res_Net & residual_net,
292  typename Res_Net::Node * src,
293  typename Res_Net::Node * tgt,
294  const typename Res_Net::Flow_Type cap,
295  const typename Res_Net::Flow_Type flow,
296  const typename Res_Net::Flow_Type cost)
297 {
298  assert(flow <= cap and cost >= 0);
299 
300  auto arc = residual_net.insert_arc(src, tgt, cap, cost);
301  auto rarc = residual_net.insert_arc(tgt, src, cap, -cost);
302 
303  arc->is_residual = false;
304  arc->flow = flow;
305  arc->img = rarc;
306 
307  rarc->is_residual = true;
308  rarc->img = arc;
309  rarc->flow = arc->cap - arc->flow;
310 
311  assert(arc->cap == cap and arc->flow == flow and arc->cost == cost);
312  assert(rarc->cap == cap and rarc->flow == cap - flow and rarc->cost == -cost);
313 
314  return arc;
315 }
316 
317 // Construye una red residual para la red net. Retorna una tupla de dos
318 // elementos. El primer elemento es la red residual. El segundo es un
319 // mapeo desde los arcos de net hacia los arcos de los arcos de la red
320 // residual. Retorna el nodo mapeo del fuente en la red residual
321 template <class Net>
323 build_residual_net(const Net & net,
326 {
327  if (not (net.is_single_source() and net.is_single_sink()))
328  throw std::domain_error("Network is not single source and single sink");
329 
331 
332  // recorre los nodos de net e inserta copias en la red residual
333  for (typename Net::Node_Iterator it(net); it.has_curr(); it.next_ne())
334  {
335  auto p = it.get_curr_ne();
336  auto q = rnet.insert_node(); // TODO: borrar get_info
337  map_nodes<Net, Rnet>(p, q); // mapeo temporal de nodos
338  }
339 
340  // Recorre arcos de net y construye mapeo arcs
341  for (typename Net::Arc_Iterator it(net); it.has_curr(); it.next_ne())
342  {
343  auto ga = it.get_curr_ne();
344  auto gsrc = (typename Net::Node*) ga->src_node;
345  auto gtgt = (typename Net::Node*) ga->tgt_node;
346 
347  auto rsrc = mapped_node<Net, Rnet>(gsrc);
348  auto rtgt = mapped_node<Net, Rnet>(gtgt);
349  auto ra =
350  create_residual_arc(rnet, rsrc, rtgt, ga->cap, ga->flow, ga->cost);
351  arcs.insert(ga, ra);
352  }
353 
354  assert(check_residual_net(rnet));
355 
356  return (typename Rnet::Node*) NODE_COOKIE(net.get_source());
357 }
358 
359 template <class Res_Net>
360 bool check_residual_net(const Res_Net & net)
361 {
362  return
363  net.all_arcs([] (typename Res_Net::Arc * a) { return a->img->img == a; });
364 }
365 
366 template <class Res_Net>
367 void cancel_cycle(const Res_Net &, const Path<Res_Net> & path)
368 {
369  assert(not path.is_empty() and path.is_cycle());
370  using Ftype = typename Res_Net::Flow_Type;
371 
372  // Determina el slack del ciclo
373  Ftype slack = std::numeric_limits<Ftype>::max();
374  path.for_each_arc([&slack] (typename Res_Net::Arc * a)
375  {
376  assert(a->cap -a->flow > 0);
377  slack = std::min(slack, a->cap - a->flow);
378  });
379 
380  // cancela el ciclo
381  path.for_each_arc([slack] (typename Res_Net::Arc * a)
382  {
383  auto img = a->img;
384  assert(img->img == a);
385  assert(a->cap == img->cap);
386  a->flow += slack;
387  img->flow -= slack;
388  });
389 }
390 
391 // recibe un mapeo de arcos desde la red residual hacia la red
392 // original. Recorre los arcos y actualiza los valores de flujo en la
393 // red original
394 template <class Net> static
395 void residual_to_net(const DynMapTree<void*, void*> & arcs)
396 {
398  arcs.for_each([] (std::pair<void*, void*> p)
399  {
400  auto a = (typename Rnet::Arc *) p.first;
401  auto ra = (typename Net::Arc *) p.second;
402  a->flow = ra->flow;
403  });
404 }
405 
434 template
435 <class Net,
436  template <class> class Max_Flow_Algo = Ford_Fulkerson_Maximum_Flow>
437 tuple<size_t, double>
439  double it_factor = 0.4,
440  size_t step = 10)
441 {
442  Max_Flow_Algo <Net> () (net); // compute max flow
443 
445  using BF =
447 
448  Rnet rnet;
450  typename Rnet::Node * source = build_residual_net(net, rnet, arcs_map);
451 
452  size_t count = 0;
453 
454  while (true)
455  { search:
456  tuple<Path<Rnet>, size_t> cycle =
457  BF(rnet).search_negative_cycle(source, it_factor, step);
458  if (get<0>(cycle).is_empty())
459  break;
460 
461  // augment it_factor according to last break counter
462  it_factor = ((double) get<1>(cycle))/net.vsize();
463  cancel_cycle(rnet, get<0>(cycle));
464  }
465 
466  tuple<Path<Rnet>, size_t> cycle =
467  BF(rnet).search_negative_cycle(it_factor, step);
468  if (not get<0>(cycle).is_empty()) // negative cycle found?
469  {
470  cancel_cycle(rnet, get<0>(cycle));
471  goto search;
472  }
473 
474  residual_to_net<Net>(arcs_map);
475 
476  return make_tuple(count, it_factor);
477 }
478 
479 
480 template <class Net,
481  template <class> class Max_Flow_Algo = Ford_Fulkerson_Maximum_Flow>
482 struct Max_Flow_Min_Cost_By_Cycle_Canceling
483 {
484  tuple<size_t, double> operator () (Net & net,
485  double it_factor = 0.4,
486  size_t step = 10)
487  {
488  return max_flow_min_cost_by_cycle_canceling<Net, Max_Flow_Algo>
489  (net, it_factor, step);
490  }
491 };
492 
493 template <class Net>
494 void print(const Net & net, ostream & out)
495 {
496  long i = 0;
497  net.nodes().for_each([&i] (typename Net::Node* p) { NODE_COUNTER(p) = i++; });
498 
499  struct Show_Node
500  {
501  void operator () (const Net &, typename Net::Node * p, ostream & out)
502  {
503  out << "label = \"(" << p->get_info() << "," << NODE_COUNTER(p) << ")\"";
504  }
505  };
506 
507  struct Show_Arc
508  {
509  void operator () (const Net &, typename Net::Arc * a, ostream & out)
510  {
511  out << "label = \"" << a->flow << "/" << a->cap << "/" << a->cost << "\"";
512  }
513  };
514 
515  To_Graphviz<Net, Show_Node, Show_Arc> ().digraph (net, out);
516 }
517 
518 template <class Net>
519 void print(const Residual_Net<typename Net::Flow_Type> & net, ostream & out)
520 {
521  long i = 0;
522  net.nodes().for_each([&i] (typename Net::Node* p) { NODE_COUNTER(p) = i++; });
523 
524  struct Show_Node
525  {
526  void operator () (const Net &, typename Net::Node * p, ostream & out)
527  {
528  out << "label = \"(" << p->get_info() << "," << NODE_COUNTER(p) << ")\"";
529  }
530  };
531 
532  struct Show_Arc
533  {
534  void operator () (const Net &, typename Net::Arc * a, ostream & out)
535  {
536  out << "label = \"" << a->flow << "/" << a->cap << "/" << a->cost << "\"";
537  if (a->is_residual)
538  out << " color = red";
539  }
540  };
541 
543  digraph (net, out);
544 }
545 
546 
547  template <class Net>
548 struct SimplexInfo
549 {
550  typename Net::Flow_Type potential;
551  long valid = 0;
552 };
553 
554 template <class Net> static inline
555 void init_simplex_info(Net & /* net */)
556 {
557 
558 }
559 
560 
561 // 1er campo arcos vacíos, 2do arcos llenos, 3ro arcos parciales
562  template <class Net>
563 using Feasible_Tree = tuple<DynList<typename Net::Arc*>,
565  DynList<typename Net::Arc*>>;
566 
567 
568 template <class Net> static inline
569 Feasible_Tree<Net> build_feasible_spanning_tree(const Net & net)
570 {
571  using Arc = typename Net::Arc;
572  DynList<Arc*> empty, full, partial;
573  for (typename Net::Arc_Iterator it(net); it.has_curr(); it.next_ne())
574  {
575  auto a = it.get_curr_ne();
576  if (a->flow == 0) // arco vacío?
577  empty.append(a);
578  else if (a->flow == a->cap) // arco lleno?
579  full.append(a);
580  else
581  partial.append(a);
582  }
583  return make_tuple(std::move(empty), std::move(full), std::move(partial));
584 }
585 
586 
587 template <class Net> static inline
588 DynList<typename Net::Arc*> get_partial_arcs(const Net & net)
589 {
590  DynList<typename Net::Arc*> ret;
591  for (typename Net::Arc_Iterator it(net); it.has_curr(); it.next_ne())
592  {
593  auto a = it.get_curr_ne();
594  if (a->flow > 0 and a->flow < a->cap)
595  ret.append(a);
596  }
597  return ret;
598 }
599 
600 
601 # define POTENTIAL(p) (NODE_COUNTER(p))
602 
603 
604 template <class Net>
605 typename Net::Flow_Type rcost(typename Net::Node * src,
606  typename Net::Node * tgt)
607 {
608  for (Out_Iterator<Net> it(src); it.has_curr(); it.next_ne())
609  {
610  auto a = it.get_curr_ne();
611  if (a->tgt_node == tgt)
612  return a->cost - (POTENTIAL(src) - POTENTIAL(tgt));
613  }
614  AH_ERROR("Arc not found");
615 }
616 
617 
618 template <class Net>
619 typename Net::Flow_Type rcost(typename Net::Arc * a)
620 {
621  using Node = typename Net::Node*;
622  return a->cost -
623  (POTENTIAL((Node*)a->src_node) - POTENTIAL((Node*)a->tgt_node));
624 }
625 
626 
627 
628 
629 # undef POTENTIAL
630 
631 } // end namespace Aleph
632 
633 # endif // TPL_MAXFLOW_MINCOST_H
Flow_Type flow
valor de flujo
Definition: tpl_net.H:92
Flow_Type & get_cost(Arc *a) noexcept
Retorna una referencia modificable al coste de un arco.
Definition: tpl_netcost.H:143
Definition: tpl_graph.H:1225
bool is_single_source() const noexcept
Retorna true si la red es de un solo fuente.
Definition: tpl_net.H:326
Definition: tpl_agraph.H:301
virtual Arc * insert_arc(Node *src_node, Node *tgt_node, const Flow_Type &cap, const Flow_Type &cost)
Definition: tpl_netcost.H:158
Flow_Type cap
valor de capacidad
Definition: tpl_net.H:89
Pair * insert(const Key &key, const Data &data)
Definition: tpl_dynMapTree.H:112
#define NODE_COOKIE(p)
Definition: aleph-graph.H:333
Container< __Graph_Node *> nodes() const
Definition: graph-dry.H:2091
Definition: tpl_dynMapTree.H:62
Definition: tpl_net.H:82
Definition: tpl_net.H:216
Flow_Type flow_cost() const noexcept
Retorna el coste del flujo circulante.
Definition: tpl_netcost.H:69
auto in_pars(Node *p) noexcept
retorna una tripleta de capacidad, flujo y costo saliente
Definition: tpl_netcost.H:221
void * tgt_node
Please don&#39;t use.
Definition: graph-dry.H:280
#define NODE_COUNTER(p)
Definition: aleph-graph.H:311
Definition: tpl_netcost.H:56
Container< T > arcs_map(GT &g, std::function< T(typename GT::Arc *)> transformation, SA sa=SA())
Definition: tpl_graph.H:1459
const Flow_Type & flow_cost(Arc *a) const noexcept
Retorna una referencia al coste de un arco:
Definition: tpl_netcost.H:146
NodeT Node
Tipo de node.
Definition: tpl_net.H:230
Definition: generate_graph.H:630
Definition: tpl_graph.H:53
Definition: tpl_agraph.H:43
DynList< typename GT::Arc * > arcs(typename GT::Node *p, SA sa=SA())
Definition: tpl_graph.H:1893
typename Arc::Flow_Type Flow_Type
Tipo que representa la capacidad y el flujo.
Definition: tpl_net.H:233
Definition: ah-comb.H:35
ArcT Arc
Tipo de arco.
Definition: tpl_net.H:227
Definition: Bellman_Ford.H:53
Flow_Type cost
coste por unidad de flujo (negativo si el arco es residual)
Definition: tpl_netcost.H:66
Container< Arc * > arcs() const
Definition: graph-dry.H:2109
Definition: tpl_graph.H:1796
Node * insert_node(const Node_Type &node_info)
Definition: tpl_net.H:481
Definition: tpl_net.H:1530
void for_each_arc(Operation op=Operation()) const noexcept(noexcept(op))
Definition: tpl_graph.H:3265
bool is_single_sink() const noexcept
Retorna true si la red es de un solo sumidero.
Definition: tpl_net.H:329
bool is_empty() const noexcept
Return true if the path is empty.
Definition: tpl_graph.H:2758
Flow_Type flow_cost() const noexcept
Usado por algorítmica interna. NO UTILIZAR.
Definition: tpl_netcost.H:194
typename GT::Out_Iterator __Out_Iterator
Definition: tpl_graph.H:1780
virtual Arc * insert_arc(Node *src_node, Node *tgt_node)
Usado por algorítmica interna. NO UTILIZAR.
Definition: tpl_netcost.H:177
tuple< size_t, double > max_flow_min_cost_by_cycle_canceling(Net &net, double it_factor=0.4, size_t step=10)
Definition: tpl_netcost.H:438
Definition: ahDry.H:41
Definition: tpl_netcost.H:105
bool is_cycle() const noexcept
Return true if this is a cycle.
Definition: tpl_graph.H:3098
typename GT::In_Iterator __In_Iterator
Definition: tpl_graph.H:1788
Node * get_source() const
Retorna un nodo fuente de la red.
Definition: tpl_net.H:466
T & append(const T &item)
Definition: htlist.H:1471
NodeT Node
Tipo de node.
Definition: tpl_netcost.H:131
auto out_pars(Node *p) noexcept
retorna una tripleta de capacidad, flujo y costo saliente
Definition: tpl_netcost.H:207

Leandro Rabindranath León