gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add traits class + named parameters to Suurballe (#323) The following types can be modified using named parameters: - FlowMap - PotentialMap - Path - Heap + HeapCrossRef
0 2 0
default
2 files changed with 146 insertions and 21 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
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_SUURBALLE_H
20 20
#define LEMON_SUURBALLE_H
21 21

	
22 22
///\ingroup shortest_path
23 23
///\file
24 24
///\brief An algorithm for finding arc-disjoint paths between two
25 25
/// nodes having minimum total length.
26 26

	
27 27
#include <vector>
28 28
#include <limits>
29 29
#include <lemon/bin_heap.h>
30 30
#include <lemon/path.h>
31 31
#include <lemon/list_graph.h>
32 32
#include <lemon/dijkstra.h>
33 33
#include <lemon/maps.h>
34 34

	
35 35
namespace lemon {
36 36

	
37
  /// \brief Default traits class of Suurballe algorithm.
38
  ///
39
  /// Default traits class of Suurballe algorithm.
40
  /// \tparam GR The digraph type the algorithm runs on.
41
  /// \tparam LEN The type of the length map.
42
  /// The default value is <tt>GR::ArcMap<int></tt>.
43
#ifdef DOXYGEN
44
  template <typename GR, typename LEN>
45
#else
46
  template < typename GR,
47
             typename LEN = typename GR::template ArcMap<int> >
48
#endif
49
  struct SuurballeDefaultTraits
50
  {
51
    /// The type of the digraph.
52
    typedef GR Digraph;
53
    /// The type of the length map.
54
    typedef LEN LengthMap;
55
    /// The type of the lengths.
56
    typedef typename LEN::Value Length;
57
    /// The type of the flow map.
58
    typedef typename GR::template ArcMap<int> FlowMap;
59
    /// The type of the potential map.
60
    typedef typename GR::template NodeMap<Length> PotentialMap;
61

	
62
    /// \brief The path type
63
    ///
64
    /// The type used for storing the found arc-disjoint paths.
65
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
66
    /// and it must have an \c addBack() function.
67
    typedef lemon::Path<Digraph> Path;
68
    
69
    /// The cross reference type used for the heap.
70
    typedef typename GR::template NodeMap<int> HeapCrossRef;
71

	
72
    /// \brief The heap type used for internal Dijkstra computations.
73
    ///
74
    /// The type of the heap used for internal Dijkstra computations.
75
    /// It must conform to the \ref lemon::concepts::Heap "Heap" concept
76
    /// and its priority type must be \c Length.
77
    typedef BinHeap<Length, HeapCrossRef> Heap;
78
  };
79

	
37 80
  /// \addtogroup shortest_path
38 81
  /// @{
39 82

	
40 83
  /// \brief Algorithm for finding arc-disjoint paths between two nodes
41 84
  /// having minimum total length.
42 85
  ///
43 86
  /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
44 87
  /// finding arc-disjoint paths having minimum total length (cost)
45 88
  /// from a given source node to a given target node in a digraph.
46 89
  ///
47 90
  /// Note that this problem is a special case of the \ref min_cost_flow
48 91
  /// "minimum cost flow problem". This implementation is actually an
49 92
  /// efficient specialized version of the \ref CapacityScaling
50 93
  /// "successive shortest path" algorithm directly for this problem.
51 94
  /// Therefore this class provides query functions for flow values and
52 95
  /// node potentials (the dual solution) just like the minimum cost flow
53 96
  /// algorithms.
54 97
  ///
55 98
  /// \tparam GR The digraph type the algorithm runs on.
56 99
  /// \tparam LEN The type of the length map.
57 100
  /// The default value is <tt>GR::ArcMap<int></tt>.
58 101
  ///
59 102
  /// \warning Length values should be \e non-negative.
60 103
  ///
61 104
  /// \note For finding \e node-disjoint paths, this algorithm can be used
62 105
  /// along with the \ref SplitNodes adaptor.
63 106
#ifdef DOXYGEN
64
  template <typename GR, typename LEN>
107
  template <typename GR, typename LEN, typename TR>
65 108
#else
66 109
  template < typename GR,
67
             typename LEN = typename GR::template ArcMap<int> >
110
             typename LEN = typename GR::template ArcMap<int>,
111
             typename TR = SuurballeDefaultTraits<GR, LEN> >
68 112
#endif
69 113
  class Suurballe
70 114
  {
71 115
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
72 116

	
73 117
    typedef ConstMap<Arc, int> ConstArcMap;
74 118
    typedef typename GR::template NodeMap<Arc> PredMap;
75 119

	
76 120
  public:
77 121

	
78
    /// The type of the digraph the algorithm runs on.
79
    typedef GR Digraph;
122
    /// The type of the digraph.
123
    typedef typename TR::Digraph Digraph;
80 124
    /// The type of the length map.
81
    typedef LEN LengthMap;
125
    typedef typename TR::LengthMap LengthMap;
82 126
    /// The type of the lengths.
83
    typedef typename LengthMap::Value Length;
84
#ifdef DOXYGEN
127
    typedef typename TR::Length Length;
128

	
85 129
    /// The type of the flow map.
86
    typedef GR::ArcMap<int> FlowMap;
130
    typedef typename TR::FlowMap FlowMap;
87 131
    /// The type of the potential map.
88
    typedef GR::NodeMap<Length> PotentialMap;
89
#else
90
    /// The type of the flow map.
91
    typedef typename Digraph::template ArcMap<int> FlowMap;
92
    /// The type of the potential map.
93
    typedef typename Digraph::template NodeMap<Length> PotentialMap;
94
#endif
132
    typedef typename TR::PotentialMap PotentialMap;
133
    /// The type of the path structures.
134
    typedef typename TR::Path Path;
135
    /// The cross reference type used for the heap.
136
    typedef typename TR::HeapCrossRef HeapCrossRef;
137
    /// The heap type used for internal Dijkstra computations.
138
    typedef typename TR::Heap Heap;
95 139

	
96
    /// The type of the path structures.
97
    typedef SimplePath<GR> Path;
140
    /// The \ref SuurballeDefaultTraits "traits class" of the algorithm.
141
    typedef TR Traits;
98 142

	
99 143
  private:
100 144

	
101
    typedef typename Digraph::template NodeMap<int> HeapCrossRef;
102
    typedef BinHeap<Length, HeapCrossRef> Heap;
103

	
104 145
    // ResidualDijkstra is a special implementation of the
105 146
    // Dijkstra algorithm for finding shortest paths in the
106 147
    // residual network with respect to the reduced arc lengths
107 148
    // and modifying the node potentials according to the
108 149
    // distance of the nodes.
109 150
    class ResidualDijkstra
110 151
    {
111 152
    private:
112 153

	
113 154
      const Digraph &_graph;
114 155
      const LengthMap &_length;
115 156
      const FlowMap &_flow;
116 157
      PotentialMap &_pi;
117 158
      PredMap &_pred;
118 159
      Node _s;
119 160
      Node _t;
120 161
      
121 162
      PotentialMap _dist;
122 163
      std::vector<Node> _proc_nodes;
123 164

	
124 165
    public:
125 166

	
126 167
      // Constructor
127 168
      ResidualDijkstra(Suurballe &srb) :
128 169
        _graph(srb._graph), _length(srb._length),
129 170
        _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred), 
130 171
        _s(srb._s), _t(srb._t), _dist(_graph) {}
131 172
        
132 173
      // Run the algorithm and return true if a path is found
133 174
      // from the source node to the target node.
134 175
      bool run(int cnt) {
135 176
        return cnt == 0 ? startFirst() : start();
136 177
      }
137 178

	
138 179
    private:
139 180
    
140 181
      // Execute the algorithm for the first time (the flow and potential
141 182
      // functions have to be identically zero).
142 183
      bool startFirst() {
143 184
        HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
144 185
        Heap heap(heap_cross_ref);
145 186
        heap.push(_s, 0);
146 187
        _pred[_s] = INVALID;
147 188
        _proc_nodes.clear();
148 189

	
149 190
        // Process nodes
150 191
        while (!heap.empty() && heap.top() != _t) {
151 192
          Node u = heap.top(), v;
152 193
          Length d = heap.prio(), dn;
153 194
          _dist[u] = heap.prio();
154 195
          _proc_nodes.push_back(u);
155 196
          heap.pop();
156 197

	
157 198
          // Traverse outgoing arcs
158 199
          for (OutArcIt e(_graph, u); e != INVALID; ++e) {
159 200
            v = _graph.target(e);
160 201
            switch(heap.state(v)) {
161 202
              case Heap::PRE_HEAP:
162 203
                heap.push(v, d + _length[e]);
163 204
                _pred[v] = e;
164 205
                break;
165 206
              case Heap::IN_HEAP:
166 207
                dn = d + _length[e];
167 208
                if (dn < heap[v]) {
168 209
                  heap.decrease(v, dn);
169 210
                  _pred[v] = e;
170 211
                }
171 212
                break;
172 213
              case Heap::POST_HEAP:
173 214
                break;
174 215
            }
175 216
          }
176 217
        }
177 218
        if (heap.empty()) return false;
178 219

	
179 220
        // Update potentials of processed nodes
180 221
        Length t_dist = heap.prio();
181 222
        for (int i = 0; i < int(_proc_nodes.size()); ++i)
182 223
          _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
183 224
        return true;
184 225
      }
185 226

	
186 227
      // Execute the algorithm.
187 228
      bool start() {
188 229
        HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
189 230
        Heap heap(heap_cross_ref);
190 231
        heap.push(_s, 0);
191 232
        _pred[_s] = INVALID;
192 233
        _proc_nodes.clear();
193 234

	
194 235
        // Process nodes
195 236
        while (!heap.empty() && heap.top() != _t) {
196 237
          Node u = heap.top(), v;
197 238
          Length d = heap.prio() + _pi[u], dn;
198 239
          _dist[u] = heap.prio();
199 240
          _proc_nodes.push_back(u);
200 241
          heap.pop();
201 242

	
202 243
          // Traverse outgoing arcs
203 244
          for (OutArcIt e(_graph, u); e != INVALID; ++e) {
204 245
            if (_flow[e] == 0) {
205 246
              v = _graph.target(e);
206 247
              switch(heap.state(v)) {
207 248
                case Heap::PRE_HEAP:
208 249
                  heap.push(v, d + _length[e] - _pi[v]);
209 250
                  _pred[v] = e;
210 251
                  break;
211 252
                case Heap::IN_HEAP:
212 253
                  dn = d + _length[e] - _pi[v];
213 254
                  if (dn < heap[v]) {
214 255
                    heap.decrease(v, dn);
215 256
                    _pred[v] = e;
216 257
                  }
217 258
                  break;
218 259
                case Heap::POST_HEAP:
219 260
                  break;
220 261
              }
221 262
            }
222 263
          }
223 264

	
224 265
          // Traverse incoming arcs
225 266
          for (InArcIt e(_graph, u); e != INVALID; ++e) {
226 267
            if (_flow[e] == 1) {
227 268
              v = _graph.source(e);
228 269
              switch(heap.state(v)) {
229 270
                case Heap::PRE_HEAP:
230 271
                  heap.push(v, d - _length[e] - _pi[v]);
231 272
                  _pred[v] = e;
232 273
                  break;
233 274
                case Heap::IN_HEAP:
234 275
                  dn = d - _length[e] - _pi[v];
235 276
                  if (dn < heap[v]) {
236 277
                    heap.decrease(v, dn);
237 278
                    _pred[v] = e;
238 279
                  }
239 280
                  break;
240 281
                case Heap::POST_HEAP:
241 282
                  break;
242 283
              }
243 284
            }
244 285
          }
245 286
        }
246 287
        if (heap.empty()) return false;
247 288

	
248 289
        // Update potentials of processed nodes
249 290
        Length t_dist = heap.prio();
250 291
        for (int i = 0; i < int(_proc_nodes.size()); ++i)
251 292
          _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
252 293
        return true;
253 294
      }
254 295

	
255 296
    }; //class ResidualDijkstra
256 297

	
298
  public:
299

	
300
    /// \name Named Template Parameters
301
    /// @{
302

	
303
    template <typename T>
304
    struct SetFlowMapTraits : public Traits {
305
      typedef T FlowMap;
306
    };
307

	
308
    /// \brief \ref named-templ-param "Named parameter" for setting
309
    /// \c FlowMap type.
310
    ///
311
    /// \ref named-templ-param "Named parameter" for setting
312
    /// \c FlowMap type.
313
    template <typename T>
314
    struct SetFlowMap
315
      : public Suurballe<GR, LEN, SetFlowMapTraits<T> > {
316
      typedef Suurballe<GR, LEN, SetFlowMapTraits<T> > Create;
317
    };
318

	
319
    template <typename T>
320
    struct SetPotentialMapTraits : public Traits {
321
      typedef T PotentialMap;
322
    };
323

	
324
    /// \brief \ref named-templ-param "Named parameter" for setting
325
    /// \c PotentialMap type.
326
    ///
327
    /// \ref named-templ-param "Named parameter" for setting
328
    /// \c PotentialMap type.
329
    template <typename T>
330
    struct SetPotentialMap
331
      : public Suurballe<GR, LEN, SetPotentialMapTraits<T> > {
332
      typedef Suurballe<GR, LEN, SetPotentialMapTraits<T> > Create;
333
    };
334

	
335
    template <typename T>
336
    struct SetPathTraits : public Traits {
337
      typedef T Path;
338
    };
339

	
340
    /// \brief \ref named-templ-param "Named parameter" for setting
341
    /// \c %Path type.
342
    ///
343
    /// \ref named-templ-param "Named parameter" for setting \c %Path type.
344
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
345
    /// and it must have an \c addBack() function.
346
    template <typename T>
347
    struct SetPath
348
      : public Suurballe<GR, LEN, SetPathTraits<T> > {
349
      typedef Suurballe<GR, LEN, SetPathTraits<T> > Create;
350
    };
351
    
352
    template <typename H, typename CR>
353
    struct SetHeapTraits : public Traits {
354
      typedef H Heap;
355
      typedef CR HeapCrossRef;
356
    };
357

	
358
    /// \brief \ref named-templ-param "Named parameter" for setting
359
    /// \c Heap and \c HeapCrossRef types.
360
    ///
361
    /// \ref named-templ-param "Named parameter" for setting \c Heap
362
    /// and \c HeapCrossRef types with automatic allocation. 
363
    /// They will be used for internal Dijkstra computations.
364
    /// The heap type must conform to the \ref lemon::concepts::Heap "Heap"
365
    /// concept and its priority type must be \c Length.
366
    template <typename H,
367
              typename CR = typename Digraph::template NodeMap<int> >
368
    struct SetHeap
369
      : public Suurballe<GR, LEN, SetHeapTraits<H, CR> > {
370
      typedef Suurballe<GR, LEN, SetHeapTraits<H, CR> > Create;
371
    };
372

	
373
    /// @}
374

	
257 375
  private:
258 376

	
259 377
    // The digraph the algorithm runs on
260 378
    const Digraph &_graph;
261 379
    // The length map
262 380
    const LengthMap &_length;
263 381

	
264 382
    // Arc map of the current flow
265 383
    FlowMap *_flow;
266 384
    bool _local_flow;
267 385
    // Node map of the current potentials
268 386
    PotentialMap *_potential;
269 387
    bool _local_potential;
270 388

	
271 389
    // The source node
272 390
    Node _s;
273 391
    // The target node
274 392
    Node _t;
275 393

	
276 394
    // Container to store the found paths
277 395
    std::vector<Path> _paths;
278 396
    int _path_num;
279 397

	
280 398
    // The pred arc map
281 399
    PredMap _pred;
282 400
    
283 401
    // Data for full init
284 402
    PotentialMap *_init_dist;
285 403
    PredMap *_init_pred;
286 404
    bool _full_init;
287 405

	
288 406
  public:
289 407

	
290 408
    /// \brief Constructor.
291 409
    ///
292 410
    /// Constructor.
293 411
    ///
294 412
    /// \param graph The digraph the algorithm runs on.
295 413
    /// \param length The length (cost) values of the arcs.
296 414
    Suurballe( const Digraph &graph,
297 415
               const LengthMap &length ) :
298 416
      _graph(graph), _length(length), _flow(0), _local_flow(false),
299 417
      _potential(0), _local_potential(false), _pred(graph),
300 418
      _init_dist(0), _init_pred(0)
301 419
    {}
302 420

	
303 421
    /// Destructor.
304 422
    ~Suurballe() {
305 423
      if (_local_flow) delete _flow;
306 424
      if (_local_potential) delete _potential;
307 425
      delete _init_dist;
308 426
      delete _init_pred;
309 427
    }
310 428

	
311 429
    /// \brief Set the flow map.
312 430
    ///
313 431
    /// This function sets the flow map.
314 432
    /// If it is not used before calling \ref run() or \ref init(),
315 433
    /// an instance will be allocated automatically. The destructor
316 434
    /// deallocates this automatically allocated map, of course.
317 435
    ///
318 436
    /// The found flow contains only 0 and 1 values, since it is the
319 437
    /// union of the found arc-disjoint paths.
320 438
    ///
321 439
    /// \return <tt>(*this)</tt>
322 440
    Suurballe& flowMap(FlowMap &map) {
323 441
      if (_local_flow) {
324 442
        delete _flow;
325 443
        _local_flow = false;
326 444
      }
327 445
      _flow = &map;
328 446
      return *this;
329 447
    }
330 448

	
331 449
    /// \brief Set the potential map.
332 450
    ///
333 451
    /// This function sets the potential map.
334 452
    /// If it is not used before calling \ref run() or \ref init(),
335 453
    /// an instance will be allocated automatically. The destructor
336 454
    /// deallocates this automatically allocated map, of course.
337 455
    ///
338 456
    /// The node potentials provide the dual solution of the underlying
339 457
    /// \ref min_cost_flow "minimum cost flow problem".
340 458
    ///
341 459
    /// \return <tt>(*this)</tt>
342 460
    Suurballe& potentialMap(PotentialMap &map) {
343 461
      if (_local_potential) {
344 462
        delete _potential;
345 463
        _local_potential = false;
346 464
      }
347 465
      _potential = &map;
348 466
      return *this;
349 467
    }
350 468

	
351 469
    /// \name Execution Control
352 470
    /// The simplest way to execute the algorithm is to call the run()
353 471
    /// function.\n
354 472
    /// If you need to execute the algorithm many times using the same
355 473
    /// source node, then you may call fullInit() once and start()
356 474
    /// for each target node.\n
357 475
    /// If you only need the flow that is the union of the found
358 476
    /// arc-disjoint paths, then you may call findFlow() instead of
359 477
    /// start().
360 478

	
361 479
    /// @{
362 480

	
363 481
    /// \brief Run the algorithm.
364 482
    ///
365 483
    /// This function runs the algorithm.
366 484
    ///
367 485
    /// \param s The source node.
368 486
    /// \param t The target node.
369 487
    /// \param k The number of paths to be found.
370 488
    ///
371 489
    /// \return \c k if there are at least \c k arc-disjoint paths from
372 490
    /// \c s to \c t in the digraph. Otherwise it returns the number of
373 491
    /// arc-disjoint paths found.
374 492
    ///
375 493
    /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
376 494
    /// just a shortcut of the following code.
377 495
    /// \code
378 496
    ///   s.init(s);
379 497
    ///   s.start(t, k);
380 498
    /// \endcode
381 499
    int run(const Node& s, const Node& t, int k = 2) {
382 500
      init(s);
383 501
      start(t, k);
384 502
      return _path_num;
385 503
    }
386 504

	
387 505
    /// \brief Initialize the algorithm.
388 506
    ///
389 507
    /// This function initializes the algorithm with the given source node.
390 508
    ///
391 509
    /// \param s The source node.
392 510
    void init(const Node& s) {
393 511
      _s = s;
394 512

	
395 513
      // Initialize maps
396 514
      if (!_flow) {
397 515
        _flow = new FlowMap(_graph);
398 516
        _local_flow = true;
399 517
      }
400 518
      if (!_potential) {
401 519
        _potential = new PotentialMap(_graph);
402 520
        _local_potential = true;
403 521
      }
404 522
      _full_init = false;
405 523
    }
406 524

	
407 525
    /// \brief Initialize the algorithm and perform Dijkstra.
408 526
    ///
409 527
    /// This function initializes the algorithm and performs a full
410 528
    /// Dijkstra search from the given source node. It makes consecutive
411 529
    /// executions of \ref start() "start(t, k)" faster, since they
412 530
    /// have to perform %Dijkstra only k-1 times.
413 531
    ///
414 532
    /// This initialization is usually worth using instead of \ref init()
415 533
    /// if the algorithm is executed many times using the same source node.
416 534
    ///
417 535
    /// \param s The source node.
418 536
    void fullInit(const Node& s) {
419 537
      // Initialize maps
420 538
      init(s);
421 539
      if (!_init_dist) {
422 540
        _init_dist = new PotentialMap(_graph);
423 541
      }
424 542
      if (!_init_pred) {
425 543
        _init_pred = new PredMap(_graph);
426 544
      }
427 545

	
428 546
      // Run a full Dijkstra
429 547
      typename Dijkstra<Digraph, LengthMap>
430 548
        ::template SetStandardHeap<Heap>
431 549
        ::template SetDistMap<PotentialMap>
432 550
        ::template SetPredMap<PredMap>
433 551
        ::Create dijk(_graph, _length);
434 552
      dijk.distMap(*_init_dist).predMap(*_init_pred);
435 553
      dijk.run(s);
436 554
      
437 555
      _full_init = true;
438 556
    }
439 557

	
440 558
    /// \brief Execute the algorithm.
441 559
    ///
442 560
    /// This function executes the algorithm.
443 561
    ///
444 562
    /// \param t The target node.
445 563
    /// \param k The number of paths to be found.
446 564
    ///
447 565
    /// \return \c k if there are at least \c k arc-disjoint paths from
448 566
    /// \c s to \c t in the digraph. Otherwise it returns the number of
449 567
    /// arc-disjoint paths found.
450 568
    ///
451 569
    /// \note Apart from the return value, <tt>s.start(t, k)</tt> is
452 570
    /// just a shortcut of the following code.
453 571
    /// \code
454 572
    ///   s.findFlow(t, k);
455 573
    ///   s.findPaths();
456 574
    /// \endcode
457 575
    int start(const Node& t, int k = 2) {
458 576
      findFlow(t, k);
459 577
      findPaths();
460 578
      return _path_num;
461 579
    }
462 580

	
463 581
    /// \brief Execute the algorithm to find an optimal flow.
464 582
    ///
465 583
    /// This function executes the successive shortest path algorithm to
466 584
    /// find a minimum cost flow, which is the union of \c k (or less)
467 585
    /// arc-disjoint paths.
468 586
    ///
469 587
    /// \param t The target node.
470 588
    /// \param k The number of paths to be found.
471 589
    ///
472 590
    /// \return \c k if there are at least \c k arc-disjoint paths from
473 591
    /// the source node to the given node \c t in the digraph.
474 592
    /// Otherwise it returns the number of arc-disjoint paths found.
475 593
    ///
476 594
    /// \pre \ref init() must be called before using this function.
477 595
    int findFlow(const Node& t, int k = 2) {
478 596
      _t = t;
479 597
      ResidualDijkstra dijkstra(*this);
480 598
      
481 599
      // Initialization
482 600
      for (ArcIt e(_graph); e != INVALID; ++e) {
483 601
        (*_flow)[e] = 0;
484 602
      }
485 603
      if (_full_init) {
486 604
        for (NodeIt n(_graph); n != INVALID; ++n) {
487 605
          (*_potential)[n] = (*_init_dist)[n];
488 606
        }
489 607
        Node u = _t;
490 608
        Arc e;
491 609
        while ((e = (*_init_pred)[u]) != INVALID) {
492 610
          (*_flow)[e] = 1;
493 611
          u = _graph.source(e);
494 612
        }        
495 613
        _path_num = 1;
496 614
      } else {
497 615
        for (NodeIt n(_graph); n != INVALID; ++n) {
498 616
          (*_potential)[n] = 0;
499 617
        }
500 618
        _path_num = 0;
501 619
      }
502 620

	
503 621
      // Find shortest paths
504 622
      while (_path_num < k) {
505 623
        // Run Dijkstra
506 624
        if (!dijkstra.run(_path_num)) break;
507 625
        ++_path_num;
508 626

	
509 627
        // Set the flow along the found shortest path
510 628
        Node u = _t;
511 629
        Arc e;
512 630
        while ((e = _pred[u]) != INVALID) {
Ignore white space 512 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
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
#include <iostream>
20 20

	
21 21
#include <lemon/list_graph.h>
22 22
#include <lemon/lgf_reader.h>
23 23
#include <lemon/path.h>
24 24
#include <lemon/suurballe.h>
25 25
#include <lemon/concepts/digraph.h>
26
#include <lemon/concepts/heap.h>
26 27

	
27 28
#include "test_tools.h"
28 29

	
29 30
using namespace lemon;
30 31

	
31 32
char test_lgf[] =
32 33
  "@nodes\n"
33 34
  "label\n"
34 35
  "1\n"
35 36
  "2\n"
36 37
  "3\n"
37 38
  "4\n"
38 39
  "5\n"
39 40
  "6\n"
40 41
  "7\n"
41 42
  "8\n"
42 43
  "9\n"
43 44
  "10\n"
44 45
  "11\n"
45 46
  "12\n"
46 47
  "@arcs\n"
47 48
  "      length\n"
48 49
  " 1  2  70\n"
49 50
  " 1  3 150\n"
50 51
  " 1  4  80\n"
51 52
  " 2  8  80\n"
52 53
  " 3  5 140\n"
53 54
  " 4  6  60\n"
54 55
  " 4  7  80\n"
55 56
  " 4  8 110\n"
56 57
  " 5  7  60\n"
57 58
  " 5 11 120\n"
58 59
  " 6  3   0\n"
59 60
  " 6  9 140\n"
60 61
  " 6 10  90\n"
61 62
  " 7  1  30\n"
62 63
  " 8 12  60\n"
63 64
  " 9 12  50\n"
64 65
  "10 12  70\n"
65 66
  "10  2 100\n"
66 67
  "10  7  60\n"
67 68
  "11 10  20\n"
68 69
  "12 11  30\n"
69 70
  "@attributes\n"
70 71
  "source  1\n"
71 72
  "target 12\n"
72 73
  "@end\n";
73 74

	
74 75
// Check the interface of Suurballe
75 76
void checkSuurballeCompile()
76 77
{
77 78
  typedef int VType;
78 79
  typedef concepts::Digraph Digraph;
79 80

	
80 81
  typedef Digraph::Node Node;
81 82
  typedef Digraph::Arc Arc;
82 83
  typedef concepts::ReadMap<Arc, VType> LengthMap;
83 84
  
84
  typedef Suurballe<Digraph, LengthMap> SuurballeType;
85
  typedef Suurballe<Digraph, LengthMap> ST;
86
  typedef Suurballe<Digraph, LengthMap>
87
    ::SetFlowMap<ST::FlowMap>
88
    ::SetPotentialMap<ST::PotentialMap>
89
    ::SetPath<SimplePath<Digraph> >
90
    ::SetHeap<concepts::Heap<VType, Digraph::NodeMap<int> > >
91
    ::Create SuurballeType;
85 92

	
86 93
  Digraph g;
87 94
  Node n;
88 95
  Arc e;
89 96
  LengthMap len;
90 97
  SuurballeType::FlowMap flow(g);
91 98
  SuurballeType::PotentialMap pi(g);
92 99

	
93 100
  SuurballeType suurb_test(g, len);
94 101
  const SuurballeType& const_suurb_test = suurb_test;
95 102

	
96 103
  suurb_test
97 104
    .flowMap(flow)
98 105
    .potentialMap(pi);
99 106

	
100 107
  int k;
101 108
  k = suurb_test.run(n, n);
102 109
  k = suurb_test.run(n, n, k);
103 110
  suurb_test.init(n);
104 111
  suurb_test.fullInit(n);
105 112
  suurb_test.start(n);
106 113
  suurb_test.start(n, k);
107 114
  k = suurb_test.findFlow(n);
108 115
  k = suurb_test.findFlow(n, k);
109 116
  suurb_test.findPaths();
110 117
  
111 118
  int f;
112 119
  VType c;
113 120
  c = const_suurb_test.totalLength();
114 121
  f = const_suurb_test.flow(e);
115 122
  const SuurballeType::FlowMap& fm =
116 123
    const_suurb_test.flowMap();
117 124
  c = const_suurb_test.potential(n);
118 125
  const SuurballeType::PotentialMap& pm =
119 126
    const_suurb_test.potentialMap();
120 127
  k = const_suurb_test.pathNum();
121 128
  Path<Digraph> p = const_suurb_test.path(k);
122 129
  
123 130
  ignore_unused_variable_warning(fm);
124 131
  ignore_unused_variable_warning(pm);
125 132
}
126 133

	
127 134
// Check the feasibility of the flow
128 135
template <typename Digraph, typename FlowMap>
129 136
bool checkFlow( const Digraph& gr, const FlowMap& flow,
130 137
                typename Digraph::Node s, typename Digraph::Node t,
131 138
                int value )
132 139
{
133 140
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
134 141
  for (ArcIt e(gr); e != INVALID; ++e)
135 142
    if (!(flow[e] == 0 || flow[e] == 1)) return false;
136 143

	
137 144
  for (NodeIt n(gr); n != INVALID; ++n) {
138 145
    int sum = 0;
139 146
    for (OutArcIt e(gr, n); e != INVALID; ++e)
140 147
      sum += flow[e];
141 148
    for (InArcIt e(gr, n); e != INVALID; ++e)
142 149
      sum -= flow[e];
143 150
    if (n == s && sum != value) return false;
144 151
    if (n == t && sum != -value) return false;
145 152
    if (n != s && n != t && sum != 0) return false;
146 153
  }
147 154

	
148 155
  return true;
149 156
}
150 157

	
151 158
// Check the optimalitiy of the flow
152 159
template < typename Digraph, typename CostMap,
153 160
           typename FlowMap, typename PotentialMap >
154 161
bool checkOptimality( const Digraph& gr, const CostMap& cost,
155 162
                      const FlowMap& flow, const PotentialMap& pi )
156 163
{
157 164
  // Check the "Complementary Slackness" optimality condition
158 165
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
159 166
  bool opt = true;
160 167
  for (ArcIt e(gr); e != INVALID; ++e) {
161 168
    typename CostMap::Value red_cost =
162 169
      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
163 170
    opt = (flow[e] == 0 && red_cost >= 0) ||
164 171
          (flow[e] == 1 && red_cost <= 0);
165 172
    if (!opt) break;
166 173
  }
167 174
  return opt;
168 175
}
169 176

	
170 177
// Check a path
171 178
template <typename Digraph, typename Path>
172 179
bool checkPath( const Digraph& gr, const Path& path,
173 180
                typename Digraph::Node s, typename Digraph::Node t)
174 181
{
175 182
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
176 183
  Node n = s;
177 184
  for (int i = 0; i < path.length(); ++i) {
178 185
    if (gr.source(path.nth(i)) != n) return false;
179 186
    n = gr.target(path.nth(i));
180 187
  }
181 188
  return n == t;
182 189
}
183 190

	
184 191

	
185 192
int main()
186 193
{
187 194
  DIGRAPH_TYPEDEFS(ListDigraph);
188 195

	
189 196
  // Read the test digraph
190 197
  ListDigraph digraph;
191 198
  ListDigraph::ArcMap<int> length(digraph);
192 199
  Node s, t;
193 200

	
194 201
  std::istringstream input(test_lgf);
195 202
  DigraphReader<ListDigraph>(digraph, input).
196 203
    arcMap("length", length).
197 204
    node("source", s).
198 205
    node("target", t).
199 206
    run();
200 207

	
201 208
  // Find 2 paths
202 209
  {
203 210
    Suurballe<ListDigraph> suurballe(digraph, length);
204 211
    check(suurballe.run(s, t) == 2, "Wrong number of paths");
205 212
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 2),
206 213
          "The flow is not feasible");
207 214
    check(suurballe.totalLength() == 510, "The flow is not optimal");
208 215
    check(checkOptimality(digraph, length, suurballe.flowMap(),
209 216
                          suurballe.potentialMap()),
210 217
          "Wrong potentials");
211 218
    for (int i = 0; i < suurballe.pathNum(); ++i)
212 219
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
213 220
  }
214 221

	
215 222
  // Find 3 paths
216 223
  {
217 224
    Suurballe<ListDigraph> suurballe(digraph, length);
218 225
    check(suurballe.run(s, t, 3) == 3, "Wrong number of paths");
219 226
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
220 227
          "The flow is not feasible");
221 228
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
222 229
    check(checkOptimality(digraph, length, suurballe.flowMap(),
223 230
                          suurballe.potentialMap()),
224 231
          "Wrong potentials");
225 232
    for (int i = 0; i < suurballe.pathNum(); ++i)
226 233
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
227 234
  }
228 235

	
229 236
  // Find 5 paths (only 3 can be found)
230 237
  {
231 238
    Suurballe<ListDigraph> suurballe(digraph, length);
232 239
    check(suurballe.run(s, t, 5) == 3, "Wrong number of paths");
233 240
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
234 241
          "The flow is not feasible");
235 242
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
236 243
    check(checkOptimality(digraph, length, suurballe.flowMap(),
237 244
                          suurballe.potentialMap()),
238 245
          "Wrong potentials");
239 246
    for (int i = 0; i < suurballe.pathNum(); ++i)
240 247
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
241 248
  }
242 249

	
243 250
  return 0;
244 251
}
0 comments (0 inline)