gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Traits class + a named parameter for CapacityScaling (#180) to specify the heap used in internal Dijkstra computations.
0 1 0
default
1 file changed with 72 insertions and 10 deletions:
↑ Collapse diff ↑
Ignore white space 24 line context
... ...
@@ -22,24 +22,51 @@
22 22
/// \ingroup min_cost_flow_algs
23 23
///
24 24
/// \file
25 25
/// \brief Capacity Scaling algorithm for finding a minimum cost flow.
26 26

	
27 27
#include <vector>
28 28
#include <limits>
29 29
#include <lemon/core.h>
30 30
#include <lemon/bin_heap.h>
31 31

	
32 32
namespace lemon {
33 33

	
34
  /// \brief Default traits class of CapacityScaling algorithm.
35
  ///
36
  /// Default traits class of CapacityScaling algorithm.
37
  /// \tparam GR Digraph type.
38
  /// \tparam V The value type used for flow amounts, capacity bounds
39
  /// and supply values. By default it is \c int.
40
  /// \tparam C The value type used for costs and potentials.
41
  /// By default it is the same as \c V.
42
  template <typename GR, typename V = int, typename C = V>
43
  struct CapacityScalingDefaultTraits
44
  {
45
    /// The type of the digraph
46
    typedef GR Digraph;
47
    /// The type of the flow amounts, capacity bounds and supply values
48
    typedef V Value;
49
    /// The type of the arc costs
50
    typedef C Cost;
51

	
52
    /// \brief The type of the heap used for internal Dijkstra computations.
53
    ///
54
    /// The type of the heap used for internal Dijkstra computations.
55
    /// It must conform to the \ref lemon::concepts::Heap "Heap" concept,
56
    /// its priority type must be \c Cost and its cross reference type
57
    /// must be \ref RangeMap "RangeMap<int>".
58
    typedef BinHeap<Cost, RangeMap<int> > Heap;
59
  };
60

	
34 61
  /// \addtogroup min_cost_flow_algs
35 62
  /// @{
36 63

	
37 64
  /// \brief Implementation of the Capacity Scaling algorithm for
38 65
  /// finding a \ref min_cost_flow "minimum cost flow".
39 66
  ///
40 67
  /// \ref CapacityScaling implements the capacity scaling version
41 68
  /// of the successive shortest path algorithm for finding a
42 69
  /// \ref min_cost_flow "minimum cost flow". It is an efficient dual
43 70
  /// solution method.
44 71
  ///
45 72
  /// Most of the parameters of the problem (except for the digraph)
... ...
@@ -48,33 +75,46 @@
48 75
  /// specified, then default values will be used.
49 76
  ///
50 77
  /// \tparam GR The digraph type the algorithm runs on.
51 78
  /// \tparam V The value type used for flow amounts, capacity bounds
52 79
  /// and supply values in the algorithm. By default it is \c int.
53 80
  /// \tparam C The value type used for costs and potentials in the
54 81
  /// algorithm. By default it is the same as \c V.
55 82
  ///
56 83
  /// \warning Both value types must be signed and all input data must
57 84
  /// be integer.
58 85
  /// \warning This algorithm does not support negative costs for such
59 86
  /// arcs that have infinite upper bound.
60
  template <typename GR, typename V = int, typename C = V>
87
#ifdef DOXYGEN
88
  template <typename GR, typename V, typename C, typename TR>
89
#else
90
  template < typename GR, typename V = int, typename C = V,
91
             typename TR = CapacityScalingDefaultTraits<GR, V, C> >
92
#endif
61 93
  class CapacityScaling
62 94
  {
63 95
  public:
64 96

	
97
    /// The type of the digraph
98
    typedef typename TR::Digraph Digraph;
65 99
    /// The type of the flow amounts, capacity bounds and supply values
66
    typedef V Value;
100
    typedef typename TR::Value Value;
67 101
    /// The type of the arc costs
68
    typedef C Cost;
102
    typedef typename TR::Cost Cost;
103

	
104
    /// The type of the heap used for internal Dijkstra computations
105
    typedef typename TR::Heap Heap;
106

	
107
    /// The \ref CapacityScalingDefaultTraits "traits class" of the algorithm
108
    typedef TR Traits;
69 109

	
70 110
  public:
71 111

	
72 112
    /// \brief Problem type constants for the \c run() function.
73 113
    ///
74 114
    /// Enum type containing the problem type constants that can be
75 115
    /// returned by the \ref run() function of the algorithm.
76 116
    enum ProblemType {
77 117
      /// The problem has no feasible solution (flow).
78 118
      INFEASIBLE,
79 119
      /// The problem has optimal solution (i.e. it is feasible and
80 120
      /// bounded), and the algorithm has found optimal flow and node
... ...
@@ -83,26 +123,24 @@
83 123
      /// The digraph contains an arc of negative cost and infinite
84 124
      /// upper bound. It means that the objective function is unbounded
85 125
      /// on that arc, however note that it could actually be bounded
86 126
      /// over the feasible flows, but this algroithm cannot handle
87 127
      /// these cases.
88 128
      UNBOUNDED
89 129
    };
90 130
  
91 131
  private:
92 132

	
93 133
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
94 134

	
95
    typedef std::vector<Arc> ArcVector;
96
    typedef std::vector<Node> NodeVector;
97 135
    typedef std::vector<int> IntVector;
98 136
    typedef std::vector<bool> BoolVector;
99 137
    typedef std::vector<Value> ValueVector;
100 138
    typedef std::vector<Cost> CostVector;
101 139

	
102 140
  private:
103 141

	
104 142
    // Data related to the underlying digraph
105 143
    const GR &_graph;
106 144
    int _node_num;
107 145
    int _arc_num;
108 146
    int _res_arc_num;
... ...
@@ -146,52 +184,49 @@
146 184
    /// It is \c std::numeric_limits<Value>::infinity() if available,
147 185
    /// \c std::numeric_limits<Value>::max() otherwise.
148 186
    const Value INF;
149 187

	
150 188
  private:
151 189

	
152 190
    // Special implementation of the Dijkstra algorithm for finding
153 191
    // shortest paths in the residual network of the digraph with
154 192
    // respect to the reduced arc costs and modifying the node
155 193
    // potentials according to the found distance labels.
156 194
    class ResidualDijkstra
157 195
    {
158
      typedef RangeMap<int> HeapCrossRef;
159
      typedef BinHeap<Cost, HeapCrossRef> Heap;
160

	
161 196
    private:
162 197

	
163 198
      int _node_num;
164 199
      const IntVector &_first_out;
165 200
      const IntVector &_target;
166 201
      const CostVector &_cost;
167 202
      const ValueVector &_res_cap;
168 203
      const ValueVector &_excess;
169 204
      CostVector &_pi;
170 205
      IntVector &_pred;
171 206
      
172 207
      IntVector _proc_nodes;
173 208
      CostVector _dist;
174 209
      
175 210
    public:
176 211

	
177 212
      ResidualDijkstra(CapacityScaling& cs) :
178 213
        _node_num(cs._node_num), _first_out(cs._first_out), 
179 214
        _target(cs._target), _cost(cs._cost), _res_cap(cs._res_cap),
180 215
        _excess(cs._excess), _pi(cs._pi), _pred(cs._pred),
181 216
        _dist(cs._node_num)
182 217
      {}
183 218

	
184 219
      int run(int s, Value delta = 1) {
185
        HeapCrossRef heap_cross_ref(_node_num, Heap::PRE_HEAP);
220
        RangeMap<int> heap_cross_ref(_node_num, Heap::PRE_HEAP);
186 221
        Heap heap(heap_cross_ref);
187 222
        heap.push(s, 0);
188 223
        _pred[s] = -1;
189 224
        _proc_nodes.clear();
190 225

	
191 226
        // Process nodes
192 227
        while (!heap.empty() && _excess[heap.top()] > -delta) {
193 228
          int u = heap.top(), v;
194 229
          Cost d = heap.prio() + _pi[u], dn;
195 230
          _dist[u] = heap.prio();
196 231
          _proc_nodes.push_back(u);
197 232
          heap.pop();
... ...
@@ -224,24 +259,50 @@
224 259
        Cost dt = heap.prio();
225 260
        for (int i = 0; i < int(_proc_nodes.size()); ++i) {
226 261
          _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - dt;
227 262
        }
228 263

	
229 264
        return t;
230 265
      }
231 266

	
232 267
    }; //class ResidualDijkstra
233 268

	
234 269
  public:
235 270

	
271
    /// \name Named Template Parameters
272
    /// @{
273

	
274
    template <typename T>
275
    struct SetHeapTraits : public Traits {
276
      typedef T Heap;
277
    };
278

	
279
    /// \brief \ref named-templ-param "Named parameter" for setting
280
    /// \c Heap type.
281
    ///
282
    /// \ref named-templ-param "Named parameter" for setting \c Heap
283
    /// type, which is used for internal Dijkstra computations.
284
    /// It must conform to the \ref lemon::concepts::Heap "Heap" concept,
285
    /// its priority type must be \c Cost and its cross reference type
286
    /// must be \ref RangeMap "RangeMap<int>".
287
    template <typename T>
288
    struct SetHeap
289
      : public CapacityScaling<GR, V, C, SetHeapTraits<T> > {
290
      typedef  CapacityScaling<GR, V, C, SetHeapTraits<T> > Create;
291
    };
292

	
293
    /// @}
294

	
295
  public:
296

	
236 297
    /// \brief Constructor.
237 298
    ///
238 299
    /// The constructor of the class.
239 300
    ///
240 301
    /// \param graph The digraph the algorithm runs on.
241 302
    CapacityScaling(const GR& graph) :
242 303
      _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
243 304
      INF(std::numeric_limits<Value>::has_infinity ?
244 305
          std::numeric_limits<Value>::infinity() :
245 306
          std::numeric_limits<Value>::max())
246 307
    {
247 308
      // Check the value types
... ...
@@ -422,24 +483,25 @@
422 483
    CapacityScaling& stSupply(const Node& s, const Node& t, Value k) {
423 484
      for (int i = 0; i != _node_num; ++i) {
424 485
        _supply[i] = 0;
425 486
      }
426 487
      _supply[_node_id[s]] =  k;
427 488
      _supply[_node_id[t]] = -k;
428 489
      return *this;
429 490
    }
430 491
    
431 492
    /// @}
432 493

	
433 494
    /// \name Execution control
495
    /// The algorithm can be executed using \ref run().
434 496

	
435 497
    /// @{
436 498

	
437 499
    /// \brief Run the algorithm.
438 500
    ///
439 501
    /// This function runs the algorithm.
440 502
    /// The paramters can be specified using functions \ref lowerMap(),
441 503
    /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
442 504
    /// For example,
443 505
    /// \code
444 506
    ///   CapacityScaling<ListDigraph> cs(graph);
445 507
    ///   cs.lowerMap(lower).upperMap(upper).costMap(cost)
... ...
@@ -738,25 +800,25 @@
738 800
      Cost pr = _pi[_root];
739 801
      if (_sum_supply < 0 || pr > 0) {
740 802
        for (int i = 0; i != _node_num; ++i) {
741 803
          _pi[i] -= pr;
742 804
        }        
743 805
      }
744 806
      
745 807
      return pt;
746 808
    }
747 809

	
748 810
    // Execute the capacity scaling algorithm
749 811
    ProblemType startWithScaling() {
750
      // Process capacity scaling phases
812
      // Perform capacity scaling phases
751 813
      int s, t;
752 814
      int phase_cnt = 0;
753 815
      int factor = 4;
754 816
      ResidualDijkstra _dijkstra(*this);
755 817
      while (true) {
756 818
        // Saturate all arcs not satisfying the optimality condition
757 819
        for (int u = 0; u != _node_num; ++u) {
758 820
          for (int a = _first_out[u]; a != _first_out[u+1]; ++a) {
759 821
            int v = _target[a];
760 822
            Cost c = _cost[a] + _pi[u] - _pi[v];
761 823
            Value rc = _res_cap[a];
762 824
            if (c < 0 && rc >= _delta) {
0 comments (0 inline)