[Lemon-commits] Peter Kovacs: Less map copying in NetworkSimplex...

Lemon HG hg at lemon.cs.elte.hu
Wed Apr 29 18:54:41 CEST 2009


details:   http://lemon.cs.elte.hu/hg/lemon/rev/111698359429
changeset: 681:111698359429
user:      Peter Kovacs <kpeter [at] inf.elte.hu>
date:      Wed Apr 29 16:54:27 2009 +0200
description:
	Less map copying in NetworkSimplex (#234)

	 - The graph is copied in the constructor instead of the init()
	function. It must not be modified after the class is constructed.
	 - The maps are copied once (instead of twice).
	 - Remove FlowMap, PotentialMap typedefs and flowMap(), pontentialMap()
	setter functions.
	 - flowMap() and potentialMap() query functions copy the values into
	the given map (reference) instead of returning a const reference
	to a previously constructed map.

diffstat:

 lemon/network_simplex.h    |  441 +++++++++++++++++-------------------------------
 test/min_cost_flow_test.cc |   61 +++---
 2 files changed, 184 insertions(+), 318 deletions(-)

diffs (truncated from 767 to 300 lines):

diff --git a/lemon/network_simplex.h b/lemon/network_simplex.h
--- a/lemon/network_simplex.h
+++ b/lemon/network_simplex.h
@@ -72,21 +72,10 @@
   {
   public:
 
-    /// The flow type of the algorithm
+    /// The type of the flow amounts, capacity bounds and supply values
     typedef V Value;
-    /// The cost type of the algorithm
+    /// The type of the arc costs
     typedef C Cost;
-#ifdef DOXYGEN
-    /// The type of the flow map
-    typedef GR::ArcMap<Value> FlowMap;
-    /// The type of the potential map
-    typedef GR::NodeMap<Cost> PotentialMap;
-#else
-    /// The type of the flow map
-    typedef typename GR::template ArcMap<Value> FlowMap;
-    /// The type of the potential map
-    typedef typename GR::template NodeMap<Cost> PotentialMap;
-#endif
 
   public:
 
@@ -206,15 +195,11 @@
 
     TEMPLATE_DIGRAPH_TYPEDEFS(GR);
 
-    typedef typename GR::template ArcMap<Value> ValueArcMap;
-    typedef typename GR::template ArcMap<Cost> CostArcMap;
-    typedef typename GR::template NodeMap<Value> ValueNodeMap;
-
     typedef std::vector<Arc> ArcVector;
     typedef std::vector<Node> NodeVector;
     typedef std::vector<int> IntVector;
     typedef std::vector<bool> BoolVector;
-    typedef std::vector<Value> FlowVector;
+    typedef std::vector<Value> ValueVector;
     typedef std::vector<Cost> CostVector;
 
     // State constants for arcs
@@ -232,34 +217,23 @@
     int _arc_num;
 
     // Parameters of the problem
-    ValueArcMap *_plower;
-    ValueArcMap *_pupper;
-    CostArcMap *_pcost;
-    ValueNodeMap *_psupply;
-    bool _pstsup;
-    Node _psource, _ptarget;
-    Value _pstflow;
+    bool _have_lower;
     SupplyType _stype;
-    
     Value _sum_supply;
 
-    // Result maps
-    FlowMap *_flow_map;
-    PotentialMap *_potential_map;
-    bool _local_flow;
-    bool _local_potential;
-
     // Data structures for storing the digraph
     IntNodeMap _node_id;
-    ArcVector _arc_ref;
+    IntArcMap _arc_id;
     IntVector _source;
     IntVector _target;
 
     // Node and arc data
-    FlowVector _cap;
+    ValueVector _lower;
+    ValueVector _upper;
+    ValueVector _cap;
     CostVector _cost;
-    FlowVector _supply;
-    FlowVector _flow;
+    ValueVector _supply;
+    ValueVector _flow;
     CostVector _pi;
 
     // Data for storing the spanning tree structure
@@ -689,12 +663,7 @@
     ///
     /// \param graph The digraph the algorithm runs on.
     NetworkSimplex(const GR& graph) :
-      _graph(graph),
-      _plower(NULL), _pupper(NULL), _pcost(NULL),
-      _psupply(NULL), _pstsup(false), _stype(GEQ),
-      _flow_map(NULL), _potential_map(NULL),
-      _local_flow(false), _local_potential(false),
-      _node_id(graph),
+      _graph(graph), _node_id(graph), _arc_id(graph),
       INF(std::numeric_limits<Value>::has_infinity ?
           std::numeric_limits<Value>::infinity() :
           std::numeric_limits<Value>::max())
@@ -704,12 +673,58 @@
         "The flow type of NetworkSimplex must be signed");
       LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
         "The cost type of NetworkSimplex must be signed");
-    }
+        
+      // Resize vectors
+      _node_num = countNodes(_graph);
+      _arc_num = countArcs(_graph);
+      int all_node_num = _node_num + 1;
+      int all_arc_num = _arc_num + _node_num;
 
-    /// Destructor.
-    ~NetworkSimplex() {
-      if (_local_flow) delete _flow_map;
-      if (_local_potential) delete _potential_map;
+      _source.resize(all_arc_num);
+      _target.resize(all_arc_num);
+
+      _lower.resize(all_arc_num);
+      _upper.resize(all_arc_num);
+      _cap.resize(all_arc_num);
+      _cost.resize(all_arc_num);
+      _supply.resize(all_node_num);
+      _flow.resize(all_arc_num);
+      _pi.resize(all_node_num);
+
+      _parent.resize(all_node_num);
+      _pred.resize(all_node_num);
+      _forward.resize(all_node_num);
+      _thread.resize(all_node_num);
+      _rev_thread.resize(all_node_num);
+      _succ_num.resize(all_node_num);
+      _last_succ.resize(all_node_num);
+      _state.resize(all_arc_num);
+
+      // Copy the graph (store the arcs in a mixed order)
+      int i = 0;
+      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
+        _node_id[n] = i;
+      }
+      int k = std::max(int(std::sqrt(double(_arc_num))), 10);
+      i = 0;
+      for (ArcIt a(_graph); a != INVALID; ++a) {
+        _arc_id[a] = i;
+        _source[i] = _node_id[_graph.source(a)];
+        _target[i] = _node_id[_graph.target(a)];
+        if ((i += k) >= _arc_num) i = (i % k) + 1;
+      }
+      
+      // Initialize maps
+      for (int i = 0; i != _node_num; ++i) {
+        _supply[i] = 0;
+      }
+      for (int i = 0; i != _arc_num; ++i) {
+        _lower[i] = 0;
+        _upper[i] = INF;
+        _cost[i] = 1;
+      }
+      _have_lower = false;
+      _stype = GEQ;
     }
 
     /// \name Parameters
@@ -731,10 +746,9 @@
     /// \return <tt>(*this)</tt>
     template <typename LowerMap>
     NetworkSimplex& lowerMap(const LowerMap& map) {
-      delete _plower;
-      _plower = new ValueArcMap(_graph);
+      _have_lower = true;
       for (ArcIt a(_graph); a != INVALID; ++a) {
-        (*_plower)[a] = map[a];
+        _lower[_arc_id[a]] = map[a];
       }
       return *this;
     }
@@ -753,10 +767,8 @@
     /// \return <tt>(*this)</tt>
     template<typename UpperMap>
     NetworkSimplex& upperMap(const UpperMap& map) {
-      delete _pupper;
-      _pupper = new ValueArcMap(_graph);
       for (ArcIt a(_graph); a != INVALID; ++a) {
-        (*_pupper)[a] = map[a];
+        _upper[_arc_id[a]] = map[a];
       }
       return *this;
     }
@@ -774,10 +786,8 @@
     /// \return <tt>(*this)</tt>
     template<typename CostMap>
     NetworkSimplex& costMap(const CostMap& map) {
-      delete _pcost;
-      _pcost = new CostArcMap(_graph);
       for (ArcIt a(_graph); a != INVALID; ++a) {
-        (*_pcost)[a] = map[a];
+        _cost[_arc_id[a]] = map[a];
       }
       return *this;
     }
@@ -796,11 +806,8 @@
     /// \return <tt>(*this)</tt>
     template<typename SupplyMap>
     NetworkSimplex& supplyMap(const SupplyMap& map) {
-      delete _psupply;
-      _pstsup = false;
-      _psupply = new ValueNodeMap(_graph);
       for (NodeIt n(_graph); n != INVALID; ++n) {
-        (*_psupply)[n] = map[n];
+        _supply[_node_id[n]] = map[n];
       }
       return *this;
     }
@@ -824,12 +831,11 @@
     ///
     /// \return <tt>(*this)</tt>
     NetworkSimplex& stSupply(const Node& s, const Node& t, Value k) {
-      delete _psupply;
-      _psupply = NULL;
-      _pstsup = true;
-      _psource = s;
-      _ptarget = t;
-      _pstflow = k;
+      for (int i = 0; i != _node_num; ++i) {
+        _supply[i] = 0;
+      }
+      _supply[_node_id[s]] =  k;
+      _supply[_node_id[t]] = -k;
       return *this;
     }
     
@@ -847,41 +853,6 @@
       return *this;
     }
 
-    /// \brief Set the flow map.
-    ///
-    /// This function sets the flow map.
-    /// If it is not used before calling \ref run(), an instance will
-    /// be allocated automatically. The destructor deallocates this
-    /// automatically allocated map, of course.
-    ///
-    /// \return <tt>(*this)</tt>
-    NetworkSimplex& flowMap(FlowMap& map) {
-      if (_local_flow) {
-        delete _flow_map;
-        _local_flow = false;
-      }
-      _flow_map = ↦
-      return *this;
-    }
-
-    /// \brief Set the potential map.
-    ///
-    /// This function sets the potential map, which is used for storing
-    /// the dual solution.
-    /// If it is not used before calling \ref run(), an instance will
-    /// be allocated automatically. The destructor deallocates this
-    /// automatically allocated map, of course.
-    ///
-    /// \return <tt>(*this)</tt>
-    NetworkSimplex& potentialMap(PotentialMap& map) {
-      if (_local_potential) {
-        delete _potential_map;
-        _local_potential = false;
-      }
-      _potential_map = ↦
-      return *this;
-    }
-    
     /// @}
 
     /// \name Execution Control
@@ -894,7 +865,7 @@
     /// This function runs the algorithm.
     /// The paramters can be specified using functions \ref lowerMap(),
     /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(), 
-    /// \ref supplyType(), \ref flowMap() and \ref potentialMap().
+    /// \ref supplyType().
     /// For example,
     /// \code
     ///   NetworkSimplex<ListDigraph> ns(graph);
@@ -906,6 +877,8 @@
     /// that have been given are kept for the next call, unless
     /// \ref reset() is called, thus only the modified parameters
     /// have to be set again. See \ref reset() for examples.
+    /// However the underlying digraph must not be modified after this
+    /// class have been constructed, since it copies and extends the graph.
     ///
     /// \param pivot_rule The pivot rule that will be used during the
     /// algorithm. For more information see \ref PivotRule.
@@ -928,12 +901,13 @@
     ///
     /// This function resets all the paramaters that have been given
     /// before using functions \ref lowerMap(), \ref upperMap(),
-    /// \ref costMap(), \ref supplyMap(), \ref stSupply(), \ref supplyType(),
-    /// \ref flowMap() and \ref potentialMap().
+    /// \ref costMap(), \ref supplyMap(), \ref stSupply(), \ref supplyType().
     ///



More information about the Lemon-commits mailing list