gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Fix critical bug in preflow (#372) The wrong transition between the bound decrease and highest active heuristics caused the bug. The last node chosen in bound decrease mode is used in the first iteration in highest active mode.
0 1 0
default
1 file changed with 24 insertions and 20 deletions:
↑ Collapse diff ↑
Ignore white space 24 line context
... ...
@@ -549,30 +549,36 @@
549 549
    ///
550 550
    /// The preflow algorithm consists of two phases, this method runs
551 551
    /// the first phase. After the first phase the maximum flow value
552 552
    /// and a minimum value cut can already be computed, although a
553 553
    /// maximum flow is not yet obtained. So after calling this method
554 554
    /// \ref flowValue() returns the value of a maximum flow and \ref
555 555
    /// minCut() returns a minimum cut.
556 556
    /// \pre One of the \ref init() functions must be called before
557 557
    /// using this function.
558 558
    void startFirstPhase() {
559 559
      _phase = true;
560 560

	
561
      Node n = _level->highestActive();
562
      int level = _level->highestActiveLevel();
563
      while (n != INVALID) {
561
      while (true) {
564 562
        int num = _node_num;
565 563

	
566
        while (num > 0 && n != INVALID) {
564
        Node n = INVALID;
565
        int level = -1;
566

	
567
        while (num > 0) {
568
          n = _level->highestActive();
569
          if (n == INVALID) goto first_phase_done;
570
          level = _level->highestActiveLevel();
571
          --num;
572
          
567 573
          Value excess = (*_excess)[n];
568 574
          int new_level = _level->maxLevel();
569 575

	
570 576
          for (OutArcIt e(_graph, n); e != INVALID; ++e) {
571 577
            Value rem = (*_capacity)[e] - (*_flow)[e];
572 578
            if (!_tolerance.positive(rem)) continue;
573 579
            Node v = _graph.target(e);
574 580
            if ((*_level)[v] < level) {
575 581
              if (!_level->active(v) && v != _target) {
576 582
                _level->activate(v);
577 583
              }
578 584
              if (!_tolerance.less(rem, excess)) {
... ...
@@ -620,32 +626,40 @@
620 626
          if (excess != 0) {
621 627
            if (new_level + 1 < _level->maxLevel()) {
622 628
              _level->liftHighestActive(new_level + 1);
623 629
            } else {
624 630
              _level->liftHighestActiveToTop();
625 631
            }
626 632
            if (_level->emptyLevel(level)) {
627 633
              _level->liftToTop(level);
628 634
            }
629 635
          } else {
630 636
            _level->deactivate(n);
631 637
          }
632

	
633
          n = _level->highestActive();
634
          level = _level->highestActiveLevel();
635
          --num;
636 638
        }
637 639

	
638 640
        num = _node_num * 20;
639
        while (num > 0 && n != INVALID) {
641
        while (num > 0) {
642
          while (level >= 0 && _level->activeFree(level)) {
643
            --level;
644
          }
645
          if (level == -1) {
646
            n = _level->highestActive();
647
            level = _level->highestActiveLevel();
648
            if (n == INVALID) goto first_phase_done;
649
          } else {
650
            n = _level->activeOn(level);
651
          }
652
          --num;
653

	
640 654
          Value excess = (*_excess)[n];
641 655
          int new_level = _level->maxLevel();
642 656

	
643 657
          for (OutArcIt e(_graph, n); e != INVALID; ++e) {
644 658
            Value rem = (*_capacity)[e] - (*_flow)[e];
645 659
            if (!_tolerance.positive(rem)) continue;
646 660
            Node v = _graph.target(e);
647 661
            if ((*_level)[v] < level) {
648 662
              if (!_level->active(v) && v != _target) {
649 663
                _level->activate(v);
650 664
              }
651 665
              if (!_tolerance.less(rem, excess)) {
... ...
@@ -693,37 +707,27 @@
693 707
          if (excess != 0) {
694 708
            if (new_level + 1 < _level->maxLevel()) {
695 709
              _level->liftActiveOn(level, new_level + 1);
696 710
            } else {
697 711
              _level->liftActiveToTop(level);
698 712
            }
699 713
            if (_level->emptyLevel(level)) {
700 714
              _level->liftToTop(level);
701 715
            }
702 716
          } else {
703 717
            _level->deactivate(n);
704 718
          }
705

	
706
          while (level >= 0 && _level->activeFree(level)) {
707
            --level;
708
          }
709
          if (level == -1) {
710
            n = _level->highestActive();
711
            level = _level->highestActiveLevel();
712
          } else {
713
            n = _level->activeOn(level);
714
          }
715
          --num;
716 719
        }
717 720
      }
721
    first_phase_done:;
718 722
    }
719 723

	
720 724
    /// \brief Starts the second phase of the preflow algorithm.
721 725
    ///
722 726
    /// The preflow algorithm consists of two phases, this method runs
723 727
    /// the second phase. After calling one of the \ref init() functions
724 728
    /// and \ref startFirstPhase() and then \ref startSecondPhase(),
725 729
    /// \ref flowMap() returns a maximum flow, \ref flowValue() returns the
726 730
    /// value of a maximum flow, \ref minCut() returns a minimum cut
727 731
    /// \pre One of the \ref init() functions and \ref startFirstPhase()
728 732
    /// must be called before using this function.
729 733
    void startSecondPhase() {
0 comments (0 inline)