[Lemon-commits] Peter Kovacs: Entirely rework CostScaling (#180)

Lemon HG hg at lemon.cs.elte.hu
Mon Dec 14 06:17:45 CET 2009


details:   http://lemon.cs.elte.hu/hg/lemon/rev/22bb98ca0101
changeset: 875:22bb98ca0101
user:      Peter Kovacs <kpeter [at] inf.elte.hu>
date:      Thu Nov 12 23:30:45 2009 +0100
description:
	Entirely rework CostScaling (#180)

	 - Use the new interface similarly to NetworkSimplex.
	  - Rework the implementation using an efficient internal structure
	for handling the residual network. This improvement made the
	code much faster.
	  - Handle GEQ supply type (LEQ is not supported).
	  - Handle infinite upper bounds.
	  - Handle negative costs (for arcs of finite upper bound).
	  - Traits class + named parameter for the LargeCost type used in
	internal computations.
	  - Extend the documentation.

diffstat:

 lemon/cost_scaling.h |  1436 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 860 insertions(+), 576 deletions(-)

diffs (truncated from 1679 to 300 lines):

diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
--- a/lemon/cost_scaling.h
+++ b/lemon/cost_scaling.h
@@ -30,548 +30,912 @@
 #include <lemon/core.h>
 #include <lemon/maps.h>
 #include <lemon/math.h>
-#include <lemon/adaptors.h>
+#include <lemon/static_graph.h>
 #include <lemon/circulation.h>
 #include <lemon/bellman_ford.h>
 
 namespace lemon {
 
+  /// \brief Default traits class of CostScaling algorithm.
+  ///
+  /// Default traits class of CostScaling algorithm.
+  /// \tparam GR Digraph type.
+  /// \tparam V The value type used for flow amounts, capacity bounds
+  /// and supply values. By default it is \c int.
+  /// \tparam C The value type used for costs and potentials.
+  /// By default it is the same as \c V.
+#ifdef DOXYGEN
+  template <typename GR, typename V = int, typename C = V>
+#else
+  template < typename GR, typename V = int, typename C = V,
+             bool integer = std::numeric_limits<C>::is_integer >
+#endif
+  struct CostScalingDefaultTraits
+  {
+    /// The type of the digraph
+    typedef GR Digraph;
+    /// The type of the flow amounts, capacity bounds and supply values
+    typedef V Value;
+    /// The type of the arc costs
+    typedef C Cost;
+
+    /// \brief The large cost type used for internal computations
+    ///
+    /// The large cost type used for internal computations.
+    /// It is \c long \c long if the \c Cost type is integer,
+    /// otherwise it is \c double.
+    /// \c Cost must be convertible to \c LargeCost.
+    typedef double LargeCost;
+  };
+
+  // Default traits class for integer cost types
+  template <typename GR, typename V, typename C>
+  struct CostScalingDefaultTraits<GR, V, C, true>
+  {
+    typedef GR Digraph;
+    typedef V Value;
+    typedef C Cost;
+#ifdef LEMON_HAVE_LONG_LONG
+    typedef long long LargeCost;
+#else
+    typedef long LargeCost;
+#endif
+  };
+
+
   /// \addtogroup min_cost_flow_algs
   /// @{
 
-  /// \brief Implementation of the cost scaling algorithm for finding a
-  /// minimum cost flow.
+  /// \brief Implementation of the Cost Scaling algorithm for
+  /// finding a \ref min_cost_flow "minimum cost flow".
   ///
-  /// \ref CostScaling implements the cost scaling algorithm performing
-  /// augment/push and relabel operations for finding a minimum cost
-  /// flow.
+  /// \ref CostScaling implements a cost scaling algorithm that performs
+  /// push/augment and relabel operations for finding a minimum cost
+  /// flow. It is an efficient primal-dual solution method, which
+  /// can be viewed as the generalization of the \ref Preflow
+  /// "preflow push-relabel" algorithm for the maximum flow problem.
   ///
-  /// \tparam Digraph The digraph type the algorithm runs on.
-  /// \tparam LowerMap The type of the lower bound map.
-  /// \tparam CapacityMap The type of the capacity (upper bound) map.
-  /// \tparam CostMap The type of the cost (length) map.
-  /// \tparam SupplyMap The type of the supply map.
+  /// 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.
   ///
-  /// \warning
-  /// - Arc capacities and costs should be \e non-negative \e integers.
-  /// - Supply values should be \e signed \e integers.
-  /// - The value types of the maps should be convertible to each other.
-  /// - \c CostMap::Value must be signed type.
+  /// \tparam GR The digraph type the algorithm runs on.
+  /// \tparam V The value type used for flow amounts, capacity bounds
+  /// and supply values in the algorithm. By default it is \c int.
+  /// \tparam C The value type used for costs and potentials in the
+  /// algorithm. By default it is the same as \c V.
   ///
-  /// \note Arc costs are multiplied with the number of nodes during
-  /// the algorithm so overflow problems may arise more easily than with
-  /// other minimum cost flow algorithms.
-  /// If it is available, <tt>long long int</tt> type is used instead of
-  /// <tt>long int</tt> in the inside computations.
-  ///
-  /// \author Peter Kovacs
-  template < typename Digraph,
-             typename LowerMap = typename Digraph::template ArcMap<int>,
-             typename CapacityMap = typename Digraph::template ArcMap<int>,
-             typename CostMap = typename Digraph::template ArcMap<int>,
-             typename SupplyMap = typename Digraph::template NodeMap<int> >
+  /// \warning Both value types must be signed and all input data must
+  /// be integer.
+  /// \warning This algorithm does not support negative costs for such
+  /// arcs that have infinite upper bound.
+#ifdef DOXYGEN
+  template <typename GR, typename V, typename C, typename TR>
+#else
+  template < typename GR, typename V = int, typename C = V,
+             typename TR = CostScalingDefaultTraits<GR, V, C> >
+#endif
   class CostScaling
   {
-    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+  public:
 
-    typedef typename CapacityMap::Value Capacity;
-    typedef typename CostMap::Value Cost;
-    typedef typename SupplyMap::Value Supply;
-    typedef typename Digraph::template ArcMap<Capacity> CapacityArcMap;
-    typedef typename Digraph::template NodeMap<Supply> SupplyNodeMap;
+    /// The type of the digraph
+    typedef typename TR::Digraph Digraph;
+    /// The type of the flow amounts, capacity bounds and supply values
+    typedef typename TR::Value Value;
+    /// The type of the arc costs
+    typedef typename TR::Cost Cost;
 
-    typedef ResidualDigraph< const Digraph,
-                             CapacityArcMap, CapacityArcMap > ResDigraph;
-    typedef typename ResDigraph::Arc ResArc;
+    /// \brief The large cost type
+    ///
+    /// The large cost type used for internal computations.
+    /// Using the \ref CostScalingDefaultTraits "default traits class",
+    /// it is \c long \c long if the \c Cost type is integer,
+    /// otherwise it is \c double.
+    typedef typename TR::LargeCost LargeCost;
 
-#if defined __GNUC__ && !defined __STRICT_ANSI__
-    typedef long long int LCost;
-#else
-    typedef long int LCost;
-#endif
-    typedef typename Digraph::template ArcMap<LCost> LargeCostMap;
+    /// The \ref CostScalingDefaultTraits "traits class" of the algorithm
+    typedef TR Traits;
 
   public:
 
-    /// The type of the flow map.
-    typedef typename Digraph::template ArcMap<Capacity> FlowMap;
-    /// The type of the potential map.
-    typedef typename Digraph::template NodeMap<LCost> PotentialMap;
+    /// \brief Problem type constants for the \c run() function.
+    ///
+    /// 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 digraph contains an arc of negative cost and infinite
+      /// upper bound. It means that the objective function is unbounded
+      /// on that arc, however note that it could actually be bounded
+      /// over the feasible flows, but this algroithm cannot handle
+      /// these cases.
+      UNBOUNDED
+    };
 
   private:
 
-    /// \brief Map adaptor class for handling residual arc costs.
-    ///
-    /// Map adaptor class for handling residual arc costs.
-    template <typename Map>
-    class ResidualCostMap : public MapBase<ResArc, typename Map::Value>
-    {
-    private:
+    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
 
-      const Map &_cost_map;
+    typedef std::vector<int> IntVector;
+    typedef std::vector<char> BoolVector;
+    typedef std::vector<Value> ValueVector;
+    typedef std::vector<Cost> CostVector;
+    typedef std::vector<LargeCost> LargeCostVector;
 
+  private:
+  
+    template <typename KT, typename VT>
+    class VectorMap {
     public:
-
-      ///\e
-      ResidualCostMap(const Map &cost_map) :
-        _cost_map(cost_map) {}
-
-      ///\e
-      inline typename Map::Value operator[](const ResArc &e) const {
-        return ResDigraph::forward(e) ? _cost_map[e] : -_cost_map[e];
+      typedef KT Key;
+      typedef VT Value;
+      
+      VectorMap(std::vector<Value>& v) : _v(v) {}
+      
+      const Value& operator[](const Key& key) const {
+        return _v[StaticDigraph::id(key)];
       }
 
-    }; //class ResidualCostMap
-
-    /// \brief Map adaptor class for handling reduced arc costs.
-    ///
-    /// Map adaptor class for handling reduced arc costs.
-    class ReducedCostMap : public MapBase<Arc, LCost>
-    {
-    private:
-
-      const Digraph &_gr;
-      const LargeCostMap &_cost_map;
-      const PotentialMap &_pot_map;
-
-    public:
-
-      ///\e
-      ReducedCostMap( const Digraph &gr,
-                      const LargeCostMap &cost_map,
-                      const PotentialMap &pot_map ) :
-        _gr(gr), _cost_map(cost_map), _pot_map(pot_map) {}
-
-      ///\e
-      inline LCost operator[](const Arc &e) const {
-        return _cost_map[e] + _pot_map[_gr.source(e)]
-                            - _pot_map[_gr.target(e)];
+      Value& operator[](const Key& key) {
+        return _v[StaticDigraph::id(key)];
+      }
+      
+      void set(const Key& key, const Value& val) {
+        _v[StaticDigraph::id(key)] = val;
       }
 
-    }; //class ReducedCostMap
+    private:
+      std::vector<Value>& _v;
+    };
+
+    typedef VectorMap<StaticDigraph::Node, LargeCost> LargeCostNodeMap;
+    typedef VectorMap<StaticDigraph::Arc, LargeCost> LargeCostArcMap;
 
   private:
 
-    // The digraph the algorithm runs on
-    const Digraph &_graph;
-    // The original lower bound map
-    const LowerMap *_lower;
-    // The modified capacity map
-    CapacityArcMap _capacity;
-    // The original cost map
-    const CostMap &_orig_cost;
-    // The scaled cost map
-    LargeCostMap _cost;
-    // The modified supply map
-    SupplyNodeMap _supply;
-    bool _valid_supply;
+    // Data related to the underlying digraph
+    const GR &_graph;
+    int _node_num;
+    int _arc_num;
+    int _res_node_num;
+    int _res_arc_num;
+    int _root;
 
-    // Arc map of the current flow
-    FlowMap *_flow;
-    bool _local_flow;
-    // Node map of the current potentials
-    PotentialMap *_potential;
-    bool _local_potential;
+    // Parameters of the problem
+    bool _have_lower;
+    Value _sum_supply;
 
-    // The residual cost map
-    ResidualCostMap<LargeCostMap> _res_cost;
-    // The residual digraph



More information about the Lemon-commits mailing list