[Lemon-commits] Peter Kovacs: Port CapacityScaling from SVN -r35...

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


details:   http://lemon.cs.elte.hu/hg/lemon/rev/d3e32a777d0b
changeset: 871:d3e32a777d0b
user:      Peter Kovacs <kpeter [at] inf.elte.hu>
date:      Thu Nov 12 23:17:34 2009 +0100
description:
	Port CapacityScaling from SVN -r3524 (#180)

diffstat:

 lemon/Makefile.am        |    1 +
 lemon/capacity_scaling.h |  717 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 718 insertions(+), 0 deletions(-)

diffs (truncated from 733 to 300 lines):

diff --git a/lemon/Makefile.am b/lemon/Makefile.am
--- a/lemon/Makefile.am
+++ b/lemon/Makefile.am
@@ -62,6 +62,7 @@
 	lemon/bin_heap.h \
 	lemon/binom_heap.h \
 	lemon/bucket_heap.h \
+	lemon/capacity_scaling.h \
 	lemon/cbc.h \
 	lemon/circulation.h \
 	lemon/clp.h \
diff --git a/lemon/capacity_scaling.h b/lemon/capacity_scaling.h
new file mode 100644
--- /dev/null
+++ b/lemon/capacity_scaling.h
@@ -0,0 +1,717 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2008
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CAPACITY_SCALING_H
+#define LEMON_CAPACITY_SCALING_H
+
+/// \ingroup min_cost_flow
+///
+/// \file
+/// \brief Capacity scaling algorithm for finding a minimum cost flow.
+
+#include <vector>
+#include <lemon/bin_heap.h>
+
+namespace lemon {
+
+  /// \addtogroup min_cost_flow
+  /// @{
+
+  /// \brief Implementation of the capacity scaling 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.
+  ///
+  /// \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.
+  ///
+  /// \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.
+  ///
+  /// \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> >
+  class CapacityScaling
+  {
+    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+
+    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;
+    typedef typename Digraph::template NodeMap<Arc> PredMap;
+
+  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<Cost> PotentialMap;
+
+  private:
+
+    /// \brief Special implementation of the \ref Dijkstra algorithm
+    /// for finding shortest paths in the residual network.
+    ///
+    /// \ref ResidualDijkstra is a special implementation of the
+    /// \ref Dijkstra algorithm for finding shortest paths in the
+    /// residual network of the digraph with respect to the reduced arc
+    /// costs and modifying the node potentials according to the
+    /// distance of the nodes.
+    class ResidualDijkstra
+    {
+      typedef typename Digraph::template NodeMap<int> HeapCrossRef;
+      typedef BinHeap<Cost, HeapCrossRef> Heap;
+
+    private:
+
+      // The digraph the algorithm runs on
+      const Digraph &_graph;
+
+      // The main maps
+      const FlowMap &_flow;
+      const CapacityArcMap &_res_cap;
+      const CostMap &_cost;
+      const SupplyNodeMap &_excess;
+      PotentialMap &_potential;
+
+      // The distance map
+      PotentialMap _dist;
+      // The pred arc map
+      PredMap &_pred;
+      // The processed (i.e. permanently labeled) nodes
+      std::vector<Node> _proc_nodes;
+
+    public:
+
+      /// Constructor.
+      ResidualDijkstra( const Digraph &digraph,
+                        const FlowMap &flow,
+                        const CapacityArcMap &res_cap,
+                        const CostMap &cost,
+                        const SupplyMap &excess,
+                        PotentialMap &potential,
+                        PredMap &pred ) :
+        _graph(digraph), _flow(flow), _res_cap(res_cap), _cost(cost),
+        _excess(excess), _potential(potential), _dist(digraph),
+        _pred(pred)
+      {}
+
+      /// Run the algorithm from the given source node.
+      Node run(Node s, Capacity delta = 1) {
+        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 arcs
+          for (OutArcIt 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 arcs
+          for (InArcIt 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 t_dist = heap.prio();
+        for (int i = 0; i < int(_proc_nodes.size()); ++i)
+          _potential[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
+
+        return t;
+      }
+
+    }; //class ResidualDijkstra
+
+  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 &_cost;
+    // The modified supply map
+    SupplyNodeMap _supply;
+    bool _valid_supply;
+
+    // Arc map of the current flow
+    FlowMap *_flow;
+    bool _local_flow;
+    // Node map of the current potentials
+    PotentialMap *_potential;
+    bool _local_potential;
+
+    // The residual capacity map
+    CapacityArcMap _res_cap;
+    // The excess map
+    SupplyNodeMap _excess;
+    // The excess nodes (i.e. nodes with positive excess)
+    std::vector<Node> _excess_nodes;
+    // The deficit nodes (i.e. nodes with negative excess)
+    std::vector<Node> _deficit_nodes;
+
+    // The delta parameter used for capacity scaling
+    Capacity _delta;
+    // The maximum number of phases
+    int _phase_num;
+
+    // The pred arc map
+    PredMap _pred;
+    // Implementation of the Dijkstra algorithm for finding augmenting
+    // shortest paths in the residual network
+    ResidualDijkstra *_dijkstra;
+
+  public:
+
+    /// \brief General constructor (with lower bounds).
+    ///
+    /// General constructor (with lower bounds).
+    ///
+    /// \param digraph The digraph the algorithm runs on.
+    /// \param lower The lower bounds of the arcs.
+    /// \param capacity The capacities (upper bounds) of the arcs.
+    /// \param cost The cost (length) values of the arcs.
+    /// \param supply The supply values of the nodes (signed).
+    CapacityScaling( const Digraph &digraph,
+                     const LowerMap &lower,
+                     const CapacityMap &capacity,
+                     const CostMap &cost,
+                     const SupplyMap &supply ) :
+      _graph(digraph), _lower(&lower), _capacity(digraph), _cost(cost),
+      _supply(digraph), _flow(NULL), _local_flow(false),
+      _potential(NULL), _local_potential(false),
+      _res_cap(digraph), _excess(digraph), _pred(digraph), _dijkstra(NULL)
+    {
+      Supply sum = 0;
+      for (NodeIt n(_graph); n != INVALID; ++n) {
+        _supply[n] = supply[n];
+        _excess[n] = supply[n];
+        sum += supply[n];
+      }
+      _valid_supply = sum == 0;
+      for (ArcIt a(_graph); a != INVALID; ++a) {
+        _capacity[a] = capacity[a];
+        _res_cap[a] = capacity[a];
+      }
+
+      // Remove non-zero lower bounds
+      typename LowerMap::Value lcap;
+      for (ArcIt e(_graph); e != INVALID; ++e) {
+        if ((lcap = lower[e]) != 0) {
+          _capacity[e] -= lcap;
+          _res_cap[e] -= lcap;
+          _supply[_graph.source(e)] -= lcap;
+          _supply[_graph.target(e)] += lcap;
+          _excess[_graph.source(e)] -= lcap;
+          _excess[_graph.target(e)] += lcap;
+        }



More information about the Lemon-commits mailing list