[Lemon-commits] kpeter: r3516 - lemon/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Thu Nov 13 17:17:51 CET 2008
Author: kpeter
Date: Thu Nov 13 17:17:50 2008
New Revision: 3516
Modified:
lemon/trunk/lemon/network_simplex.h
Log:
Various improvements in NetworkSimplex.
- Faster variant of "Altering Candidate List" pivot rule using make_heap
instead of partial_sort.
- Doc improvements.
- Removing unecessary inline keywords.
Modified: lemon/trunk/lemon/network_simplex.h
==============================================================================
--- lemon/trunk/lemon/network_simplex.h (original)
+++ lemon/trunk/lemon/network_simplex.h Thu Nov 13 17:17:50 2008
@@ -26,6 +26,7 @@
#include <vector>
#include <limits>
+#include <algorithm>
#include <lemon/graph_adaptor.h>
#include <lemon/graph_utils.h>
@@ -137,7 +138,7 @@
///\e
Cost operator[](const Edge &e) const {
return _cost_map[e] + _pot_map[_gr.source(e)]
- - _pot_map[_gr.target(e)];
+ - _pot_map[_gr.target(e)];
}
}; //class ReducedCostMap
@@ -168,7 +169,7 @@
_ns(ns), _edges(edges), _next_edge(0) {}
/// Find next entering edge
- inline bool findEnteringEdge() {
+ bool findEnteringEdge() {
Edge e;
for (int i = _next_edge; i < int(_edges.size()); ++i) {
e = _edges[i];
@@ -212,7 +213,7 @@
_ns(ns), _edges(edges) {}
/// Find next entering edge
- inline bool findEnteringEdge() {
+ bool findEnteringEdge() {
Cost min = 0;
Edge e;
for (int i = 0; i < int(_edges.size()); ++i) {
@@ -259,7 +260,7 @@
}
/// Find next entering edge
- inline bool findEnteringEdge() {
+ bool findEnteringEdge() {
Cost curr, min = 0;
Edge e;
int cnt = _block_size;
@@ -336,11 +337,11 @@
}
/// Find next entering edge
- inline bool findEnteringEdge() {
+ bool findEnteringEdge() {
Cost min, curr;
if (_curr_length > 0 && _minor_count < _minor_limit) {
- // Minor iteration: selecting the best eligible edge from
- // the current candidate list
+ // Minor iteration: select the best eligible edge from the
+ // current candidate list
++_minor_count;
Edge e;
min = 0;
@@ -358,7 +359,7 @@
if (min < 0) return true;
}
- // Major iteration: building a new candidate list
+ // Major iteration: build a new candidate list
Edge e;
min = 0;
_curr_length = 0;
@@ -423,7 +424,7 @@
public:
SortFunc(const SCostMap &map) : _map(map) {}
bool operator()(const Edge &e1, const Edge &e2) {
- return _map[e1] < _map[e2];
+ return _map[e1] > _map[e2];
}
};
@@ -437,10 +438,10 @@
_next_edge(0), _sort_func(_cand_cost)
{
// The main parameters of the pivot rule
- const double BLOCK_SIZE_FACTOR = 1.0;
+ const double BLOCK_SIZE_FACTOR = 1.5;
const int MIN_BLOCK_SIZE = 10;
const double HEAD_LENGTH_FACTOR = 0.1;
- const int MIN_HEAD_LENGTH = 5;
+ const int MIN_HEAD_LENGTH = 3;
_block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_edges.size())),
MIN_BLOCK_SIZE );
@@ -451,17 +452,17 @@
}
/// Find next entering edge
- inline bool findEnteringEdge() {
- // Checking the current candidate list
+ bool findEnteringEdge() {
+ // Check the current candidate list
Edge e;
- for (int idx = 0; idx < _curr_length; ++idx) {
- e = _candidates[idx];
+ for (int ix = 0; ix < _curr_length; ++ix) {
+ e = _candidates[ix];
if ((_cand_cost[e] = _ns._state[e] * _ns._red_cost[e]) >= 0) {
- _candidates[idx--] = _candidates[--_curr_length];
+ _candidates[ix--] = _candidates[--_curr_length];
}
}
- // Extending the list
+ // Extend the list
int cnt = _block_size;
int last_edge = 0;
int limit = _head_length;
@@ -494,24 +495,15 @@
if (_curr_length == 0) return false;
_next_edge = last_edge + 1;
- // Sorting the list partially
- EdgeVector::iterator sort_end = _candidates.begin();
- EdgeVector::iterator vector_end = _candidates.begin();
- for (int idx = 0; idx < _curr_length; ++idx) {
- ++vector_end;
- if (idx <= _head_length) ++sort_end;
- }
- partial_sort(_candidates.begin(), sort_end, vector_end, _sort_func);
+ // Make heap of the candidate list (approximating a partial sort)
+ make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
+ _sort_func );
+ // Pop the first element of the heap
_ns._in_edge = _candidates[0];
- if (_curr_length > _head_length) {
- _candidates[0] = _candidates[_head_length - 1];
- _curr_length = _head_length - 1;
- } else {
- _candidates[0] = _candidates[_curr_length - 1];
- --_curr_length;
- }
-
+ pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
+ _sort_func );
+ _curr_length = std::min(_head_length, _curr_length - 1);
return true;
}
}; //class AlteringListPivotRule
@@ -558,7 +550,7 @@
BoolNodeMap _forward;
// The state edge map
IntEdgeMap _state;
- // The root node of the starting spanning tree
+ // The artificial root node of the spanning tree structure
Node _root;
// The reduced cost map
@@ -575,15 +567,15 @@
NodeRefMap _node_ref;
EdgeRefMap _edge_ref;
- // The entering edge of the current pivot iteration.
+ // The entering edge of the current pivot iteration
Edge _in_edge;
- // Temporary nodes used in the current pivot iteration.
+ // Temporary nodes used in the current pivot iteration
Node join, u_in, v_in, u_out, v_out;
Node right, first, second, last;
Node stem, par_stem, new_stem;
// The maximum augment amount along the found cycle in the current
- // pivot iteration.
+ // pivot iteration
Capacity delta;
public :
@@ -837,8 +829,8 @@
/// list in every iteration (\ref AlteringListPivotRule).
///
/// According to our comprehensive benchmark tests the "Block Search"
- /// pivot rule proved to be by far the fastest and the most robust
- /// on various test inputs. Thus it is the default option.
+ /// pivot rule proved to be the fastest and the most robust on
+ /// various test inputs. Thus it is the default option.
///
/// \return \c true if a feasible flow can be found.
bool run(PivotRuleEnum pivot_rule = BLOCK_SEARCH_PIVOT) {
@@ -911,12 +903,11 @@
private:
- /// \brief Extend the underlying graph and initialize all the
- /// node and edge maps.
+ // Extend the underlying graph and initialize all the node and edge maps
bool init() {
if (!_valid_supply) return false;
- // Initializing result maps
+ // Initialize result maps
if (!_flow_result) {
_flow_result = new FlowMap(_graph_ref);
_local_flow = true;
@@ -926,7 +917,7 @@
_local_potential = true;
}
- // Initializing the edge vector and the edge maps
+ // Initialize the edge vector and the edge maps
_edges.reserve(countEdges(_graph));
for (EdgeIt e(_graph); e != INVALID; ++e) {
_edges.push_back(e);
@@ -934,7 +925,7 @@
_state[e] = STATE_LOWER;
}
- // Adding an artificial root node to the graph
+ // Add an artificial root node to the graph
_root = _graph.addNode();
_parent[_root] = INVALID;
_pred_edge[_root] = INVALID;
@@ -942,8 +933,8 @@
_supply[_root] = 0;
_potential[_root] = 0;
- // Adding artificial edges to the graph and initializing the node
- // maps of the spanning tree data structure
+ // Add artificial edges to the graph and initialize the node maps
+ // of the spanning tree data structure
Node last = _root;
Edge e;
Cost max_cost = std::numeric_limits<Cost>::max() / 4;
@@ -974,8 +965,8 @@
return true;
}
- /// Find the join node.
- inline Node findJoinNode() {
+ // Find the join node
+ void findJoinNode() {
Node u = _graph.source(_in_edge);
Node v = _graph.target(_in_edge);
while (u != v) {
@@ -986,14 +977,13 @@
else if (_depth[u] > _depth[v]) u = _parent[u];
else v = _parent[v];
}
- return u;
+ join = u;
}
- /// \brief Find the leaving edge of the cycle.
- /// \return \c true if the leaving edge is not the same as the
- /// entering edge.
- inline bool findLeavingEdge() {
- // Initializing first and second nodes according to the direction
+ // Find the leaving edge of the cycle and returns true if the
+ // leaving edge is not the same as the entering edge
+ bool findLeavingEdge() {
+ // Initialize first and second nodes according to the direction
// of the cycle
if (_state[_in_edge] == STATE_LOWER) {
first = _graph.source(_in_edge);
@@ -1007,8 +997,7 @@
Capacity d;
Edge e;
- // Searching the cycle along the path form the first node to the
- // root node
+ // Search the cycle along the path form the first node to the root
for (Node u = first; u != join; u = _parent[u]) {
e = _pred_edge[u];
d = _forward[u] ? _flow[e] : _capacity[e] - _flow[e];
@@ -1020,8 +1009,7 @@
result = true;
}
}
- // Searching the cycle along the path form the second node to the
- // root node
+ // Search the cycle along the path form the second node to the root
for (Node u = second; u != join; u = _parent[u]) {
e = _pred_edge[u];
d = _forward[u] ? _capacity[e] - _flow[e] : _flow[e];
@@ -1036,9 +1024,9 @@
return result;
}
- /// Change \c flow and \c state edge maps.
- inline void changeFlows(bool change) {
- // Augmenting along the cycle
+ // Change _flow and _state edge maps
+ void changeFlows(bool change) {
+ // Augment along the cycle
if (delta > 0) {
Capacity val = _state[_in_edge] * delta;
_flow[_in_edge] += val;
@@ -1049,7 +1037,7 @@
_flow[_pred_edge[u]] += _forward[u] ? val : -val;
}
}
- // Updating the state of the entering and leaving edges
+ // Update the state of the entering and leaving edges
if (change) {
_state[_in_edge] = STATE_TREE;
_state[_pred_edge[u_out]] =
@@ -1059,12 +1047,12 @@
}
}
- /// Update \c thread and \c parent node maps.
- inline void updateThreadParent() {
+ // Update _thread and _parent node maps
+ void updateThreadParent() {
Node u;
v_out = _parent[u_out];
- // Handling the case when join and v_out coincide
+ // Handle the case when join and v_out coincide
bool par_first = false;
if (join == v_out) {
for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
@@ -1075,8 +1063,8 @@
}
}
- // Finding the last successor of u_in (u) and the node after it
- // (right) according to the thread index
+ // Find the last successor of u_in (u) and the node after it (right)
+ // according to the thread index
for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
right = _thread[u];
if (_thread[v_in] == u_out) {
@@ -1085,25 +1073,24 @@
}
else last = _thread[v_in];
- // Updating stem nodes
+ // Update stem nodes
_thread[v_in] = stem = u_in;
par_stem = v_in;
while (stem != u_out) {
_thread[u] = new_stem = _parent[stem];
- // Finding the node just before the stem node (u) according to
+ // Find the node just before the stem node (u) according to
// the original thread index
for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
_thread[u] = right;
- // Changing the parent node of stem and shifting stem and
- // par_stem nodes
+ // Change the parent node of stem and shift stem and par_stem nodes
_parent[stem] = par_stem;
par_stem = stem;
stem = new_stem;
- // Finding the last successor of stem (u) and the node after it
- // (right) according to the thread index
+ // Find the last successor of stem (u) and the node after it (right)
+ // according to the thread index
for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
right = _thread[u];
}
@@ -1118,8 +1105,8 @@
}
}
- /// Update \c pred_edge and \c forward node maps.
- inline void updatePredEdge() {
+ // Update _pred_edge and _forward node maps.
+ void updatePredEdge() {
Node u = u_out, v;
while (u != u_in) {
v = _parent[u];
@@ -1131,8 +1118,8 @@
_forward[u_in] = (u_in == _graph.source(_in_edge));
}
- /// Update \c depth and \c potential node maps.
- inline void updateDepthPotential() {
+ // Update _depth and _potential node maps
+ void updateDepthPotential() {
_depth[u_in] = _depth[v_in] + 1;
Cost sigma = _forward[u_in] ?
_potential[v_in] - _potential[u_in] - _cost[_pred_edge[u_in]] :
@@ -1145,9 +1132,9 @@
}
}
- /// Execute the algorithm.
+ // Execute the algorithm
bool start(PivotRuleEnum pivot_rule) {
- // Selecting the pivot rule implementation
+ // Select the pivot rule implementation
switch (pivot_rule) {
case FIRST_ELIGIBLE_PIVOT:
return start<FirstEligiblePivotRule>();
@@ -1167,9 +1154,9 @@
bool start() {
PivotRuleImplementation pivot(*this, _edges);
- // Executing the network simplex algorithm
+ // Execute the network simplex algorithm
while (pivot.findEnteringEdge()) {
- join = findJoinNode();
+ findJoinNode();
bool change = findLeavingEdge();
changeFlows(change);
if (change) {
@@ -1179,14 +1166,13 @@
}
}
- // Checking if the flow amount equals zero on all the artificial
- // edges
+ // Check if the flow amount equals zero on all the artificial edges
for (InEdgeIt e(_graph, _root); e != INVALID; ++e)
if (_flow[e] > 0) return false;
for (OutEdgeIt e(_graph, _root); e != INVALID; ++e)
if (_flow[e] > 0) return false;
- // Copying flow values to _flow_result
+ // Copy flow values to _flow_result
if (_lower) {
for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
(*_flow_result)[e] = (*_lower)[e] + _flow[_edge_ref[e]];
@@ -1194,7 +1180,7 @@
for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
(*_flow_result)[e] = _flow[_edge_ref[e]];
}
- // Copying potential values to _potential_result
+ // Copy potential values to _potential_result
for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
(*_potential_result)[n] = _potential[_node_ref[n]];
More information about the Lemon-commits
mailing list