[Lemon-commits] kpeter: r3413 - lemon/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Wed Dec 5 14:03:20 CET 2007
Author: kpeter
Date: Wed Dec 5 14:03:19 2007
New Revision: 3413
Modified:
lemon/trunk/lemon/capacity_scaling.h
Log:
Redesigned CapacityScaling algorithm with almost the same interface.
The new version does not use the ResidualGraphAdaptor for performance reasons.
Scaling can be enabled and disabled with a parameter of the run() function.
Modified: lemon/trunk/lemon/capacity_scaling.h
==============================================================================
--- lemon/trunk/lemon/capacity_scaling.h (original)
+++ lemon/trunk/lemon/capacity_scaling.h Wed Dec 5 14:03:19 2007
@@ -25,17 +25,9 @@
/// \brief The capacity scaling algorithm for finding a minimum cost
/// flow.
-#include <vector>
#include <lemon/graph_adaptor.h>
-#include <lemon/dijkstra.h>
-
-#define WITH_SCALING
-
-#ifdef WITH_SCALING
-#define SCALING_FACTOR 2
-#endif
-
-//#define _DEBUG_ITER_
+#include <lemon/bin_heap.h>
+#include <vector>
namespace lemon {
@@ -46,9 +38,9 @@
/// successive shortest path algorithm for finding a minimum cost
/// flow.
///
- /// \ref lemon::CapacityScaling "CapacityScaling" implements the
- /// capacity scaling version of the successive shortest path
- /// algorithm for finding a minimum cost flow.
+ /// \ref CapacityScaling implements the capacity scaling version
+ /// of the successive shortest path algorithm for finding a minimum
+ /// cost flow.
///
/// \param Graph The directed graph type the algorithm runs on.
/// \param LowerMap The type of the lower bound map.
@@ -58,20 +50,20 @@
///
/// \warning
/// - Edge capacities and costs should be nonnegative integers.
- /// However \c CostMap::Value should be signed type.
+ /// However \c CostMap::Value should be signed type.
/// - Supply values should be signed integers.
/// - \c LowerMap::Value must be convertible to
- /// \c CapacityMap::Value and \c CapacityMap::Value must be
- /// convertible to \c SupplyMap::Value.
+ /// \c CapacityMap::Value and \c CapacityMap::Value must be
+ /// convertible to \c SupplyMap::Value.
///
/// \author Peter Kovacs
template < typename Graph,
- typename LowerMap = typename Graph::template EdgeMap<int>,
- typename CapacityMap = LowerMap,
- typename CostMap = typename Graph::template EdgeMap<int>,
- typename SupplyMap = typename Graph::template NodeMap
- <typename CapacityMap::Value> >
+ typename LowerMap = typename Graph::template EdgeMap<int>,
+ typename CapacityMap = LowerMap,
+ typename CostMap = typename Graph::template EdgeMap<int>,
+ typename SupplyMap = typename Graph::template NodeMap
+ <typename CapacityMap::Value> >
class CapacityScaling
{
typedef typename Graph::Node Node;
@@ -87,16 +79,16 @@
typedef typename SupplyMap::Value Supply;
typedef typename Graph::template EdgeMap<Capacity> CapacityRefMap;
typedef typename Graph::template NodeMap<Supply> SupplyRefMap;
-
- typedef ResGraphAdaptor< const Graph, Capacity,
- CapacityRefMap, CapacityRefMap > ResGraph;
- typedef typename ResGraph::Node ResNode;
- typedef typename ResGraph::NodeIt ResNodeIt;
- typedef typename ResGraph::Edge ResEdge;
- typedef typename ResGraph::EdgeIt ResEdgeIt;
+ typedef typename Graph::template NodeMap<Edge> PredMap;
public:
+ /// \brief Type to enable or disable capacity scaling.
+ enum ScalingEnum {
+ WITH_SCALING = 0,
+ WITHOUT_SCALING = -1
+ };
+
/// \brief The type of the flow map.
typedef CapacityRefMap FlowMap;
/// \brief The type of the potential map.
@@ -104,151 +96,129 @@
protected:
- /// \brief Map adaptor class for handling reduced edge costs.
- class ReducedCostMap : public MapBase<ResEdge, Cost>
- {
- private:
-
- const ResGraph &gr;
- const CostMap &cost_map;
- const PotentialMap &pot_map;
-
- public:
-
- ReducedCostMap( const ResGraph &_gr,
- const CostMap &_cost,
- const PotentialMap &_pot ) :
- gr(_gr), cost_map(_cost), pot_map(_pot) {}
-
- Cost operator[](const ResEdge &e) const {
- return ResGraph::forward(e) ?
- cost_map[e] - pot_map[gr.source(e)] + pot_map[gr.target(e)] :
- -cost_map[e] - pot_map[gr.source(e)] + pot_map[gr.target(e)];
- }
-
- }; //class ReducedCostMap
-
- /// \brief Map class for the \ref lemon::Dijkstra "Dijkstra"
- /// algorithm to update node potentials.
- class PotentialUpdateMap : public MapBase<ResNode, Cost>
- {
- private:
-
- PotentialMap *pot;
- typedef std::pair<ResNode, Cost> Pair;
- std::vector<Pair> data;
-
- public:
-
- void potentialMap(PotentialMap &_pot) {
- pot = &_pot;
- }
-
- void init() {
- data.clear();
- }
-
- void set(const ResNode &n, const Cost &v) {
- data.push_back(Pair(n, v));
- }
-
- void update() {
- Cost val = data[data.size()-1].second;
- for (int i = 0; i < data.size()-1; ++i)
- (*pot)[data[i].first] += val - data[i].second;
- }
-
- }; //class PotentialUpdateMap
-
-#ifdef WITH_SCALING
- /// \brief Map adaptor class for identifing deficit nodes.
- class DeficitBoolMap : public MapBase<ResNode, bool>
- {
- private:
-
- const SupplyRefMap &imb;
- const Capacity δ
-
- public:
-
- DeficitBoolMap(const SupplyRefMap &_imb, const Capacity &_delta) :
- imb(_imb), delta(_delta) {}
-
- bool operator[](const ResNode &n) const {
- return imb[n] <= -delta;
- }
-
- }; //class DeficitBoolMap
-
- /// \brief Map adaptor class for filtering edges with at least
- /// \c delta residual capacity.
- class DeltaFilterMap : public MapBase<ResEdge, bool>
- {
- private:
-
- const ResGraph &gr;
- const Capacity δ
-
- public:
-
- DeltaFilterMap(const ResGraph &_gr, const Capacity &_delta) :
- gr(_gr), delta(_delta) {}
-
- bool operator[](const ResEdge &e) const {
- return gr.rescap(e) >= delta;
- }
-
- }; //class DeltaFilterMap
-
- typedef EdgeSubGraphAdaptor<const ResGraph, const DeltaFilterMap>
- DeltaResGraph;
-
- /// \brief Traits class for \ref lemon::Dijkstra "Dijkstra" class.
- class ResDijkstraTraits :
- public DijkstraDefaultTraits<DeltaResGraph, ReducedCostMap>
- {
- public:
-
- typedef PotentialUpdateMap DistMap;
-
- static DistMap *createDistMap(const DeltaResGraph&) {
- return new DistMap();
- }
-
- }; //class ResDijkstraTraits
-
-#else //WITHOUT_CAPACITY_SCALING
- /// \brief Map adaptor class for identifing deficit nodes.
- class DeficitBoolMap : public MapBase<ResNode, bool>
- {
- private:
-
- const SupplyRefMap &imb;
+ /// \brief Special implementation of the \ref Dijkstra algorithm
+ /// for finding shortest paths in the residual network of the graph
+ /// with respect to the reduced edge costs and modifying the
+ /// node potentials according to the distance of the nodes.
+ class ResidualDijkstra
+ {
+ typedef typename Graph::template NodeMap<Cost> CostNodeMap;
+ typedef typename Graph::template NodeMap<Edge> PredMap;
+
+ typedef typename Graph::template NodeMap<int> HeapCrossRef;
+ typedef BinHeap<Cost, HeapCrossRef> Heap;
+
+ protected:
+
+ /// \brief The directed graph the algorithm runs on.
+ const Graph &graph;
+
+ /// \brief The flow map.
+ const FlowMap &flow;
+ /// \brief The residual capacity map.
+ const CapacityRefMap &res_cap;
+ /// \brief The cost map.
+ const CostMap &cost;
+ /// \brief The excess map.
+ const SupplyRefMap &excess;
+
+ /// \brief The potential map.
+ PotentialMap &potential;
+
+ /// \brief The distance map.
+ CostNodeMap dist;
+ /// \brief The map of predecessors edges.
+ PredMap &pred;
+ /// \brief The processed (i.e. permanently labeled) nodes.
+ std::vector<Node> proc_nodes;
public:
- DeficitBoolMap(const SupplyRefMap &_imb) : imb(_imb) {}
+ /// \brief The constructor of the class.
+ ResidualDijkstra( const Graph &_graph,
+ const FlowMap &_flow,
+ const CapacityRefMap &_res_cap,
+ const CostMap &_cost,
+ const SupplyMap &_excess,
+ PotentialMap &_potential,
+ PredMap &_pred ) :
+ graph(_graph), flow(_flow), res_cap(_res_cap), cost(_cost),
+ excess(_excess), potential(_potential), dist(_graph),
+ pred(_pred)
+ {}
+
+ /// \brief Runs the algorithm from the given source node.
+ Node run(Node s, Capacity delta) {
+ HeapCrossRef heap_cross_ref(graph, Heap::PRE_HEAP);
+ Heap heap(heap_cross_ref);
+ heap.push(s, 0);
+ pred[s] = INVALID;
+ proc_nodes.clear();
+
+ // Processing nodes
+ while (!heap.empty() && excess[heap.top()] > -delta) {
+ Node u = heap.top(), v;
+ Cost d = heap.prio() - potential[u], nd;
+ dist[u] = heap.prio();
+ heap.pop();
+ proc_nodes.push_back(u);
+
+ // Traversing outgoing edges
+ for (OutEdgeIt e(graph, u); e != INVALID; ++e) {
+ if (res_cap[e] >= delta) {
+ v = graph.target(e);
+ switch(heap.state(v)) {
+ case Heap::PRE_HEAP:
+ heap.push(v, d + cost[e] + potential[v]);
+ pred[v] = e;
+ break;
+ case Heap::IN_HEAP:
+ nd = d + cost[e] + potential[v];
+ if (nd < heap[v]) {
+ heap.decrease(v, nd);
+ pred[v] = e;
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ }
+
+ // Traversing incoming edges
+ for (InEdgeIt e(graph, u); e != INVALID; ++e) {
+ if (flow[e] >= delta) {
+ v = graph.source(e);
+ switch(heap.state(v)) {
+ case Heap::PRE_HEAP:
+ heap.push(v, d - cost[e] + potential[v]);
+ pred[v] = e;
+ break;
+ case Heap::IN_HEAP:
+ nd = d - cost[e] + potential[v];
+ if (nd < heap[v]) {
+ heap.decrease(v, nd);
+ pred[v] = e;
+ }
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ }
+ }
+ if (heap.empty()) return INVALID;
+
+ // Updating potentials of processed nodes
+ Node t = heap.top();
+ Cost dt = heap.prio();
+ for (int i = 0; i < proc_nodes.size(); ++i)
+ potential[proc_nodes[i]] -= dist[proc_nodes[i]] - dt;
- bool operator[](const ResNode &n) const {
- return imb[n] < 0;
+ return t;
}
- }; //class DeficitBoolMap
-
- /// \brief Traits class for \ref lemon::Dijkstra "Dijkstra" class.
- class ResDijkstraTraits :
- public DijkstraDefaultTraits<ResGraph, ReducedCostMap>
- {
- public:
-
- typedef PotentialUpdateMap DistMap;
-
- static DistMap *createDistMap(const ResGraph&) {
- return new DistMap();
- }
-
- }; //class ResDijkstraTraits
-#endif
+ }; //class ResidualDijkstra
protected:
@@ -269,57 +239,30 @@
FlowMap flow;
/// \brief The potential node map.
PotentialMap potential;
- /// \brief The residual graph.
- ResGraph res_graph;
- /// \brief The reduced cost map.
- ReducedCostMap red_cost;
-
- /// \brief The imbalance map.
- SupplyRefMap imbalance;
- /// \brief The excess nodes.
- std::vector<ResNode> excess_nodes;
+
+ /// \brief The residual capacity map.
+ CapacityRefMap res_cap;
+ /// \brief The excess map.
+ SupplyRefMap excess;
+ /// \brief The excess nodes (i.e. nodes with positive excess).
+ std::vector<Node> excess_nodes;
/// \brief The index of the next excess node.
int next_node;
-#ifdef WITH_SCALING
- typedef Dijkstra<DeltaResGraph, ReducedCostMap, ResDijkstraTraits>
- ResDijkstra;
- /// \brief \ref lemon::Dijkstra "Dijkstra" class for finding
- /// shortest paths in the residual graph with respect to the
- /// reduced edge costs.
- ResDijkstra dijkstra;
-
+ /// \brief The scaling status (enabled or disabled).
+ ScalingEnum scaling;
/// \brief The delta parameter used for capacity scaling.
Capacity delta;
- /// \brief Edge filter map for filtering edges with at least
- /// \c delta residual capacity.
- DeltaFilterMap delta_filter;
- /// \brief The delta residual graph (i.e. the subgraph of the
- /// residual graph consisting of edges with at least \c delta
- /// residual capacity).
- DeltaResGraph dres_graph;
- /// \brief Map for identifing deficit nodes.
- DeficitBoolMap delta_deficit;
-
+ /// \brief The maximum number of phases.
+ Capacity phase_num;
/// \brief The deficit nodes.
- std::vector<ResNode> deficit_nodes;
+ std::vector<Node> deficit_nodes;
-#else //WITHOUT_CAPACITY_SCALING
- typedef Dijkstra<ResGraph, ReducedCostMap, ResDijkstraTraits>
- ResDijkstra;
- /// \brief \ref lemon::Dijkstra "Dijkstra" class for finding
- /// shortest paths in the residual graph with respect to the
- /// reduced edge costs.
- ResDijkstra dijkstra;
- /// \brief Map for identifing deficit nodes.
- DeficitBoolMap has_deficit;
-#endif
-
- /// \brief Pred map for the \ref lemon::Dijkstra "Dijkstra" class.
- typename ResDijkstra::PredMap pred;
- /// \brief Dist map for the \ref lemon::Dijkstra "Dijkstra" class to
- /// update node potentials.
- PotentialUpdateMap updater;
+ /// \brief Implementation of the \ref Dijkstra algorithm for
+ /// finding augmenting shortest paths in the residual network.
+ ResidualDijkstra dijkstra;
+ /// \brief The map of predecessors edges.
+ PredMap pred;
public :
@@ -333,35 +276,27 @@
/// \param _cost The cost (length) values of the edges.
/// \param _supply The supply values of the nodes (signed).
CapacityScaling( const Graph &_graph,
- const LowerMap &_lower,
- const CapacityMap &_capacity,
- const CostMap &_cost,
- const SupplyMap &_supply ) :
+ const LowerMap &_lower,
+ const CapacityMap &_capacity,
+ const CostMap &_cost,
+ const SupplyMap &_supply ) :
graph(_graph), lower(&_lower), capacity(_graph), cost(_cost),
supply(_graph), flow(_graph, 0), potential(_graph, 0),
- res_graph(_graph, capacity, flow),
- red_cost(res_graph, cost, potential), imbalance(_graph),
-#ifdef WITH_SCALING
- delta(0), delta_filter(res_graph, delta),
- dres_graph(res_graph, delta_filter),
- dijkstra(dres_graph, red_cost), pred(dres_graph),
- delta_deficit(imbalance, delta)
-#else //WITHOUT_CAPACITY_SCALING
- dijkstra(res_graph, red_cost), pred(res_graph),
- has_deficit(imbalance)
-#endif
+ res_cap(_graph), excess(_graph), pred(_graph),
+ dijkstra(graph, flow, res_cap, cost, excess, potential, pred)
{
// Removing nonzero lower bounds
capacity = subMap(_capacity, _lower);
+ res_cap = capacity;
Supply sum = 0;
for (NodeIt n(graph); n != INVALID; ++n) {
- Supply s = _supply[n];
- for (InEdgeIt e(graph, n); e != INVALID; ++e)
- s += _lower[e];
- for (OutEdgeIt e(graph, n); e != INVALID; ++e)
- s -= _lower[e];
- supply[n] = s;
- sum += s;
+ Supply s = _supply[n];
+ for (InEdgeIt e(graph, n); e != INVALID; ++e)
+ s += _lower[e];
+ for (OutEdgeIt e(graph, n); e != INVALID; ++e)
+ s -= _lower[e];
+ supply[n] = s;
+ sum += s;
}
valid_supply = sum == 0;
}
@@ -375,22 +310,13 @@
/// \param _cost The cost (length) values of the edges.
/// \param _supply The supply values of the nodes (signed).
CapacityScaling( const Graph &_graph,
- const CapacityMap &_capacity,
- const CostMap &_cost,
- const SupplyMap &_supply ) :
+ const CapacityMap &_capacity,
+ const CostMap &_cost,
+ const SupplyMap &_supply ) :
graph(_graph), lower(NULL), capacity(_capacity), cost(_cost),
supply(_supply), flow(_graph, 0), potential(_graph, 0),
- res_graph(_graph, capacity, flow),
- red_cost(res_graph, cost, potential), imbalance(_graph),
-#ifdef WITH_SCALING
- delta(0), delta_filter(res_graph, delta),
- dres_graph(res_graph, delta_filter),
- dijkstra(dres_graph, red_cost), pred(dres_graph),
- delta_deficit(imbalance, delta)
-#else //WITHOUT_CAPACITY_SCALING
- dijkstra(res_graph, red_cost), pred(res_graph),
- has_deficit(imbalance)
-#endif
+ res_cap(_capacity), excess(_graph), pred(_graph),
+ dijkstra(graph, flow, res_cap, cost, excess, potential)
{
// Checking the sum of supply values
Supply sum = 0;
@@ -412,36 +338,28 @@
/// to node \c _t (i.e. the supply of \c _s and the demand of
/// \c _t).
CapacityScaling( const Graph &_graph,
- const LowerMap &_lower,
- const CapacityMap &_capacity,
- const CostMap &_cost,
- Node _s, Node _t,
- Supply _flow_value ) :
+ const LowerMap &_lower,
+ const CapacityMap &_capacity,
+ const CostMap &_cost,
+ Node _s, Node _t,
+ Supply _flow_value ) :
graph(_graph), lower(&_lower), capacity(_graph), cost(_cost),
supply(_graph), flow(_graph, 0), potential(_graph, 0),
- res_graph(_graph, capacity, flow),
- red_cost(res_graph, cost, potential), imbalance(_graph),
-#ifdef WITH_SCALING
- delta(0), delta_filter(res_graph, delta),
- dres_graph(res_graph, delta_filter),
- dijkstra(dres_graph, red_cost), pred(dres_graph),
- delta_deficit(imbalance, delta)
-#else //WITHOUT_CAPACITY_SCALING
- dijkstra(res_graph, red_cost), pred(res_graph),
- has_deficit(imbalance)
-#endif
+ res_cap(_graph), excess(_graph), pred(_graph),
+ dijkstra(graph, flow, res_cap, cost, excess, potential)
{
// Removing nonzero lower bounds
capacity = subMap(_capacity, _lower);
+ res_cap = capacity;
for (NodeIt n(graph); n != INVALID; ++n) {
- Supply s = 0;
- if (n == _s) s = _flow_value;
- if (n == _t) s = -_flow_value;
- for (InEdgeIt e(graph, n); e != INVALID; ++e)
- s += _lower[e];
- for (OutEdgeIt e(graph, n); e != INVALID; ++e)
- s -= _lower[e];
- supply[n] = s;
+ Supply s = 0;
+ if (n == _s) s = _flow_value;
+ if (n == _t) s = -_flow_value;
+ for (InEdgeIt e(graph, n); e != INVALID; ++e)
+ s += _lower[e];
+ for (OutEdgeIt e(graph, n); e != INVALID; ++e)
+ s -= _lower[e];
+ supply[n] = s;
}
valid_supply = true;
}
@@ -459,23 +377,14 @@
/// to node \c _t (i.e. the supply of \c _s and the demand of
/// \c _t).
CapacityScaling( const Graph &_graph,
- const CapacityMap &_capacity,
- const CostMap &_cost,
- Node _s, Node _t,
- Supply _flow_value ) :
+ const CapacityMap &_capacity,
+ const CostMap &_cost,
+ Node _s, Node _t,
+ Supply _flow_value ) :
graph(_graph), lower(NULL), capacity(_capacity), cost(_cost),
supply(_graph, 0), flow(_graph, 0), potential(_graph, 0),
- res_graph(_graph, capacity, flow),
- red_cost(res_graph, cost, potential), imbalance(_graph),
-#ifdef WITH_SCALING
- delta(0), delta_filter(res_graph, delta),
- dres_graph(res_graph, delta_filter),
- dijkstra(dres_graph, red_cost), pred(dres_graph),
- delta_deficit(imbalance, delta)
-#else //WITHOUT_CAPACITY_SCALING
- dijkstra(res_graph, red_cost), pred(res_graph),
- has_deficit(imbalance)
-#endif
+ res_cap(_capacity), excess(_graph), pred(_graph),
+ dijkstra(graph, flow, res_cap, cost, excess, potential)
{
supply[_s] = _flow_value;
supply[_t] = -_flow_value;
@@ -511,7 +420,7 @@
Cost totalCost() const {
Cost c = 0;
for (EdgeIt e(graph); e != INVALID; ++e)
- c += flow[e] * cost[e];
+ c += flow[e] * cost[e];
return c;
}
@@ -519,190 +428,216 @@
///
/// Runs the algorithm.
///
+ /// \param scaling_mode The scaling mode. In case of WITH_SCALING
+ /// capacity scaling is enabled in the algorithm (this is the
+ /// default value) otherwise it is disabled.
+ /// If the maximum edge capacity and/or the amount of total supply
+ /// is small, the algorithm could be faster without scaling.
+ ///
/// \return \c true if a feasible flow can be found.
- bool run() {
- return init() && start();
+ bool run(int scaling_mode = WITH_SCALING) {
+ return init(scaling_mode) && start();
}
protected:
/// \brief Initializes the algorithm.
- bool init() {
+ bool init(int scaling_mode) {
if (!valid_supply) return false;
- imbalance = supply;
-
- // Initalizing Dijkstra class
- updater.potentialMap(potential);
- dijkstra.distMap(updater).predMap(pred);
+ excess = supply;
-#ifdef WITH_SCALING
// Initilaizing delta value
- Supply max_sup = 0, max_dem = 0;
- for (NodeIt n(graph); n != INVALID; ++n) {
- if (supply[n] > max_sup) max_sup = supply[n];
- if (supply[n] < -max_dem) max_dem = -supply[n];
+ if (scaling_mode == WITH_SCALING) {
+ // With scaling
+ Supply max_sup = 0, max_dem = 0;
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ if ( supply[n] > max_sup) max_sup = supply[n];
+ if (-supply[n] > max_dem) max_dem = -supply[n];
+ }
+ if (max_dem < max_sup) max_sup = max_dem;
+ phase_num = 0;
+ for (delta = 1; 2 * delta <= max_sup; delta *= 2)
+ ++phase_num;
+ } else {
+ // Without scaling
+ delta = 1;
}
- if (max_dem < max_sup) max_sup = max_dem;
- for ( delta = 1; SCALING_FACTOR * delta < max_sup;
- delta *= SCALING_FACTOR ) ;
-#endif
return true;
}
-#ifdef WITH_SCALING
- /// \brief Executes the capacity scaling version of the successive
- /// shortest path algorithm.
+ /// \brief Executes the algorithm.
bool start() {
- typedef typename DeltaResGraph::EdgeIt DeltaResEdgeIt;
- typedef typename DeltaResGraph::Edge DeltaResEdge;
-#ifdef _DEBUG_ITER_
- int dijk_num = 0;
-#endif
+ if (delta > 1)
+ return startWithScaling();
+ else
+ return startWithoutScaling();
+ }
+ /// \brief Executes the capacity scaling version of the successive
+ /// shortest path algorithm.
+ bool startWithScaling() {
// Processing capacity scaling phases
- ResNode s, t;
- for ( ; delta >= 1; delta = delta < SCALING_FACTOR && delta > 1 ?
- 1 : delta / SCALING_FACTOR )
- {
- // Saturating edges not satisfying the optimality condition
- Capacity r;
- for (DeltaResEdgeIt e(dres_graph); e != INVALID; ++e) {
- if (red_cost[e] < 0) {
- res_graph.augment(e, r = res_graph.rescap(e));
- imbalance[dres_graph.source(e)] -= r;
- imbalance[dres_graph.target(e)] += r;
- }
- }
-
- // Finding excess nodes
- excess_nodes.clear();
- deficit_nodes.clear();
- for (ResNodeIt n(res_graph); n != INVALID; ++n) {
- if (imbalance[n] >= delta) excess_nodes.push_back(n);
- if (imbalance[n] <= -delta) deficit_nodes.push_back(n);
- }
- next_node = 0;
-
- // Finding shortest paths
- while (next_node < excess_nodes.size()) {
- // Checking deficit nodes
- if (delta > 1) {
- bool delta_def = false;
- for (int i = 0; i < deficit_nodes.size(); ++i) {
- if (imbalance[deficit_nodes[i]] <= -delta) {
- delta_def = true;
- break;
- }
- }
- if (!delta_def) break;
- }
-
- // Running Dijkstra
- s = excess_nodes[next_node];
- updater.init();
- dijkstra.init();
- dijkstra.addSource(s);
-#ifdef _DEBUG_ITER_
- ++dijk_num;
-#endif
- if ((t = dijkstra.start(delta_deficit)) == INVALID) {
- if (delta > 1) {
- ++next_node;
- continue;
- }
- return false;
- }
-
- // Updating node potentials
- updater.update();
-
- // Augment along a shortest path from s to t
- Capacity d = imbalance[s] < -imbalance[t] ?
- imbalance[s] : -imbalance[t];
- ResNode u = t;
- ResEdge e;
- if (d > delta) {
- while ((e = pred[u]) != INVALID) {
- if (res_graph.rescap(e) < d) d = res_graph.rescap(e);
- u = dres_graph.source(e);
- }
- }
- u = t;
- while ((e = pred[u]) != INVALID) {
- res_graph.augment(e, d);
- u = dres_graph.source(e);
- }
- imbalance[s] -= d;
- imbalance[t] += d;
- if (imbalance[s] < delta) ++next_node;
- }
+ Node s, t;
+ int phase_cnt = 0;
+ int factor = 4;
+ while (true) {
+ // Saturating all edges not satisfying the optimality condition
+ for (EdgeIt e(graph); e != INVALID; ++e) {
+ Node u = graph.source(e), v = graph.target(e);
+ Cost c = cost[e] - potential[u] + potential[v];
+ if (c < 0 && res_cap[e] >= delta) {
+ excess[u] -= res_cap[e];
+ excess[v] += res_cap[e];
+ flow[e] = capacity[e];
+ res_cap[e] = 0;
+ }
+ else if (c > 0 && flow[e] >= delta) {
+ excess[u] += flow[e];
+ excess[v] -= flow[e];
+ flow[e] = 0;
+ res_cap[e] = capacity[e];
+ }
+ }
+
+ // Finding excess nodes and deficit nodes
+ excess_nodes.clear();
+ deficit_nodes.clear();
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ if (excess[n] >= delta) excess_nodes.push_back(n);
+ if (excess[n] <= -delta) deficit_nodes.push_back(n);
+ }
+ next_node = 0;
+
+ // Finding augmenting shortest paths
+ while (next_node < excess_nodes.size()) {
+ // Checking deficit nodes
+ if (delta > 1) {
+ bool delta_deficit = false;
+ for (int i = 0; i < deficit_nodes.size(); ++i) {
+ if (excess[deficit_nodes[i]] <= -delta) {
+ delta_deficit = true;
+ break;
+ }
+ }
+ if (!delta_deficit) break;
+ }
+
+ // Running Dijkstra
+ s = excess_nodes[next_node];
+ if ((t = dijkstra.run(s, delta)) == INVALID) {
+ if (delta > 1) {
+ ++next_node;
+ continue;
+ }
+ return false;
+ }
+
+ // Augmenting along a shortest path from s to t.
+ Capacity d = excess[s] < -excess[t] ? excess[s] : -excess[t];
+ Node u = t;
+ Edge e;
+ if (d > delta) {
+ while ((e = pred[u]) != INVALID) {
+ Capacity rc;
+ if (u == graph.target(e)) {
+ rc = res_cap[e];
+ u = graph.source(e);
+ } else {
+ rc = flow[e];
+ u = graph.target(e);
+ }
+ if (rc < d) d = rc;
+ }
+ }
+ u = t;
+ while ((e = pred[u]) != INVALID) {
+ if (u == graph.target(e)) {
+ flow[e] += d;
+ res_cap[e] -= d;
+ u = graph.source(e);
+ } else {
+ flow[e] -= d;
+ res_cap[e] += d;
+ u = graph.target(e);
+ }
+ }
+ excess[s] -= d;
+ excess[t] += d;
+
+ if (excess[s] < delta) ++next_node;
+ }
+
+ if (delta == 1) break;
+ if (++phase_cnt > phase_num / 4) factor = 2;
+ delta = delta <= factor ? 1 : delta / factor;
}
-#ifdef _DEBUG_ITER_
- std::cout << "Capacity Scaling algorithm finished with running Dijkstra algorithm "
- << dijk_num << " times." << std::endl;
-#endif
// Handling nonzero lower bounds
if (lower) {
- for (EdgeIt e(graph); e != INVALID; ++e)
- flow[e] += (*lower)[e];
+ for (EdgeIt e(graph); e != INVALID; ++e)
+ flow[e] += (*lower)[e];
}
return true;
}
-#else //WITHOUT_CAPACITY_SCALING
/// \brief Executes the successive shortest path algorithm without
/// capacity scaling.
- bool start() {
+ bool startWithoutScaling() {
// Finding excess nodes
- for (ResNodeIt n(res_graph); n != INVALID; ++n) {
- if (imbalance[n] > 0) excess_nodes.push_back(n);
+ for (NodeIt n(graph); n != INVALID; ++n) {
+ if (excess[n] > 0) excess_nodes.push_back(n);
}
if (excess_nodes.size() == 0) return true;
next_node = 0;
// Finding shortest paths
- ResNode s, t;
- while ( imbalance[excess_nodes[next_node]] > 0 ||
- ++next_node < excess_nodes.size() )
+ Node s, t;
+ while ( excess[excess_nodes[next_node]] > 0 ||
+ ++next_node < excess_nodes.size() )
{
- // Running Dijkstra
- s = excess_nodes[next_node];
- updater.init();
- dijkstra.init();
- dijkstra.addSource(s);
- if ((t = dijkstra.start(has_deficit)) == INVALID)
- return false;
-
- // Updating node potentials
- updater.update();
-
- // Augmenting along a shortest path from s to t
- Capacity delta = imbalance[s] < -imbalance[t] ?
- imbalance[s] : -imbalance[t];
- ResNode u = t;
- ResEdge e;
- while ((e = pred[u]) != INVALID) {
- if (res_graph.rescap(e) < delta) delta = res_graph.rescap(e);
- u = res_graph.source(e);
- }
- u = t;
- while ((e = pred[u]) != INVALID) {
- res_graph.augment(e, delta);
- u = res_graph.source(e);
- }
- imbalance[s] -= delta;
- imbalance[t] += delta;
+ // Running Dijkstra
+ s = excess_nodes[next_node];
+ if ((t = dijkstra.run(s, 1)) == INVALID)
+ return false;
+
+ // Augmenting along a shortest path from s to t
+ Capacity d = excess[s] < -excess[t] ? excess[s] : -excess[t];
+ Node u = t;
+ Edge e;
+ while ((e = pred[u]) != INVALID) {
+ Capacity rc;
+ if (u == graph.target(e)) {
+ rc = res_cap[e];
+ u = graph.source(e);
+ } else {
+ rc = flow[e];
+ u = graph.target(e);
+ }
+ if (rc < d) d = rc;
+ }
+ u = t;
+ while ((e = pred[u]) != INVALID) {
+ if (u == graph.target(e)) {
+ flow[e] += d;
+ res_cap[e] -= d;
+ u = graph.source(e);
+ } else {
+ flow[e] -= d;
+ res_cap[e] += d;
+ u = graph.target(e);
+ }
+ }
+ excess[s] -= d;
+ excess[t] += d;
}
// Handling nonzero lower bounds
if (lower) {
- for (EdgeIt e(graph); e != INVALID; ++e)
- flow[e] += (*lower)[e];
+ for (EdgeIt e(graph); e != INVALID; ++e)
+ flow[e] += (*lower)[e];
}
return true;
}
-#endif
}; //class CapacityScaling
More information about the Lemon-commits
mailing list