Limbo 3.5.4
Loading...
Searching...
No Matches
MinCostFlow.h
Go to the documentation of this file.
1
7#ifndef LIMBO_SOLVERS_MINCOSTFLOW_H
8#define LIMBO_SOLVERS_MINCOSTFLOW_H
9
10#include <lemon/smart_graph.h>
11#include <lemon/network_simplex.h>
12#include <lemon/cost_scaling.h>
13#include <lemon/capacity_scaling.h>
14#include <lemon/cycle_canceling.h>
15#include <lemon/lgf_writer.h>
16
18
20namespace limbo
21{
23namespace solvers
24{
25
26// forward declaration
27// Only CapacityScaling supports real value costs.
28// All other methods require integer costs.
29template <typename T, typename V>
31template <typename T, typename V>
32class CapacityScaling;
33template <typename T, typename V>
34class CostScaling;
35template <typename T, typename V>
36class NetworkSimplex;
37template <typename T, typename V>
38class CycleCanceling;
39
59template <typename T, typename V>
61{
62 public:
66 typedef typename model_type::coefficient_value_type coefficient_value_type;
67 typedef typename model_type::variable_value_type variable_value_type;
68 typedef variable_value_type value_type; // use only one kind of value type
69 typedef typename model_type::variable_type variable_type;
70 typedef typename model_type::constraint_type constraint_type;
71 typedef typename model_type::expression_type expression_type;
72 typedef typename model_type::term_type term_type;
73 typedef typename model_type::property_type property_type;
74
75 typedef lemon::SmartDigraph graph_type;
76 typedef graph_type::Node node_type;
77 typedef graph_type::Arc arc_type;
78 typedef graph_type::NodeMap<value_type> node_value_map_type;
79 typedef graph_type::NodeMap<std::string> node_name_map_type;
80 typedef graph_type::ArcMap<std::string> arc_name_map_type;
81 typedef graph_type::ArcMap<value_type> arc_value_map_type;
82 typedef graph_type::ArcMap<value_type> arc_cost_map_type;
83 typedef graph_type::ArcMap<value_type> arc_flow_map_type;
84 typedef graph_type::NodeMap<value_type> node_pot_map_type; // potential of each node
85
88
92 : m_model(model)
93 , m_graph()
98 , m_totalFlowCost(std::numeric_limits<typename MinCostFlow<T, V>::value_type>::max())
101 {
102 }
103
105 {
106 }
107
110 SolverProperty operator()(solver_type* solver = NULL)
111 {
112 return solve(solver);
113 }
114
116 graph_type const& graph() const;
118 arc_value_map_type const& lowerMap() const;
120 arc_value_map_type const& upperMap() const;
122 arc_cost_map_type const& costMap() const;
124 node_value_map_type const& supplyMap() const;
126 arc_flow_map_type& flowMap();
128 node_pot_map_type& potentialMap();
130 value_type totalFlowCost() const;
132 void setTotalFlowCost(value_type cost);
134 value_type totalCost() const;
135
140 void printGraph(bool writeSol) const;
142 protected:
149
152 SolverProperty solve(solver_type* solver);
154 void buildGraph();
156 void setObjective(expression_type const& obj);
158 void applySolution();
159
161
162 graph_type m_graph;
163 arc_value_map_type m_mLower;
164 arc_value_map_type m_mUpper;
165 arc_cost_map_type m_mCost;
166 node_value_map_type m_mSupply;
167 value_type m_totalFlowCost;
168
169 arc_flow_map_type m_mFlow;
170 node_pot_map_type m_mPotential;
171};
172
173template <typename T, typename V>
174typename MinCostFlow<T, V>::graph_type const& MinCostFlow<T, V>::graph() const
175{
176 return m_graph;
177}
178template <typename T, typename V>
179typename MinCostFlow<T, V>::arc_value_map_type const& MinCostFlow<T, V>::lowerMap() const
180{
181 return m_mLower;
182}
183template <typename T, typename V>
184typename MinCostFlow<T, V>::arc_value_map_type const& MinCostFlow<T, V>::upperMap() const
185{
186 return m_mUpper;
187}
188template <typename T, typename V>
189typename MinCostFlow<T, V>::arc_cost_map_type const& MinCostFlow<T, V>::costMap() const
190{
191 return m_mCost;
192}
193template <typename T, typename V>
194typename MinCostFlow<T, V>::node_value_map_type const& MinCostFlow<T, V>::supplyMap() const
195{
196 return m_mSupply;
197}
198template <typename T, typename V>
199typename MinCostFlow<T, V>::arc_flow_map_type& MinCostFlow<T, V>::flowMap()
200{
201 return m_mFlow;
202}
203template <typename T, typename V>
204typename MinCostFlow<T, V>::node_pot_map_type& MinCostFlow<T, V>::potentialMap()
205{
206 return m_mPotential;
207}
208template <typename T, typename V>
209typename MinCostFlow<T, V>::value_type MinCostFlow<T, V>::totalFlowCost() const
210{
211 return m_totalFlowCost;
212}
213template <typename T, typename V>
214void MinCostFlow<T, V>::setTotalFlowCost(typename MinCostFlow<T, V>::value_type cost)
215{
216 m_totalFlowCost = cost;
217}
218template <typename T, typename V>
219typename MinCostFlow<T, V>::value_type MinCostFlow<T, V>::totalCost() const
220{
221 return totalFlowCost();
222}
223template <typename T, typename V>
224void MinCostFlow<T, V>::printGraph(bool writeSol) const
225{
226 if (writeSol)
227 limboPrint(kDEBUG, "totalFlowCost = %ld, totalCost = %ld\n", (long)totalFlowCost(), (long)totalCost());
228
229 node_name_map_type nodeNameMap (m_graph);
230 for (unsigned int i = 0, ie = m_model->constraints().size(); i < ie; ++i)
231 nodeNameMap[m_graph.nodeFromId(i)] = m_model->constraintNames().at(i);
232 nodeNameMap[m_graph.nodeFromId(m_graph.maxNodeId())] = "st";
233
234 arc_name_map_type arcNameMap (m_graph);
235 for (unsigned int i = 0, ie = m_model->numVariables(); i < ie; ++i)
236 arcNameMap[m_graph.arcFromId(i)] = m_model->variableName(variable_type(i));
237
238 // dump lgf file
239 lemon::DigraphWriter<graph_type> writer(m_graph, "debug.lgf");
240 writer.nodeMap("supply", m_mSupply)
241 .nodeMap("name", nodeNameMap)
242 .arcMap("name", arcNameMap)
243 .arcMap("capacity_lower", m_mLower)
244 .arcMap("capacity_upper", m_mUpper)
245 .arcMap("cost", m_mCost);
246 if (writeSol)
247 writer.nodeMap("potential", m_mPotential)
248 .arcMap("flow", m_mFlow);
249 writer.run();
250}
251template <typename T, typename V>
252SolverProperty MinCostFlow<T, V>::solve(typename MinCostFlow<T, V>::solver_type* solver)
253{
254 bool defaultSolver = false;
255 // use default solver if NULL
256 if (solver == NULL)
257 {
259 defaultSolver = true;
260 }
261
262 // skip empty problem
263 if (m_model->numVariables() == 0)
264 return OPTIMAL;
265
266 // build graph if no nodes, I know in corner cases it may be called repeatedly
267 // but this seems to be the best way
268 if (m_graph.nodeNum() == 0)
269 buildGraph();
270 setObjective(m_model->objective());
271#ifdef DEBUG_MINCOSTFLOW
272 printGraph(false);
273 // total supply must be zero
274 coefficient_value_type totalSupply = 0;
275 for (graph_type::NodeIt it (m_graph); it != lemon::INVALID; ++it)
276 totalSupply += m_mSupply[it];
277 limboAssert(totalSupply == 0);
278#endif
279 // solve min-cost flow problem
280 SolverProperty status = solver->operator()(this);
281 // apply solution
282 applySolution();
283
284#ifdef DEBUG_MINCOSTFLOW
285 printGraph(true);
286#endif
287
288 if (defaultSolver)
289 delete solver;
290
291 return status;
292}
293template <typename T, typename V>
295{
296 // compute how many nodes
297 // regard equality constraints as nodes except for s and t
298 unsigned int numNodes = 0;
299 for (typename std::vector<constraint_type>::const_iterator it = m_model->constraints().begin(), ite = m_model->constraints().end(); it != ite; ++it)
300 {
301 // assume only equality constraints
302 limboAssertMsg(it->sense() == '=', "only support equality constraints %s", m_model->constraintName(*it).c_str());
303 // equality constraints
304 numNodes += 1;
305 }
306
307 // construct nodes
308 coefficient_value_type totalSupply = 0;
309 m_graph.reserveNode(numNodes+1); // additional nodes for s and t
310 for (unsigned int i = 0, ie = numNodes+1; i < ie; ++i)
311 m_graph.addNode();
312 // node st
313 node_type st = m_graph.nodeFromId(numNodes);
314
315 // a map record arc to its two nodes
316 // arc id, source node id, target node id
317 // variable id, constraint id positive, constraint id negative
318 // I assume vVar2Constr sorts according to variable id
319 std::vector<std::pair<unsigned int, unsigned int> > vVar2Constr (m_model->numVariables(), std::make_pair(std::numeric_limits<unsigned int>::max(), std::numeric_limits<unsigned int>::max()));
320 unsigned int constrIndex = 0;
321 for (typename std::vector<constraint_type>::const_iterator it = m_model->constraints().begin(), ite = m_model->constraints().end(); it != ite; ++it)
322 {
323 constraint_type constr = *it;
324 // equality constraints
325 //if (constr.sense() == '=')
326 {
327 // whether need to inverse the sign of the constraint
328 // only need to check the first found term
329 for (typename std::vector<term_type>::const_iterator itt = constr.expression().terms().begin(), itte = constr.expression().terms().end(); itt != itte; ++itt)
330 {
331 term_type const& term = *itt;
332 std::pair<unsigned int, unsigned int> const& value = vVar2Constr[term.variable().id()];
333 if (term.coefficient() == 1)
334 {
335 // I want value.first is not set
336 if (value.first != std::numeric_limits<unsigned int>::max())
337 {
338 constr.scale(-1);
339 break;
340 }
341 else if (value.second != std::numeric_limits<unsigned int>::max())
342 {
343 break;
344 }
345 }
346 else if (term.coefficient() == -1)
347 {
348 // I want value.first is not set
349 if (value.second != std::numeric_limits<unsigned int>::max())
350 {
351 constr.scale(-1);
352 break;
353 }
354 else if (value.first != std::numeric_limits<unsigned int>::max())
355 {
356 break;
357 }
358 }
359 else
360 {
361 limboAssertMsg(0, "unsupported coefficient %g in constraint %d\n", double(term.coefficient()), constr.id());
362 }
363 }
364 // record map
365 for (typename std::vector<term_type>::const_iterator itt = constr.expression().terms().begin(), itte = constr.expression().terms().end(); itt != itte; ++itt)
366 {
367 term_type const& term = *itt;
368 std::pair<unsigned int, unsigned int>& value = vVar2Constr[term.variable().id()];
369 if (term.coefficient() == 1)
370 {
371 limboAssertMsg(value.first == std::numeric_limits<unsigned int>::max(),
372 "variable %s appears in more than 1 constraint with coefficient 1", m_model->variableName(term.variable()).c_str());
373 value.first = constrIndex;
374 }
375 else if (term.coefficient() == -1)
376 {
377 limboAssertMsg(value.second == std::numeric_limits<unsigned int>::max(),
378 "variable %s appears in more than 1 constraint with coefficient -1", m_model->variableName(term.variable()).c_str());
379 value.second = constrIndex;
380 }
381 }
382 // compute supply
383 // since here we know whether this constraint is inversed
384 m_mSupply[m_graph.nodeFromId(constrIndex)] = constr.rightHandSide();
385 totalSupply += constr.rightHandSide();
386 // next cosntraint
387 ++constrIndex;
388 }
389 }
390 // supply for s and t
391 m_mSupply[st] = -totalSupply;
392
393 // construct arcs
394 m_graph.reserveArc(vVar2Constr.size());
395 // I assume vVar2Constr sorts according to variable id
396 unsigned int var = 0;
397 for (std::vector<std::pair<unsigned int, unsigned int> >::const_iterator it = vVar2Constr.begin(), ite = vVar2Constr.end(); it != ite; ++it, ++var)
398 {
399 unsigned int constrSrc = it->first;
400 unsigned int constrTgt = it->second;
401
402 arc_type arc;
403 if (constrSrc == std::numeric_limits<unsigned int>::max()) // from s
404 {
405 arc = m_graph.addArc(st, m_graph.nodeFromId(constrTgt));
406 }
407 else if (constrTgt == std::numeric_limits<unsigned int>::max()) // to t
408 {
409 arc = m_graph.addArc(m_graph.nodeFromId(constrSrc), st);
410 }
411 else
412 {
413 arc = m_graph.addArc(m_graph.nodeFromId(constrSrc), m_graph.nodeFromId(constrTgt));
414 }
415 m_mLower[arc] = m_model->variableLowerBound(m_model->variable(var));
416 m_mUpper[arc] = m_model->variableUpperBound(m_model->variable(var));
417#ifdef DEBUG_MINCOSTFLOW
418 limboAssert(arc == m_graph.arcFromId(var));
419#endif
420 }
421
422 // construct cost map
423 // everytime solver is called
424}
425template <typename T, typename V>
426void MinCostFlow<T, V>::setObjective(typename MinCostFlow<T, V>::expression_type const& obj)
427{
428 for (typename std::vector<term_type>::const_iterator it = obj.terms().begin(), ite = obj.terms().end(); it != ite; ++it)
429 {
430 term_type const& term = *it;
431 switch (m_model->optimizeType())
432 {
433 case MIN:
434 m_mCost[m_graph.arcFromId(term.variable().id())] = term.coefficient();
435 break;
436 case MAX:
437 m_mCost[m_graph.arcFromId(term.variable().id())] = -term.coefficient();
438 break;
439 default:
440 limboAssertMsg(0, "Unknown optimization type");
441 break;
442 }
443 }
444}
445template <typename T, typename V>
447{
448 unsigned int i = 0;
449 for (typename std::vector<value_type>::iterator it = m_model->variableSolutions().begin(), ite = m_model->variableSolutions().end(); it != ite; ++it, ++i)
450 *it = m_mFlow[m_graph.arcFromId(i)];
451}
452
456template <typename T, typename V>
458{
459 public:
462
468 {
469 copy(rhs);
470 }
471
474 {
475 if (this != &rhs)
476 copy(rhs);
477 return *this;
478 }
479
481
485 protected:
487 void copy(MinCostFlowSolver const& /*rhs*/) {}
488};
489
493template <typename T, typename V>
495{
496 public:
498 typedef T value_type;
504 typedef lemon::CapacityScaling<typename primalsolver_type::graph_type,
505 value_type,
507
510 CapacityScaling(int factor = 4)
511 : base_type()
512 , m_factor(factor)
513 {
514 }
515
519 {
520 copy(rhs);
521 }
522
525 {
526 if (this != &rhs)
527 {
528 this->base_type::operator=(rhs);
529 copy(rhs);
530 }
531 return *this;
532 }
533
537 {
538 // 1. choose algorithm
539 alg_type alg (d->graph());
540
541 // 2. run
542 typename alg_type::ProblemType status = alg.resetParams()
543 .lowerMap(d->lowerMap())
544 .upperMap(d->upperMap())
545 .costMap(d->costMap())
546 .supplyMap(d->supplyMap())
547 .run(m_factor);
548
549 // 3. check results
550 SolverProperty solverStatus;
551 switch (status)
552 {
553 case alg_type::OPTIMAL:
554 solverStatus = OPTIMAL;
555 break;
556 case alg_type::INFEASIBLE:
557 solverStatus = INFEASIBLE;
558 break;
559 case alg_type::UNBOUNDED:
560 solverStatus = UNBOUNDED;
561 break;
562 default:
563 limboAssertMsg(0, "unknown status");
564 }
565
566 // 4. apply results
567 // get dual solution of LP, which is the flow of min-cost flow, skip this if not necessary
568 alg.flowMap(d->flowMap());
569 // get solution of LP, which is the dual solution of min-cost flow
570 alg.potentialMap(d->potentialMap());
571 // set total cost of min-cost flow
572 d->setTotalFlowCost(alg.totalCost());
573
574 return solverStatus;
575 }
576 protected:
578 void copy(CapacityScaling const& rhs)
579 {
580 m_factor = rhs.m_factor;
581 }
582
583 int m_factor;
584};
585
589template <typename T, typename V>
590class CostScaling : public MinCostFlowSolver<T, V>
591{
592 public:
594 typedef T value_type;
600 typedef lemon::CostScaling<typename primalsolver_type::graph_type,
601 value_type,
603
607 CostScaling(typename alg_type::Method method = alg_type::PARTIAL_AUGMENT, int factor = 16)
608 : base_type()
609 , m_method(method)
610 , m_factor(factor)
611 {
612 }
613
616 : base_type(rhs)
617 {
618 copy(rhs);
619 }
620
623 {
624 if (this != &rhs)
625 {
626 this->base_type::operator=(rhs);
627 copy(rhs);
628 }
629 return *this;
630 }
631
635 {
636 // 1. choose algorithm
637 alg_type alg (d->graph());
638
639 // 2. run
640 typename alg_type::ProblemType status = alg.resetParams()
641 .lowerMap(d->lowerMap())
642 .upperMap(d->upperMap())
643 .costMap(d->costMap())
644 .supplyMap(d->supplyMap())
645 .run(m_method, m_factor);
646
647 // 3. check results
648 SolverProperty solverStatus;
649 switch (status)
650 {
651 case alg_type::OPTIMAL:
652 solverStatus = OPTIMAL;
653 break;
654 case alg_type::INFEASIBLE:
655 solverStatus = INFEASIBLE;
656 break;
657 case alg_type::UNBOUNDED:
658 solverStatus = UNBOUNDED;
659 break;
660 default:
661 limboAssertMsg(0, "unknown status");
662 }
663
664 // 4. apply results
665 // get dual solution of LP, which is the flow of min-cost flow, skip this if not necessary
666 alg.flowMap(d->flowMap());
667 // get solution of LP, which is the dual solution of min-cost flow
668 alg.potentialMap(d->potentialMap());
669 // set total cost of min-cost flow
670 d->setTotalFlowCost(alg.totalCost());
671
672 return solverStatus;
673 }
674 protected:
676 void copy(CostScaling const& rhs)
677 {
678 m_method = rhs.m_method;
679 m_factor = rhs.m_factor;
680 }
681
682 typename alg_type::Method m_method;
683 int m_factor;
684};
685
689template <typename T, typename V>
691{
692 public:
694 typedef T value_type;
700 typedef lemon::NetworkSimplex<typename primalsolver_type::graph_type,
701 value_type,
703
706 NetworkSimplex(typename alg_type::PivotRule pivotRule = alg_type::BLOCK_SEARCH)
707 : base_type()
708 , m_pivotRule(pivotRule)
709 {
710 }
711
714 : base_type(rhs)
715 {
716 copy(rhs);
717 }
718
721 {
722 if (this != &rhs)
723 {
724 this->base_type::operator=(rhs);
725 copy(rhs);
726 }
727 return *this;
728 }
729
733 {
734 // 1. choose algorithm
735 alg_type alg (d->graph());
736
737 // 2. run
738 typename alg_type::ProblemType status = alg.resetParams()
739 .lowerMap(d->lowerMap())
740 .upperMap(d->upperMap())
741 .costMap(d->costMap())
742 .supplyMap(d->supplyMap())
743 .run(m_pivotRule);
744
745 // 3. check results
746 SolverProperty solverStatus;
747 switch (status)
748 {
749 case alg_type::OPTIMAL:
750 solverStatus = OPTIMAL;
751 break;
752 case alg_type::INFEASIBLE:
753 solverStatus = INFEASIBLE;
754 break;
755 case alg_type::UNBOUNDED:
756 solverStatus = UNBOUNDED;
757 break;
758 default:
759 limboAssertMsg(0, "unknown status");
760 }
761
762 // 4. apply results
763 // get dual solution of LP, which is the flow of min-cost flow, skip this if not necessary
764 alg.flowMap(d->flowMap());
765 // get solution of LP, which is the dual solution of min-cost flow
766 alg.potentialMap(d->potentialMap());
767 // set total cost of min-cost flow
768 d->setTotalFlowCost(alg.totalCost());
769
770 return solverStatus;
771 }
772 protected:
774 void copy(NetworkSimplex const& rhs)
775 {
777 }
778
779 typename alg_type::PivotRule m_pivotRule;
780};
781
785template <typename T, typename V>
787{
788 public:
790 typedef T value_type;
796 typedef lemon::CycleCanceling<typename primalsolver_type::graph_type,
797 value_type,
799
802 CycleCanceling(typename alg_type::Method method = alg_type::CANCEL_AND_TIGHTEN)
803 : base_type()
804 , m_method(method)
805 {
806 }
807
810 : base_type(rhs)
811 {
812 copy(rhs);
813 }
814
817 {
818 if (this != &rhs)
819 {
820 this->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_method);
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(CycleCanceling const& rhs)
871 {
872 m_method = rhs.m_method;
873 }
874
875 typename alg_type::Method m_method;
876};
877
878
879} // namespace solvers
880} // namespace limbo
881
882#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
base_type::primalsolver_type primalsolver_type
dual min-cost flow solver type
virtual SolverProperty operator()(primalsolver_type *d)
API to run min-cost flow solver.
MinCostFlowSolver< T, V > base_type
base type
int m_factor
scaling factor for the algorithm
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
CostScaling(CostScaling const &rhs)
copy constructor
alg_type::Method m_method
PUSH, AUGMENT, PARTIAL_AUGMENT.
base_type::primalsolver_type primalsolver_type
dual min-cost flow solver type
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
virtual SolverProperty operator()(primalsolver_type *d)
API to run min-cost flow solver.
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
base_type::primalsolver_type primalsolver_type
dual min-cost flow solver type
CycleCanceling & operator=(CycleCanceling const &rhs)
assignment
void copy(CycleCanceling const &rhs)
copy object
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
virtual SolverProperty operator()(primalsolver_type *d)
API to run min-cost flow solver.
unsigned int id() const
Definition Solvers.h:1024
coefficient_value_type rightHandSide() const
Definition Solvers.h:1034
void scale(coefficient_value_type factor)
scale constraint by a scaling factor
Definition Solvers.h:1076
expression_type const & expression() const
Definition Solvers.h:1028
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
coefficient_value_type coefficient() const
Definition Solvers.h:388
variable_type const & variable() const
Definition Solvers.h:384
LP solved with min-cost flow.
Definition MinCostFlow.h:61
graph_type const & graph() const
SolverProperty operator()(solver_type *solver=NULL)
API to run the algorithm.
node_pot_map_type & potentialMap()
arc_cost_map_type const & costMap() const
MinCostFlow(model_type *model)
constructor
Definition MinCostFlow.h:91
arc_value_map_type m_mUpper
upper bound of flow, arc capacity in min-cost flow
void applySolution()
apply solutions to model
arc_value_map_type const & upperMap() const
arc_flow_map_type & flowMap()
MinCostFlow & operator=(MinCostFlow const &rhs)
assignment, forbidden
void setTotalFlowCost(value_type cost)
arc_cost_map_type m_mCost
arc cost in min-cost flow
MinCostFlow(MinCostFlow const &rhs)
copy constructor, forbidden
SolverProperty solve(solver_type *solver)
kernel function to solve the problem
void buildGraph()
build min-cost flow graph
node_pot_map_type m_mPotential
solution of min-cost flow, which is the dual solution of LP
value_type m_totalFlowCost
total cost after solving
value_type totalCost() const
value_type totalFlowCost() const
node_value_map_type const & supplyMap() const
arc_value_map_type m_mLower
lower bound of flow, usually zero
node_value_map_type m_mSupply
node supply in min-cost flow
arc_flow_map_type m_mFlow
solution of min-cost flow, which is the solution of LP
arc_value_map_type const & lowerMap() const
model_type * m_model
model for the problem
graph_type m_graph
input graph
void printGraph(bool writeSol) const
print graph
void setObjective(expression_type const &obj)
set objective, support incremental set
LinearModel< T, V > model_type
linear model type for the problem
Definition MinCostFlow.h:64
A base class of min-cost flow solver.
MinCostFlow< coefficient_value_type, variable_value_type > primalsolver_type
MinCostFlowSolver & operator=(MinCostFlowSolver const &rhs)
assignment
MinCostFlowSolver(MinCostFlowSolver const &rhs)
copy constructor
virtual ~MinCostFlowSolver()
destructor
virtual SolverProperty operator()(primalsolver_type *d)=0
API to run min-cost flow solver.
void copy(MinCostFlowSolver const &)
copy object
Network simplex algorithm for min-cost flow.
virtual SolverProperty operator()(primalsolver_type *d)
API to run min-cost flow solver.
base_type::primalsolver_type primalsolver_type
dual min-cost flow solver type
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
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
@ MIN
minimize objective
Definition Solvers.h:31
@ MAX
maximize objective
Definition Solvers.h:32
@ 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