gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 1 0
merge default
1 file changed with 71 insertions and 64 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
... ...
@@ -173,703 +173,710 @@
173 173
      STATE_LOWER =  1
174 174
    };
175 175

	
176 176
  private:
177 177

	
178 178
    // Data related to the underlying digraph
179 179
    const GR &_graph;
180 180
    int _node_num;
181 181
    int _arc_num;
182 182
    int _all_arc_num;
183 183
    int _search_arc_num;
184 184

	
185 185
    // Parameters of the problem
186 186
    bool _have_lower;
187 187
    SupplyType _stype;
188 188
    Value _sum_supply;
189 189

	
190 190
    // Data structures for storing the digraph
191 191
    IntNodeMap _node_id;
192 192
    IntArcMap _arc_id;
193 193
    IntVector _source;
194 194
    IntVector _target;
195 195

	
196 196
    // Node and arc data
197 197
    ValueVector _lower;
198 198
    ValueVector _upper;
199 199
    ValueVector _cap;
200 200
    CostVector _cost;
201 201
    ValueVector _supply;
202 202
    ValueVector _flow;
203 203
    CostVector _pi;
204 204

	
205 205
    // Data for storing the spanning tree structure
206 206
    IntVector _parent;
207 207
    IntVector _pred;
208 208
    IntVector _thread;
209 209
    IntVector _rev_thread;
210 210
    IntVector _succ_num;
211 211
    IntVector _last_succ;
212 212
    IntVector _dirty_revs;
213 213
    BoolVector _forward;
214 214
    IntVector _state;
215 215
    int _root;
216 216

	
217 217
    // Temporary data used in the current pivot iteration
218 218
    int in_arc, join, u_in, v_in, u_out, v_out;
219 219
    int first, second, right, last;
220 220
    int stem, par_stem, new_stem;
221 221
    Value delta;
222 222

	
223 223
  public:
224 224
  
225 225
    /// \brief Constant for infinite upper bounds (capacities).
226 226
    ///
227 227
    /// Constant for infinite upper bounds (capacities).
228 228
    /// It is \c std::numeric_limits<Value>::infinity() if available,
229 229
    /// \c std::numeric_limits<Value>::max() otherwise.
230 230
    const Value INF;
231 231

	
232 232
  private:
233 233

	
234 234
    // Implementation of the First Eligible pivot rule
235 235
    class FirstEligiblePivotRule
236 236
    {
237 237
    private:
238 238

	
239 239
      // References to the NetworkSimplex class
240 240
      const IntVector  &_source;
241 241
      const IntVector  &_target;
242 242
      const CostVector &_cost;
243 243
      const IntVector  &_state;
244 244
      const CostVector &_pi;
245 245
      int &_in_arc;
246 246
      int _search_arc_num;
247 247

	
248 248
      // Pivot rule data
249 249
      int _next_arc;
250 250

	
251 251
    public:
252 252

	
253 253
      // Constructor
254 254
      FirstEligiblePivotRule(NetworkSimplex &ns) :
255 255
        _source(ns._source), _target(ns._target),
256 256
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
257 257
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
258 258
        _next_arc(0)
259 259
      {}
260 260

	
261 261
      // Find next entering arc
262 262
      bool findEnteringArc() {
263 263
        Cost c;
264 264
        for (int e = _next_arc; e < _search_arc_num; ++e) {
265 265
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
266 266
          if (c < 0) {
267 267
            _in_arc = e;
268 268
            _next_arc = e + 1;
269 269
            return true;
270 270
          }
271 271
        }
272 272
        for (int e = 0; e < _next_arc; ++e) {
273 273
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
274 274
          if (c < 0) {
275 275
            _in_arc = e;
276 276
            _next_arc = e + 1;
277 277
            return true;
278 278
          }
279 279
        }
280 280
        return false;
281 281
      }
282 282

	
283 283
    }; //class FirstEligiblePivotRule
284 284

	
285 285

	
286 286
    // Implementation of the Best Eligible pivot rule
287 287
    class BestEligiblePivotRule
288 288
    {
289 289
    private:
290 290

	
291 291
      // References to the NetworkSimplex class
292 292
      const IntVector  &_source;
293 293
      const IntVector  &_target;
294 294
      const CostVector &_cost;
295 295
      const IntVector  &_state;
296 296
      const CostVector &_pi;
297 297
      int &_in_arc;
298 298
      int _search_arc_num;
299 299

	
300 300
    public:
301 301

	
302 302
      // Constructor
303 303
      BestEligiblePivotRule(NetworkSimplex &ns) :
304 304
        _source(ns._source), _target(ns._target),
305 305
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
306 306
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num)
307 307
      {}
308 308

	
309 309
      // Find next entering arc
310 310
      bool findEnteringArc() {
311 311
        Cost c, min = 0;
312 312
        for (int e = 0; e < _search_arc_num; ++e) {
313 313
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
314 314
          if (c < min) {
315 315
            min = c;
316 316
            _in_arc = e;
317 317
          }
318 318
        }
319 319
        return min < 0;
320 320
      }
321 321

	
322 322
    }; //class BestEligiblePivotRule
323 323

	
324 324

	
325 325
    // Implementation of the Block Search pivot rule
326 326
    class BlockSearchPivotRule
327 327
    {
328 328
    private:
329 329

	
330 330
      // References to the NetworkSimplex class
331 331
      const IntVector  &_source;
332 332
      const IntVector  &_target;
333 333
      const CostVector &_cost;
334 334
      const IntVector  &_state;
335 335
      const CostVector &_pi;
336 336
      int &_in_arc;
337 337
      int _search_arc_num;
338 338

	
339 339
      // Pivot rule data
340 340
      int _block_size;
341 341
      int _next_arc;
342 342

	
343 343
    public:
344 344

	
345 345
      // Constructor
346 346
      BlockSearchPivotRule(NetworkSimplex &ns) :
347 347
        _source(ns._source), _target(ns._target),
348 348
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
349 349
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
350 350
        _next_arc(0)
351 351
      {
352 352
        // The main parameters of the pivot rule
353 353
        const double BLOCK_SIZE_FACTOR = 0.5;
354 354
        const int MIN_BLOCK_SIZE = 10;
355 355

	
356 356
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
357 357
                                    std::sqrt(double(_search_arc_num))),
358 358
                                MIN_BLOCK_SIZE );
359 359
      }
360 360

	
361 361
      // Find next entering arc
362 362
      bool findEnteringArc() {
363 363
        Cost c, min = 0;
364 364
        int cnt = _block_size;
365
        int e, min_arc = _next_arc;
365
        int e;
366 366
        for (e = _next_arc; e < _search_arc_num; ++e) {
367 367
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
368 368
          if (c < min) {
369 369
            min = c;
370
            min_arc = e;
370
            _in_arc = e;
371 371
          }
372 372
          if (--cnt == 0) {
373
            if (min < 0) break;
373
            if (min < 0) goto search_end;
374 374
            cnt = _block_size;
375 375
          }
376 376
        }
377
        if (min == 0 || cnt > 0) {
378
          for (e = 0; e < _next_arc; ++e) {
379
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
380
            if (c < min) {
381
              min = c;
382
              min_arc = e;
383
            }
384
            if (--cnt == 0) {
385
              if (min < 0) break;
386
              cnt = _block_size;
387
            }
377
        for (e = 0; e < _next_arc; ++e) {
378
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
379
          if (c < min) {
380
            min = c;
381
            _in_arc = e;
382
          }
383
          if (--cnt == 0) {
384
            if (min < 0) goto search_end;
385
            cnt = _block_size;
388 386
          }
389 387
        }
390 388
        if (min >= 0) return false;
391
        _in_arc = min_arc;
389

	
390
      search_end:
392 391
        _next_arc = e;
393 392
        return true;
394 393
      }
395 394

	
396 395
    }; //class BlockSearchPivotRule
397 396

	
398 397

	
399 398
    // Implementation of the Candidate List pivot rule
400 399
    class CandidateListPivotRule
401 400
    {
402 401
    private:
403 402

	
404 403
      // References to the NetworkSimplex class
405 404
      const IntVector  &_source;
406 405
      const IntVector  &_target;
407 406
      const CostVector &_cost;
408 407
      const IntVector  &_state;
409 408
      const CostVector &_pi;
410 409
      int &_in_arc;
411 410
      int _search_arc_num;
412 411

	
413 412
      // Pivot rule data
414 413
      IntVector _candidates;
415 414
      int _list_length, _minor_limit;
416 415
      int _curr_length, _minor_count;
417 416
      int _next_arc;
418 417

	
419 418
    public:
420 419

	
421 420
      /// Constructor
422 421
      CandidateListPivotRule(NetworkSimplex &ns) :
423 422
        _source(ns._source), _target(ns._target),
424 423
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
425 424
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
426 425
        _next_arc(0)
427 426
      {
428 427
        // The main parameters of the pivot rule
429
        const double LIST_LENGTH_FACTOR = 1.0;
428
        const double LIST_LENGTH_FACTOR = 0.25;
430 429
        const int MIN_LIST_LENGTH = 10;
431 430
        const double MINOR_LIMIT_FACTOR = 0.1;
432 431
        const int MIN_MINOR_LIMIT = 3;
433 432

	
434 433
        _list_length = std::max( int(LIST_LENGTH_FACTOR *
435 434
                                     std::sqrt(double(_search_arc_num))),
436 435
                                 MIN_LIST_LENGTH );
437 436
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
438 437
                                 MIN_MINOR_LIMIT );
439 438
        _curr_length = _minor_count = 0;
440 439
        _candidates.resize(_list_length);
441 440
      }
442 441

	
443 442
      /// Find next entering arc
444 443
      bool findEnteringArc() {
445 444
        Cost min, c;
446
        int e, min_arc = _next_arc;
445
        int e;
447 446
        if (_curr_length > 0 && _minor_count < _minor_limit) {
448 447
          // Minor iteration: select the best eligible arc from the
449 448
          // current candidate list
450 449
          ++_minor_count;
451 450
          min = 0;
452 451
          for (int i = 0; i < _curr_length; ++i) {
453 452
            e = _candidates[i];
454 453
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
455 454
            if (c < min) {
456 455
              min = c;
457
              min_arc = e;
456
              _in_arc = e;
458 457
            }
459
            if (c >= 0) {
458
            else if (c >= 0) {
460 459
              _candidates[i--] = _candidates[--_curr_length];
461 460
            }
462 461
          }
463
          if (min < 0) {
464
            _in_arc = min_arc;
465
            return true;
466
          }
462
          if (min < 0) return true;
467 463
        }
468 464

	
469 465
        // Major iteration: build a new candidate list
470 466
        min = 0;
471 467
        _curr_length = 0;
472 468
        for (e = _next_arc; e < _search_arc_num; ++e) {
473 469
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
474 470
          if (c < 0) {
475 471
            _candidates[_curr_length++] = e;
476 472
            if (c < min) {
477 473
              min = c;
478
              min_arc = e;
474
              _in_arc = e;
479 475
            }
480
            if (_curr_length == _list_length) break;
476
            if (_curr_length == _list_length) goto search_end;
481 477
          }
482 478
        }
483
        if (_curr_length < _list_length) {
484
          for (e = 0; e < _next_arc; ++e) {
485
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
486
            if (c < 0) {
487
              _candidates[_curr_length++] = e;
488
              if (c < min) {
489
                min = c;
490
                min_arc = e;
491
              }
492
              if (_curr_length == _list_length) break;
479
        for (e = 0; e < _next_arc; ++e) {
480
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
481
          if (c < 0) {
482
            _candidates[_curr_length++] = e;
483
            if (c < min) {
484
              min = c;
485
              _in_arc = e;
493 486
            }
487
            if (_curr_length == _list_length) goto search_end;
494 488
          }
495 489
        }
496 490
        if (_curr_length == 0) return false;
491
      
492
      search_end:        
497 493
        _minor_count = 1;
498
        _in_arc = min_arc;
499 494
        _next_arc = e;
500 495
        return true;
501 496
      }
502 497

	
503 498
    }; //class CandidateListPivotRule
504 499

	
505 500

	
506 501
    // Implementation of the Altering Candidate List pivot rule
507 502
    class AlteringListPivotRule
508 503
    {
509 504
    private:
510 505

	
511 506
      // References to the NetworkSimplex class
512 507
      const IntVector  &_source;
513 508
      const IntVector  &_target;
514 509
      const CostVector &_cost;
515 510
      const IntVector  &_state;
516 511
      const CostVector &_pi;
517 512
      int &_in_arc;
518 513
      int _search_arc_num;
519 514

	
520 515
      // Pivot rule data
521 516
      int _block_size, _head_length, _curr_length;
522 517
      int _next_arc;
523 518
      IntVector _candidates;
524 519
      CostVector _cand_cost;
525 520

	
526 521
      // Functor class to compare arcs during sort of the candidate list
527 522
      class SortFunc
528 523
      {
529 524
      private:
530 525
        const CostVector &_map;
531 526
      public:
532 527
        SortFunc(const CostVector &map) : _map(map) {}
533 528
        bool operator()(int left, int right) {
534 529
          return _map[left] > _map[right];
535 530
        }
536 531
      };
537 532

	
538 533
      SortFunc _sort_func;
539 534

	
540 535
    public:
541 536

	
542 537
      // Constructor
543 538
      AlteringListPivotRule(NetworkSimplex &ns) :
544 539
        _source(ns._source), _target(ns._target),
545 540
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
546 541
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
547 542
        _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost)
548 543
      {
549 544
        // The main parameters of the pivot rule
550
        const double BLOCK_SIZE_FACTOR = 1.5;
545
        const double BLOCK_SIZE_FACTOR = 1.0;
551 546
        const int MIN_BLOCK_SIZE = 10;
552 547
        const double HEAD_LENGTH_FACTOR = 0.1;
553 548
        const int MIN_HEAD_LENGTH = 3;
554 549

	
555 550
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
556 551
                                    std::sqrt(double(_search_arc_num))),
557 552
                                MIN_BLOCK_SIZE );
558 553
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
559 554
                                 MIN_HEAD_LENGTH );
560 555
        _candidates.resize(_head_length + _block_size);
561 556
        _curr_length = 0;
562 557
      }
563 558

	
564 559
      // Find next entering arc
565 560
      bool findEnteringArc() {
566 561
        // Check the current candidate list
567 562
        int e;
568 563
        for (int i = 0; i < _curr_length; ++i) {
569 564
          e = _candidates[i];
570 565
          _cand_cost[e] = _state[e] *
571 566
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
572 567
          if (_cand_cost[e] >= 0) {
573 568
            _candidates[i--] = _candidates[--_curr_length];
574 569
          }
575 570
        }
576 571

	
577 572
        // Extend the list
578 573
        int cnt = _block_size;
579
        int last_arc = 0;
580 574
        int limit = _head_length;
581 575

	
582
        for (int e = _next_arc; e < _search_arc_num; ++e) {
576
        for (e = _next_arc; e < _search_arc_num; ++e) {
583 577
          _cand_cost[e] = _state[e] *
584 578
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
585 579
          if (_cand_cost[e] < 0) {
586 580
            _candidates[_curr_length++] = e;
587
            last_arc = e;
588 581
          }
589 582
          if (--cnt == 0) {
590
            if (_curr_length > limit) break;
583
            if (_curr_length > limit) goto search_end;
591 584
            limit = 0;
592 585
            cnt = _block_size;
593 586
          }
594 587
        }
595
        if (_curr_length <= limit) {
596
          for (int e = 0; e < _next_arc; ++e) {
597
            _cand_cost[e] = _state[e] *
598
              (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
599
            if (_cand_cost[e] < 0) {
600
              _candidates[_curr_length++] = e;
601
              last_arc = e;
602
            }
603
            if (--cnt == 0) {
604
              if (_curr_length > limit) break;
605
              limit = 0;
606
              cnt = _block_size;
607
            }
588
        for (e = 0; e < _next_arc; ++e) {
589
          _cand_cost[e] = _state[e] *
590
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
591
          if (_cand_cost[e] < 0) {
592
            _candidates[_curr_length++] = e;
593
          }
594
          if (--cnt == 0) {
595
            if (_curr_length > limit) goto search_end;
596
            limit = 0;
597
            cnt = _block_size;
608 598
          }
609 599
        }
610 600
        if (_curr_length == 0) return false;
611
        _next_arc = last_arc + 1;
601
        
602
      search_end:
612 603

	
613 604
        // Make heap of the candidate list (approximating a partial sort)
614 605
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
615 606
                   _sort_func );
616 607

	
617 608
        // Pop the first element of the heap
618 609
        _in_arc = _candidates[0];
610
        _next_arc = e;
619 611
        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
620 612
                  _sort_func );
621 613
        _curr_length = std::min(_head_length, _curr_length - 1);
622 614
        return true;
623 615
      }
624 616

	
625 617
    }; //class AlteringListPivotRule
626 618

	
627 619
  public:
628 620

	
629 621
    /// \brief Constructor.
630 622
    ///
631 623
    /// The constructor of the class.
632 624
    ///
633 625
    /// \param graph The digraph the algorithm runs on.
634
    NetworkSimplex(const GR& graph) :
626
    /// \param arc_mixing Indicate if the arcs have to be stored in a
627
    /// mixed order in the internal data structure. 
628
    /// In special cases, it could lead to better overall performance,
629
    /// but it is usually slower. Therefore it is disabled by default.
630
    NetworkSimplex(const GR& graph, bool arc_mixing = false) :
635 631
      _graph(graph), _node_id(graph), _arc_id(graph),
636 632
      INF(std::numeric_limits<Value>::has_infinity ?
637 633
          std::numeric_limits<Value>::infinity() :
638 634
          std::numeric_limits<Value>::max())
639 635
    {
640 636
      // Check the value types
641 637
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
642 638
        "The flow type of NetworkSimplex must be signed");
643 639
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
644 640
        "The cost type of NetworkSimplex must be signed");
645 641
        
646 642
      // Resize vectors
647 643
      _node_num = countNodes(_graph);
648 644
      _arc_num = countArcs(_graph);
649 645
      int all_node_num = _node_num + 1;
650 646
      int max_arc_num = _arc_num + 2 * _node_num;
651 647

	
652 648
      _source.resize(max_arc_num);
653 649
      _target.resize(max_arc_num);
654 650

	
655 651
      _lower.resize(_arc_num);
656 652
      _upper.resize(_arc_num);
657 653
      _cap.resize(max_arc_num);
658 654
      _cost.resize(max_arc_num);
659 655
      _supply.resize(all_node_num);
660 656
      _flow.resize(max_arc_num);
661 657
      _pi.resize(all_node_num);
662 658

	
663 659
      _parent.resize(all_node_num);
664 660
      _pred.resize(all_node_num);
665 661
      _forward.resize(all_node_num);
666 662
      _thread.resize(all_node_num);
667 663
      _rev_thread.resize(all_node_num);
668 664
      _succ_num.resize(all_node_num);
669 665
      _last_succ.resize(all_node_num);
670 666
      _state.resize(max_arc_num);
671 667

	
672
      // Copy the graph (store the arcs in a mixed order)
668
      // Copy the graph
673 669
      int i = 0;
674 670
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
675 671
        _node_id[n] = i;
676 672
      }
677
      int k = std::max(int(std::sqrt(double(_arc_num))), 10);
678
      i = 0;
679
      for (ArcIt a(_graph); a != INVALID; ++a) {
680
        _arc_id[a] = i;
681
        _source[i] = _node_id[_graph.source(a)];
682
        _target[i] = _node_id[_graph.target(a)];
683
        if ((i += k) >= _arc_num) i = (i % k) + 1;
673
      if (arc_mixing) {
674
        // Store the arcs in a mixed order
675
        int k = std::max(int(std::sqrt(double(_arc_num))), 10);
676
        int i = 0, j = 0;
677
        for (ArcIt a(_graph); a != INVALID; ++a) {
678
          _arc_id[a] = i;
679
          _source[i] = _node_id[_graph.source(a)];
680
          _target[i] = _node_id[_graph.target(a)];
681
          if ((i += k) >= _arc_num) i = ++j;
682
        }
683
      } else {
684
        // Store the arcs in the original order
685
        int i = 0;
686
        for (ArcIt a(_graph); a != INVALID; ++a, ++i) {
687
          _arc_id[a] = i;
688
          _source[i] = _node_id[_graph.source(a)];
689
          _target[i] = _node_id[_graph.target(a)];
690
        }
684 691
      }
685 692
      
686 693
      // Reset parameters
687 694
      reset();
688 695
    }
689 696

	
690 697
    /// \name Parameters
691 698
    /// The parameters of the algorithm can be specified using these
692 699
    /// functions.
693 700

	
694 701
    /// @{
695 702

	
696 703
    /// \brief Set the lower bounds on the arcs.
697 704
    ///
698 705
    /// This function sets the lower bounds on the arcs.
699 706
    /// If it is not used before calling \ref run(), the lower bounds
700 707
    /// will be set to zero on all arcs.
701 708
    ///
702 709
    /// \param map An arc map storing the lower bounds.
703 710
    /// Its \c Value type must be convertible to the \c Value type
704 711
    /// of the algorithm.
705 712
    ///
706 713
    /// \return <tt>(*this)</tt>
707 714
    template <typename LowerMap>
708 715
    NetworkSimplex& lowerMap(const LowerMap& map) {
709 716
      _have_lower = true;
710 717
      for (ArcIt a(_graph); a != INVALID; ++a) {
711 718
        _lower[_arc_id[a]] = map[a];
712 719
      }
713 720
      return *this;
714 721
    }
715 722

	
716 723
    /// \brief Set the upper bounds (capacities) on the arcs.
717 724
    ///
718 725
    /// This function sets the upper bounds (capacities) on the arcs.
719 726
    /// If it is not used before calling \ref run(), the upper bounds
720 727
    /// will be set to \ref INF on all arcs (i.e. the flow value will be
721 728
    /// unbounded from above on each arc).
722 729
    ///
723 730
    /// \param map An arc map storing the upper bounds.
724 731
    /// Its \c Value type must be convertible to the \c Value type
725 732
    /// of the algorithm.
726 733
    ///
727 734
    /// \return <tt>(*this)</tt>
728 735
    template<typename UpperMap>
729 736
    NetworkSimplex& upperMap(const UpperMap& map) {
730 737
      for (ArcIt a(_graph); a != INVALID; ++a) {
731 738
        _upper[_arc_id[a]] = map[a];
732 739
      }
733 740
      return *this;
734 741
    }
735 742

	
736 743
    /// \brief Set the costs of the arcs.
737 744
    ///
738 745
    /// This function sets the costs of the arcs.
739 746
    /// If it is not used before calling \ref run(), the costs
740 747
    /// will be set to \c 1 on all arcs.
741 748
    ///
742 749
    /// \param map An arc map storing the costs.
743 750
    /// Its \c Value type must be convertible to the \c Cost type
744 751
    /// of the algorithm.
745 752
    ///
746 753
    /// \return <tt>(*this)</tt>
747 754
    template<typename CostMap>
748 755
    NetworkSimplex& costMap(const CostMap& map) {
749 756
      for (ArcIt a(_graph); a != INVALID; ++a) {
750 757
        _cost[_arc_id[a]] = map[a];
751 758
      }
752 759
      return *this;
753 760
    }
754 761

	
755 762
    /// \brief Set the supply values of the nodes.
756 763
    ///
757 764
    /// This function sets the supply values of the nodes.
758 765
    /// If neither this function nor \ref stSupply() is used before
759 766
    /// calling \ref run(), the supply of each node will be set to zero.
760 767
    ///
761 768
    /// \param map A node map storing the supply values.
762 769
    /// Its \c Value type must be convertible to the \c Value type
763 770
    /// of the algorithm.
764 771
    ///
765 772
    /// \return <tt>(*this)</tt>
766 773
    template<typename SupplyMap>
767 774
    NetworkSimplex& supplyMap(const SupplyMap& map) {
768 775
      for (NodeIt n(_graph); n != INVALID; ++n) {
769 776
        _supply[_node_id[n]] = map[n];
770 777
      }
771 778
      return *this;
772 779
    }
773 780

	
774 781
    /// \brief Set single source and target nodes and a supply value.
775 782
    ///
776 783
    /// This function sets a single source node and a single target node
777 784
    /// and the required flow value.
778 785
    /// If neither this function nor \ref supplyMap() is used before
779 786
    /// calling \ref run(), the supply of each node will be set to zero.
780 787
    ///
781 788
    /// Using this function has the same effect as using \ref supplyMap()
782 789
    /// with such a map in which \c k is assigned to \c s, \c -k is
783 790
    /// assigned to \c t and all other nodes have zero supply value.
784 791
    ///
785 792
    /// \param s The source node.
786 793
    /// \param t The target node.
787 794
    /// \param k The required amount of flow from node \c s to node \c t
788 795
    /// (i.e. the supply of \c s and the demand of \c t).
789 796
    ///
790 797
    /// \return <tt>(*this)</tt>
791 798
    NetworkSimplex& stSupply(const Node& s, const Node& t, Value k) {
792 799
      for (int i = 0; i != _node_num; ++i) {
793 800
        _supply[i] = 0;
794 801
      }
795 802
      _supply[_node_id[s]] =  k;
796 803
      _supply[_node_id[t]] = -k;
797 804
      return *this;
798 805
    }
799 806
    
800 807
    /// \brief Set the type of the supply constraints.
801 808
    ///
802 809
    /// This function sets the type of the supply/demand constraints.
803 810
    /// If it is not used before calling \ref run(), the \ref GEQ supply
804 811
    /// type will be used.
805 812
    ///
806 813
    /// For more information see \ref SupplyType.
807 814
    ///
808 815
    /// \return <tt>(*this)</tt>
809 816
    NetworkSimplex& supplyType(SupplyType supply_type) {
810 817
      _stype = supply_type;
811 818
      return *this;
812 819
    }
813 820

	
814 821
    /// @}
815 822

	
816 823
    /// \name Execution Control
817 824
    /// The algorithm can be executed using \ref run().
818 825

	
819 826
    /// @{
820 827

	
821 828
    /// \brief Run the algorithm.
822 829
    ///
823 830
    /// This function runs the algorithm.
824 831
    /// The paramters can be specified using functions \ref lowerMap(),
825 832
    /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(), 
826 833
    /// \ref supplyType().
827 834
    /// For example,
828 835
    /// \code
829 836
    ///   NetworkSimplex<ListDigraph> ns(graph);
830 837
    ///   ns.lowerMap(lower).upperMap(upper).costMap(cost)
831 838
    ///     .supplyMap(sup).run();
832 839
    /// \endcode
833 840
    ///
834 841
    /// This function can be called more than once. All the parameters
835 842
    /// that have been given are kept for the next call, unless
836 843
    /// \ref reset() is called, thus only the modified parameters
837 844
    /// have to be set again. See \ref reset() for examples.
838 845
    /// However the underlying digraph must not be modified after this
839 846
    /// class have been constructed, since it copies and extends the graph.
840 847
    ///
841 848
    /// \param pivot_rule The pivot rule that will be used during the
842 849
    /// algorithm. For more information see \ref PivotRule.
843 850
    ///
844 851
    /// \return \c INFEASIBLE if no feasible flow exists,
845 852
    /// \n \c OPTIMAL if the problem has optimal solution
846 853
    /// (i.e. it is feasible and bounded), and the algorithm has found
847 854
    /// optimal flow and node potentials (primal and dual solutions),
848 855
    /// \n \c UNBOUNDED if the objective function of the problem is
849 856
    /// unbounded, i.e. there is a directed cycle having negative total
850 857
    /// cost and infinite upper bound.
851 858
    ///
852 859
    /// \see ProblemType, PivotRule
853 860
    ProblemType run(PivotRule pivot_rule = BLOCK_SEARCH) {
854 861
      if (!init()) return INFEASIBLE;
855 862
      return start(pivot_rule);
856 863
    }
857 864

	
858 865
    /// \brief Reset all the parameters that have been given before.
859 866
    ///
860 867
    /// This function resets all the paramaters that have been given
861 868
    /// before using functions \ref lowerMap(), \ref upperMap(),
862 869
    /// \ref costMap(), \ref supplyMap(), \ref stSupply(), \ref supplyType().
863 870
    ///
864 871
    /// It is useful for multiple run() calls. If this function is not
865 872
    /// used, all the parameters given before are kept for the next
866 873
    /// \ref run() call.
867 874
    /// However the underlying digraph must not be modified after this
868 875
    /// class have been constructed, since it copies and extends the graph.
869 876
    ///
870 877
    /// For example,
871 878
    /// \code
872 879
    ///   NetworkSimplex<ListDigraph> ns(graph);
873 880
    ///
874 881
    ///   // First run
875 882
    ///   ns.lowerMap(lower).upperMap(upper).costMap(cost)
0 comments (0 inline)