Limbo 3.5.4
Loading...
Searching...
No Matches
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
19
21namespace limbo
22{
24namespace solvers
25{
26
27// forward declaration
28template <typename T, typename V>
30template <typename T, typename V>
31class CapacityScaling;
32template <typename T, typename V>
33class CostScaling;
34template <typename T, typename V>
35class NetworkSimplex;
36template <typename T, typename V>
37class CycleCanceling;
38
101template <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;
112 typedef typename model_type::constraint_type constraint_type;
113 typedef typename model_type::expression_type expression_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
133 : m_model(model)
134 , m_graph()
135 //, m_mLower(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())
144 {
145 }
146
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:
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
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
246template <typename T, typename V>
247typename DualMinCostFlow<T, V>::value_type DualMinCostFlow<T, V>::diffBigM() const
248{
249 return m_diffBigM;
250}
251template <typename T, typename V>
252void DualMinCostFlow<T, V>::setDiffBigM(DualMinCostFlow<T, V>::value_type v)
253{
254 m_diffBigM = v;
255}
256template <typename T, typename V>
257typename DualMinCostFlow<T, V>::value_type DualMinCostFlow<T, V>::boundBigM() const
258{
259 return m_boundBigM;
260}
261template <typename T, typename V>
262void DualMinCostFlow<T, V>::setBoundBigM(DualMinCostFlow<T, V>::value_type v)
263{
264 m_boundBigM = v;
265}
266template <typename T, typename V>
267typename 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//}
276template <typename T, typename V>
277typename DualMinCostFlow<T, V>::arc_value_map_type const& DualMinCostFlow<T, V>::upperMap() const
278{
279 return m_mUpper;
280}
281template <typename T, typename V>
282typename DualMinCostFlow<T, V>::arc_cost_map_type const& DualMinCostFlow<T, V>::costMap() const
283{
284 return m_mCost;
285}
286template <typename T, typename V>
287typename DualMinCostFlow<T, V>::node_value_map_type const& DualMinCostFlow<T, V>::supplyMap() const
288{
289 return m_mSupply;
290}
291template <typename T, typename V>
292typename DualMinCostFlow<T, V>::arc_flow_map_type& DualMinCostFlow<T, V>::flowMap()
293{
294 return m_mFlow;
295}
296template <typename T, typename V>
297typename DualMinCostFlow<T, V>::node_pot_map_type& DualMinCostFlow<T, V>::potentialMap()
298{
299 return m_mPotential;
300}
301template <typename T, typename V>
302typename DualMinCostFlow<T, V>::value_type DualMinCostFlow<T, V>::totalFlowCost() const
303{
304 return m_totalFlowCost;
305}
306template <typename T, typename V>
307void DualMinCostFlow<T, V>::setTotalFlowCost(typename DualMinCostFlow<T, V>::value_type cost)
308{
309 m_totalFlowCost = cost;
310}
311template <typename T, typename V>
312typename 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
317}
318template <typename T, typename V>
319void 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}
341template <typename T, typename V>
342SolverProperty DualMinCostFlow<T, V>::solve(typename DualMinCostFlow<T, V>::solver_type* solver)
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}
382template <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())
401
402 // reset data members
404}
405template <typename T, typename V>
407{
408 // 1. preparing nodes
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
418
419 // 3. arcs for variable bounds
421}
422template <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}
433template <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}
462template <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}
507template <typename T, typename V>
508void 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}
536template <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
552template <typename T, typename V>
554{
555 public:
558
564 {
565 copy(rhs);
566 }
567
570 {
571 if (this != &rhs)
572 copy(rhs);
573 return *this;
574 }
575
577
581 protected:
583 void copy(MinCostFlowSolver const& /*rhs*/) {}
584};
585
589template <typename T, typename V>
590class 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,
603
606 CapacityScaling(int factor = 4)
607 : base_type()
608 , m_factor(factor)
609 {
610 }
611
615 {
616 copy(rhs);
617 }
618
621 {
622 if (this != &rhs)
623 {
624 this->base_type::operator=(rhs);
625 copy(rhs);
626 }
627 return *this;
628 }
629
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;
652 case alg_type::INFEASIBLE:
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
680};
681
685template <typename T, typename V>
686class 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,
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 }
709
712 : base_type(rhs)
713 {
714 copy(rhs);
715 }
716
719 {
720 if (this != &rhs)
721 {
722 this->base_type::operator=(rhs);
723 copy(rhs);
724 }
725 return *this;
726 }
727
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;
750 case alg_type::INFEASIBLE:
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;
780};
781
785template <typename T, typename V>
786class 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,
799
802 NetworkSimplex(typename alg_type::PivotRule pivotRule = alg_type::BLOCK_SEARCH)
803 : base_type()
804 , m_pivotRule(pivotRule)
805 {
806 }
807
810 : base_type(rhs)
811 {
812 copy(rhs);
813 }
814
817 {
818 if (this != &rhs)
819 {
820 this->base_type::operator=(rhs);
821 copy(rhs);
822 }
823 return *this;
824 }
825
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;
848 case alg_type::INFEASIBLE:
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 {
873 }
874
875 typename alg_type::PivotRule m_pivotRule;
876};
877
881template <typename T, typename V>
882class 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,
895
898 CycleCanceling(typename alg_type::Method method = alg_type::CANCEL_AND_TIGHTEN)
899 : base_type()
900 , m_method(method)
901 {
902 }
903
906 : base_type(rhs)
907 {
908 copy(rhs);
909 }
910
913 {
914 if (this != &rhs)
915 {
916 this->operator=(rhs);
917 copy(rhs);
918 }
919 return *this;
920 }
921
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;
944 case alg_type::INFEASIBLE:
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
#define limboAssertMsg(condition, args...)
custom assertion with message
Definition AssertMsg.h:24
#define limboAssert(condition)
custom assertion without message
Definition AssertMsg.h:36
Basic utilities such as variables and linear expressions in solvers.
Capacity scaling algorithm for min-cost flow.
void copy(CapacityScaling const &rhs)
copy object
MinCostFlowSolver< T, V > base_type
base type
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
int m_factor
scaling factor for the algorithm
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
CapacityScaling(CapacityScaling const &rhs)
copy constructor
CapacityScaling & operator=(CapacityScaling const &rhs)
assignment
lemon::CapacityScaling< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
CapacityScaling(int factor=4)
constructor
Cost scaling algorithm for min-cost flow.
void copy(CostScaling const &rhs)
copy object
int m_factor
scaling factor for the algorithm
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
CostScaling(CostScaling const &rhs)
copy constructor
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
alg_type::Method m_method
PUSH, AUGMENT, PARTIAL_AUGMENT.
lemon::CostScaling< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
MinCostFlowSolver< T, V > base_type
base type
CostScaling(typename alg_type::Method method=alg_type::PARTIAL_AUGMENT, int factor=16)
constructor
CostScaling & operator=(CostScaling const &rhs)
assignment
Cycle canceling algorithm for min-cost flow.
CycleCanceling(CycleCanceling const &rhs)
copy constructor
CycleCanceling(typename alg_type::Method method=alg_type::CANCEL_AND_TIGHTEN)
constructor
MinCostFlowSolver< T, V > base_type
base type
CycleCanceling & operator=(CycleCanceling const &rhs)
assignment
void copy(CycleCanceling const &rhs)
copy object
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
lemon::CycleCanceling< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
alg_type::Method m_method
method for the algorithm, SIMPLE_CYCLE_CANCELING, MINIMUM_MEAN_CYCLE_CANCELING, CANCEL_AND_TIGHTEN
LP solved with min-cost flow. A better implementation of limbo::solvers::lpmcf::LpDualMcf.
void buildGraph()
build dual min-cost flow graph
value_type m_diffBigM
a big number for infinity for differential constraints
LinearModel< T, V > model_type
linear model type for the problem
arc_value_map_type m_mUpper
upper bound of flow, arc capacity in min-cost flow
DualMinCostFlow & operator=(DualMinCostFlow const &rhs)
assignment, forbidden
node_pot_map_type m_mPotential
dual solution of min-cost flow, which is the solution of LP
SolverProperty operator()(solver_type *solver=NULL)
API to run the algorithm.
value_type m_totalFlowCost
total cost after solving
arc_flow_map_type m_mFlow
solution of min-cost flow, which is the dual solution of LP
model_type * m_model
model for the problem
arc_cost_map_type const & costMap() const
graph_type const & graph() const
void mapObjective2Graph()
map variables and the objective to graph nodes
void applySolution()
apply solutions to model
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...
SolverProperty solve(solver_type *solver)
kernel function to solve the problem
void printGraph(bool writeSol) const
print graph
node_value_map_type m_mSupply
node supply in min-cost flow
unsigned int mapDiffConstraint2Graph(bool countArcs)
map differential constraints to graph arcs
value_type m_boundBigM
a big number for infinity for bound constraints
node_pot_map_type & potentialMap()
void setTotalFlowCost(value_type cost)
DualMinCostFlow(DualMinCostFlow const &rhs)
copy constructor, forbidden
unsigned int mapBoundConstraint2Graph(bool countArcs)
map bound constraints to graph arcs
void setBoundBigM(value_type v)
set big M as a large number for bound constraints
node_value_map_type const & supplyMap() const
value_type m_reversedArcFlowCost
normalized flow cost of overall reversed arcs to resolve negative arc cost, to get total flow cost of...
DualMinCostFlow(model_type *model)
constructor
void prepare()
prepare data like big M
arc_value_map_type const & upperMap() const
arc_cost_map_type m_mCost
arc cost in min-cost flow
void setDiffBigM(value_type v)
set big M as a large number for differential constraints
coefficient_value_type rightHandSide() const
Definition Solvers.h:1034
expression_type const & expression() const
Definition Solvers.h:1028
void normalize(char s)
normalize sense
Definition Solvers.h:1063
std::vector< term_type > const & terms() const
Definition Solvers.h:655
model to describe an optimization problem
Definition Solvers.h:1161
V variable_value_type
V variable.
Definition Solvers.h:1166
VariableProperty< variable_value_type > property_type
variable property type
Definition Solvers.h:1178
Variable< coefficient_value_type > variable_type
variable type
Definition Solvers.h:1170
T coefficient_value_type
T coefficient.
Definition Solvers.h:1164
LinearConstraint< coefficient_value_type > constraint_type
constraint type
Definition Solvers.h:1176
LinearExpression< coefficient_value_type > expression_type
expression type
Definition Solvers.h:1174
LinearTerm< coefficient_value_type > term_type
term type
Definition Solvers.h:1172
A base class of min-cost flow solver.
DualMinCostFlow< coefficient_value_type, variable_value_type > dualsolver_type
MinCostFlowSolver & operator=(MinCostFlowSolver const &rhs)
assignment
MinCostFlowSolver(MinCostFlowSolver const &rhs)
copy constructor
void copy(MinCostFlowSolver const &)
copy object
virtual SolverProperty operator()(dualsolver_type *d)=0
API to run min-cost flow solver.
Network simplex algorithm for min-cost flow.
lemon::NetworkSimplex< typename dualsolver_type::graph_type, value_type, value_type > alg_type
algorithm type
NetworkSimplex(typename alg_type::PivotRule pivotRule=alg_type::BLOCK_SEARCH)
constructor
MinCostFlowSolver< T, V > base_type
base type
alg_type::PivotRule m_pivotRule
pivot rule for the algorithm, FIRST_ELIGIBLE, BEST_ELIGIBLE, BLOCK_SEARCH, CANDIDATE_LIST,...
void copy(NetworkSimplex const &rhs)
copy object
NetworkSimplex & operator=(NetworkSimplex const &rhs)
assignment
virtual SolverProperty operator()(dualsolver_type *d)
API to run min-cost flow solver.
base_type::dualsolver_type dualsolver_type
dual min-cost flow solver type
NetworkSimplex(NetworkSimplex const &rhs)
copy constructor
unsigned int id() const
Definition Solvers.h:117
namespace for Limbo.Solvers
SolverProperty
Some enums used in solver.
Definition Solvers.h:30
@ OPTIMAL
optimally solved
Definition Solvers.h:36
@ INFEASIBLE
the model is infeasible
Definition Solvers.h:37
@ UNBOUNDED
the model is unbounded
Definition Solvers.h:39
namespace for Limbo
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
Definition Math.h:61
int limboPrint(MessageType m, const char *format,...)
formatted print with prefix
Definition PrintMsg.h:49
T lowest()
generic function to get lowest value of numbers