[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