gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Separate types for flow and cost values in NetworkSimplex (#234)
0 2 0
default
2 files changed with 90 insertions and 80 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_NETWORK_SIMPLEX_H
20 20
#define LEMON_NETWORK_SIMPLEX_H
21 21

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

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

	
31 31
#include <lemon/core.h>
32 32
#include <lemon/math.h>
33 33

	
34 34
namespace lemon {
35 35

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

	
39 39
  /// \brief Implementation of the primal Network Simplex algorithm
40 40
  /// for finding a \ref min_cost_flow "minimum cost flow".
41 41
  ///
42 42
  /// \ref NetworkSimplex implements the primal Network Simplex algorithm
43 43
  /// for finding a \ref min_cost_flow "minimum cost flow".
44 44
  /// This algorithm is a specialized version of the linear programming
45 45
  /// simplex method directly for the minimum cost flow problem.
46 46
  /// It is one of the most efficient solution methods.
47 47
  ///
48 48
  /// In general this class is the fastest implementation available
49 49
  /// in LEMON for the minimum cost flow problem.
50 50
  ///
51 51
  /// \tparam GR The digraph type the algorithm runs on.
52
  /// \tparam V The value type used in the algorithm.
53
  /// By default it is \c int.
52
  /// \tparam F The value type used for flow amounts, capacity bounds
53
  /// and supply values in the algorithm. By default it is \c int.
54
  /// \tparam C The value type used for costs and potentials in the
55
  /// algorithm. By default it is the same as \c F.
54 56
  ///
55
  /// \warning The value type must be a signed integer type.
57
  /// \warning Both value types must be signed integer types.
56 58
  ///
57 59
  /// \note %NetworkSimplex provides five different pivot rule
58 60
  /// implementations. For more information see \ref PivotRule.
59
  template <typename GR, typename V = int>
61
  template <typename GR, typename F = int, typename C = F>
60 62
  class NetworkSimplex
61 63
  {
62 64
  public:
63 65

	
64
    /// The value type of the algorithm
65
    typedef V Value;
66
    /// The flow type of the algorithm
67
    typedef F Flow;
68
    /// The cost type of the algorithm
69
    typedef C Cost;
66 70
    /// The type of the flow map
67
    typedef typename GR::template ArcMap<Value> FlowMap;
71
    typedef typename GR::template ArcMap<Flow> FlowMap;
68 72
    /// The type of the potential map
69
    typedef typename GR::template NodeMap<Value> PotentialMap;
73
    typedef typename GR::template NodeMap<Cost> PotentialMap;
70 74

	
71 75
  public:
72 76

	
73 77
    /// \brief Enum type for selecting the pivot rule.
74 78
    ///
75 79
    /// Enum type for selecting the pivot rule for the \ref run()
76 80
    /// function.
77 81
    ///
78 82
    /// \ref NetworkSimplex provides five different pivot rule
79 83
    /// implementations that significantly affect the running time
80 84
    /// of the algorithm.
81 85
    /// By default \ref BLOCK_SEARCH "Block Search" is used, which
82 86
    /// proved to be the most efficient and the most robust on various
83 87
    /// test inputs according to our benchmark tests.
84 88
    /// However another pivot rule can be selected using the \ref run()
85 89
    /// function with the proper parameter.
86 90
    enum PivotRule {
87 91

	
88 92
      /// The First Eligible pivot rule.
89 93
      /// The next eligible arc is selected in a wraparound fashion
90 94
      /// in every iteration.
91 95
      FIRST_ELIGIBLE,
92 96

	
93 97
      /// The Best Eligible pivot rule.
94 98
      /// The best eligible arc is selected in every iteration.
95 99
      BEST_ELIGIBLE,
96 100

	
97 101
      /// The Block Search pivot rule.
98 102
      /// A specified number of arcs are examined in every iteration
99 103
      /// in a wraparound fashion and the best eligible arc is selected
100 104
      /// from this block.
101 105
      BLOCK_SEARCH,
102 106

	
103 107
      /// The Candidate List pivot rule.
104 108
      /// In a major iteration a candidate list is built from eligible arcs
105 109
      /// in a wraparound fashion and in the following minor iterations
106 110
      /// the best eligible arc is selected from this list.
107 111
      CANDIDATE_LIST,
108 112

	
109 113
      /// The Altering Candidate List pivot rule.
110 114
      /// It is a modified version of the Candidate List method.
111 115
      /// It keeps only the several best eligible arcs from the former
112 116
      /// candidate list and extends this list in every iteration.
113 117
      ALTERING_LIST
114 118
    };
115 119

	
116 120
  private:
117 121

	
118 122
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
119 123

	
120
    typedef typename GR::template ArcMap<Value> ValueArcMap;
121
    typedef typename GR::template NodeMap<Value> ValueNodeMap;
124
    typedef typename GR::template ArcMap<Flow> FlowArcMap;
125
    typedef typename GR::template ArcMap<Cost> CostArcMap;
126
    typedef typename GR::template NodeMap<Flow> FlowNodeMap;
122 127

	
123 128
    typedef std::vector<Arc> ArcVector;
124 129
    typedef std::vector<Node> NodeVector;
125 130
    typedef std::vector<int> IntVector;
126 131
    typedef std::vector<bool> BoolVector;
127
    typedef std::vector<Value> ValueVector;
132
    typedef std::vector<Flow> FlowVector;
133
    typedef std::vector<Cost> CostVector;
128 134

	
129 135
    // State constants for arcs
130 136
    enum ArcStateEnum {
131 137
      STATE_UPPER = -1,
132 138
      STATE_TREE  =  0,
133 139
      STATE_LOWER =  1
134 140
    };
135 141

	
136 142
  private:
137 143

	
138 144
    // Data related to the underlying digraph
139 145
    const GR &_graph;
140 146
    int _node_num;
141 147
    int _arc_num;
142 148

	
143 149
    // Parameters of the problem
144
    ValueArcMap *_plower;
145
    ValueArcMap *_pupper;
146
    ValueArcMap *_pcost;
147
    ValueNodeMap *_psupply;
150
    FlowArcMap *_plower;
151
    FlowArcMap *_pupper;
152
    CostArcMap *_pcost;
153
    FlowNodeMap *_psupply;
148 154
    bool _pstsup;
149 155
    Node _psource, _ptarget;
150
    Value _pstflow;
156
    Flow _pstflow;
151 157

	
152 158
    // Result maps
153 159
    FlowMap *_flow_map;
154 160
    PotentialMap *_potential_map;
155 161
    bool _local_flow;
156 162
    bool _local_potential;
157 163

	
158 164
    // Data structures for storing the digraph
159 165
    IntNodeMap _node_id;
160 166
    ArcVector _arc_ref;
161 167
    IntVector _source;
162 168
    IntVector _target;
163 169

	
164 170
    // Node and arc data
165
    ValueVector _cap;
166
    ValueVector _cost;
167
    ValueVector _supply;
168
    ValueVector _flow;
169
    ValueVector _pi;
171
    FlowVector _cap;
172
    CostVector _cost;
173
    FlowVector _supply;
174
    FlowVector _flow;
175
    CostVector _pi;
170 176

	
171 177
    // Data for storing the spanning tree structure
172 178
    IntVector _parent;
173 179
    IntVector _pred;
174 180
    IntVector _thread;
175 181
    IntVector _rev_thread;
176 182
    IntVector _succ_num;
177 183
    IntVector _last_succ;
178 184
    IntVector _dirty_revs;
179 185
    BoolVector _forward;
180 186
    IntVector _state;
181 187
    int _root;
182 188

	
183 189
    // Temporary data used in the current pivot iteration
184 190
    int in_arc, join, u_in, v_in, u_out, v_out;
185 191
    int first, second, right, last;
186 192
    int stem, par_stem, new_stem;
187
    Value delta;
193
    Flow delta;
188 194

	
189 195
  private:
190 196

	
191 197
    // Implementation of the First Eligible pivot rule
192 198
    class FirstEligiblePivotRule
193 199
    {
194 200
    private:
195 201

	
196 202
      // References to the NetworkSimplex class
197 203
      const IntVector  &_source;
198 204
      const IntVector  &_target;
199
      const ValueVector &_cost;
205
      const CostVector &_cost;
200 206
      const IntVector  &_state;
201
      const ValueVector &_pi;
207
      const CostVector &_pi;
202 208
      int &_in_arc;
203 209
      int _arc_num;
204 210

	
205 211
      // Pivot rule data
206 212
      int _next_arc;
207 213

	
208 214
    public:
209 215

	
210 216
      // Constructor
211 217
      FirstEligiblePivotRule(NetworkSimplex &ns) :
212 218
        _source(ns._source), _target(ns._target),
213 219
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
214 220
        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
215 221
      {}
216 222

	
217 223
      // Find next entering arc
218 224
      bool findEnteringArc() {
219
        Value c;
225
        Cost c;
220 226
        for (int e = _next_arc; e < _arc_num; ++e) {
221 227
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
222 228
          if (c < 0) {
223 229
            _in_arc = e;
224 230
            _next_arc = e + 1;
225 231
            return true;
226 232
          }
227 233
        }
228 234
        for (int e = 0; e < _next_arc; ++e) {
229 235
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
230 236
          if (c < 0) {
231 237
            _in_arc = e;
232 238
            _next_arc = e + 1;
233 239
            return true;
234 240
          }
235 241
        }
236 242
        return false;
237 243
      }
238 244

	
239 245
    }; //class FirstEligiblePivotRule
240 246

	
241 247

	
242 248
    // Implementation of the Best Eligible pivot rule
243 249
    class BestEligiblePivotRule
244 250
    {
245 251
    private:
246 252

	
247 253
      // References to the NetworkSimplex class
248 254
      const IntVector  &_source;
249 255
      const IntVector  &_target;
250
      const ValueVector &_cost;
256
      const CostVector &_cost;
251 257
      const IntVector  &_state;
252
      const ValueVector &_pi;
258
      const CostVector &_pi;
253 259
      int &_in_arc;
254 260
      int _arc_num;
255 261

	
256 262
    public:
257 263

	
258 264
      // Constructor
259 265
      BestEligiblePivotRule(NetworkSimplex &ns) :
260 266
        _source(ns._source), _target(ns._target),
261 267
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
262 268
        _in_arc(ns.in_arc), _arc_num(ns._arc_num)
263 269
      {}
264 270

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

	
278 284
    }; //class BestEligiblePivotRule
279 285

	
280 286

	
281 287
    // Implementation of the Block Search pivot rule
282 288
    class BlockSearchPivotRule
283 289
    {
284 290
    private:
285 291

	
286 292
      // References to the NetworkSimplex class
287 293
      const IntVector  &_source;
288 294
      const IntVector  &_target;
289
      const ValueVector &_cost;
295
      const CostVector &_cost;
290 296
      const IntVector  &_state;
291
      const ValueVector &_pi;
297
      const CostVector &_pi;
292 298
      int &_in_arc;
293 299
      int _arc_num;
294 300

	
295 301
      // Pivot rule data
296 302
      int _block_size;
297 303
      int _next_arc;
298 304

	
299 305
    public:
300 306

	
301 307
      // Constructor
302 308
      BlockSearchPivotRule(NetworkSimplex &ns) :
303 309
        _source(ns._source), _target(ns._target),
304 310
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
305 311
        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
306 312
      {
307 313
        // The main parameters of the pivot rule
308 314
        const double BLOCK_SIZE_FACTOR = 2.0;
309 315
        const int MIN_BLOCK_SIZE = 10;
310 316

	
311 317
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
312 318
                                MIN_BLOCK_SIZE );
313 319
      }
314 320

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

	
350 356
    }; //class BlockSearchPivotRule
351 357

	
352 358

	
353 359
    // Implementation of the Candidate List pivot rule
354 360
    class CandidateListPivotRule
355 361
    {
356 362
    private:
357 363

	
358 364
      // References to the NetworkSimplex class
359 365
      const IntVector  &_source;
360 366
      const IntVector  &_target;
361
      const ValueVector &_cost;
367
      const CostVector &_cost;
362 368
      const IntVector  &_state;
363
      const ValueVector &_pi;
369
      const CostVector &_pi;
364 370
      int &_in_arc;
365 371
      int _arc_num;
366 372

	
367 373
      // Pivot rule data
368 374
      IntVector _candidates;
369 375
      int _list_length, _minor_limit;
370 376
      int _curr_length, _minor_count;
371 377
      int _next_arc;
372 378

	
373 379
    public:
374 380

	
375 381
      /// Constructor
376 382
      CandidateListPivotRule(NetworkSimplex &ns) :
377 383
        _source(ns._source), _target(ns._target),
378 384
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
379 385
        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
380 386
      {
381 387
        // The main parameters of the pivot rule
382 388
        const double LIST_LENGTH_FACTOR = 1.0;
383 389
        const int MIN_LIST_LENGTH = 10;
384 390
        const double MINOR_LIMIT_FACTOR = 0.1;
385 391
        const int MIN_MINOR_LIMIT = 3;
386 392

	
387 393
        _list_length = std::max( int(LIST_LENGTH_FACTOR * sqrt(_arc_num)),
388 394
                                 MIN_LIST_LENGTH );
389 395
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
390 396
                                 MIN_MINOR_LIMIT );
391 397
        _curr_length = _minor_count = 0;
392 398
        _candidates.resize(_list_length);
393 399
      }
394 400

	
395 401
      /// Find next entering arc
396 402
      bool findEnteringArc() {
397
        Value min, c;
403
        Cost min, c;
398 404
        int e, min_arc = _next_arc;
399 405
        if (_curr_length > 0 && _minor_count < _minor_limit) {
400 406
          // Minor iteration: select the best eligible arc from the
401 407
          // current candidate list
402 408
          ++_minor_count;
403 409
          min = 0;
404 410
          for (int i = 0; i < _curr_length; ++i) {
405 411
            e = _candidates[i];
406 412
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
407 413
            if (c < min) {
408 414
              min = c;
409 415
              min_arc = e;
410 416
            }
411 417
            if (c >= 0) {
412 418
              _candidates[i--] = _candidates[--_curr_length];
413 419
            }
414 420
          }
415 421
          if (min < 0) {
416 422
            _in_arc = min_arc;
417 423
            return true;
418 424
          }
419 425
        }
420 426

	
421 427
        // Major iteration: build a new candidate list
422 428
        min = 0;
423 429
        _curr_length = 0;
424 430
        for (e = _next_arc; e < _arc_num; ++e) {
425 431
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
426 432
          if (c < 0) {
427 433
            _candidates[_curr_length++] = e;
428 434
            if (c < min) {
429 435
              min = c;
430 436
              min_arc = e;
431 437
            }
432 438
            if (_curr_length == _list_length) break;
433 439
          }
434 440
        }
435 441
        if (_curr_length < _list_length) {
436 442
          for (e = 0; e < _next_arc; ++e) {
437 443
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
438 444
            if (c < 0) {
439 445
              _candidates[_curr_length++] = e;
440 446
              if (c < min) {
441 447
                min = c;
442 448
                min_arc = e;
443 449
              }
444 450
              if (_curr_length == _list_length) break;
445 451
            }
446 452
          }
447 453
        }
448 454
        if (_curr_length == 0) return false;
449 455
        _minor_count = 1;
450 456
        _in_arc = min_arc;
451 457
        _next_arc = e;
452 458
        return true;
453 459
      }
454 460

	
455 461
    }; //class CandidateListPivotRule
456 462

	
457 463

	
458 464
    // Implementation of the Altering Candidate List pivot rule
459 465
    class AlteringListPivotRule
460 466
    {
461 467
    private:
462 468

	
463 469
      // References to the NetworkSimplex class
464 470
      const IntVector  &_source;
465 471
      const IntVector  &_target;
466
      const ValueVector &_cost;
472
      const CostVector &_cost;
467 473
      const IntVector  &_state;
468
      const ValueVector &_pi;
474
      const CostVector &_pi;
469 475
      int &_in_arc;
470 476
      int _arc_num;
471 477

	
472 478
      // Pivot rule data
473 479
      int _block_size, _head_length, _curr_length;
474 480
      int _next_arc;
475 481
      IntVector _candidates;
476
      ValueVector _cand_cost;
482
      CostVector _cand_cost;
477 483

	
478 484
      // Functor class to compare arcs during sort of the candidate list
479 485
      class SortFunc
480 486
      {
481 487
      private:
482
        const ValueVector &_map;
488
        const CostVector &_map;
483 489
      public:
484
        SortFunc(const ValueVector &map) : _map(map) {}
490
        SortFunc(const CostVector &map) : _map(map) {}
485 491
        bool operator()(int left, int right) {
486 492
          return _map[left] > _map[right];
487 493
        }
488 494
      };
489 495

	
490 496
      SortFunc _sort_func;
491 497

	
492 498
    public:
493 499

	
494 500
      // Constructor
495 501
      AlteringListPivotRule(NetworkSimplex &ns) :
496 502
        _source(ns._source), _target(ns._target),
497 503
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
498 504
        _in_arc(ns.in_arc), _arc_num(ns._arc_num),
499 505
        _next_arc(0), _cand_cost(ns._arc_num), _sort_func(_cand_cost)
500 506
      {
501 507
        // The main parameters of the pivot rule
502 508
        const double BLOCK_SIZE_FACTOR = 1.5;
503 509
        const int MIN_BLOCK_SIZE = 10;
504 510
        const double HEAD_LENGTH_FACTOR = 0.1;
505 511
        const int MIN_HEAD_LENGTH = 3;
506 512

	
507 513
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
508 514
                                MIN_BLOCK_SIZE );
509 515
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
510 516
                                 MIN_HEAD_LENGTH );
511 517
        _candidates.resize(_head_length + _block_size);
512 518
        _curr_length = 0;
513 519
      }
514 520

	
515 521
      // Find next entering arc
516 522
      bool findEnteringArc() {
517 523
        // Check the current candidate list
518 524
        int e;
519 525
        for (int i = 0; i < _curr_length; ++i) {
520 526
          e = _candidates[i];
521 527
          _cand_cost[e] = _state[e] *
522 528
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
523 529
          if (_cand_cost[e] >= 0) {
524 530
            _candidates[i--] = _candidates[--_curr_length];
525 531
          }
526 532
        }
527 533

	
528 534
        // Extend the list
529 535
        int cnt = _block_size;
530 536
        int last_arc = 0;
531 537
        int limit = _head_length;
532 538

	
533 539
        for (int e = _next_arc; e < _arc_num; ++e) {
534 540
          _cand_cost[e] = _state[e] *
535 541
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
536 542
          if (_cand_cost[e] < 0) {
537 543
            _candidates[_curr_length++] = e;
538 544
            last_arc = e;
539 545
          }
540 546
          if (--cnt == 0) {
541 547
            if (_curr_length > limit) break;
542 548
            limit = 0;
543 549
            cnt = _block_size;
544 550
          }
545 551
        }
546 552
        if (_curr_length <= limit) {
547 553
          for (int e = 0; e < _next_arc; ++e) {
548 554
            _cand_cost[e] = _state[e] *
549 555
              (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
550 556
            if (_cand_cost[e] < 0) {
551 557
              _candidates[_curr_length++] = e;
552 558
              last_arc = e;
553 559
            }
554 560
            if (--cnt == 0) {
555 561
              if (_curr_length > limit) break;
556 562
              limit = 0;
557 563
              cnt = _block_size;
558 564
            }
559 565
          }
560 566
        }
561 567
        if (_curr_length == 0) return false;
562 568
        _next_arc = last_arc + 1;
563 569

	
564 570
        // Make heap of the candidate list (approximating a partial sort)
565 571
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
566 572
                   _sort_func );
567 573

	
568 574
        // Pop the first element of the heap
569 575
        _in_arc = _candidates[0];
570 576
        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
571 577
                  _sort_func );
572 578
        _curr_length = std::min(_head_length, _curr_length - 1);
573 579
        return true;
574 580
      }
575 581

	
576 582
    }; //class AlteringListPivotRule
577 583

	
578 584
  public:
579 585

	
580 586
    /// \brief Constructor.
581 587
    ///
582 588
    /// Constructor.
583 589
    ///
584 590
    /// \param graph The digraph the algorithm runs on.
585 591
    NetworkSimplex(const GR& graph) :
586 592
      _graph(graph),
587 593
      _plower(NULL), _pupper(NULL), _pcost(NULL),
588 594
      _psupply(NULL), _pstsup(false),
589 595
      _flow_map(NULL), _potential_map(NULL),
590 596
      _local_flow(false), _local_potential(false),
591 597
      _node_id(graph)
592 598
    {
593
      LEMON_ASSERT(std::numeric_limits<Value>::is_integer &&
594
                   std::numeric_limits<Value>::is_signed,
595
        "The value type of NetworkSimplex must be a signed integer");
599
      LEMON_ASSERT(std::numeric_limits<Flow>::is_integer &&
600
                   std::numeric_limits<Flow>::is_signed,
601
        "The flow type of NetworkSimplex must be signed integer");
602
      LEMON_ASSERT(std::numeric_limits<Cost>::is_integer &&
603
                   std::numeric_limits<Cost>::is_signed,
604
        "The cost type of NetworkSimplex must be signed integer");
596 605
    }
597 606

	
598 607
    /// Destructor.
599 608
    ~NetworkSimplex() {
600 609
      if (_local_flow) delete _flow_map;
601 610
      if (_local_potential) delete _potential_map;
602 611
    }
603 612

	
604 613
    /// \brief Set the lower bounds on the arcs.
605 614
    ///
606 615
    /// This function sets the lower bounds on the arcs.
607 616
    /// If neither this function nor \ref boundMaps() is used before
608 617
    /// calling \ref run(), the lower bounds will be set to zero
609 618
    /// on all arcs.
610 619
    ///
611 620
    /// \param map An arc map storing the lower bounds.
612
    /// Its \c Value type must be convertible to the \c Value type
621
    /// Its \c Value type must be convertible to the \c Flow type
613 622
    /// of the algorithm.
614 623
    ///
615 624
    /// \return <tt>(*this)</tt>
616 625
    template <typename LOWER>
617 626
    NetworkSimplex& lowerMap(const LOWER& map) {
618 627
      delete _plower;
619
      _plower = new ValueArcMap(_graph);
628
      _plower = new FlowArcMap(_graph);
620 629
      for (ArcIt a(_graph); a != INVALID; ++a) {
621 630
        (*_plower)[a] = map[a];
622 631
      }
623 632
      return *this;
624 633
    }
625 634

	
626 635
    /// \brief Set the upper bounds (capacities) on the arcs.
627 636
    ///
628 637
    /// This function sets the upper bounds (capacities) on the arcs.
629 638
    /// If none of the functions \ref upperMap(), \ref capacityMap()
630 639
    /// and \ref boundMaps() is used before calling \ref run(),
631 640
    /// the upper bounds (capacities) will be set to
632
    /// \c std::numeric_limits<Value>::max() on all arcs.
641
    /// \c std::numeric_limits<Flow>::max() on all arcs.
633 642
    ///
634 643
    /// \param map An arc map storing the upper bounds.
635
    /// Its \c Value type must be convertible to the \c Value type
644
    /// Its \c Value type must be convertible to the \c Flow type
636 645
    /// of the algorithm.
637 646
    ///
638 647
    /// \return <tt>(*this)</tt>
639 648
    template<typename UPPER>
640 649
    NetworkSimplex& upperMap(const UPPER& map) {
641 650
      delete _pupper;
642
      _pupper = new ValueArcMap(_graph);
651
      _pupper = new FlowArcMap(_graph);
643 652
      for (ArcIt a(_graph); a != INVALID; ++a) {
644 653
        (*_pupper)[a] = map[a];
645 654
      }
646 655
      return *this;
647 656
    }
648 657

	
649 658
    /// \brief Set the upper bounds (capacities) on the arcs.
650 659
    ///
651 660
    /// This function sets the upper bounds (capacities) on the arcs.
652 661
    /// It is just an alias for \ref upperMap().
653 662
    ///
654 663
    /// \return <tt>(*this)</tt>
655 664
    template<typename CAP>
656 665
    NetworkSimplex& capacityMap(const CAP& map) {
657 666
      return upperMap(map);
658 667
    }
659 668

	
660 669
    /// \brief Set the lower and upper bounds on the arcs.
661 670
    ///
662 671
    /// This function sets the lower and upper bounds on the arcs.
663 672
    /// If neither this function nor \ref lowerMap() is used before
664 673
    /// calling \ref run(), the lower bounds will be set to zero
665 674
    /// on all arcs.
666 675
    /// If none of the functions \ref upperMap(), \ref capacityMap()
667 676
    /// and \ref boundMaps() is used before calling \ref run(),
668 677
    /// the upper bounds (capacities) will be set to
669
    /// \c std::numeric_limits<Value>::max() on all arcs.
678
    /// \c std::numeric_limits<Flow>::max() on all arcs.
670 679
    ///
671 680
    /// \param lower An arc map storing the lower bounds.
672 681
    /// \param upper An arc map storing the upper bounds.
673 682
    ///
674 683
    /// The \c Value type of the maps must be convertible to the
675
    /// \c Value type of the algorithm.
684
    /// \c Flow type of the algorithm.
676 685
    ///
677 686
    /// \note This function is just a shortcut of calling \ref lowerMap()
678 687
    /// and \ref upperMap() separately.
679 688
    ///
680 689
    /// \return <tt>(*this)</tt>
681 690
    template <typename LOWER, typename UPPER>
682 691
    NetworkSimplex& boundMaps(const LOWER& lower, const UPPER& upper) {
683 692
      return lowerMap(lower).upperMap(upper);
684 693
    }
685 694

	
686 695
    /// \brief Set the costs of the arcs.
687 696
    ///
688 697
    /// This function sets the costs of the arcs.
689 698
    /// If it is not used before calling \ref run(), the costs
690 699
    /// will be set to \c 1 on all arcs.
691 700
    ///
692 701
    /// \param map An arc map storing the costs.
693
    /// Its \c Value type must be convertible to the \c Value type
702
    /// Its \c Value type must be convertible to the \c Cost type
694 703
    /// of the algorithm.
695 704
    ///
696 705
    /// \return <tt>(*this)</tt>
697 706
    template<typename COST>
698 707
    NetworkSimplex& costMap(const COST& map) {
699 708
      delete _pcost;
700
      _pcost = new ValueArcMap(_graph);
709
      _pcost = new CostArcMap(_graph);
701 710
      for (ArcIt a(_graph); a != INVALID; ++a) {
702 711
        (*_pcost)[a] = map[a];
703 712
      }
704 713
      return *this;
705 714
    }
706 715

	
707 716
    /// \brief Set the supply values of the nodes.
708 717
    ///
709 718
    /// This function sets the supply values of the nodes.
710 719
    /// If neither this function nor \ref stSupply() is used before
711 720
    /// calling \ref run(), the supply of each node will be set to zero.
712 721
    /// (It makes sense only if non-zero lower bounds are given.)
713 722
    ///
714 723
    /// \param map A node map storing the supply values.
715
    /// Its \c Value type must be convertible to the \c Value type
724
    /// Its \c Value type must be convertible to the \c Flow type
716 725
    /// of the algorithm.
717 726
    ///
718 727
    /// \return <tt>(*this)</tt>
719 728
    template<typename SUP>
720 729
    NetworkSimplex& supplyMap(const SUP& map) {
721 730
      delete _psupply;
722 731
      _pstsup = false;
723
      _psupply = new ValueNodeMap(_graph);
732
      _psupply = new FlowNodeMap(_graph);
724 733
      for (NodeIt n(_graph); n != INVALID; ++n) {
725 734
        (*_psupply)[n] = map[n];
726 735
      }
727 736
      return *this;
728 737
    }
729 738

	
730 739
    /// \brief Set single source and target nodes and a supply value.
731 740
    ///
732 741
    /// This function sets a single source node and a single target node
733 742
    /// and the required flow value.
734 743
    /// If neither this function nor \ref supplyMap() is used before
735 744
    /// calling \ref run(), the supply of each node will be set to zero.
736 745
    /// (It makes sense only if non-zero lower bounds are given.)
737 746
    ///
738 747
    /// \param s The source node.
739 748
    /// \param t The target node.
740 749
    /// \param k The required amount of flow from node \c s to node \c t
741 750
    /// (i.e. the supply of \c s and the demand of \c t).
742 751
    ///
743 752
    /// \return <tt>(*this)</tt>
744
    NetworkSimplex& stSupply(const Node& s, const Node& t, Value k) {
753
    NetworkSimplex& stSupply(const Node& s, const Node& t, Flow k) {
745 754
      delete _psupply;
746 755
      _psupply = NULL;
747 756
      _pstsup = true;
748 757
      _psource = s;
749 758
      _ptarget = t;
750 759
      _pstflow = k;
751 760
      return *this;
752 761
    }
753 762

	
754 763
    /// \brief Set the flow map.
755 764
    ///
756 765
    /// This function sets the flow map.
757 766
    /// If it is not used before calling \ref run(), an instance will
758 767
    /// be allocated automatically. The destructor deallocates this
759 768
    /// automatically allocated map, of course.
760 769
    ///
761 770
    /// \return <tt>(*this)</tt>
762 771
    NetworkSimplex& flowMap(FlowMap& map) {
763 772
      if (_local_flow) {
764 773
        delete _flow_map;
765 774
        _local_flow = false;
766 775
      }
767 776
      _flow_map = &map;
768 777
      return *this;
769 778
    }
770 779

	
771 780
    /// \brief Set the potential map.
772 781
    ///
773 782
    /// This function sets the potential map, which is used for storing
774 783
    /// the dual solution.
775 784
    /// If it is not used before calling \ref run(), an instance will
776 785
    /// be allocated automatically. The destructor deallocates this
777 786
    /// automatically allocated map, of course.
778 787
    ///
779 788
    /// \return <tt>(*this)</tt>
780 789
    NetworkSimplex& potentialMap(PotentialMap& map) {
781 790
      if (_local_potential) {
782 791
        delete _potential_map;
783 792
        _local_potential = false;
784 793
      }
785 794
      _potential_map = &map;
786 795
      return *this;
787 796
    }
788 797

	
789 798
    /// \name Execution Control
790 799
    /// The algorithm can be executed using \ref run().
791 800

	
792 801
    /// @{
793 802

	
794 803
    /// \brief Run the algorithm.
795 804
    ///
796 805
    /// This function runs the algorithm.
797 806
    /// The paramters can be specified using \ref lowerMap(),
798 807
    /// \ref upperMap(), \ref capacityMap(), \ref boundMaps(),
799 808
    /// \ref costMap(), \ref supplyMap() and \ref stSupply()
800 809
    /// functions. For example,
801 810
    /// \code
802 811
    ///   NetworkSimplex<ListDigraph> ns(graph);
803 812
    ///   ns.boundMaps(lower, upper).costMap(cost)
804 813
    ///     .supplyMap(sup).run();
805 814
    /// \endcode
806 815
    ///
807 816
    /// This function can be called more than once. All the parameters
808 817
    /// that have been given are kept for the next call, unless
809 818
    /// \ref reset() is called, thus only the modified parameters
810 819
    /// have to be set again. See \ref reset() for examples.
811 820
    ///
812 821
    /// \param pivot_rule The pivot rule that will be used during the
813 822
    /// algorithm. For more information see \ref PivotRule.
814 823
    ///
815 824
    /// \return \c true if a feasible flow can be found.
816 825
    bool run(PivotRule pivot_rule = BLOCK_SEARCH) {
817 826
      return init() && start(pivot_rule);
818 827
    }
819 828

	
820 829
    /// \brief Reset all the parameters that have been given before.
821 830
    ///
822 831
    /// This function resets all the paramaters that have been given
823 832
    /// using \ref lowerMap(), \ref upperMap(), \ref capacityMap(),
824 833
    /// \ref boundMaps(), \ref costMap(), \ref supplyMap() and
825 834
    /// \ref stSupply() functions before.
826 835
    ///
827 836
    /// It is useful for multiple run() calls. If this function is not
828 837
    /// used, all the parameters given before are kept for the next
829 838
    /// \ref run() call.
830 839
    ///
831 840
    /// For example,
832 841
    /// \code
833 842
    ///   NetworkSimplex<ListDigraph> ns(graph);
834 843
    ///
835 844
    ///   // First run
836 845
    ///   ns.lowerMap(lower).capacityMap(cap).costMap(cost)
837 846
    ///     .supplyMap(sup).run();
838 847
    ///
839 848
    ///   // Run again with modified cost map (reset() is not called,
840 849
    ///   // so only the cost map have to be set again)
841 850
    ///   cost[e] += 100;
842 851
    ///   ns.costMap(cost).run();
843 852
    ///
844 853
    ///   // Run again from scratch using reset()
845 854
    ///   // (the lower bounds will be set to zero on all arcs)
846 855
    ///   ns.reset();
847 856
    ///   ns.capacityMap(cap).costMap(cost)
848 857
    ///     .supplyMap(sup).run();
849 858
    /// \endcode
850 859
    ///
851 860
    /// \return <tt>(*this)</tt>
852 861
    NetworkSimplex& reset() {
853 862
      delete _plower;
854 863
      delete _pupper;
855 864
      delete _pcost;
856 865
      delete _psupply;
857 866
      _plower = NULL;
858 867
      _pupper = NULL;
859 868
      _pcost = NULL;
860 869
      _psupply = NULL;
861 870
      _pstsup = false;
862 871
      return *this;
863 872
    }
864 873

	
865 874
    /// @}
866 875

	
867 876
    /// \name Query Functions
868 877
    /// The results of the algorithm can be obtained using these
869 878
    /// functions.\n
870 879
    /// The \ref run() function must be called before using them.
871 880

	
872 881
    /// @{
873 882

	
874 883
    /// \brief Return the total cost of the found flow.
875 884
    ///
876 885
    /// This function returns the total cost of the found flow.
877
    /// The complexity of the function is \f$ O(e) \f$.
886
    /// The complexity of the function is O(e).
878 887
    ///
879 888
    /// \note The return type of the function can be specified as a
880 889
    /// template parameter. For example,
881 890
    /// \code
882 891
    ///   ns.totalCost<double>();
883 892
    /// \endcode
884
    /// It is useful if the total cost cannot be stored in the \c Value
893
    /// It is useful if the total cost cannot be stored in the \c Cost
885 894
    /// type of the algorithm, which is the default return type of the
886 895
    /// function.
887 896
    ///
888 897
    /// \pre \ref run() must be called before using this function.
889 898
    template <typename Num>
890 899
    Num totalCost() const {
891 900
      Num c = 0;
892 901
      if (_pcost) {
893 902
        for (ArcIt e(_graph); e != INVALID; ++e)
894 903
          c += (*_flow_map)[e] * (*_pcost)[e];
895 904
      } else {
896 905
        for (ArcIt e(_graph); e != INVALID; ++e)
897 906
          c += (*_flow_map)[e];
898 907
      }
899 908
      return c;
900 909
    }
901 910

	
902 911
#ifndef DOXYGEN
903
    Value totalCost() const {
904
      return totalCost<Value>();
912
    Cost totalCost() const {
913
      return totalCost<Cost>();
905 914
    }
906 915
#endif
907 916

	
908 917
    /// \brief Return the flow on the given arc.
909 918
    ///
910 919
    /// This function returns the flow on the given arc.
911 920
    ///
912 921
    /// \pre \ref run() must be called before using this function.
913
    Value flow(const Arc& a) const {
922
    Flow flow(const Arc& a) const {
914 923
      return (*_flow_map)[a];
915 924
    }
916 925

	
917 926
    /// \brief Return a const reference to the flow map.
918 927
    ///
919 928
    /// This function returns a const reference to an arc map storing
920 929
    /// the found flow.
921 930
    ///
922 931
    /// \pre \ref run() must be called before using this function.
923 932
    const FlowMap& flowMap() const {
924 933
      return *_flow_map;
925 934
    }
926 935

	
927 936
    /// \brief Return the potential (dual value) of the given node.
928 937
    ///
929 938
    /// This function returns the potential (dual value) of the
930 939
    /// given node.
931 940
    ///
932 941
    /// \pre \ref run() must be called before using this function.
933
    Value potential(const Node& n) const {
942
    Cost potential(const Node& n) const {
934 943
      return (*_potential_map)[n];
935 944
    }
936 945

	
937 946
    /// \brief Return a const reference to the potential map
938 947
    /// (the dual solution).
939 948
    ///
940 949
    /// This function returns a const reference to a node map storing
941 950
    /// the found potentials, which form the dual solution of the
942 951
    /// \ref min_cost_flow "minimum cost flow" problem.
943 952
    ///
944 953
    /// \pre \ref run() must be called before using this function.
945 954
    const PotentialMap& potentialMap() const {
946 955
      return *_potential_map;
947 956
    }
948 957

	
949 958
    /// @}
950 959

	
951 960
  private:
952 961

	
953 962
    // Initialize internal data structures
954 963
    bool init() {
955 964
      // Initialize result maps
956 965
      if (!_flow_map) {
957 966
        _flow_map = new FlowMap(_graph);
958 967
        _local_flow = true;
959 968
      }
960 969
      if (!_potential_map) {
961 970
        _potential_map = new PotentialMap(_graph);
962 971
        _local_potential = true;
963 972
      }
964 973

	
965 974
      // Initialize vectors
966 975
      _node_num = countNodes(_graph);
967 976
      _arc_num = countArcs(_graph);
968 977
      int all_node_num = _node_num + 1;
969 978
      int all_arc_num = _arc_num + _node_num;
970 979
      if (_node_num == 0) return false;
971 980

	
972 981
      _arc_ref.resize(_arc_num);
973 982
      _source.resize(all_arc_num);
974 983
      _target.resize(all_arc_num);
975 984

	
976 985
      _cap.resize(all_arc_num);
977 986
      _cost.resize(all_arc_num);
978 987
      _supply.resize(all_node_num);
979 988
      _flow.resize(all_arc_num);
980 989
      _pi.resize(all_node_num);
981 990

	
982 991
      _parent.resize(all_node_num);
983 992
      _pred.resize(all_node_num);
984 993
      _forward.resize(all_node_num);
985 994
      _thread.resize(all_node_num);
986 995
      _rev_thread.resize(all_node_num);
987 996
      _succ_num.resize(all_node_num);
988 997
      _last_succ.resize(all_node_num);
989 998
      _state.resize(all_arc_num);
990 999

	
991 1000
      // Initialize node related data
992 1001
      bool valid_supply = true;
993 1002
      if (!_pstsup && !_psupply) {
994 1003
        _pstsup = true;
995 1004
        _psource = _ptarget = NodeIt(_graph);
996 1005
        _pstflow = 0;
997 1006
      }
998 1007
      if (_psupply) {
999
        Value sum = 0;
1008
        Flow sum = 0;
1000 1009
        int i = 0;
1001 1010
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1002 1011
          _node_id[n] = i;
1003 1012
          _supply[i] = (*_psupply)[n];
1004 1013
          sum += _supply[i];
1005 1014
        }
1006 1015
        valid_supply = (sum == 0);
1007 1016
      } else {
1008 1017
        int i = 0;
1009 1018
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1010 1019
          _node_id[n] = i;
1011 1020
          _supply[i] = 0;
1012 1021
        }
1013 1022
        _supply[_node_id[_psource]] =  _pstflow;
1014 1023
        _supply[_node_id[_ptarget]]   = -_pstflow;
1015 1024
      }
1016 1025
      if (!valid_supply) return false;
1017 1026

	
1018 1027
      // Set data for the artificial root node
1019 1028
      _root = _node_num;
1020 1029
      _parent[_root] = -1;
1021 1030
      _pred[_root] = -1;
1022 1031
      _thread[_root] = 0;
1023 1032
      _rev_thread[0] = _root;
1024 1033
      _succ_num[_root] = all_node_num;
1025 1034
      _last_succ[_root] = _root - 1;
1026 1035
      _supply[_root] = 0;
1027 1036
      _pi[_root] = 0;
1028 1037

	
1029 1038
      // Store the arcs in a mixed order
1030 1039
      int k = std::max(int(sqrt(_arc_num)), 10);
1031 1040
      int i = 0;
1032 1041
      for (ArcIt e(_graph); e != INVALID; ++e) {
1033 1042
        _arc_ref[i] = e;
1034 1043
        if ((i += k) >= _arc_num) i = (i % k) + 1;
1035 1044
      }
1036 1045

	
1037 1046
      // Initialize arc maps
1047
      Flow max_cap = std::numeric_limits<Flow>::max();
1048
      Cost max_cost = std::numeric_limits<Cost>::max() / 4;
1038 1049
      if (_pupper && _pcost) {
1039 1050
        for (int i = 0; i != _arc_num; ++i) {
1040 1051
          Arc e = _arc_ref[i];
1041 1052
          _source[i] = _node_id[_graph.source(e)];
1042 1053
          _target[i] = _node_id[_graph.target(e)];
1043 1054
          _cap[i] = (*_pupper)[e];
1044 1055
          _cost[i] = (*_pcost)[e];
1045 1056
          _flow[i] = 0;
1046 1057
          _state[i] = STATE_LOWER;
1047 1058
        }
1048 1059
      } else {
1049 1060
        for (int i = 0; i != _arc_num; ++i) {
1050 1061
          Arc e = _arc_ref[i];
1051 1062
          _source[i] = _node_id[_graph.source(e)];
1052 1063
          _target[i] = _node_id[_graph.target(e)];
1053 1064
          _flow[i] = 0;
1054 1065
          _state[i] = STATE_LOWER;
1055 1066
        }
1056 1067
        if (_pupper) {
1057 1068
          for (int i = 0; i != _arc_num; ++i)
1058 1069
            _cap[i] = (*_pupper)[_arc_ref[i]];
1059 1070
        } else {
1060
          Value val = std::numeric_limits<Value>::max();
1061 1071
          for (int i = 0; i != _arc_num; ++i)
1062
            _cap[i] = val;
1072
            _cap[i] = max_cap;
1063 1073
        }
1064 1074
        if (_pcost) {
1065 1075
          for (int i = 0; i != _arc_num; ++i)
1066 1076
            _cost[i] = (*_pcost)[_arc_ref[i]];
1067 1077
        } else {
1068 1078
          for (int i = 0; i != _arc_num; ++i)
1069 1079
            _cost[i] = 1;
1070 1080
        }
1071 1081
      }
1072 1082

	
1073 1083
      // Remove non-zero lower bounds
1074 1084
      if (_plower) {
1075 1085
        for (int i = 0; i != _arc_num; ++i) {
1076
          Value c = (*_plower)[_arc_ref[i]];
1086
          Flow c = (*_plower)[_arc_ref[i]];
1077 1087
          if (c != 0) {
1078 1088
            _cap[i] -= c;
1079 1089
            _supply[_source[i]] -= c;
1080 1090
            _supply[_target[i]] += c;
1081 1091
          }
1082 1092
        }
1083 1093
      }
1084 1094

	
1085 1095
      // Add artificial arcs and initialize the spanning tree data structure
1086
      Value max_cap = std::numeric_limits<Value>::max();
1087
      Value max_cost = std::numeric_limits<Value>::max() / 4;
1088 1096
      for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1089 1097
        _thread[u] = u + 1;
1090 1098
        _rev_thread[u + 1] = u;
1091 1099
        _succ_num[u] = 1;
1092 1100
        _last_succ[u] = u;
1093 1101
        _parent[u] = _root;
1094 1102
        _pred[u] = e;
1095 1103
        _cost[e] = max_cost;
1096 1104
        _cap[e] = max_cap;
1097 1105
        _state[e] = STATE_TREE;
1098 1106
        if (_supply[u] >= 0) {
1099 1107
          _flow[e] = _supply[u];
1100 1108
          _forward[u] = true;
1101 1109
          _pi[u] = -max_cost;
1102 1110
        } else {
1103 1111
          _flow[e] = -_supply[u];
1104 1112
          _forward[u] = false;
1105 1113
          _pi[u] = max_cost;
1106 1114
        }
1107 1115
      }
1108 1116

	
1109 1117
      return true;
1110 1118
    }
1111 1119

	
1112 1120
    // Find the join node
1113 1121
    void findJoinNode() {
1114 1122
      int u = _source[in_arc];
1115 1123
      int v = _target[in_arc];
1116 1124
      while (u != v) {
1117 1125
        if (_succ_num[u] < _succ_num[v]) {
1118 1126
          u = _parent[u];
1119 1127
        } else {
1120 1128
          v = _parent[v];
1121 1129
        }
1122 1130
      }
1123 1131
      join = u;
1124 1132
    }
1125 1133

	
1126 1134
    // Find the leaving arc of the cycle and returns true if the
1127 1135
    // leaving arc is not the same as the entering arc
1128 1136
    bool findLeavingArc() {
1129 1137
      // Initialize first and second nodes according to the direction
1130 1138
      // of the cycle
1131 1139
      if (_state[in_arc] == STATE_LOWER) {
1132 1140
        first  = _source[in_arc];
1133 1141
        second = _target[in_arc];
1134 1142
      } else {
1135 1143
        first  = _target[in_arc];
1136 1144
        second = _source[in_arc];
1137 1145
      }
1138 1146
      delta = _cap[in_arc];
1139 1147
      int result = 0;
1140
      Value d;
1148
      Flow d;
1141 1149
      int e;
1142 1150

	
1143 1151
      // Search the cycle along the path form the first node to the root
1144 1152
      for (int u = first; u != join; u = _parent[u]) {
1145 1153
        e = _pred[u];
1146 1154
        d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
1147 1155
        if (d < delta) {
1148 1156
          delta = d;
1149 1157
          u_out = u;
1150 1158
          result = 1;
1151 1159
        }
1152 1160
      }
1153 1161
      // Search the cycle along the path form the second node to the root
1154 1162
      for (int u = second; u != join; u = _parent[u]) {
1155 1163
        e = _pred[u];
1156 1164
        d = _forward[u] ? _cap[e] - _flow[e] : _flow[e];
1157 1165
        if (d <= delta) {
1158 1166
          delta = d;
1159 1167
          u_out = u;
1160 1168
          result = 2;
1161 1169
        }
1162 1170
      }
1163 1171

	
1164 1172
      if (result == 1) {
1165 1173
        u_in = first;
1166 1174
        v_in = second;
1167 1175
      } else {
1168 1176
        u_in = second;
1169 1177
        v_in = first;
1170 1178
      }
1171 1179
      return result != 0;
1172 1180
    }
1173 1181

	
1174 1182
    // Change _flow and _state vectors
1175 1183
    void changeFlow(bool change) {
1176 1184
      // Augment along the cycle
1177 1185
      if (delta > 0) {
1178
        Value val = _state[in_arc] * delta;
1186
        Flow val = _state[in_arc] * delta;
1179 1187
        _flow[in_arc] += val;
1180 1188
        for (int u = _source[in_arc]; u != join; u = _parent[u]) {
1181 1189
          _flow[_pred[u]] += _forward[u] ? -val : val;
1182 1190
        }
1183 1191
        for (int u = _target[in_arc]; u != join; u = _parent[u]) {
1184 1192
          _flow[_pred[u]] += _forward[u] ? val : -val;
1185 1193
        }
1186 1194
      }
1187 1195
      // Update the state of the entering and leaving arcs
1188 1196
      if (change) {
1189 1197
        _state[in_arc] = STATE_TREE;
1190 1198
        _state[_pred[u_out]] =
1191 1199
          (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
1192 1200
      } else {
1193 1201
        _state[in_arc] = -_state[in_arc];
1194 1202
      }
1195 1203
    }
1196 1204

	
1197 1205
    // Update the tree structure
1198 1206
    void updateTreeStructure() {
1199 1207
      int u, w;
1200 1208
      int old_rev_thread = _rev_thread[u_out];
1201 1209
      int old_succ_num = _succ_num[u_out];
1202 1210
      int old_last_succ = _last_succ[u_out];
1203 1211
      v_out = _parent[u_out];
1204 1212

	
1205 1213
      u = _last_succ[u_in];  // the last successor of u_in
1206 1214
      right = _thread[u];    // the node after it
1207 1215

	
1208 1216
      // Handle the case when old_rev_thread equals to v_in
1209 1217
      // (it also means that join and v_out coincide)
1210 1218
      if (old_rev_thread == v_in) {
1211 1219
        last = _thread[_last_succ[u_out]];
1212 1220
      } else {
1213 1221
        last = _thread[v_in];
1214 1222
      }
1215 1223

	
1216 1224
      // Update _thread and _parent along the stem nodes (i.e. the nodes
1217 1225
      // between u_in and u_out, whose parent have to be changed)
1218 1226
      _thread[v_in] = stem = u_in;
1219 1227
      _dirty_revs.clear();
1220 1228
      _dirty_revs.push_back(v_in);
1221 1229
      par_stem = v_in;
1222 1230
      while (stem != u_out) {
1223 1231
        // Insert the next stem node into the thread list
1224 1232
        new_stem = _parent[stem];
1225 1233
        _thread[u] = new_stem;
1226 1234
        _dirty_revs.push_back(u);
1227 1235

	
1228 1236
        // Remove the subtree of stem from the thread list
1229 1237
        w = _rev_thread[stem];
1230 1238
        _thread[w] = right;
1231 1239
        _rev_thread[right] = w;
1232 1240

	
1233 1241
        // Change the parent node and shift stem nodes
1234 1242
        _parent[stem] = par_stem;
1235 1243
        par_stem = stem;
1236 1244
        stem = new_stem;
1237 1245

	
1238 1246
        // Update u and right
1239 1247
        u = _last_succ[stem] == _last_succ[par_stem] ?
1240 1248
          _rev_thread[par_stem] : _last_succ[stem];
1241 1249
        right = _thread[u];
1242 1250
      }
1243 1251
      _parent[u_out] = par_stem;
1244 1252
      _thread[u] = last;
1245 1253
      _rev_thread[last] = u;
1246 1254
      _last_succ[u_out] = u;
1247 1255

	
1248 1256
      // Remove the subtree of u_out from the thread list except for
1249 1257
      // the case when old_rev_thread equals to v_in
1250 1258
      // (it also means that join and v_out coincide)
1251 1259
      if (old_rev_thread != v_in) {
1252 1260
        _thread[old_rev_thread] = right;
1253 1261
        _rev_thread[right] = old_rev_thread;
1254 1262
      }
1255 1263

	
1256 1264
      // Update _rev_thread using the new _thread values
1257 1265
      for (int i = 0; i < int(_dirty_revs.size()); ++i) {
1258 1266
        u = _dirty_revs[i];
1259 1267
        _rev_thread[_thread[u]] = u;
1260 1268
      }
1261 1269

	
1262 1270
      // Update _pred, _forward, _last_succ and _succ_num for the
1263 1271
      // stem nodes from u_out to u_in
1264 1272
      int tmp_sc = 0, tmp_ls = _last_succ[u_out];
1265 1273
      u = u_out;
1266 1274
      while (u != u_in) {
1267 1275
        w = _parent[u];
1268 1276
        _pred[u] = _pred[w];
1269 1277
        _forward[u] = !_forward[w];
1270 1278
        tmp_sc += _succ_num[u] - _succ_num[w];
1271 1279
        _succ_num[u] = tmp_sc;
1272 1280
        _last_succ[w] = tmp_ls;
1273 1281
        u = w;
1274 1282
      }
1275 1283
      _pred[u_in] = in_arc;
1276 1284
      _forward[u_in] = (u_in == _source[in_arc]);
1277 1285
      _succ_num[u_in] = old_succ_num;
1278 1286

	
1279 1287
      // Set limits for updating _last_succ form v_in and v_out
1280 1288
      // towards the root
1281 1289
      int up_limit_in = -1;
1282 1290
      int up_limit_out = -1;
1283 1291
      if (_last_succ[join] == v_in) {
1284 1292
        up_limit_out = join;
1285 1293
      } else {
1286 1294
        up_limit_in = join;
1287 1295
      }
1288 1296

	
1289 1297
      // Update _last_succ from v_in towards the root
1290 1298
      for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
1291 1299
           u = _parent[u]) {
1292 1300
        _last_succ[u] = _last_succ[u_out];
1293 1301
      }
1294 1302
      // Update _last_succ from v_out towards the root
1295 1303
      if (join != old_rev_thread && v_in != old_rev_thread) {
1296 1304
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1297 1305
             u = _parent[u]) {
1298 1306
          _last_succ[u] = old_rev_thread;
1299 1307
        }
1300 1308
      } else {
1301 1309
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1302 1310
             u = _parent[u]) {
1303 1311
          _last_succ[u] = _last_succ[u_out];
1304 1312
        }
1305 1313
      }
1306 1314

	
1307 1315
      // Update _succ_num from v_in to join
1308 1316
      for (u = v_in; u != join; u = _parent[u]) {
1309 1317
        _succ_num[u] += old_succ_num;
1310 1318
      }
1311 1319
      // Update _succ_num from v_out to join
1312 1320
      for (u = v_out; u != join; u = _parent[u]) {
1313 1321
        _succ_num[u] -= old_succ_num;
1314 1322
      }
1315 1323
    }
1316 1324

	
1317 1325
    // Update potentials
1318 1326
    void updatePotential() {
1319
      Value sigma = _forward[u_in] ?
1327
      Cost sigma = _forward[u_in] ?
1320 1328
        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1321 1329
        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
1322 1330
      if (_succ_num[u_in] > _node_num / 2) {
1323 1331
        // Update in the upper subtree (which contains the root)
1324 1332
        int before = _rev_thread[u_in];
1325 1333
        int after = _thread[_last_succ[u_in]];
1326 1334
        _thread[before] = after;
1327 1335
        _pi[_root] -= sigma;
1328 1336
        for (int u = _thread[_root]; u != _root; u = _thread[u]) {
1329 1337
          _pi[u] -= sigma;
1330 1338
        }
1331 1339
        _thread[before] = u_in;
1332 1340
      } else {
1333 1341
        // Update in the lower subtree (which has been moved)
1334 1342
        int end = _thread[_last_succ[u_in]];
1335 1343
        for (int u = u_in; u != end; u = _thread[u]) {
1336 1344
          _pi[u] += sigma;
1337 1345
        }
1338 1346
      }
1339 1347
    }
1340 1348

	
1341 1349
    // Execute the algorithm
1342 1350
    bool start(PivotRule pivot_rule) {
1343 1351
      // Select the pivot rule implementation
1344 1352
      switch (pivot_rule) {
1345 1353
        case FIRST_ELIGIBLE:
1346 1354
          return start<FirstEligiblePivotRule>();
1347 1355
        case BEST_ELIGIBLE:
1348 1356
          return start<BestEligiblePivotRule>();
1349 1357
        case BLOCK_SEARCH:
1350 1358
          return start<BlockSearchPivotRule>();
1351 1359
        case CANDIDATE_LIST:
1352 1360
          return start<CandidateListPivotRule>();
1353 1361
        case ALTERING_LIST:
1354 1362
          return start<AlteringListPivotRule>();
1355 1363
      }
1356 1364
      return false;
1357 1365
    }
1358 1366

	
1359 1367
    template <typename PivotRuleImpl>
1360 1368
    bool start() {
1361 1369
      PivotRuleImpl pivot(*this);
1362 1370

	
1363 1371
      // Execute the Network Simplex algorithm
1364 1372
      while (pivot.findEnteringArc()) {
1365 1373
        findJoinNode();
1366 1374
        bool change = findLeavingArc();
1367 1375
        changeFlow(change);
1368 1376
        if (change) {
1369 1377
          updateTreeStructure();
1370 1378
          updatePotential();
1371 1379
        }
1372 1380
      }
1373 1381

	
1374 1382
      // Check if the flow amount equals zero on all the artificial arcs
1375 1383
      for (int e = _arc_num; e != _arc_num + _node_num; ++e) {
1376 1384
        if (_flow[e] > 0) return false;
1377 1385
      }
1378 1386

	
1379 1387
      // Copy flow values to _flow_map
1380 1388
      if (_plower) {
1381 1389
        for (int i = 0; i != _arc_num; ++i) {
1382 1390
          Arc e = _arc_ref[i];
1383 1391
          _flow_map->set(e, (*_plower)[e] + _flow[i]);
1384 1392
        }
1385 1393
      } else {
1386 1394
        for (int i = 0; i != _arc_num; ++i) {
1387 1395
          _flow_map->set(_arc_ref[i], _flow[i]);
1388 1396
        }
1389 1397
      }
1390 1398
      // Copy potential values to _potential_map
1391 1399
      for (NodeIt n(_graph); n != INVALID; ++n) {
1392 1400
        _potential_map->set(n, _pi[_node_id[n]]);
1393 1401
      }
1394 1402

	
1395 1403
      return true;
1396 1404
    }
1397 1405

	
1398 1406
  }; //class NetworkSimplex
1399 1407

	
1400 1408
  ///@}
1401 1409

	
1402 1410
} //namespace lemon
1403 1411

	
1404 1412
#endif //LEMON_NETWORK_SIMPLEX_H
Ignore white space 6291456 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
#include <fstream>
21 21

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

	
25 25
#include <lemon/network_simplex.h>
26 26

	
27 27
#include <lemon/concepts/digraph.h>
28 28
#include <lemon/concept_check.h>
29 29

	
30 30
#include "test_tools.h"
31 31

	
32 32
using namespace lemon;
33 33

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

	
78 78

	
79 79
// Check the interface of an MCF algorithm
80
template <typename GR, typename Value>
80
template <typename GR, typename Flow, typename Cost>
81 81
class McfClassConcept
82 82
{
83 83
public:
84 84

	
85 85
  template <typename MCF>
86 86
  struct Constraints {
87 87
    void constraints() {
88 88
      checkConcept<concepts::Digraph, GR>();
89 89

	
90 90
      MCF mcf(g);
91 91

	
92 92
      b = mcf.reset()
93 93
             .lowerMap(lower)
94 94
             .upperMap(upper)
95 95
             .capacityMap(upper)
96 96
             .boundMaps(lower, upper)
97 97
             .costMap(cost)
98 98
             .supplyMap(sup)
99 99
             .stSupply(n, n, k)
100 100
             .run();
101 101

	
102 102
      const typename MCF::FlowMap &fm = mcf.flowMap();
103 103
      const typename MCF::PotentialMap &pm = mcf.potentialMap();
104 104

	
105 105
      v = mcf.totalCost();
106 106
      double x = mcf.template totalCost<double>();
107 107
      v = mcf.flow(a);
108 108
      v = mcf.potential(n);
109 109
      mcf.flowMap(flow);
110 110
      mcf.potentialMap(pot);
111 111

	
112 112
      ignore_unused_variable_warning(fm);
113 113
      ignore_unused_variable_warning(pm);
114 114
      ignore_unused_variable_warning(x);
115 115
    }
116 116

	
117 117
    typedef typename GR::Node Node;
118 118
    typedef typename GR::Arc Arc;
119
    typedef concepts::ReadMap<Node, Value> NM;
120
    typedef concepts::ReadMap<Arc, Value> AM;
119
    typedef concepts::ReadMap<Node, Flow> NM;
120
    typedef concepts::ReadMap<Arc, Flow> FAM;
121
    typedef concepts::ReadMap<Arc, Cost> CAM;
121 122

	
122 123
    const GR &g;
123
    const AM &lower;
124
    const AM &upper;
125
    const AM &cost;
124
    const FAM &lower;
125
    const FAM &upper;
126
    const CAM &cost;
126 127
    const NM &sup;
127 128
    const Node &n;
128 129
    const Arc &a;
129
    const Value &k;
130
    Value v;
130
    const Flow &k;
131
    Flow v;
131 132
    bool b;
132 133

	
133 134
    typename MCF::FlowMap &flow;
134 135
    typename MCF::PotentialMap &pot;
135 136
  };
136 137

	
137 138
};
138 139

	
139 140

	
140 141
// Check the feasibility of the given flow (primal soluiton)
141 142
template < typename GR, typename LM, typename UM,
142 143
           typename SM, typename FM >
143 144
bool checkFlow( const GR& gr, const LM& lower, const UM& upper,
144 145
                const SM& supply, const FM& flow )
145 146
{
146 147
  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
147 148

	
148 149
  for (ArcIt e(gr); e != INVALID; ++e) {
149 150
    if (flow[e] < lower[e] || flow[e] > upper[e]) return false;
150 151
  }
151 152

	
152 153
  for (NodeIt n(gr); n != INVALID; ++n) {
153 154
    typename SM::Value sum = 0;
154 155
    for (OutArcIt e(gr, n); e != INVALID; ++e)
155 156
      sum += flow[e];
156 157
    for (InArcIt e(gr, n); e != INVALID; ++e)
157 158
      sum -= flow[e];
158 159
    if (sum != supply[n]) return false;
159 160
  }
160 161

	
161 162
  return true;
162 163
}
163 164

	
164 165
// Check the feasibility of the given potentials (dual soluiton)
165 166
// using the "Complementary Slackness" optimality condition
166 167
template < typename GR, typename LM, typename UM,
167 168
           typename CM, typename FM, typename PM >
168 169
bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
169 170
                     const CM& cost, const FM& flow, const PM& pi )
170 171
{
171 172
  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
172 173

	
173 174
  bool opt = true;
174 175
  for (ArcIt e(gr); opt && e != INVALID; ++e) {
175 176
    typename CM::Value red_cost =
176 177
      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
177 178
    opt = red_cost == 0 ||
178 179
          (red_cost > 0 && flow[e] == lower[e]) ||
179 180
          (red_cost < 0 && flow[e] == upper[e]);
180 181
  }
181 182
  return opt;
182 183
}
183 184

	
184 185
// Run a minimum cost flow algorithm and check the results
185 186
template < typename MCF, typename GR,
186 187
           typename LM, typename UM,
187 188
           typename CM, typename SM >
188 189
void checkMcf( const MCF& mcf, bool mcf_result,
189 190
               const GR& gr, const LM& lower, const UM& upper,
190 191
               const CM& cost, const SM& supply,
191 192
               bool result, typename CM::Value total,
192 193
               const std::string &test_id = "" )
193 194
{
194 195
  check(mcf_result == result, "Wrong result " + test_id);
195 196
  if (result) {
196 197
    check(checkFlow(gr, lower, upper, supply, mcf.flowMap()),
197 198
          "The flow is not feasible " + test_id);
198 199
    check(mcf.totalCost() == total, "The flow is not optimal " + test_id);
199 200
    check(checkPotential(gr, lower, upper, cost, mcf.flowMap(),
200 201
                         mcf.potentialMap()),
201 202
          "Wrong potentials " + test_id);
202 203
  }
203 204
}
204 205

	
205 206
int main()
206 207
{
207 208
  // Check the interfaces
208 209
  {
209
    typedef int Value;
210
    typedef int Flow;
211
    typedef int Cost;
210 212
    // TODO: This typedef should be enabled if the standard maps are
211 213
    // reference maps in the graph concepts (See #190).
212 214
/**/
213 215
    //typedef concepts::Digraph GR;
214 216
    typedef ListDigraph GR;
215 217
/**/
216
    checkConcept< McfClassConcept<GR, Value>,
217
                  NetworkSimplex<GR, Value> >();
218
    checkConcept< McfClassConcept<GR, Flow, Cost>,
219
                  NetworkSimplex<GR, Flow, Cost> >();
218 220
  }
219 221

	
220 222
  // Run various MCF tests
221 223
  typedef ListDigraph Digraph;
222 224
  DIGRAPH_TYPEDEFS(ListDigraph);
223 225

	
224 226
  // Read the test digraph
225 227
  Digraph gr;
226 228
  Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), u(gr);
227 229
  Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr);
228 230
  ConstMap<Arc, int> cc(1), cu(std::numeric_limits<int>::max());
229 231
  Node v, w;
230 232

	
231 233
  std::istringstream input(test_lgf);
232 234
  DigraphReader<Digraph>(gr, input)
233 235
    .arcMap("cost", c)
234 236
    .arcMap("cap", u)
235 237
    .arcMap("low1", l1)
236 238
    .arcMap("low2", l2)
237 239
    .nodeMap("sup1", s1)
238 240
    .nodeMap("sup2", s2)
239 241
    .nodeMap("sup3", s3)
240 242
    .node("source", v)
241 243
    .node("target", w)
242 244
    .run();
243 245

	
244 246
  // A. Test NetworkSimplex with the default pivot rule
245 247
  {
246 248
    NetworkSimplex<Digraph> mcf(gr);
247 249

	
248 250
    mcf.upperMap(u).costMap(c);
249 251
    checkMcf(mcf, mcf.supplyMap(s1).run(),
250 252
             gr, l1, u, c, s1, true,  5240, "#A1");
251 253
    checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
252 254
             gr, l1, u, c, s2, true,  7620, "#A2");
253 255
    mcf.lowerMap(l2);
254 256
    checkMcf(mcf, mcf.supplyMap(s1).run(),
255 257
             gr, l2, u, c, s1, true,  5970, "#A3");
256 258
    checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
257 259
             gr, l2, u, c, s2, true,  8010, "#A4");
258 260
    mcf.reset();
259 261
    checkMcf(mcf, mcf.supplyMap(s1).run(),
260 262
             gr, l1, cu, cc, s1, true,  74, "#A5");
261 263
    checkMcf(mcf, mcf.lowerMap(l2).stSupply(v, w, 27).run(),
262 264
             gr, l2, cu, cc, s2, true,  94, "#A6");
263 265
    mcf.reset();
264 266
    checkMcf(mcf, mcf.run(),
265 267
             gr, l1, cu, cc, s3, true,   0, "#A7");
266 268
    checkMcf(mcf, mcf.boundMaps(l2, u).run(),
267 269
             gr, l2, u, cc, s3, false,   0, "#A8");
268 270
  }
269 271

	
270 272
  // B. Test NetworkSimplex with each pivot rule
271 273
  {
272 274
    NetworkSimplex<Digraph> mcf(gr);
273 275
    mcf.supplyMap(s1).costMap(c).capacityMap(u).lowerMap(l2);
274 276

	
275 277
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::FIRST_ELIGIBLE),
276 278
             gr, l2, u, c, s1, true,  5970, "#B1");
277 279
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::BEST_ELIGIBLE),
278 280
             gr, l2, u, c, s1, true,  5970, "#B2");
279 281
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::BLOCK_SEARCH),
280 282
             gr, l2, u, c, s1, true,  5970, "#B3");
281 283
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::CANDIDATE_LIST),
282 284
             gr, l2, u, c, s1, true,  5970, "#B4");
283 285
    checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::ALTERING_LIST),
284 286
             gr, l2, u, c, s1, true,  5970, "#B5");
285 287
  }
286 288

	
287 289
  return 0;
288 290
}
0 comments (0 inline)