gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add a parameter to control arc mixing in NS (#298)
0 1 0
default
1 file changed with 19 insertions and 4 deletions:
↑ Collapse diff ↑
Show white space 192 line context
... ...
@@ -532,242 +532,257 @@
532 532
        }
533 533
      };
534 534

	
535 535
      SortFunc _sort_func;
536 536

	
537 537
    public:
538 538

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

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

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

	
574 574
        // Extend the list
575 575
        int cnt = _block_size;
576 576
        int limit = _head_length;
577 577

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

	
606 606
        // Make heap of the candidate list (approximating a partial sort)
607 607
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
608 608
                   _sort_func );
609 609

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

	
619 619
    }; //class AlteringListPivotRule
620 620

	
621 621
  public:
622 622

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

	
646 650
      _source.resize(max_arc_num);
647 651
      _target.resize(max_arc_num);
648 652

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

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

	
666
      // Copy the graph (store the arcs in a mixed order)
670
      // Copy the graph
667 671
      int i = 0;
668 672
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
669 673
        _node_id[n] = i;
670 674
      }
675
      if (arc_mixing) {
676
        // Store the arcs in a mixed order
671 677
      int k = std::max(int(std::sqrt(double(_arc_num))), 10);
672
      i = 0;
678
        int i = 0, j = 0;
673 679
      for (ArcIt a(_graph); a != INVALID; ++a) {
674 680
        _arc_id[a] = i;
675 681
        _source[i] = _node_id[_graph.source(a)];
676 682
        _target[i] = _node_id[_graph.target(a)];
677
        if ((i += k) >= _arc_num) i = (i % k) + 1;
683
          if ((i += k) >= _arc_num) i = ++j;
684
        }
685
      } else {
686
        // Store the arcs in the original order
687
        int i = 0;
688
        for (ArcIt a(_graph); a != INVALID; ++a, ++i) {
689
          _arc_id[a] = i;
690
          _source[i] = _node_id[_graph.source(a)];
691
          _target[i] = _node_id[_graph.target(a)];
692
        }
678 693
      }
679 694
      
680 695
      // Initialize maps
681 696
      for (int i = 0; i != _node_num; ++i) {
682 697
        _supply[i] = 0;
683 698
      }
684 699
      for (int i = 0; i != _arc_num; ++i) {
685 700
        _lower[i] = 0;
686 701
        _upper[i] = INF;
687 702
        _cost[i] = 1;
688 703
      }
689 704
      _have_lower = false;
690 705
      _stype = GEQ;
691 706
    }
692 707

	
693 708
    /// \name Parameters
694 709
    /// The parameters of the algorithm can be specified using these
695 710
    /// functions.
696 711

	
697 712
    /// @{
698 713

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

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

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

	
758 773
    /// \brief Set the supply values of the nodes.
759 774
    ///
760 775
    /// This function sets the supply values of the nodes.
761 776
    /// If neither this function nor \ref stSupply() is used before
762 777
    /// calling \ref run(), the supply of each node will be set to zero.
763 778
    /// (It makes sense only if non-zero lower bounds are given.)
764 779
    ///
765 780
    /// \param map A node map storing the supply values.
766 781
    /// Its \c Value type must be convertible to the \c Value type
767 782
    /// of the algorithm.
768 783
    ///
769 784
    /// \return <tt>(*this)</tt>
770 785
    template<typename SupplyMap>
771 786
    NetworkSimplex& supplyMap(const SupplyMap& map) {
772 787
      for (NodeIt n(_graph); n != INVALID; ++n) {
773 788
        _supply[_node_id[n]] = map[n];
0 comments (0 inline)