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 48 line context
... ...
@@ -10,111 +10,149 @@
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_CAPACITY_SCALING_H
20 20
#define LEMON_CAPACITY_SCALING_H
21 21

	
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)
46 73
  /// can be given using separate functions, and the algorithm can be
47 74
  /// executed using the \ref run() function. If some parameters are not
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
81 121
      /// potentials (primal and dual solutions).
82 122
      OPTIMAL,
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;
109 147
    int _root;
110 148

	
111 149
    // Parameters of the problem
112 150
    bool _have_lower;
113 151
    Value _sum_supply;
114 152

	
115 153
    // Data structures for storing the digraph
116 154
    IntNodeMap _node_id;
117 155
    IntArcMap _arc_idf;
118 156
    IntArcMap _arc_idb;
119 157
    IntVector _first_out;
120 158
    BoolVector _forward;
... ...
@@ -134,76 +172,73 @@
134 172
    IntVector _excess_nodes;
135 173
    IntVector _deficit_nodes;
136 174

	
137 175
    Value _delta;
138 176
    int _phase_num;
139 177
    IntVector _pred;
140 178

	
141 179
  public:
142 180
  
143 181
    /// \brief Constant for infinite upper bounds (capacities).
144 182
    ///
145 183
    /// Constant for infinite upper bounds (capacities).
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();
198 233

	
199 234
          // Traverse outgoing residual arcs
200 235
          for (int a = _first_out[u]; a != _first_out[u+1]; ++a) {
201 236
            if (_res_cap[a] < delta) continue;
202 237
            v = _target[a];
203 238
            switch (heap.state(v)) {
204 239
              case Heap::PRE_HEAP:
205 240
                heap.push(v, d + _cost[a] - _pi[v]);
206 241
                _pred[v] = a;
207 242
                break;
208 243
              case Heap::IN_HEAP:
209 244
                dn = d + _cost[a] - _pi[v];
... ...
@@ -212,48 +247,74 @@
212 247
                  _pred[v] = a;
213 248
                }
214 249
                break;
215 250
              case Heap::POST_HEAP:
216 251
                break;
217 252
            }
218 253
          }
219 254
        }
220 255
        if (heap.empty()) return -1;
221 256

	
222 257
        // Update potentials of processed nodes
223 258
        int t = heap.top();
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
248 309
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
249 310
        "The flow type of CapacityScaling must be signed");
250 311
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
251 312
        "The cost type of CapacityScaling must be signed");
252 313

	
253 314
      // Resize vectors
254 315
      _node_num = countNodes(_graph);
255 316
      _arc_num = countArcs(_graph);
256 317
      _res_arc_num = 2 * (_arc_num + _node_num);
257 318
      _root = _node_num;
258 319
      ++_node_num;
259 320

	
... ...
@@ -410,48 +471,49 @@
410 471
    /// calling \ref run(), the supply of each node will be set to zero.
411 472
    ///
412 473
    /// Using this function has the same effect as using \ref supplyMap()
413 474
    /// with such a map in which \c k is assigned to \c s, \c -k is
414 475
    /// assigned to \c t and all other nodes have zero supply value.
415 476
    ///
416 477
    /// \param s The source node.
417 478
    /// \param t The target node.
418 479
    /// \param k The required amount of flow from node \c s to node \c t
419 480
    /// (i.e. the supply of \c s and the demand of \c t).
420 481
    ///
421 482
    /// \return <tt>(*this)</tt>
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)
446 508
    ///     .supplyMap(sup).run();
447 509
    /// \endcode
448 510
    ///
449 511
    /// This function can be called more than once. All the parameters
450 512
    /// that have been given are kept for the next call, unless
451 513
    /// \ref reset() is called, thus only the modified parameters
452 514
    /// have to be set again. See \ref reset() for examples.
453 515
    /// However the underlying digraph must not be modified after this
454 516
    /// class have been constructed, since it copies the digraph.
455 517
    ///
456 518
    /// \param scaling Enable or disable capacity scaling.
457 519
    /// If the maximum upper bound and/or the amount of total supply
... ...
@@ -726,49 +788,49 @@
726 788
        pt = startWithScaling();
727 789
      else
728 790
        pt = startWithoutScaling();
729 791

	
730 792
      // Handle non-zero lower bounds
731 793
      if (_have_lower) {
732 794
        for (int j = 0; j != _res_arc_num - _node_num + 1; ++j) {
733 795
          if (!_forward[j]) _res_cap[j] += _lower[j];
734 796
        }
735 797
      }
736 798

	
737 799
      // Shift potentials if necessary
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) {
763 825
              _excess[u] -= rc;
764 826
              _excess[v] += rc;
765 827
              _res_cap[a] = 0;
766 828
              _res_cap[_reverse[a]] += rc;
767 829
            }
768 830
          }
769 831
        }
770 832

	
771 833
        // Find excess nodes and deficit nodes
772 834
        _excess_nodes.clear();
773 835
        _deficit_nodes.clear();
774 836
        for (int u = 0; u != _node_num; ++u) {
0 comments (0 inline)