Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DualMinCostFlow.h
Go to the documentation of this file.
1 
8 #ifndef LIMBO_SOLVERS_DUALMINCOSTFLOW_H
9 #define LIMBO_SOLVERS_DUALMINCOSTFLOW_H
10 
11 #include <lemon/smart_graph.h>
12 #include <lemon/network_simplex.h>
13 #include <lemon/cost_scaling.h>
14 #include <lemon/capacity_scaling.h>
15 #include <lemon/cycle_canceling.h>
16 #include <lemon/lgf_writer.h>
17 
18 #include <limbo/solvers/Solvers.h>
19 
21 namespace limbo
22 {
24 namespace solvers
25 {
26 
27 // forward declaration
28 template <typename T, typename V>
30 template <typename T, typename V>
32 template <typename T, typename V>
34 template <typename T, typename V>
36 template <typename T, typename V>
38 
101 template <typename T, typename V>
103 {
104  public:
108  typedef typename model_type::coefficient_value_type coefficient_value_type;
109  typedef typename model_type::variable_value_type variable_value_type;
110  typedef variable_value_type value_type; // use only one kind of value type
111  typedef typename model_type::variable_type variable_type;
114  typedef typename model_type::term_type term_type;
115  typedef typename model_type::property_type property_type;
116 
117  typedef lemon::SmartDigraph graph_type;
118  typedef graph_type::Node node_type;
119  typedef graph_type::Arc arc_type;
120  typedef graph_type::NodeMap<value_type> node_value_map_type;
121  typedef graph_type::NodeMap<std::string> node_name_map_type;
122  typedef graph_type::ArcMap<value_type> arc_value_map_type;
123  typedef graph_type::ArcMap<value_type> arc_cost_map_type;
124  typedef graph_type::ArcMap<value_type> arc_flow_map_type;
125  typedef graph_type::NodeMap<value_type> node_pot_map_type; // potential of each node
126 
129 
132  DualMinCostFlow(model_type* model)
133  : m_model(model)
134  , m_graph()
135  //, m_mLower(m_graph)
136  , m_mUpper(m_graph)
137  , m_mCost(m_graph)
138  , m_mSupply(m_graph)
139  , m_totalFlowCost(std::numeric_limits<typename DualMinCostFlow<T, V>::value_type>::max())
140  , m_diffBigM(std::numeric_limits<typename DualMinCostFlow<T, V>::value_type>::max())
141  , m_boundBigM(std::numeric_limits<typename DualMinCostFlow<T, V>::value_type>::max())
142  , m_mFlow(m_graph)
144  {
145  }
148  {
149  }
150 
153  SolverProperty operator()(solver_type* solver = NULL)
154  {
155  return solve(solver);
156  }
157 
159  value_type diffBigM() const;
162  void setDiffBigM(value_type v);
164  value_type boundBigM() const;
167  void setBoundBigM(value_type v);
168 
170  graph_type const& graph() const;
172  //arc_value_map_type const& lowerMap() const;
174  arc_value_map_type const& upperMap() const;
176  arc_cost_map_type const& costMap() const;
178  node_value_map_type const& supplyMap() const;
180  arc_flow_map_type& flowMap();
182  node_pot_map_type& potentialMap();
184  value_type totalFlowCost() const;
186  void setTotalFlowCost(value_type cost);
188  value_type totalCost() const;
189 
194  void printGraph(bool writeSol) const;
196  protected:
199  DualMinCostFlow(DualMinCostFlow const& rhs);
203 
206  SolverProperty solve(solver_type* solver);
208  void prepare();
210  void buildGraph();
212  void mapObjective2Graph();
216  unsigned int mapDiffConstraint2Graph(bool countArcs);
220  unsigned int mapBoundConstraint2Graph(bool countArcs);
226  void addArcForDiffConstraint(node_type xi, node_type xj, value_type cij, value_type bigM);
228  void applySolution();
229 
230  model_type* m_model;
231 
232  graph_type m_graph;
233  //arc_value_map_type m_mLower; ///< lower bound of flow, usually zero
234  arc_value_map_type m_mUpper;
235  arc_cost_map_type m_mCost;
236  node_value_map_type m_mSupply;
237  value_type m_totalFlowCost;
238  value_type m_diffBigM;
239  value_type m_boundBigM;
241 
242  arc_flow_map_type m_mFlow;
243  node_pot_map_type m_mPotential;
244 };
245 
246 template <typename T, typename V>
247 typename DualMinCostFlow<T, V>::value_type DualMinCostFlow<T, V>::diffBigM() const
248 {
249  return m_diffBigM;
250 }
251 template <typename T, typename V>
252 void DualMinCostFlow<T, V>::setDiffBigM(DualMinCostFlow<T, V>::value_type v)
253 {
254  m_diffBigM = v;
255 }
256 template <typename T, typename V>
257 typename DualMinCostFlow<T, V>::value_type DualMinCostFlow<T, V>::boundBigM() const
258 {
259  return m_boundBigM;
260 }
261 template <typename T, typename V>
262 void DualMinCostFlow<T, V>::setBoundBigM(DualMinCostFlow<T, V>::value_type v)
263 {
264  m_boundBigM = v;
265 }
266 template <typename T, typename V>
267 typename DualMinCostFlow<T, V>::graph_type const& DualMinCostFlow<T, V>::graph() const
268 {
269  return m_graph;
270 }
271 //template <typename T, typename V>
272 //DualMinCostFlow<T, V>::arc_value_map_type const& DualMinCostFlow<T, V>::lowerMap() const
273 //{
274 // return m_mLower;
275 //}
276 template <typename T, typename V>
277 typename DualMinCostFlow<T, V>::arc_value_map_type const& DualMinCostFlow<T, V>::upperMap() const
278 {
279  return m_mUpper;
280 }
281 template <typename T, typename V>
282 typename DualMinCostFlow<T, V>::arc_cost_map_type const& DualMinCostFlow<T, V>::costMap() const
283 {
284  return m_mCost;
285 }
286 template <typename T, typename V>
287 typename DualMinCostFlow<T, V>::node_value_map_type const& DualMinCostFlow<T, V>::supplyMap() const
288 {
289  return m_mSupply;
290 }
291 template <typename T, typename V>
292 typename DualMinCostFlow<T, V>::arc_flow_map_type& DualMinCostFlow<T, V>::flowMap()
293 {
294  return m_mFlow;
295 }
296 template <typename T, typename V>
297 typename DualMinCostFlow<T, V>::node_pot_map_type& DualMinCostFlow<T, V>::potentialMap()
298 {
299  return m_mPotential;
300 }
301 template <typename T, typename V>
302 typename DualMinCostFlow<T, V>::value_type DualMinCostFlow<T, V>::totalFlowCost() const
303 {
304  return m_totalFlowCost;
305 }
306 template <typename T, typename V>
307 void DualMinCostFlow<T, V>::setTotalFlowCost(typename DualMinCostFlow<T, V>::value_type cost)
308 {
309  m_totalFlowCost = cost;
310 }
311 template <typename T, typename V>
312 typename DualMinCostFlow<T, V>::value_type DualMinCostFlow<T, V>::totalCost() const
313 {
314  // the negation comes from we change maximization problem into minimization problem
315  // the dual LP problem should be a maximization problem, but we solve it with min-cost flow
316  return -(totalFlowCost()-m_reversedArcFlowCost);
317 }
318 template <typename T, typename V>
319 void DualMinCostFlow<T, V>::printGraph(bool writeSol) const
320 {
321  limboPrint(kDEBUG, "diffBigM = %ld, boundBigM = %ld, reversedArcFlowCost = %ld\n", (long)m_diffBigM, (long)m_boundBigM, (long)m_reversedArcFlowCost);
322  if (writeSol)
323  limboPrint(kDEBUG, "totalFlowCost = %ld, totalCost = %ld\n", (long)totalFlowCost(), (long)totalCost());
324 
325  node_name_map_type nameMap (m_graph);
326  for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
327  nameMap[m_graph.nodeFromId(i)] = m_model->variableName(variable_type(i));
328  nameMap[m_graph.nodeFromId(m_graph.maxNodeId())] = "additional";
329 
330  // dump lgf file
331  lemon::DigraphWriter<graph_type> writer(m_graph, "debug.lgf");
332  writer.nodeMap("supply", m_mSupply)
333  .nodeMap("name", nameMap)
334  .arcMap("capacity_upper", m_mUpper)
335  .arcMap("cost", m_mCost);
336  if (writeSol)
337  writer.nodeMap("potential", m_mPotential)
338  .arcMap("flow", m_mFlow);
339  writer.run();
340 }
341 template <typename T, typename V>
343 {
344  bool defaultSolver = false;
345  // use default solver if NULL
346  if (solver == NULL)
347  {
349  defaultSolver = true;
350  }
351 
352  // skip empty problem
353  if (m_model->numVariables() == 0)
354  return OPTIMAL;
355 
356  // prepare
357  prepare();
358  // build graph
359  buildGraph();
360 #ifdef DEBUG_DUALMINCOSTFLOW
361  printGraph(false);
362  // total supply must be zero
363  coefficient_value_type totalSupply = 0;
364  for (graph_type::NodeIt it (m_graph); it != lemon::INVALID; ++it)
365  totalSupply += m_mSupply[it];
366  limboAssert(totalSupply == 0);
367 #endif
368  // solve min-cost flow problem
369  SolverProperty status = solver->operator()(this);
370  // apply solution
371  applySolution();
372 
373 #ifdef DEBUG_DUALMINCOSTFLOW
374  printGraph(true);
375 #endif
376 
377  if (defaultSolver)
378  delete solver;
379 
380  return status;
381 }
382 template <typename T, typename V>
384 {
385  // big M should be larger than the summation of all non-negative supply in the graph
386  // because this is the largest possible amount of flows.
387  // The supply for each node is the coefficient of variable in the objective.
388  if (m_diffBigM == std::numeric_limits<value_type>::max()) // if not set
389  {
390  m_diffBigM = 0;
391  for (typename std::vector<term_type>::const_iterator it = m_model->objective().terms().begin(), ite = m_model->objective().terms().end(); it != ite; ++it)
392  {
393  if (it->coefficient() > 0)
394  m_diffBigM += it->coefficient();
395  }
396  }
397  // big M for bound constraints should be larger than that for differential constraints
398  // so the results are more controllable for INFEASIBLE models
399  if (m_boundBigM == std::numeric_limits<value_type>::max())
400  m_boundBigM = m_diffBigM<<1;
401 
402  // reset data members
403  m_reversedArcFlowCost = 0;
404 }
405 template <typename T, typename V>
407 {
408  // 1. preparing nodes
409  mapObjective2Graph();
410 
411  // reserve arcs
412  // use count arcs mode to compute number of arcs needed
413  unsigned int numArcs = mapDiffConstraint2Graph(true)+mapBoundConstraint2Graph(true);
414  m_graph.reserveArc(numArcs);
415 
416  // 2. preparing arcs for differential constraints
417  mapDiffConstraint2Graph(false);
418 
419  // 3. arcs for variable bounds
420  mapBoundConstraint2Graph(false);
421 }
422 template <typename T, typename V>
424 {
425  // preparing nodes
426  // set supply to its weight in the objective
427  m_graph.reserveNode(m_model->numVariables()+1); // in case an additional node is necessary, which will be the last node
428  for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
429  m_graph.addNode();
430  for (typename std::vector<term_type>::const_iterator it = m_model->objective().terms().begin(), ite = m_model->objective().terms().end(); it != ite; ++it)
431  m_mSupply[m_graph.nodeFromId(it->variable().id())] = it->coefficient();
432 }
433 template <typename T, typename V>
435 {
436  // preparing arcs
437  // arcs constraints like xi - xj >= cij
438  // add arc from node i to node j with cost -cij and capacity unlimited
439 
440  unsigned int numArcs = m_model->constraints().size();
441  if (!countArcs) // skip in count arcs mode
442  {
443  // normalize to '>' format
444  for (typename std::vector<constraint_type>::iterator it = m_model->constraints().begin(), ite = m_model->constraints().end(); it != ite; ++it)
445  {
446  constraint_type& constr = *it;
447  limboAssertMsg(constr.expression().terms().size() == 2, "only support differential constraints like xi - xj >= cij");
448  constr.normalize('>');
449  }
450  for (typename std::vector<constraint_type>::const_iterator it = m_model->constraints().begin(), ite = m_model->constraints().end(); it != ite; ++it)
451  {
452  constraint_type const& constr = *it;
453  std::vector<term_type> const& vTerm = constr.expression().terms();
454  variable_type xi = (vTerm[0].coefficient() > 0)? vTerm[0].variable() : vTerm[1].variable();
455  variable_type xj = (vTerm[0].coefficient() > 0)? vTerm[1].variable() : vTerm[0].variable();
456 
457  addArcForDiffConstraint(m_graph.nodeFromId(xi.id()), m_graph.nodeFromId(xj.id()), constr.rightHandSide(), m_diffBigM);
458  }
459  }
460  return numArcs;
461 }
462 template <typename T, typename V>
464 {
465  // 3. arcs for variable bounds
466  // from node to additional node
467 
468  // check whether there is node with non-zero lower bound or non-infinity upper bound
469  unsigned int numArcs = 0;
470  for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
471  {
472  value_type lowerBound = m_model->variableLowerBound(variable_type(i));
473  value_type upperBound = m_model->variableUpperBound(variable_type(i));
474  if (lowerBound != limbo::lowest<value_type>())
475  ++numArcs;
476  if (upperBound != std::numeric_limits<value_type>::max())
477  ++numArcs;
478  }
479  if (!countArcs && numArcs) // skip in count arcs mode
480  {
481  // 3.1 create additional node
482  // its corresponding weight is the negative sum of weight for other nodes
483  node_type addlNode = m_graph.addNode();
484  value_type addlWeight = 0;
485  for (typename std::vector<term_type>::const_iterator it = m_model->objective().terms().begin(), ite = m_model->objective().terms().end(); it != ite; ++it)
486  addlWeight -= it->coefficient();
487  m_mSupply[addlNode] = addlWeight;
488 
489  // bound constraint is more important
490  // so it has higher cost than normal differential constraints
491  for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
492  {
493  value_type lowerBound = m_model->variableLowerBound(variable_type(i));
494  value_type upperBound = m_model->variableUpperBound(variable_type(i));
495  // has lower bound
496  // add arc from node to additional node with cost d and cap unlimited
497  if (lowerBound != limbo::lowest<value_type>())
498  addArcForDiffConstraint(m_graph.nodeFromId(i), addlNode, lowerBound, m_boundBigM);
499  // has upper bound
500  // add arc from additional node to node with cost u and capacity unlimited
501  if (upperBound != std::numeric_limits<value_type>::max())
502  addArcForDiffConstraint(addlNode, m_graph.nodeFromId(i), -upperBound, m_boundBigM);
503  }
504  }
505  return numArcs;
506 }
507 template <typename T, typename V>
508 void DualMinCostFlow<T, V>::addArcForDiffConstraint(typename DualMinCostFlow<T, V>::node_type xi, typename DualMinCostFlow<T, V>::node_type xj, typename DualMinCostFlow<T, V>::value_type cij, typename DualMinCostFlow<T, V>::value_type bigM)
509 {
510  // add constraint xi - xj >= cij
511  //
512  // negative arc cost can be fixed by arc reversal
513  // for an arc with i -> j, with supply bi and bj, cost cij, capacity uij
514  // reverse the arc to
515  // i <- j, with supply bi-uij and bj+uij, cost -cij, capacity uij
516 
517  if (cij <= 0)
518  {
519  arc_type arc = m_graph.addArc(xi, xj);
520  m_mCost[arc] = -cij;
521  //m_mLower[arc] = 0;
522  m_mUpper[arc] = bigM;
523  }
524  else // reverse arc
525  {
526  arc_type arc = m_graph.addArc(xj, xi); // arc reversal
527  m_mCost[arc] = cij;
528  //m_mLower[arc] = 0;
529  m_mUpper[arc] = bigM;
530  m_mSupply[xi] -= bigM;
531  m_mSupply[xj] += bigM;
532 
533  m_reversedArcFlowCost += cij*bigM;
534  }
535 }
536 template <typename T, typename V>
538 {
539  // update solution
540  value_type addlValue = 0;
541  if ((unsigned int)m_graph.nodeNum() > m_model->numVariables()) // additional node has been introduced
542  addlValue = m_mPotential[m_graph.nodeFromId(m_graph.maxNodeId())];
543  unsigned int i = 0;
544  for (typename std::vector<value_type>::iterator it = m_model->variableSolutions().begin(), ite = m_model->variableSolutions().end(); it != ite; ++it, ++i)
545  *it = m_mPotential[m_graph.nodeFromId(i)]-addlValue;
546 }
547 
548 
552 template <typename T, typename V>
553 class MinCostFlowSolver
554 {
555  public:
558 
564  {
565  copy(rhs);
566  }
570  {
571  if (this != &rhs)
572  copy(rhs);
573  return *this;
574  }
576  virtual ~MinCostFlowSolver() {}
577 
580  virtual SolverProperty operator()(dualsolver_type* d) = 0;
581  protected:
583  void copy(MinCostFlowSolver const& /*rhs*/) {}
584 };
585 
589 template <typename T, typename V>
590 class CapacityScaling : public MinCostFlowSolver<T, V>
591 {
592  public:
594  typedef T value_type;
600  typedef lemon::CapacityScaling<typename dualsolver_type::graph_type,
601  value_type,
602  value_type> alg_type;
603 
606  CapacityScaling(int factor = 4)
607  : base_type()
608  , m_factor(factor)
609  {
610  }
614  : CapacityScaling::base_type(rhs)
615  {
616  copy(rhs);
617  }
621  {
622  if (this != &rhs)
623  {
624  this->base_type::operator=(rhs);
625  copy(rhs);
626  }
627  return *this;
628  }
629 
632  virtual SolverProperty operator()(dualsolver_type* d)
633  {
634  // 1. choose algorithm
635  alg_type alg (d->graph());
636 
637  // 2. run
638  typename alg_type::ProblemType status = alg.resetParams()
639  //.lowerMap(d->lowerMap())
640  .upperMap(d->upperMap())
641  .costMap(d->costMap())
642  .supplyMap(d->supplyMap())
643  .run(m_factor);
644 
645  // 3. check results
646  SolverProperty solverStatus;
647  switch (status)
648  {
649  case alg_type::OPTIMAL:
650  solverStatus = OPTIMAL;
651  break;
653  solverStatus = INFEASIBLE;
654  break;
655  case alg_type::UNBOUNDED:
656  solverStatus = UNBOUNDED;
657  break;
658  default:
659  limboAssertMsg(0, "unknown status");
660  }
661 
662  // 4. apply results
663  // get dual solution of LP, which is the flow of min-cost flow, skip this if not necessary
664  alg.flowMap(d->flowMap());
665  // get solution of LP, which is the dual solution of min-cost flow
666  alg.potentialMap(d->potentialMap());
667  // set total cost of min-cost flow
668  d->setTotalFlowCost(alg.totalCost());
669 
670  return solverStatus;
671  }
672  protected:
674  void copy(CapacityScaling const& rhs)
675  {
676  m_factor = rhs.m_factor;
677  }
678 
679  int m_factor;
680 };
681 
685 template <typename T, typename V>
686 class CostScaling : public MinCostFlowSolver<T, V>
687 {
688  public:
690  typedef T value_type;
696  typedef lemon::CostScaling<typename dualsolver_type::graph_type,
697  value_type,
698  value_type> alg_type;
699 
703  CostScaling(typename alg_type::Method method = alg_type::PARTIAL_AUGMENT, int factor = 16)
704  : base_type()
705  , m_method(method)
706  , m_factor(factor)
707  {
708  }
712  : base_type(rhs)
713  {
714  copy(rhs);
715  }
719  {
720  if (this != &rhs)
721  {
722  this->base_type::operator=(rhs);
723  copy(rhs);
724  }
725  return *this;
726  }
727 
730  virtual SolverProperty operator()(dualsolver_type* d)
731  {
732  // 1. choose algorithm
733  alg_type alg (d->graph());
734 
735  // 2. run
736  typename alg_type::ProblemType status = alg.resetParams()
737  //.lowerMap(d->lowerMap())
738  .upperMap(d->upperMap())
739  .costMap(d->costMap())
740  .supplyMap(d->supplyMap())
741  .run(m_method, m_factor);
742 
743  // 3. check results
744  SolverProperty solverStatus;
745  switch (status)
746  {
747  case alg_type::OPTIMAL:
748  solverStatus = OPTIMAL;
749  break;
751  solverStatus = INFEASIBLE;
752  break;
753  case alg_type::UNBOUNDED:
754  solverStatus = UNBOUNDED;
755  break;
756  default:
757  limboAssertMsg(0, "unknown status");
758  }
759 
760  // 4. apply results
761  // get dual solution of LP, which is the flow of min-cost flow, skip this if not necessary
762  alg.flowMap(d->flowMap());
763  // get solution of LP, which is the dual solution of min-cost flow
764  alg.potentialMap(d->potentialMap());
765  // set total cost of min-cost flow
766  d->setTotalFlowCost(alg.totalCost());
767 
768  return solverStatus;
769  }
770  protected:
772  void copy(CostScaling const& rhs)
773  {
774  m_method = rhs.m_method;
775  m_factor = rhs.m_factor;
776  }
777 
778  typename alg_type::Method m_method;
779  int m_factor;
780 };
781 
785 template <typename T, typename V>
786 class NetworkSimplex : public MinCostFlowSolver<T, V>
787 {
788  public:
790  typedef T value_type;
796  typedef lemon::NetworkSimplex<typename dualsolver_type::graph_type,
797  value_type,
798  value_type> alg_type;
799 
802  NetworkSimplex(typename alg_type::PivotRule pivotRule = alg_type::BLOCK_SEARCH)
803  : base_type()
804  , m_pivotRule(pivotRule)
805  {
806  }
810  : base_type(rhs)
811  {
812  copy(rhs);
813  }
817  {
818  if (this != &rhs)
819  {
820  this->base_type::operator=(rhs);
821  copy(rhs);
822  }
823  return *this;
824  }
825 
828  virtual SolverProperty operator()(dualsolver_type* d)
829  {
830  // 1. choose algorithm
831  alg_type alg (d->graph());
832 
833  // 2. run
834  typename alg_type::ProblemType status = alg.resetParams()
835  //.lowerMap(d->lowerMap())
836  .upperMap(d->upperMap())
837  .costMap(d->costMap())
838  .supplyMap(d->supplyMap())
839  .run(m_pivotRule);
840 
841  // 3. check results
842  SolverProperty solverStatus;
843  switch (status)
844  {
845  case alg_type::OPTIMAL:
846  solverStatus = OPTIMAL;
847  break;
849  solverStatus = INFEASIBLE;
850  break;
851  case alg_type::UNBOUNDED:
852  solverStatus = UNBOUNDED;
853  break;
854  default:
855  limboAssertMsg(0, "unknown status");
856  }
857 
858  // 4. apply results
859  // get dual solution of LP, which is the flow of min-cost flow, skip this if not necessary
860  alg.flowMap(d->flowMap());
861  // get solution of LP, which is the dual solution of min-cost flow
862  alg.potentialMap(d->potentialMap());
863  // set total cost of min-cost flow
864  d->setTotalFlowCost(alg.totalCost());
865 
866  return solverStatus;
867  }
868  protected:
870  void copy(NetworkSimplex const& rhs)
871  {
872  m_pivotRule = rhs.m_pivotRule;
873  }
874 
875  typename alg_type::PivotRule m_pivotRule;
876 };
877 
881 template <typename T, typename V>
882 class CycleCanceling : public MinCostFlowSolver<T, V>
883 {
884  public:
886  typedef T value_type;
892  typedef lemon::CycleCanceling<typename dualsolver_type::graph_type,
893  value_type,
894  value_type> alg_type;
895 
898  CycleCanceling(typename alg_type::Method method = alg_type::CANCEL_AND_TIGHTEN)
899  : base_type()
900  , m_method(method)
901  {
902  }
906  : base_type(rhs)
907  {
908  copy(rhs);
909  }
913  {
914  if (this != &rhs)
915  {
916  this->operator=(rhs);
917  copy(rhs);
918  }
919  return *this;
920  }
921 
924  virtual SolverProperty operator()(dualsolver_type* d)
925  {
926  // 1. choose algorithm
927  alg_type alg (d->graph());
928 
929  // 2. run
930  typename alg_type::ProblemType status = alg.resetParams()
931  //.lowerMap(d->lowerMap())
932  .upperMap(d->upperMap())
933  .costMap(d->costMap())
934  .supplyMap(d->supplyMap())
935  .run(m_method);
936 
937  // 3. check results
938  SolverProperty solverStatus;
939  switch (status)
940  {
941  case alg_type::OPTIMAL:
942  solverStatus = OPTIMAL;
943  break;
945  solverStatus = INFEASIBLE;
946  break;
947  case alg_type::UNBOUNDED:
948  solverStatus = UNBOUNDED;
949  break;
950  default:
951  limboAssertMsg(0, "unknown status");
952  }
953 
954  // 4. apply results
955  // get dual solution of LP, which is the flow of min-cost flow, skip this if not necessary
956  alg.flowMap(d->flowMap());
957  // get solution of LP, which is the dual solution of min-cost flow
958  alg.potentialMap(d->potentialMap());
959  // set total cost of min-cost flow
960  d->setTotalFlowCost(alg.totalCost());
961 
962  return solverStatus;
963  }
964  protected:
966  void copy(CycleCanceling const& rhs)
967  {
968  m_method = rhs.m_method;
969  }
970 
971  typename alg_type::Method m_method;
972 };
973 
974 
975 } // namespace solvers
976 } // namespace limbo
977 
978 #endif
CostScaling & operator=(CostScaling const &rhs)
assignment
Capacity scaling algorithm for min-cost flow.
CycleCanceling(CycleCanceling const &rhs)
copy constructor
unsigned int id() const
Definition: Solvers.h:117
void copy(CapacityScaling const &rhs)
copy object
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
Describe properties of a variable.
Definition: Solvers.h:72
SolverProperty operator()(solver_type *solver=NULL)
API to run the algorithm.
void applySolution()
apply solutions to model
int m_factor
scaling factor for the algorithm
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
SolverProperty
Some enums used in solver.
Definition: Solvers.h:29
arc_value_map_type const & upperMap() const
NetworkSimplex & operator=(NetworkSimplex const &rhs)
assignment
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
Basic utilities such as variables and linear expressions in solvers.
void buildGraph()
build dual min-cost flow graph
CycleCanceling(typename alg_type::Method method=alg_type::CANCEL_AND_TIGHTEN)
constructor
CapacityScaling(int factor=4)
constructor
node_pot_map_type m_mPotential
dual solution of min-cost flow, which is the solution of LP
MinCostFlowSolver< T, V > base_type
base type
Network simplex algorithm for min-cost flow.
virtual ~MinCostFlowSolver()
destructor
void setTotalFlowCost(value_type cost)
value_type m_reversedArcFlowCost
normalized flow cost of overall reversed arcs to resolve negative arc cost, to get total flow cost of...
SolverProperty solve(solver_type *solver)
kernel function to solve the problem
V variable_value_type
V variable.
Definition: Solvers.h:1166
arc_flow_map_type & flowMap()
arc_cost_map_type m_mCost
arc cost in min-cost flow
value_type totalFlowCost() const
T coefficient_value_type
T coefficient.
Definition: Solvers.h:1164
graph_type const & graph() const
alg_type::Method m_method
method for the algorithm, SIMPLE_CYCLE_CANCELING, MINIMUM_MEAN_CYCLE_CANCELING, CANCEL_AND_TIGHTEN ...
void mapObjective2Graph()
map variables and the objective to graph nodes
Describe linear constraint.
Definition: Solvers.h:78
arc_value_map_type m_mUpper
upper bound of flow, arc capacity in min-cost flow
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
unsigned int mapDiffConstraint2Graph(bool countArcs)
map differential constraints to graph arcs
MinCostFlowSolver< T, V > base_type
base type
lemon::CapacityScaling< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
CapacityScaling(CapacityScaling const &rhs)
copy constructor
void setDiffBigM(value_type v)
set big M as a large number for differential constraints
CycleCanceling & operator=(CycleCanceling const &rhs)
assignment
value_type m_boundBigM
a big number for infinity for bound constraints
the model is infeasible
Definition: Solvers.h:37
DualMinCostFlow & operator=(DualMinCostFlow const &rhs)
assignment, forbidden
virtual SolverProperty operator()(dualsolver_type *d)=0
API to run min-cost flow solver.
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
node_pot_map_type & potentialMap()
node_value_map_type const & supplyMap() const
arc_flow_map_type m_mFlow
solution of min-cost flow, which is the dual solution of LP
expression_type const & expression() const
Definition: Solvers.h:1028
Cycle canceling algorithm for min-cost flow.
node_value_map_type m_mSupply
node supply in min-cost flow
CapacityScaling & operator=(CapacityScaling const &rhs)
assignment
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
model_type * m_model
model for the problem
void copy(CostScaling const &rhs)
copy object
DualMinCostFlow(model_type *model)
constructor
MinCostFlowSolver< T, V > base_type
base type
value_type m_diffBigM
a big number for infinity for differential constraints
LinearModel< T, V > model_type
linear model type for the problem
lemon::CostScaling< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
void normalize(char s)
normalize sense
Definition: Solvers.h:1063
int m_factor
scaling factor for the algorithm
namespace for Limbo
Definition: GraphUtility.h:22
CostScaling(typename alg_type::Method method=alg_type::PARTIAL_AUGMENT, int factor=16)
constructor
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
Definition: Math.h:61
NetworkSimplex(typename alg_type::PivotRule pivotRule=alg_type::BLOCK_SEARCH)
constructor
coefficient_value_type rightHandSide() const
Definition: Solvers.h:1034
void copy(CycleCanceling const &rhs)
copy object
unsigned int mapBoundConstraint2Graph(bool countArcs)
map bound constraints to graph arcs
NetworkSimplex(NetworkSimplex const &rhs)
copy constructor
the model is unbounded
Definition: Solvers.h:39
arc_cost_map_type const & costMap() const
alg_type::Method m_method
PUSH, AUGMENT, PARTIAL_AUGMENT.
void copy(NetworkSimplex const &rhs)
copy object
#define limboAssert(condition)
custom assertion without message
Definition: AssertMsg.h:64
int limboPrint(MessageType m, const char *format,...)
formatted print with prefix
Definition: PrintMsg.h:49
std::vector< term_type > const & terms() const
Definition: Solvers.h:655
optimally solved
Definition: Solvers.h:36
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
Cost scaling algorithm for min-cost flow.
void addArcForDiffConstraint(node_type xi, node_type xj, value_type cij, value_type bigM)
generalized method to add an arc for differential constraint , resolve negative arc costs by arc reve...
MinCostFlowSolver(MinCostFlowSolver const &rhs)
copy constructor
MinCostFlowSolver & operator=(MinCostFlowSolver const &rhs)
assignment
alg_type::PivotRule m_pivotRule
pivot rule for the algorithm, FIRST_ELIGIBLE, BEST_ELIGIBLE, BLOCK_SEARCH, CANDIDATE_LIST, ALTERING_LIST
MinCostFlowSolver< T, V > base_type
base type
void setBoundBigM(value_type v)
set big M as a large number for bound constraints
lemon::NetworkSimplex< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
void copy(MinCostFlowSolver const &)
copy object
model to describe an optimization problem
Definition: Solvers.h:80
lemon::CycleCanceling< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
#define limboAssertMsg(condition, args...)
custom assertion with message
Definition: AssertMsg.h:52
CostScaling(CostScaling const &rhs)
copy constructor
value_type m_totalFlowCost
total cost after solving
void prepare()
prepare data like big M
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
LP solved with min-cost flow. A better implementation of limbo::solvers::lpmcf::LpDualMcf.
graph_type m_graph
input graph
DualMinCostFlow< T, V > dualsolver_type
dual min-cost flow solver type
A base class of min-cost flow solver.