[Lemon-commits] Peter Kovacs: Support negative costs and bounds ...
Lemon HG
hg at lemon.cs.elte.hu
Wed Apr 29 18:54:40 CEST 2009
details: http://lemon.cs.elte.hu/hg/lemon/rev/6c408d864fa1
changeset: 679:6c408d864fa1
user: Peter Kovacs <kpeter [at] inf.elte.hu>
date: Wed Apr 29 03:15:24 2009 +0200
description:
Support negative costs and bounds in NetworkSimplex (#270)
* The interface is reworked to support negative costs and bounds.
- ProblemType and problemType() are renamed to SupplyType and
supplyType(), see also #234.
- ProblemType type is introduced similarly to the LP interface.
- 'bool run()' is replaced by 'ProblemType run()' to handle
unbounded problem instances, as well.
- Add INF public member constant similarly to the LP interface.
* Remove capacityMap() and boundMaps(), see also #266.
* Update the problem definition in the MCF module.
* Remove the usage of Circulation (and adaptors) for checking
feasibility. Check feasibility by examining the artifical arcs
instead (after solving the problem).
* Additional check for unbounded negative cycles found during the
algorithm (it is possible now, since negative costs are allowed).
* Fix in the constructor (the value types needn't be integer any
more), see also #254.
* Improve and extend the doc.
* Rework the test file and add test cases for negative costs and
bounds.
diffstat:
doc/groups.dox | 20 +-
lemon/network_simplex.h | 447 ++++++++++++++++++++------------------------
test/min_cost_flow_test.cc | 211 +++++++++++++-------
tools/dimacs-solver.cc | 4 +-
4 files changed, 350 insertions(+), 332 deletions(-)
diffs (truncated from 1155 to 300 lines):
diff --git a/doc/groups.dox b/doc/groups.dox
--- a/doc/groups.dox
+++ b/doc/groups.dox
@@ -352,17 +352,17 @@
minimum total cost from a set of supply nodes to a set of demand nodes
in a network with capacity constraints (lower and upper bounds)
and arc costs.
-Formally, let \f$G=(V,A)\f$ be a digraph,
-\f$lower, upper: A\rightarrow\mathbf{Z}^+_0\f$ denote the lower and
+Formally, let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{Z}\f$,
+\f$upper: A\rightarrow\mathbf{Z}\cup\{+\infty\}\f$ denote the lower and
upper bounds for the flow values on the arcs, for which
-\f$0 \leq lower(uv) \leq upper(uv)\f$ holds for all \f$uv\in A\f$.
-\f$cost: A\rightarrow\mathbf{Z}^+_0\f$ denotes the cost per unit flow
-on the arcs, and \f$sup: V\rightarrow\mathbf{Z}\f$ denotes the
+\f$lower(uv) \leq upper(uv)\f$ must hold for all \f$uv\in A\f$,
+\f$cost: A\rightarrow\mathbf{Z}\f$ denotes the cost per unit flow
+on the arcs and \f$sup: V\rightarrow\mathbf{Z}\f$ denotes the
signed supply values of the nodes.
If \f$sup(u)>0\f$, then \f$u\f$ is a supply node with \f$sup(u)\f$
supply, if \f$sup(u)<0\f$, then \f$u\f$ is a demand node with
\f$-sup(u)\f$ demand.
-A minimum cost flow is an \f$f: A\rightarrow\mathbf{Z}^+_0\f$ solution
+A minimum cost flow is an \f$f: A\rightarrow\mathbf{Z}\f$ solution
of the following optimization problem.
\f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
@@ -404,7 +404,7 @@
The dual solution of the minimum cost flow problem is represented by node
potentials \f$\pi: V\rightarrow\mathbf{Z}\f$.
-An \f$f: A\rightarrow\mathbf{Z}^+_0\f$ feasible solution of the problem
+An \f$f: A\rightarrow\mathbf{Z}\f$ feasible solution of the problem
is optimal if and only if for some \f$\pi: V\rightarrow\mathbf{Z}\f$
node potentials the following \e complementary \e slackness optimality
conditions hold.
@@ -413,15 +413,15 @@
- if \f$cost^\pi(uv)>0\f$, then \f$f(uv)=lower(uv)\f$;
- if \f$lower(uv)<f(uv)<upper(uv)\f$, then \f$cost^\pi(uv)=0\f$;
- if \f$cost^\pi(uv)<0\f$, then \f$f(uv)=upper(uv)\f$.
- - For all \f$u\in V\f$:
+ - For all \f$u\in V\f$ nodes:
- if \f$\sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \neq sup(u)\f$,
then \f$\pi(u)=0\f$.
Here \f$cost^\pi(uv)\f$ denotes the \e reduced \e cost of the arc
-\f$uv\in A\f$ with respect to the node potentials \f$\pi\f$, i.e.
+\f$uv\in A\f$ with respect to the potential function \f$\pi\f$, i.e.
\f[ cost^\pi(uv) = cost(uv) + \pi(u) - \pi(v).\f]
-All algorithms provide dual solution (node potentials) as well
+All algorithms provide dual solution (node potentials) as well,
if an optimal flow is found.
LEMON contains several algorithms for solving minimum cost flow problems.
diff --git a/lemon/network_simplex.h b/lemon/network_simplex.h
--- a/lemon/network_simplex.h
+++ b/lemon/network_simplex.h
@@ -30,9 +30,6 @@
#include <lemon/core.h>
#include <lemon/math.h>
-#include <lemon/maps.h>
-#include <lemon/circulation.h>
-#include <lemon/adaptors.h>
namespace lemon {
@@ -50,8 +47,13 @@
///
/// In general this class is the fastest implementation available
/// in LEMON for the minimum cost flow problem.
- /// Moreover it supports both direction of the supply/demand inequality
- /// constraints. For more information see \ref ProblemType.
+ /// Moreover it supports both directions of the supply/demand inequality
+ /// constraints. For more information see \ref SupplyType.
+ ///
+ /// Most of the parameters of the problem (except for the digraph)
+ /// can be given using separate functions, and the algorithm can be
+ /// executed using the \ref run() function. If some parameters are not
+ /// specified, then default values will be used.
///
/// \tparam GR The digraph type the algorithm runs on.
/// \tparam F The value type used for flow amounts, capacity bounds
@@ -88,11 +90,80 @@
public:
- /// \brief Enum type for selecting the pivot rule.
+ /// \brief Problem type constants for the \c run() function.
///
- /// Enum type for selecting the pivot rule for the \ref run()
+ /// Enum type containing the problem type constants that can be
+ /// returned by the \ref run() function of the algorithm.
+ enum ProblemType {
+ /// The problem has no feasible solution (flow).
+ INFEASIBLE,
+ /// The problem has optimal solution (i.e. it is feasible and
+ /// bounded), and the algorithm has found optimal flow and node
+ /// potentials (primal and dual solutions).
+ OPTIMAL,
+ /// The objective function of the problem is unbounded, i.e.
+ /// there is a directed cycle having negative total cost and
+ /// infinite upper bound.
+ UNBOUNDED
+ };
+
+ /// \brief Constants for selecting the type of the supply constraints.
+ ///
+ /// Enum type containing constants for selecting the supply type,
+ /// i.e. the direction of the inequalities in the supply/demand
+ /// constraints of the \ref min_cost_flow "minimum cost flow problem".
+ ///
+ /// The default supply type is \c GEQ, since this form is supported
+ /// by other minimum cost flow algorithms and the \ref Circulation
+ /// algorithm, as well.
+ /// The \c LEQ problem type can be selected using the \ref supplyType()
/// function.
///
+ /// Note that the equality form is a special case of both supply types.
+ enum SupplyType {
+
+ /// This option means that there are <em>"greater or equal"</em>
+ /// supply/demand constraints in the definition, i.e. the exact
+ /// formulation of the problem is the following.
+ /**
+ \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
+ \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \geq
+ sup(u) \quad \forall u\in V \f]
+ \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
+ */
+ /// It means that the total demand must be greater or equal to the
+ /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or
+ /// negative) and all the supplies have to be carried out from
+ /// the supply nodes, but there could be demands that are not
+ /// satisfied.
+ GEQ,
+ /// It is just an alias for the \c GEQ option.
+ CARRY_SUPPLIES = GEQ,
+
+ /// This option means that there are <em>"less or equal"</em>
+ /// supply/demand constraints in the definition, i.e. the exact
+ /// formulation of the problem is the following.
+ /**
+ \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
+ \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \leq
+ sup(u) \quad \forall u\in V \f]
+ \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
+ */
+ /// It means that the total demand must be less or equal to the
+ /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or
+ /// positive) and all the demands have to be satisfied, but there
+ /// could be supplies that are not carried out from the supply
+ /// nodes.
+ LEQ,
+ /// It is just an alias for the \c LEQ option.
+ SATISFY_DEMANDS = LEQ
+ };
+
+ /// \brief Constants for selecting the pivot rule.
+ ///
+ /// Enum type containing constants for selecting the pivot rule for
+ /// the \ref run() function.
+ ///
/// \ref NetworkSimplex provides five different pivot rule
/// implementations that significantly affect the running time
/// of the algorithm.
@@ -131,58 +202,6 @@
ALTERING_LIST
};
- /// \brief Enum type for selecting the problem type.
- ///
- /// Enum type for selecting the problem type, i.e. the direction of
- /// the inequalities in the supply/demand constraints of the
- /// \ref min_cost_flow "minimum cost flow problem".
- ///
- /// The default problem type is \c GEQ, since this form is supported
- /// by other minimum cost flow algorithms and the \ref Circulation
- /// algorithm as well.
- /// The \c LEQ problem type can be selected using the \ref problemType()
- /// function.
- ///
- /// Note that the equality form is a special case of both problem type.
- enum ProblemType {
-
- /// This option means that there are "<em>greater or equal</em>"
- /// constraints in the defintion, i.e. the exact formulation of the
- /// problem is the following.
- /**
- \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
- \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \geq
- sup(u) \quad \forall u\in V \f]
- \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
- */
- /// It means that the total demand must be greater or equal to the
- /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or
- /// negative) and all the supplies have to be carried out from
- /// the supply nodes, but there could be demands that are not
- /// satisfied.
- GEQ,
- /// It is just an alias for the \c GEQ option.
- CARRY_SUPPLIES = GEQ,
-
- /// This option means that there are "<em>less or equal</em>"
- /// constraints in the defintion, i.e. the exact formulation of the
- /// problem is the following.
- /**
- \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
- \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \leq
- sup(u) \quad \forall u\in V \f]
- \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
- */
- /// It means that the total demand must be less or equal to the
- /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or
- /// positive) and all the demands have to be satisfied, but there
- /// could be supplies that are not carried out from the supply
- /// nodes.
- LEQ,
- /// It is just an alias for the \c LEQ option.
- SATISFY_DEMANDS = LEQ
- };
-
private:
TEMPLATE_DIGRAPH_TYPEDEFS(GR);
@@ -220,7 +239,9 @@
bool _pstsup;
Node _psource, _ptarget;
Flow _pstflow;
- ProblemType _ptype;
+ SupplyType _stype;
+
+ Flow _sum_supply;
// Result maps
FlowMap *_flow_map;
@@ -259,6 +280,15 @@
int stem, par_stem, new_stem;
Flow delta;
+ public:
+
+ /// \brief Constant for infinite upper bounds (capacities).
+ ///
+ /// Constant for infinite upper bounds (capacities).
+ /// It is \c std::numeric_limits<Flow>::infinity() if available,
+ /// \c std::numeric_limits<Flow>::max() otherwise.
+ const Flow INF;
+
private:
// Implementation of the First Eligible pivot rule
@@ -661,17 +691,19 @@
NetworkSimplex(const GR& graph) :
_graph(graph),
_plower(NULL), _pupper(NULL), _pcost(NULL),
- _psupply(NULL), _pstsup(false), _ptype(GEQ),
+ _psupply(NULL), _pstsup(false), _stype(GEQ),
_flow_map(NULL), _potential_map(NULL),
_local_flow(false), _local_potential(false),
- _node_id(graph)
+ _node_id(graph),
+ INF(std::numeric_limits<Flow>::has_infinity ?
+ std::numeric_limits<Flow>::infinity() :
+ std::numeric_limits<Flow>::max())
{
- LEMON_ASSERT(std::numeric_limits<Flow>::is_integer &&
- std::numeric_limits<Flow>::is_signed,
- "The flow type of NetworkSimplex must be signed integer");
- LEMON_ASSERT(std::numeric_limits<Cost>::is_integer &&
- std::numeric_limits<Cost>::is_signed,
- "The cost type of NetworkSimplex must be signed integer");
+ // Check the value types
+ LEMON_ASSERT(std::numeric_limits<Flow>::is_signed,
+ "The flow type of NetworkSimplex must be signed");
+ LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
+ "The cost type of NetworkSimplex must be signed");
}
/// Destructor.
@@ -689,17 +721,16 @@
/// \brief Set the lower bounds on the arcs.
///
/// This function sets the lower bounds on the arcs.
- /// If neither this function nor \ref boundMaps() is used before
- /// calling \ref run(), the lower bounds will be set to zero
- /// on all arcs.
+ /// If it is not used before calling \ref run(), the lower bounds
+ /// will be set to zero on all arcs.
///
/// \param map An arc map storing the lower bounds.
/// Its \c Value type must be convertible to the \c Flow type
/// of the algorithm.
///
/// \return <tt>(*this)</tt>
- template <typename LOWER>
- NetworkSimplex& lowerMap(const LOWER& map) {
+ template <typename LowerMap>
+ NetworkSimplex& lowerMap(const LowerMap& map) {
More information about the Lemon-commits
mailing list