[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