gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Port NetworkSimplex from SVN -r3520 (#234)
0 3 2
default
5 files changed with 1650 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_NETWORK_SIMPLEX_H
20
#define LEMON_NETWORK_SIMPLEX_H
21

	
22
/// \ingroup min_cost_flow
23
///
24
/// \file
25
/// \brief Network simplex algorithm for finding a minimum cost flow.
26

	
27
#include <vector>
28
#include <limits>
29
#include <algorithm>
30

	
31
#include <lemon/math.h>
32

	
33
namespace lemon {
34

	
35
  /// \addtogroup min_cost_flow
36
  /// @{
37

	
38
  /// \brief Implementation of the primal network simplex algorithm
39
  /// for finding a \ref min_cost_flow "minimum cost flow".
40
  ///
41
  /// \ref NetworkSimplex implements the primal network simplex algorithm
42
  /// for finding a \ref min_cost_flow "minimum cost flow".
43
  ///
44
  /// \tparam Digraph The digraph type the algorithm runs on.
45
  /// \tparam LowerMap The type of the lower bound map.
46
  /// \tparam CapacityMap The type of the capacity (upper bound) map.
47
  /// \tparam CostMap The type of the cost (length) map.
48
  /// \tparam SupplyMap The type of the supply map.
49
  ///
50
  /// \warning
51
  /// - Arc capacities and costs should be \e non-negative \e integers.
52
  /// - Supply values should be \e signed \e integers.
53
  /// - The value types of the maps should be convertible to each other.
54
  /// - \c CostMap::Value must be signed type.
55
  ///
56
  /// \note \ref NetworkSimplex provides five different pivot rule
57
  /// implementations that significantly affect the efficiency of the
58
  /// algorithm.
59
  /// By default "Block Search" pivot rule is used, which proved to be
60
  /// by far the most efficient according to our benchmark tests.
61
  /// However another pivot rule can be selected using \ref run()
62
  /// function with the proper parameter.
63
#ifdef DOXYGEN
64
  template < typename Digraph,
65
             typename LowerMap,
66
             typename CapacityMap,
67
             typename CostMap,
68
             typename SupplyMap >
69

	
70
#else
71
  template < typename Digraph,
72
             typename LowerMap = typename Digraph::template ArcMap<int>,
73
             typename CapacityMap = typename Digraph::template ArcMap<int>,
74
             typename CostMap = typename Digraph::template ArcMap<int>,
75
             typename SupplyMap = typename Digraph::template NodeMap<int> >
76
#endif
77
  class NetworkSimplex
78
  {
79
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
80

	
81
    typedef typename CapacityMap::Value Capacity;
82
    typedef typename CostMap::Value Cost;
83
    typedef typename SupplyMap::Value Supply;
84

	
85
    typedef std::vector<Arc> ArcVector;
86
    typedef std::vector<Node> NodeVector;
87
    typedef std::vector<int> IntVector;
88
    typedef std::vector<bool> BoolVector;
89
    typedef std::vector<Capacity> CapacityVector;
90
    typedef std::vector<Cost> CostVector;
91
    typedef std::vector<Supply> SupplyVector;
92

	
93
  public:
94

	
95
    /// The type of the flow map
96
    typedef typename Digraph::template ArcMap<Capacity> FlowMap;
97
    /// The type of the potential map
98
    typedef typename Digraph::template NodeMap<Cost> PotentialMap;
99

	
100
  public:
101

	
102
    /// Enum type for selecting the pivot rule used by \ref run()
103
    enum PivotRuleEnum {
104
      FIRST_ELIGIBLE_PIVOT,
105
      BEST_ELIGIBLE_PIVOT,
106
      BLOCK_SEARCH_PIVOT,
107
      CANDIDATE_LIST_PIVOT,
108
      ALTERING_LIST_PIVOT
109
    };
110

	
111
  private:
112

	
113
    // State constants for arcs
114
    enum ArcStateEnum {
115
      STATE_UPPER = -1,
116
      STATE_TREE  =  0,
117
      STATE_LOWER =  1
118
    };
119

	
120
  private:
121

	
122
    // References for the original data
123
    const Digraph &_orig_graph;
124
    const LowerMap *_orig_lower;
125
    const CapacityMap &_orig_cap;
126
    const CostMap &_orig_cost;
127
    const SupplyMap *_orig_supply;
128
    Node _orig_source;
129
    Node _orig_target;
130
    Capacity _orig_flow_value;
131

	
132
    // Result maps
133
    FlowMap *_flow_result;
134
    PotentialMap *_potential_result;
135
    bool _local_flow;
136
    bool _local_potential;
137

	
138
    // Data structures for storing the graph
139
    ArcVector _arc;
140
    NodeVector _node;
141
    IntNodeMap _node_id;
142
    IntVector _source;
143
    IntVector _target;
144

	
145
    // The number of nodes and arcs in the original graph
146
    int _node_num;
147
    int _arc_num;
148

	
149
    // Node and arc maps
150
    CapacityVector _cap;
151
    CostVector _cost;
152
    CostVector _supply;
153
    CapacityVector _flow;
154
    CostVector _pi;
155

	
156
    // Node and arc maps for the spanning tree structure
157
    IntVector _depth;
158
    IntVector _parent;
159
    IntVector _pred;
160
    IntVector _thread;
161
    BoolVector _forward;
162
    IntVector _state;
163

	
164
    // The root node
165
    int _root;
166

	
167
    // The entering arc in the current pivot iteration
168
    int _in_arc;
169

	
170
    // Temporary data used in the current pivot iteration
171
    int join, u_in, v_in, u_out, v_out;
172
    int right, first, second, last;
173
    int stem, par_stem, new_stem;
174
    Capacity delta;
175

	
176
  private:
177

	
178
    /// \brief Implementation of the "First Eligible" pivot rule for the
179
    /// \ref NetworkSimplex "network simplex" algorithm.
180
    ///
181
    /// This class implements the "First Eligible" pivot rule
182
    /// for the \ref NetworkSimplex "network simplex" algorithm.
183
    ///
184
    /// For more information see \ref NetworkSimplex::run().
185
    class FirstEligiblePivotRule
186
    {
187
    private:
188

	
189
      // References to the NetworkSimplex class
190
      const ArcVector &_arc;
191
      const IntVector  &_source;
192
      const IntVector  &_target;
193
      const CostVector &_cost;
194
      const IntVector  &_state;
195
      const CostVector &_pi;
196
      int &_in_arc;
197
      int _arc_num;
198

	
199
      // Pivot rule data
200
      int _next_arc;
201

	
202
    public:
203

	
204
      /// Constructor
205
      FirstEligiblePivotRule(NetworkSimplex &ns) :
206
        _arc(ns._arc), _source(ns._source), _target(ns._target),
207
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
208
        _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
209
      {}
210

	
211
      /// Find next entering arc
212
      bool findEnteringArc() {
213
        Cost c;
214
        for (int e = _next_arc; e < _arc_num; ++e) {
215
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
216
          if (c < 0) {
217
            _in_arc = e;
218
            _next_arc = e + 1;
219
            return true;
220
          }
221
        }
222
        for (int e = 0; e < _next_arc; ++e) {
223
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
224
          if (c < 0) {
225
            _in_arc = e;
226
            _next_arc = e + 1;
227
            return true;
228
          }
229
        }
230
        return false;
231
      }
232

	
233
    }; //class FirstEligiblePivotRule
234

	
235

	
236
    /// \brief Implementation of the "Best Eligible" pivot rule for the
237
    /// \ref NetworkSimplex "network simplex" algorithm.
238
    ///
239
    /// This class implements the "Best Eligible" pivot rule
240
    /// for the \ref NetworkSimplex "network simplex" algorithm.
241
    ///
242
    /// For more information see \ref NetworkSimplex::run().
243
    class BestEligiblePivotRule
244
    {
245
    private:
246

	
247
      // References to the NetworkSimplex class
248
      const ArcVector &_arc;
249
      const IntVector  &_source;
250
      const IntVector  &_target;
251
      const CostVector &_cost;
252
      const IntVector  &_state;
253
      const CostVector &_pi;
254
      int &_in_arc;
255
      int _arc_num;
256

	
257
    public:
258

	
259
      /// Constructor
260
      BestEligiblePivotRule(NetworkSimplex &ns) :
261
        _arc(ns._arc), _source(ns._source), _target(ns._target),
262
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
263
        _in_arc(ns._in_arc), _arc_num(ns._arc_num)
264
      {}
265

	
266
      /// Find next entering arc
267
      bool findEnteringArc() {
268
        Cost c, min = 0;
269
        for (int e = 0; e < _arc_num; ++e) {
270
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
271
          if (c < min) {
272
            min = c;
273
            _in_arc = e;
274
          }
275
        }
276
        return min < 0;
277
      }
278

	
279
    }; //class BestEligiblePivotRule
280

	
281

	
282
    /// \brief Implementation of the "Block Search" pivot rule for the
283
    /// \ref NetworkSimplex "network simplex" algorithm.
284
    ///
285
    /// This class implements the "Block Search" pivot rule
286
    /// for the \ref NetworkSimplex "network simplex" algorithm.
287
    ///
288
    /// For more information see \ref NetworkSimplex::run().
289
    class BlockSearchPivotRule
290
    {
291
    private:
292

	
293
      // References to the NetworkSimplex class
294
      const ArcVector &_arc;
295
      const IntVector  &_source;
296
      const IntVector  &_target;
297
      const CostVector &_cost;
298
      const IntVector  &_state;
299
      const CostVector &_pi;
300
      int &_in_arc;
301
      int _arc_num;
302

	
303
      // Pivot rule data
304
      int _block_size;
305
      int _next_arc;
306

	
307
    public:
308

	
309
      /// Constructor
310
      BlockSearchPivotRule(NetworkSimplex &ns) :
311
        _arc(ns._arc), _source(ns._source), _target(ns._target),
312
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
313
        _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
314
      {
315
        // The main parameters of the pivot rule
316
        const double BLOCK_SIZE_FACTOR = 2.0;
317
        const int MIN_BLOCK_SIZE = 10;
318

	
319
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
320
                                MIN_BLOCK_SIZE );
321
      }
322

	
323
      /// Find next entering arc
324
      bool findEnteringArc() {
325
        Cost c, min = 0;
326
        int cnt = _block_size;
327
        int e, min_arc = _next_arc;
328
        for (e = _next_arc; e < _arc_num; ++e) {
329
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
330
          if (c < min) {
331
            min = c;
332
            min_arc = e;
333
          }
334
          if (--cnt == 0) {
335
            if (min < 0) break;
336
            cnt = _block_size;
337
          }
338
        }
339
        if (min == 0 || cnt > 0) {
340
          for (e = 0; e < _next_arc; ++e) {
341
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
342
            if (c < min) {
343
              min = c;
344
              min_arc = e;
345
            }
346
            if (--cnt == 0) {
347
              if (min < 0) break;
348
              cnt = _block_size;
349
            }
350
          }
351
        }
352
        if (min >= 0) return false;
353
        _in_arc = min_arc;
354
        _next_arc = e;
355
        return true;
356
      }
357

	
358
    }; //class BlockSearchPivotRule
359

	
360

	
361
    /// \brief Implementation of the "Candidate List" pivot rule for the
362
    /// \ref NetworkSimplex "network simplex" algorithm.
363
    ///
364
    /// This class implements the "Candidate List" pivot rule
365
    /// for the \ref NetworkSimplex "network simplex" algorithm.
366
    ///
367
    /// For more information see \ref NetworkSimplex::run().
368
    class CandidateListPivotRule
369
    {
370
    private:
371

	
372
      // References to the NetworkSimplex class
373
      const ArcVector &_arc;
374
      const IntVector  &_source;
375
      const IntVector  &_target;
376
      const CostVector &_cost;
377
      const IntVector  &_state;
378
      const CostVector &_pi;
379
      int &_in_arc;
380
      int _arc_num;
381

	
382
      // Pivot rule data
383
      IntVector _candidates;
384
      int _list_length, _minor_limit;
385
      int _curr_length, _minor_count;
386
      int _next_arc;
387

	
388
    public:
389

	
390
      /// Constructor
391
      CandidateListPivotRule(NetworkSimplex &ns) :
392
        _arc(ns._arc), _source(ns._source), _target(ns._target),
393
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
394
        _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
395
      {
396
        // The main parameters of the pivot rule
397
        const double LIST_LENGTH_FACTOR = 1.0;
398
        const int MIN_LIST_LENGTH = 10;
399
        const double MINOR_LIMIT_FACTOR = 0.1;
400
        const int MIN_MINOR_LIMIT = 3;
401

	
402
        _list_length = std::max( int(LIST_LENGTH_FACTOR * sqrt(_arc_num)),
403
                                 MIN_LIST_LENGTH );
404
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
405
                                 MIN_MINOR_LIMIT );
406
        _curr_length = _minor_count = 0;
407
        _candidates.resize(_list_length);
408
      }
409

	
410
      /// Find next entering arc
411
      bool findEnteringArc() {
412
        Cost min, c;
413
        int e, min_arc = _next_arc;
414
        if (_curr_length > 0 && _minor_count < _minor_limit) {
415
          // Minor iteration: select the best eligible arc from the
416
          // current candidate list
417
          ++_minor_count;
418
          min = 0;
419
          for (int i = 0; i < _curr_length; ++i) {
420
            e = _candidates[i];
421
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
422
            if (c < min) {
423
              min = c;
424
              min_arc = e;
425
            }
426
            if (c >= 0) {
427
              _candidates[i--] = _candidates[--_curr_length];
428
            }
429
          }
430
          if (min < 0) {
431
            _in_arc = min_arc;
432
            return true;
433
          }
434
        }
435

	
436
        // Major iteration: build a new candidate list
437
        min = 0;
438
        _curr_length = 0;
439
        for (e = _next_arc; e < _arc_num; ++e) {
440
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
441
          if (c < 0) {
442
            _candidates[_curr_length++] = e;
443
            if (c < min) {
444
              min = c;
445
              min_arc = e;
446
            }
447
            if (_curr_length == _list_length) break;
448
          }
449
        }
450
        if (_curr_length < _list_length) {
451
          for (e = 0; e < _next_arc; ++e) {
452
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
453
            if (c < 0) {
454
              _candidates[_curr_length++] = e;
455
              if (c < min) {
456
                min = c;
457
                min_arc = e;
458
              }
459
              if (_curr_length == _list_length) break;
460
            }
461
          }
462
        }
463
        if (_curr_length == 0) return false;
464
        _minor_count = 1;
465
        _in_arc = min_arc;
466
        _next_arc = e;
467
        return true;
468
      }
469

	
470
    }; //class CandidateListPivotRule
471

	
472

	
473
    /// \brief Implementation of the "Altering Candidate List" pivot rule
474
    /// for the \ref NetworkSimplex "network simplex" algorithm.
475
    ///
476
    /// This class implements the "Altering Candidate List" pivot rule
477
    /// for the \ref NetworkSimplex "network simplex" algorithm.
478
    ///
479
    /// For more information see \ref NetworkSimplex::run().
480
    class AlteringListPivotRule
481
    {
482
    private:
483

	
484
      // References to the NetworkSimplex class
485
      const ArcVector &_arc;
486
      const IntVector  &_source;
487
      const IntVector  &_target;
488
      const CostVector &_cost;
489
      const IntVector  &_state;
490
      const CostVector &_pi;
491
      int &_in_arc;
492
      int _arc_num;
493

	
494
      // Pivot rule data
495
      int _block_size, _head_length, _curr_length;
496
      int _next_arc;
497
      IntVector _candidates;
498
      CostVector _cand_cost;
499

	
500
      // Functor class to compare arcs during sort of the candidate list
501
      class SortFunc
502
      {
503
      private:
504
        const CostVector &_map;
505
      public:
506
        SortFunc(const CostVector &map) : _map(map) {}
507
        bool operator()(int left, int right) {
508
          return _map[left] > _map[right];
509
        }
510
      };
511

	
512
      SortFunc _sort_func;
513

	
514
    public:
515

	
516
      /// Constructor
517
      AlteringListPivotRule(NetworkSimplex &ns) :
518
        _arc(ns._arc), _source(ns._source), _target(ns._target),
519
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
520
        _in_arc(ns._in_arc), _arc_num(ns._arc_num),
521
        _next_arc(0), _cand_cost(ns._arc_num), _sort_func(_cand_cost)
522
      {
523
        // The main parameters of the pivot rule
524
        const double BLOCK_SIZE_FACTOR = 1.5;
525
        const int MIN_BLOCK_SIZE = 10;
526
        const double HEAD_LENGTH_FACTOR = 0.1;
527
        const int MIN_HEAD_LENGTH = 3;
528

	
529
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
530
                                MIN_BLOCK_SIZE );
531
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
532
                                 MIN_HEAD_LENGTH );
533
        _candidates.resize(_head_length + _block_size);
534
        _curr_length = 0;
535
      }
536

	
537
      /// Find next entering arc
538
      bool findEnteringArc() {
539
        // Check the current candidate list
540
        int e;
541
        for (int i = 0; i < _curr_length; ++i) {
542
          e = _candidates[i];
543
          _cand_cost[e] = _state[e] *
544
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
545
          if (_cand_cost[e] >= 0) {
546
            _candidates[i--] = _candidates[--_curr_length];
547
          }
548
        }
549

	
550
        // Extend the list
551
        int cnt = _block_size;
552
        int last_edge = 0;
553
        int limit = _head_length;
554

	
555
        for (int e = _next_arc; e < _arc_num; ++e) {
556
          _cand_cost[e] = _state[e] *
557
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
558
          if (_cand_cost[e] < 0) {
559
            _candidates[_curr_length++] = e;
560
            last_edge = e;
561
          }
562
          if (--cnt == 0) {
563
            if (_curr_length > limit) break;
564
            limit = 0;
565
            cnt = _block_size;
566
          }
567
        }
568
        if (_curr_length <= limit) {
569
          for (int e = 0; e < _next_arc; ++e) {
570
            _cand_cost[e] = _state[e] *
571
              (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
572
            if (_cand_cost[e] < 0) {
573
              _candidates[_curr_length++] = e;
574
              last_edge = e;
575
            }
576
            if (--cnt == 0) {
577
              if (_curr_length > limit) break;
578
              limit = 0;
579
              cnt = _block_size;
580
            }
581
          }
582
        }
583
        if (_curr_length == 0) return false;
584
        _next_arc = last_edge + 1;
585

	
586
        // Make heap of the candidate list (approximating a partial sort)
587
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
588
                   _sort_func );
589

	
590
        // Pop the first element of the heap
591
        _in_arc = _candidates[0];
592
        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
593
                  _sort_func );
594
        _curr_length = std::min(_head_length, _curr_length - 1);
595
        return true;
596
      }
597

	
598
    }; //class AlteringListPivotRule
599

	
600
  public:
601

	
602
    /// \brief General constructor (with lower bounds).
603
    ///
604
    /// General constructor (with lower bounds).
605
    ///
606
    /// \param digraph The digraph the algorithm runs on.
607
    /// \param lower The lower bounds of the arcs.
608
    /// \param capacity The capacities (upper bounds) of the arcs.
609
    /// \param cost The cost (length) values of the arcs.
610
    /// \param supply The supply values of the nodes (signed).
611
    NetworkSimplex( const Digraph &digraph,
612
                    const LowerMap &lower,
613
                    const CapacityMap &capacity,
614
                    const CostMap &cost,
615
                    const SupplyMap &supply ) :
616
      _orig_graph(digraph), _orig_lower(&lower), _orig_cap(capacity),
617
      _orig_cost(cost), _orig_supply(&supply),
618
      _flow_result(NULL), _potential_result(NULL),
619
      _local_flow(false), _local_potential(false),
620
      _node_id(digraph)
621
    {}
622

	
623
    /// \brief General constructor (without lower bounds).
624
    ///
625
    /// General constructor (without lower bounds).
626
    ///
627
    /// \param digraph The digraph the algorithm runs on.
628
    /// \param capacity The capacities (upper bounds) of the arcs.
629
    /// \param cost The cost (length) values of the arcs.
630
    /// \param supply The supply values of the nodes (signed).
631
    NetworkSimplex( const Digraph &digraph,
632
                    const CapacityMap &capacity,
633
                    const CostMap &cost,
634
                    const SupplyMap &supply ) :
635
      _orig_graph(digraph), _orig_lower(NULL), _orig_cap(capacity),
636
      _orig_cost(cost), _orig_supply(&supply),
637
      _flow_result(NULL), _potential_result(NULL),
638
      _local_flow(false), _local_potential(false),
639
      _node_id(digraph)
640
    {}
641

	
642
    /// \brief Simple constructor (with lower bounds).
643
    ///
644
    /// Simple constructor (with lower bounds).
645
    ///
646
    /// \param digraph The digraph the algorithm runs on.
647
    /// \param lower The lower bounds of the arcs.
648
    /// \param capacity The capacities (upper bounds) of the arcs.
649
    /// \param cost The cost (length) values of the arcs.
650
    /// \param s The source node.
651
    /// \param t The target node.
652
    /// \param flow_value The required amount of flow from node \c s
653
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
654
    NetworkSimplex( const Digraph &digraph,
655
                    const LowerMap &lower,
656
                    const CapacityMap &capacity,
657
                    const CostMap &cost,
658
                    Node s, Node t,
659
                    Capacity flow_value ) :
660
      _orig_graph(digraph), _orig_lower(&lower), _orig_cap(capacity),
661
      _orig_cost(cost), _orig_supply(NULL),
662
      _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
663
      _flow_result(NULL), _potential_result(NULL),
664
      _local_flow(false), _local_potential(false),
665
      _node_id(digraph)
666
    {}
667

	
668
    /// \brief Simple constructor (without lower bounds).
669
    ///
670
    /// Simple constructor (without lower bounds).
671
    ///
672
    /// \param digraph The digraph the algorithm runs on.
673
    /// \param capacity The capacities (upper bounds) of the arcs.
674
    /// \param cost The cost (length) values of the arcs.
675
    /// \param s The source node.
676
    /// \param t The target node.
677
    /// \param flow_value The required amount of flow from node \c s
678
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
679
    NetworkSimplex( const Digraph &digraph,
680
                    const CapacityMap &capacity,
681
                    const CostMap &cost,
682
                    Node s, Node t,
683
                    Capacity flow_value ) :
684
      _orig_graph(digraph), _orig_lower(NULL), _orig_cap(capacity),
685
      _orig_cost(cost), _orig_supply(NULL),
686
      _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
687
      _flow_result(NULL), _potential_result(NULL),
688
      _local_flow(false), _local_potential(false),
689
      _node_id(digraph)
690
    {}
691

	
692
    /// Destructor.
693
    ~NetworkSimplex() {
694
      if (_local_flow) delete _flow_result;
695
      if (_local_potential) delete _potential_result;
696
    }
697

	
698
    /// \brief Set the flow map.
699
    ///
700
    /// This function sets the flow map.
701
    ///
702
    /// \return <tt>(*this)</tt>
703
    NetworkSimplex& flowMap(FlowMap &map) {
704
      if (_local_flow) {
705
        delete _flow_result;
706
        _local_flow = false;
707
      }
708
      _flow_result = &map;
709
      return *this;
710
    }
711

	
712
    /// \brief Set the potential map.
713
    ///
714
    /// This function sets the potential map.
715
    ///
716
    /// \return <tt>(*this)</tt>
717
    NetworkSimplex& potentialMap(PotentialMap &map) {
718
      if (_local_potential) {
719
        delete _potential_result;
720
        _local_potential = false;
721
      }
722
      _potential_result = &map;
723
      return *this;
724
    }
725

	
726
    /// \name Execution control
727
    /// The algorithm can be executed using the
728
    /// \ref lemon::NetworkSimplex::run() "run()" function.
729
    /// @{
730

	
731
    /// \brief Run the algorithm.
732
    ///
733
    /// This function runs the algorithm.
734
    ///
735
    /// \param pivot_rule The pivot rule that is used during the
736
    /// algorithm.
737
    ///
738
    /// The available pivot rules:
739
    ///
740
    /// - FIRST_ELIGIBLE_PIVOT The next eligible arc is selected in
741
    /// a wraparound fashion in every iteration
742
    /// (\ref FirstEligiblePivotRule).
743
    ///
744
    /// - BEST_ELIGIBLE_PIVOT The best eligible arc is selected in
745
    /// every iteration (\ref BestEligiblePivotRule).
746
    ///
747
    /// - BLOCK_SEARCH_PIVOT A specified number of arcs are examined in
748
    /// every iteration in a wraparound fashion and the best eligible
749
    /// arc is selected from this block (\ref BlockSearchPivotRule).
750
    ///
751
    /// - CANDIDATE_LIST_PIVOT In a major iteration a candidate list is
752
    /// built from eligible arcs in a wraparound fashion and in the
753
    /// following minor iterations the best eligible arc is selected
754
    /// from this list (\ref CandidateListPivotRule).
755
    ///
756
    /// - ALTERING_LIST_PIVOT It is a modified version of the
757
    /// "Candidate List" pivot rule. It keeps only the several best
758
    /// eligible arcs from the former candidate list and extends this
759
    /// list in every iteration (\ref AlteringListPivotRule).
760
    ///
761
    /// According to our comprehensive benchmark tests the "Block Search"
762
    /// pivot rule proved to be the fastest and the most robust on
763
    /// various test inputs. Thus it is the default option.
764
    ///
765
    /// \return \c true if a feasible flow can be found.
766
    bool run(PivotRuleEnum pivot_rule = BLOCK_SEARCH_PIVOT) {
767
      return init() && start(pivot_rule);
768
    }
769

	
770
    /// @}
771

	
772
    /// \name Query Functions
773
    /// The results of the algorithm can be obtained using these
774
    /// functions.\n
775
    /// \ref lemon::NetworkSimplex::run() "run()" must be called before
776
    /// using them.
777
    /// @{
778

	
779
    /// \brief Return a const reference to the flow map.
780
    ///
781
    /// This function returns a const reference to an arc map storing
782
    /// the found flow.
783
    ///
784
    /// \pre \ref run() must be called before using this function.
785
    const FlowMap& flowMap() const {
786
      return *_flow_result;
787
    }
788

	
789
    /// \brief Return a const reference to the potential map
790
    /// (the dual solution).
791
    ///
792
    /// This function returns a const reference to a node map storing
793
    /// the found potentials (the dual solution).
794
    ///
795
    /// \pre \ref run() must be called before using this function.
796
    const PotentialMap& potentialMap() const {
797
      return *_potential_result;
798
    }
799

	
800
    /// \brief Return the flow on the given arc.
801
    ///
802
    /// This function returns the flow on the given arc.
803
    ///
804
    /// \pre \ref run() must be called before using this function.
805
    Capacity flow(const Arc& arc) const {
806
      return (*_flow_result)[arc];
807
    }
808

	
809
    /// \brief Return the potential of the given node.
810
    ///
811
    /// This function returns the potential of the given node.
812
    ///
813
    /// \pre \ref run() must be called before using this function.
814
    Cost potential(const Node& node) const {
815
      return (*_potential_result)[node];
816
    }
817

	
818
    /// \brief Return the total cost of the found flow.
819
    ///
820
    /// This function returns the total cost of the found flow.
821
    /// The complexity of the function is \f$ O(e) \f$.
822
    ///
823
    /// \pre \ref run() must be called before using this function.
824
    Cost totalCost() const {
825
      Cost c = 0;
826
      for (ArcIt e(_orig_graph); e != INVALID; ++e)
827
        c += (*_flow_result)[e] * _orig_cost[e];
828
      return c;
829
    }
830

	
831
    /// @}
832

	
833
  private:
834

	
835
    // Initialize internal data structures
836
    bool init() {
837
      // Initialize result maps
838
      if (!_flow_result) {
839
        _flow_result = new FlowMap(_orig_graph);
840
        _local_flow = true;
841
      }
842
      if (!_potential_result) {
843
        _potential_result = new PotentialMap(_orig_graph);
844
        _local_potential = true;
845
      }
846

	
847
      // Initialize vectors
848
      _node_num = countNodes(_orig_graph);
849
      _arc_num = countArcs(_orig_graph);
850
      int all_node_num = _node_num + 1;
851
      int all_edge_num = _arc_num + _node_num;
852

	
853
      _arc.resize(_arc_num);
854
      _node.reserve(_node_num);
855
      _source.resize(all_edge_num);
856
      _target.resize(all_edge_num);
857

	
858
      _cap.resize(all_edge_num);
859
      _cost.resize(all_edge_num);
860
      _supply.resize(all_node_num);
861
      _flow.resize(all_edge_num, 0);
862
      _pi.resize(all_node_num, 0);
863

	
864
      _depth.resize(all_node_num);
865
      _parent.resize(all_node_num);
866
      _pred.resize(all_node_num);
867
      _thread.resize(all_node_num);
868
      _forward.resize(all_node_num);
869
      _state.resize(all_edge_num, STATE_LOWER);
870

	
871
      // Initialize node related data
872
      bool valid_supply = true;
873
      if (_orig_supply) {
874
        Supply sum = 0;
875
        int i = 0;
876
        for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
877
          _node.push_back(n);
878
          _node_id[n] = i;
879
          _supply[i] = (*_orig_supply)[n];
880
          sum += _supply[i];
881
        }
882
        valid_supply = (sum == 0);
883
      } else {
884
        int i = 0;
885
        for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
886
          _node.push_back(n);
887
          _node_id[n] = i;
888
          _supply[i] = 0;
889
        }
890
        _supply[_node_id[_orig_source]] =  _orig_flow_value;
891
        _supply[_node_id[_orig_target]] = -_orig_flow_value;
892
      }
893
      if (!valid_supply) return false;
894

	
895
      // Set data for the artificial root node
896
      _root = _node_num;
897
      _depth[_root] = 0;
898
      _parent[_root] = -1;
899
      _pred[_root] = -1;
900
      _thread[_root] = 0;
901
      _supply[_root] = 0;
902
      _pi[_root] = 0;
903

	
904
      // Store the arcs in a mixed order
905
      int k = std::max(int(sqrt(_arc_num)), 10);
906
      int i = 0;
907
      for (ArcIt e(_orig_graph); e != INVALID; ++e) {
908
        _arc[i] = e;
909
        if ((i += k) >= _arc_num) i = (i % k) + 1;
910
      }
911

	
912
      // Initialize arc maps
913
      for (int i = 0; i != _arc_num; ++i) {
914
        Arc e = _arc[i];
915
        _source[i] = _node_id[_orig_graph.source(e)];
916
        _target[i] = _node_id[_orig_graph.target(e)];
917
        _cost[i] = _orig_cost[e];
918
        _cap[i] = _orig_cap[e];
919
      }
920

	
921
      // Remove non-zero lower bounds
922
      if (_orig_lower) {
923
        for (int i = 0; i != _arc_num; ++i) {
924
          Capacity c = (*_orig_lower)[_arc[i]];
925
          if (c != 0) {
926
            _cap[i] -= c;
927
            _supply[_source[i]] -= c;
928
            _supply[_target[i]] += c;
929
          }
930
        }
931
      }
932

	
933
      // Add artificial arcs and initialize the spanning tree data structure
934
      Cost max_cost = std::numeric_limits<Cost>::max() / 4;
935
      Capacity max_cap = std::numeric_limits<Capacity>::max();
936
      for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
937
        _thread[u] = u + 1;
938
        _depth[u] = 1;
939
        _parent[u] = _root;
940
        _pred[u] = e;
941
        if (_supply[u] >= 0) {
942
          _flow[e] = _supply[u];
943
          _forward[u] = true;
944
          _pi[u] = -max_cost;
945
        } else {
946
          _flow[e] = -_supply[u];
947
          _forward[u] = false;
948
          _pi[u] = max_cost;
949
        }
950
        _cost[e] = max_cost;
951
        _cap[e] = max_cap;
952
        _state[e] = STATE_TREE;
953
      }
954

	
955
      return true;
956
    }
957

	
958
    // Find the join node
959
    void findJoinNode() {
960
      int u = _source[_in_arc];
961
      int v = _target[_in_arc];
962
      while (_depth[u] > _depth[v]) u = _parent[u];
963
      while (_depth[v] > _depth[u]) v = _parent[v];
964
      while (u != v) {
965
        u = _parent[u];
966
        v = _parent[v];
967
      }
968
      join = u;
969
    }
970

	
971
    // Find the leaving arc of the cycle and returns true if the
972
    // leaving arc is not the same as the entering arc
973
    bool findLeavingArc() {
974
      // Initialize first and second nodes according to the direction
975
      // of the cycle
976
      if (_state[_in_arc] == STATE_LOWER) {
977
        first  = _source[_in_arc];
978
        second = _target[_in_arc];
979
      } else {
980
        first  = _target[_in_arc];
981
        second = _source[_in_arc];
982
      }
983
      delta = _cap[_in_arc];
984
      int result = 0;
985
      Capacity d;
986
      int e;
987

	
988
      // Search the cycle along the path form the first node to the root
989
      for (int u = first; u != join; u = _parent[u]) {
990
        e = _pred[u];
991
        d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
992
        if (d < delta) {
993
          delta = d;
994
          u_out = u;
995
          result = 1;
996
        }
997
      }
998
      // Search the cycle along the path form the second node to the root
999
      for (int u = second; u != join; u = _parent[u]) {
1000
        e = _pred[u];
1001
        d = _forward[u] ? _cap[e] - _flow[e] : _flow[e];
1002
        if (d <= delta) {
1003
          delta = d;
1004
          u_out = u;
1005
          result = 2;
1006
        }
1007
      }
1008

	
1009
      if (result == 1) {
1010
        u_in = first;
1011
        v_in = second;
1012
      } else {
1013
        u_in = second;
1014
        v_in = first;
1015
      }
1016
      return result != 0;
1017
    }
1018

	
1019
    // Change _flow and _state vectors
1020
    void changeFlow(bool change) {
1021
      // Augment along the cycle
1022
      if (delta > 0) {
1023
        Capacity val = _state[_in_arc] * delta;
1024
        _flow[_in_arc] += val;
1025
        for (int u = _source[_in_arc]; u != join; u = _parent[u]) {
1026
          _flow[_pred[u]] += _forward[u] ? -val : val;
1027
        }
1028
        for (int u = _target[_in_arc]; u != join; u = _parent[u]) {
1029
          _flow[_pred[u]] += _forward[u] ? val : -val;
1030
        }
1031
      }
1032
      // Update the state of the entering and leaving arcs
1033
      if (change) {
1034
        _state[_in_arc] = STATE_TREE;
1035
        _state[_pred[u_out]] =
1036
          (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
1037
      } else {
1038
        _state[_in_arc] = -_state[_in_arc];
1039
      }
1040
    }
1041

	
1042
    // Update _thread and _parent vectors
1043
    void updateThreadParent() {
1044
      int u;
1045
      v_out = _parent[u_out];
1046

	
1047
      // Handle the case when join and v_out coincide
1048
      bool par_first = false;
1049
      if (join == v_out) {
1050
        for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
1051
        if (u == v_in) {
1052
          par_first = true;
1053
          while (_thread[u] != u_out) u = _thread[u];
1054
          first = u;
1055
        }
1056
      }
1057

	
1058
      // Find the last successor of u_in (u) and the node after it (right)
1059
      // according to the thread index
1060
      for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
1061
      right = _thread[u];
1062
      if (_thread[v_in] == u_out) {
1063
        for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
1064
        if (last == u_out) last = _thread[last];
1065
      }
1066
      else last = _thread[v_in];
1067

	
1068
      // Update stem nodes
1069
      _thread[v_in] = stem = u_in;
1070
      par_stem = v_in;
1071
      while (stem != u_out) {
1072
        _thread[u] = new_stem = _parent[stem];
1073

	
1074
        // Find the node just before the stem node (u) according to
1075
        // the original thread index
1076
        for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
1077
        _thread[u] = right;
1078

	
1079
        // Change the parent node of stem and shift stem and par_stem nodes
1080
        _parent[stem] = par_stem;
1081
        par_stem = stem;
1082
        stem = new_stem;
1083

	
1084
        // Find the last successor of stem (u) and the node after it (right)
1085
        // according to the thread index
1086
        for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
1087
        right = _thread[u];
1088
      }
1089
      _parent[u_out] = par_stem;
1090
      _thread[u] = last;
1091

	
1092
      if (join == v_out && par_first) {
1093
        if (first != v_in) _thread[first] = right;
1094
      } else {
1095
        for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
1096
        _thread[u] = right;
1097
      }
1098
    }
1099

	
1100
    // Update _pred and _forward vectors
1101
    void updatePredArc() {
1102
      int u = u_out, v;
1103
      while (u != u_in) {
1104
        v = _parent[u];
1105
        _pred[u] = _pred[v];
1106
        _forward[u] = !_forward[v];
1107
        u = v;
1108
      }
1109
      _pred[u_in] = _in_arc;
1110
      _forward[u_in] = (u_in == _source[_in_arc]);
1111
    }
1112

	
1113
    // Update _depth and _potential vectors
1114
    void updateDepthPotential() {
1115
      _depth[u_in] = _depth[v_in] + 1;
1116
      Cost sigma = _forward[u_in] ?
1117
        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1118
        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
1119
      _pi[u_in] += sigma;
1120
      for(int u = _thread[u_in]; _parent[u] != -1; u = _thread[u]) {
1121
        _depth[u] = _depth[_parent[u]] + 1;
1122
        if (_depth[u] <= _depth[u_in]) break;
1123
        _pi[u] += sigma;
1124
      }
1125
    }
1126

	
1127
    // Execute the algorithm
1128
    bool start(PivotRuleEnum pivot_rule) {
1129
      // Select the pivot rule implementation
1130
      switch (pivot_rule) {
1131
        case FIRST_ELIGIBLE_PIVOT:
1132
          return start<FirstEligiblePivotRule>();
1133
        case BEST_ELIGIBLE_PIVOT:
1134
          return start<BestEligiblePivotRule>();
1135
        case BLOCK_SEARCH_PIVOT:
1136
          return start<BlockSearchPivotRule>();
1137
        case CANDIDATE_LIST_PIVOT:
1138
          return start<CandidateListPivotRule>();
1139
        case ALTERING_LIST_PIVOT:
1140
          return start<AlteringListPivotRule>();
1141
      }
1142
      return false;
1143
    }
1144

	
1145
    template<class PivotRuleImplementation>
1146
    bool start() {
1147
      PivotRuleImplementation pivot(*this);
1148

	
1149
      // Execute the network simplex algorithm
1150
      while (pivot.findEnteringArc()) {
1151
        findJoinNode();
1152
        bool change = findLeavingArc();
1153
        changeFlow(change);
1154
        if (change) {
1155
          updateThreadParent();
1156
          updatePredArc();
1157
          updateDepthPotential();
1158
        }
1159
      }
1160

	
1161
      // Check if the flow amount equals zero on all the artificial arcs
1162
      for (int e = _arc_num; e != _arc_num + _node_num; ++e) {
1163
        if (_flow[e] > 0) return false;
1164
      }
1165

	
1166
      // Copy flow values to _flow_result
1167
      if (_orig_lower) {
1168
        for (int i = 0; i != _arc_num; ++i) {
1169
          Arc e = _arc[i];
1170
          (*_flow_result)[e] = (*_orig_lower)[e] + _flow[i];
1171
        }
1172
      } else {
1173
        for (int i = 0; i != _arc_num; ++i) {
1174
          (*_flow_result)[_arc[i]] = _flow[i];
1175
        }
1176
      }
1177
      // Copy potential values to _potential_result
1178
      for (int i = 0; i != _node_num; ++i) {
1179
        (*_potential_result)[_node[i]] = _pi[i];
1180
      }
1181

	
1182
      return true;
1183
    }
1184

	
1185
  }; //class NetworkSimplex
1186

	
1187
  ///@}
1188

	
1189
} //namespace lemon
1190

	
1191
#endif //LEMON_NETWORK_SIMPLEX_H
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#include <iostream>
20
#include <fstream>
21

	
22
#include <lemon/list_graph.h>
23
#include <lemon/smart_graph.h>
24
#include <lemon/lgf_reader.h>
25

	
26
//#include <lemon/cycle_canceling.h>
27
//#include <lemon/capacity_scaling.h>
28
//#include <lemon/cost_scaling.h>
29
#include <lemon/network_simplex.h>
30
//#include <lemon/min_cost_flow.h>
31
//#include <lemon/min_cost_max_flow.h>
32

	
33
#include <lemon/concepts/digraph.h>
34
#include <lemon/concept_check.h>
35

	
36
#include "test_tools.h"
37

	
38
using namespace lemon;
39

	
40
char test_lgf[] =
41
  "@nodes\n"
42
  "label  sup1 sup2 sup3\n"
43
  "    1    20   27    0\n"
44
  "    2    -4    0    0\n"
45
  "    3     0    0    0\n"
46
  "    4     0    0    0\n"
47
  "    5     9    0    0\n"
48
  "    6    -6    0    0\n"
49
  "    7     0    0    0\n"
50
  "    8     0    0    0\n"
51
  "    9     3    0    0\n"
52
  "   10    -2    0    0\n"
53
  "   11     0    0    0\n"
54
  "   12   -20  -27    0\n"
55
  "\n"
56
  "@arcs\n"
57
  "       cost  cap low1 low2\n"
58
  " 1  2    70   11    0    8\n"
59
  " 1  3   150    3    0    1\n"
60
  " 1  4    80   15    0    2\n"
61
  " 2  8    80   12    0    0\n"
62
  " 3  5   140    5    0    3\n"
63
  " 4  6    60   10    0    1\n"
64
  " 4  7    80    2    0    0\n"
65
  " 4  8   110    3    0    0\n"
66
  " 5  7    60   14    0    0\n"
67
  " 5 11   120   12    0    0\n"
68
  " 6  3     0    3    0    0\n"
69
  " 6  9   140    4    0    0\n"
70
  " 6 10    90    8    0    0\n"
71
  " 7  1    30    5    0    0\n"
72
  " 8 12    60   16    0    4\n"
73
  " 9 12    50    6    0    0\n"
74
  "10 12    70   13    0    5\n"
75
  "10  2   100    7    0    0\n"
76
  "10  7    60   10    0    0\n"
77
  "11 10    20   14    0    6\n"
78
  "12 11    30   10    0    0\n"
79
  "\n"
80
  "@attributes\n"
81
  "source 1\n"
82
  "target 12\n";
83

	
84

	
85
// Check the interface of an MCF algorithm
86
template <typename GR, typename Value>
87
class McfClassConcept
88
{
89
public:
90

	
91
  template <typename MCF>
92
  struct Constraints {
93
    void constraints() {
94
      checkConcept<concepts::Digraph, GR>();
95

	
96
      MCF mcf_test1(g, lower, upper, cost, sup);
97
      MCF mcf_test2(g, upper, cost, sup);
98
      MCF mcf_test3(g, lower, upper, cost, n, n, k);
99
      MCF mcf_test4(g, upper, cost, n, n, k);
100

	
101
      // TODO: This part should be enabled and the next part
102
      // should be removed if map copying is supported
103
/*
104
      flow = mcf_test1.flowMap();
105
      mcf_test1.flowMap(flow);
106

	
107
      pot = mcf_test1.potentialMap();
108
      mcf_test1.potentialMap(pot);
109
*/
110
/**/
111
      const typename MCF::FlowMap &fm =
112
        mcf_test1.flowMap();
113
      mcf_test1.flowMap(flow);
114
      const typename MCF::PotentialMap &pm =
115
        mcf_test1.potentialMap();
116
      mcf_test1.potentialMap(pot);
117
      ignore_unused_variable_warning(fm);
118
      ignore_unused_variable_warning(pm);
119
/**/
120

	
121
      mcf_test1.run();
122

	
123
      v = mcf_test1.totalCost();
124
      v = mcf_test1.flow(a);
125
      v = mcf_test1.potential(n);
126
    }
127

	
128
    typedef typename GR::Node Node;
129
    typedef typename GR::Arc Arc;
130
    typedef concepts::ReadMap<Node, Value> NM;
131
    typedef concepts::ReadMap<Arc, Value> AM;
132

	
133
    const GR &g;
134
    const AM &lower;
135
    const AM &upper;
136
    const AM &cost;
137
    const NM &sup;
138
    const Node &n;
139
    const Arc &a;
140
    const Value &k;
141
    Value v;
142

	
143
    typename MCF::FlowMap &flow;
144
    typename MCF::PotentialMap &pot;
145
  };
146

	
147
};
148

	
149

	
150
// Check the feasibility of the given flow (primal soluiton)
151
template < typename GR, typename LM, typename UM,
152
           typename SM, typename FM >
153
bool checkFlow( const GR& gr, const LM& lower, const UM& upper,
154
                const SM& supply, const FM& flow )
155
{
156
  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
157

	
158
  for (ArcIt e(gr); e != INVALID; ++e) {
159
    if (flow[e] < lower[e] || flow[e] > upper[e]) return false;
160
  }
161

	
162
  for (NodeIt n(gr); n != INVALID; ++n) {
163
    typename SM::Value sum = 0;
164
    for (OutArcIt e(gr, n); e != INVALID; ++e)
165
      sum += flow[e];
166
    for (InArcIt e(gr, n); e != INVALID; ++e)
167
      sum -= flow[e];
168
    if (sum != supply[n]) return false;
169
  }
170

	
171
  return true;
172
}
173

	
174
// Check the feasibility of the given potentials (dual soluiton)
175
// using the Complementary Slackness optimality condition
176
template < typename GR, typename LM, typename UM,
177
           typename CM, typename FM, typename PM >
178
bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
179
                     const CM& cost, const FM& flow, const PM& pi )
180
{
181
  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
182

	
183
  bool opt = true;
184
  for (ArcIt e(gr); opt && e != INVALID; ++e) {
185
    typename CM::Value red_cost =
186
      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
187
    opt = red_cost == 0 ||
188
          (red_cost > 0 && flow[e] == lower[e]) ||
189
          (red_cost < 0 && flow[e] == upper[e]);
190
  }
191
  return opt;
192
}
193

	
194
// Run a minimum cost flow algorithm and check the results
195
template < typename MCF, typename GR,
196
           typename LM, typename UM,
197
           typename CM, typename SM >
198
void checkMcf( const MCF& mcf, bool mcf_result,
199
               const GR& gr, const LM& lower, const UM& upper,
200
               const CM& cost, const SM& supply,
201
               bool result, typename CM::Value total,
202
               const std::string &test_id = "" )
203
{
204
  check(mcf_result == result, "Wrong result " + test_id);
205
  if (result) {
206
    check(checkFlow(gr, lower, upper, supply, mcf.flowMap()),
207
          "The flow is not feasible " + test_id);
208
    check(mcf.totalCost() == total, "The flow is not optimal " + test_id);
209
    check(checkPotential(gr, lower, upper, cost, mcf.flowMap(),
210
                         mcf.potentialMap()),
211
          "Wrong potentials " + test_id);
212
  }
213
}
214

	
215
int main()
216
{
217
  // Check the interfaces
218
  {
219
    typedef int Value;
220
    // This typedef should be enabled if the standard maps are
221
    // reference maps in the graph concepts
222
    //typedef concepts::Digraph GR;
223
    typedef ListDigraph GR;
224
    typedef concepts::ReadMap<GR::Node, Value> NM;
225
    typedef concepts::ReadMap<GR::Arc, Value> AM;
226

	
227
    //checkConcept< McfClassConcept<GR, Value>,
228
    //              CycleCanceling<GR, AM, AM, AM, NM> >();
229
    //checkConcept< McfClassConcept<GR, Value>,
230
    //              CapacityScaling<GR, AM, AM, AM, NM> >();
231
    //checkConcept< McfClassConcept<GR, Value>,
232
    //              CostScaling<GR, AM, AM, AM, NM> >();
233
    checkConcept< McfClassConcept<GR, Value>,
234
                  NetworkSimplex<GR, AM, AM, AM, NM> >();
235
    //checkConcept< MinCostFlow<GR, Value>,
236
    //              NetworkSimplex<GR, AM, AM, AM, NM> >();
237
  }
238

	
239
  // Run various MCF tests
240
  typedef ListDigraph Digraph;
241
  DIGRAPH_TYPEDEFS(ListDigraph);
242

	
243
  // Read the test digraph
244
  Digraph gr;
245
  Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), u(gr);
246
  Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr);
247
  Node v, w;
248

	
249
  std::istringstream input(test_lgf);
250
  DigraphReader<Digraph>(gr, input)
251
    .arcMap("cost", c)
252
    .arcMap("cap", u)
253
    .arcMap("low1", l1)
254
    .arcMap("low2", l2)
255
    .nodeMap("sup1", s1)
256
    .nodeMap("sup2", s2)
257
    .nodeMap("sup3", s3)
258
    .node("source", v)
259
    .node("target", w)
260
    .run();
261

	
262
/*
263
  // A. Test CapacityScaling with scaling
264
  {
265
    CapacityScaling<Digraph> mcf1(gr, u, c, s1);
266
    CapacityScaling<Digraph> mcf2(gr, u, c, v, w, 27);
267
    CapacityScaling<Digraph> mcf3(gr, u, c, s3);
268
    CapacityScaling<Digraph> mcf4(gr, l2, u, c, s1);
269
    CapacityScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
270
    CapacityScaling<Digraph> mcf6(gr, l2, u, c, s3);
271

	
272
    checkMcf(mcf1, mcf1.run(), gr, l1, u, c, s1, true,  5240, "#A1");
273
    checkMcf(mcf2, mcf2.run(), gr, l1, u, c, s2, true,  7620, "#A2");
274
    checkMcf(mcf3, mcf3.run(), gr, l1, u, c, s3, true,     0, "#A3");
275
    checkMcf(mcf4, mcf4.run(), gr, l2, u, c, s1, true,  5970, "#A4");
276
    checkMcf(mcf5, mcf5.run(), gr, l2, u, c, s2, true,  8010, "#A5");
277
    checkMcf(mcf6, mcf6.run(), gr, l2, u, c, s3, false,    0, "#A6");
278
  }
279

	
280
  // B. Test CapacityScaling without scaling
281
  {
282
    CapacityScaling<Digraph> mcf1(gr, u, c, s1);
283
    CapacityScaling<Digraph> mcf2(gr, u, c, v, w, 27);
284
    CapacityScaling<Digraph> mcf3(gr, u, c, s3);
285
    CapacityScaling<Digraph> mcf4(gr, l2, u, c, s1);
286
    CapacityScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
287
    CapacityScaling<Digraph> mcf6(gr, l2, u, c, s3);
288

	
289
    checkMcf(mcf1, mcf1.run(false), gr, l1, u, c, s1, true,  5240, "#B1");
290
    checkMcf(mcf2, mcf2.run(false), gr, l1, u, c, s2, true,  7620, "#B2");
291
    checkMcf(mcf3, mcf3.run(false), gr, l1, u, c, s3, true,     0, "#B3");
292
    checkMcf(mcf4, mcf4.run(false), gr, l2, u, c, s1, true,  5970, "#B4");
293
    checkMcf(mcf5, mcf5.run(false), gr, l2, u, c, s2, true,  8010, "#B5");
294
    checkMcf(mcf6, mcf6.run(false), gr, l2, u, c, s3, false,    0, "#B6");
295
  }
296

	
297
  // C. Test CostScaling using partial augment-relabel method
298
  {
299
    CostScaling<Digraph> mcf1(gr, u, c, s1);
300
    CostScaling<Digraph> mcf2(gr, u, c, v, w, 27);
301
    CostScaling<Digraph> mcf3(gr, u, c, s3);
302
    CostScaling<Digraph> mcf4(gr, l2, u, c, s1);
303
    CostScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
304
    CostScaling<Digraph> mcf6(gr, l2, u, c, s3);
305

	
306
    checkMcf(mcf1, mcf1.run(), gr, l1, u, c, s1, true,  5240, "#C1");
307
    checkMcf(mcf2, mcf2.run(), gr, l1, u, c, s2, true,  7620, "#C2");
308
    checkMcf(mcf3, mcf3.run(), gr, l1, u, c, s3, true,     0, "#C3");
309
    checkMcf(mcf4, mcf4.run(), gr, l2, u, c, s1, true,  5970, "#C4");
310
    checkMcf(mcf5, mcf5.run(), gr, l2, u, c, s2, true,  8010, "#C5");
311
    checkMcf(mcf6, mcf6.run(), gr, l2, u, c, s3, false,    0, "#C6");
312
  }
313

	
314
  // D. Test CostScaling using push-relabel method
315
  {
316
    CostScaling<Digraph> mcf1(gr, u, c, s1);
317
    CostScaling<Digraph> mcf2(gr, u, c, v, w, 27);
318
    CostScaling<Digraph> mcf3(gr, u, c, s3);
319
    CostScaling<Digraph> mcf4(gr, l2, u, c, s1);
320
    CostScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
321
    CostScaling<Digraph> mcf6(gr, l2, u, c, s3);
322

	
323
    checkMcf(mcf1, mcf1.run(false), gr, l1, u, c, s1, true,  5240, "#D1");
324
    checkMcf(mcf2, mcf2.run(false), gr, l1, u, c, s2, true,  7620, "#D2");
325
    checkMcf(mcf3, mcf3.run(false), gr, l1, u, c, s3, true,     0, "#D3");
326
    checkMcf(mcf4, mcf4.run(false), gr, l2, u, c, s1, true,  5970, "#D4");
327
    checkMcf(mcf5, mcf5.run(false), gr, l2, u, c, s2, true,  8010, "#D5");
328
    checkMcf(mcf6, mcf6.run(false), gr, l2, u, c, s3, false,    0, "#D6");
329
  }
330
*/
331

	
332
  // E. Test NetworkSimplex with FIRST_ELIGIBLE_PIVOT
333
  {
334
    NetworkSimplex<Digraph>::PivotRuleEnum pr =
335
      NetworkSimplex<Digraph>::FIRST_ELIGIBLE_PIVOT;
336
    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
337
    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
338
    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
339
    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
340
    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
341
    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
342

	
343
    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#E1");
344
    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#E2");
345
    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#E3");
346
    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#E4");
347
    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#E5");
348
    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#E6");
349
  }
350

	
351
  // F. Test NetworkSimplex with BEST_ELIGIBLE_PIVOT
352
  {
353
    NetworkSimplex<Digraph>::PivotRuleEnum pr =
354
      NetworkSimplex<Digraph>::BEST_ELIGIBLE_PIVOT;
355
    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
356
    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
357
    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
358
    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
359
    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
360
    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
361

	
362
    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#F1");
363
    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#F2");
364
    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#F3");
365
    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#F4");
366
    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#F5");
367
    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#F6");
368
  }
369

	
370
  // G. Test NetworkSimplex with BLOCK_SEARCH_PIVOT
371
  {
372
    NetworkSimplex<Digraph>::PivotRuleEnum pr =
373
      NetworkSimplex<Digraph>::BLOCK_SEARCH_PIVOT;
374
    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
375
    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
376
    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
377
    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
378
    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
379
    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
380

	
381
    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#G1");
382
    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#G2");
383
    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#G3");
384
    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#G4");
385
    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#G5");
386
    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#G6");
387
  }
388

	
389
  // H. Test NetworkSimplex with CANDIDATE_LIST_PIVOT
390
  {
391
    NetworkSimplex<Digraph>::PivotRuleEnum pr =
392
      NetworkSimplex<Digraph>::CANDIDATE_LIST_PIVOT;
393
    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
394
    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
395
    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
396
    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
397
    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
398
    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
399

	
400
    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#H1");
401
    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#H2");
402
    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#H3");
403
    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#H4");
404
    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#H5");
405
    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#H6");
406
  }
407

	
408
  // I. Test NetworkSimplex with ALTERING_LIST_PIVOT
409
  {
410
    NetworkSimplex<Digraph>::PivotRuleEnum pr =
411
      NetworkSimplex<Digraph>::ALTERING_LIST_PIVOT;
412
    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
413
    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
414
    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
415
    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
416
    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
417
    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
418

	
419
    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#I1");
420
    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#I2");
421
    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#I3");
422
    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#I4");
423
    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#I5");
424
    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#I6");
425
  }
426

	
427
/*
428
  // J. Test MinCostFlow
429
  {
430
    MinCostFlow<Digraph> mcf1(gr, u, c, s1);
431
    MinCostFlow<Digraph> mcf2(gr, u, c, v, w, 27);
432
    MinCostFlow<Digraph> mcf3(gr, u, c, s3);
433
    MinCostFlow<Digraph> mcf4(gr, l2, u, c, s1);
434
    MinCostFlow<Digraph> mcf5(gr, l2, u, c, v, w, 27);
435
    MinCostFlow<Digraph> mcf6(gr, l2, u, c, s3);
436

	
437
    checkMcf(mcf1, mcf1.run(), gr, l1, u, c, s1, true,  5240, "#J1");
438
    checkMcf(mcf2, mcf2.run(), gr, l1, u, c, s2, true,  7620, "#J2");
439
    checkMcf(mcf3, mcf3.run(), gr, l1, u, c, s3, true,     0, "#J3");
440
    checkMcf(mcf4, mcf4.run(), gr, l2, u, c, s1, true,  5970, "#J4");
441
    checkMcf(mcf5, mcf5.run(), gr, l2, u, c, s2, true,  8010, "#J5");
442
    checkMcf(mcf6, mcf6.run(), gr, l2, u, c, s3, false,    0, "#J6");
443
  }
444
*/
445
/*
446
  // K. Test MinCostMaxFlow
447
  {
448
    MinCostMaxFlow<Digraph> mcmf(gr, u, c, v, w);
449
    mcmf.run();
450
    checkMcf(mcmf, true, gr, l1, u, c, s3, true, 7620, "#K1");
451
  }
452
*/
453

	
454
  return 0;
455
}
Ignore white space 6 line context
... ...
@@ -87,2 +87,3 @@
87 87
	lemon/nauty_reader.h \
88
	lemon/network_simplex.h \
88 89
	lemon/path.h \
Ignore white space 6 line context
... ...
@@ -32,2 +32,3 @@
32 32
  min_cost_arborescence_test
33
  min_cost_flow_test
33 34
  path_test
Show white space 6 line context
... ...
@@ -28,2 +28,3 @@
28 28
	test/min_cost_arborescence_test \
29
	test/min_cost_flow_test \
29 30
	test/path_test \
... ...
@@ -70,2 +71,3 @@
70 71
test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
72
test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc
71 73
test_path_test_SOURCES = test/path_test.cc
0 comments (0 inline)