gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Improve arc mixing in NS and enable it by default (#391)
0 1 0
default
1 file changed with 7 insertions and 6 deletions:
↑ Collapse diff ↑
Show white space 96 line context
... ...
@@ -591,101 +591,102 @@
591 591
          if (c < 0) {
592 592
            _cand_cost[e] = c;
593 593
            _candidates[_curr_length++] = e;
594 594
          }
595 595
          if (--cnt == 0) {
596 596
            if (_curr_length > limit) goto search_end;
597 597
            limit = 0;
598 598
            cnt = _block_size;
599 599
          }
600 600
        }
601 601
        for (e = 0; e != _next_arc; ++e) {
602 602
          _cand_cost[e] = _state[e] *
603 603
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
604 604
          if (_cand_cost[e] < 0) {
605 605
            _candidates[_curr_length++] = e;
606 606
          }
607 607
          if (--cnt == 0) {
608 608
            if (_curr_length > limit) goto search_end;
609 609
            limit = 0;
610 610
            cnt = _block_size;
611 611
          }
612 612
        }
613 613
        if (_curr_length == 0) return false;
614 614

	
615 615
      search_end:
616 616

	
617 617
        // Make heap of the candidate list (approximating a partial sort)
618 618
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
619 619
                   _sort_func );
620 620

	
621 621
        // Pop the first element of the heap
622 622
        _in_arc = _candidates[0];
623 623
        _next_arc = e;
624 624
        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
625 625
                  _sort_func );
626 626
        _curr_length = std::min(_head_length, _curr_length - 1);
627 627
        return true;
628 628
      }
629 629

	
630 630
    }; //class AlteringListPivotRule
631 631

	
632 632
  public:
633 633

	
634 634
    /// \brief Constructor.
635 635
    ///
636 636
    /// The constructor of the class.
637 637
    ///
638 638
    /// \param graph The digraph the algorithm runs on.
639
    /// \param arc_mixing Indicate if the arcs have to be stored in a
639
    /// \param arc_mixing Indicate if the arcs will be stored in a
640 640
    /// mixed order in the internal data structure.
641
    /// In special cases, it could lead to better overall performance,
642
    /// but it is usually slower. Therefore it is disabled by default.
643
    NetworkSimplex(const GR& graph, bool arc_mixing = false) :
641
    /// In general, it leads to similar performance as using the original
642
    /// arc order, but it makes the algorithm more robust and in special
643
    /// cases, even significantly faster. Therefore, it is enabled by default.
644
    NetworkSimplex(const GR& graph, bool arc_mixing = true) :
644 645
      _graph(graph), _node_id(graph), _arc_id(graph),
645 646
      _arc_mixing(arc_mixing),
646 647
      MAX(std::numeric_limits<Value>::max()),
647 648
      INF(std::numeric_limits<Value>::has_infinity ?
648 649
          std::numeric_limits<Value>::infinity() : MAX)
649 650
    {
650 651
      // Check the number types
651 652
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
652 653
        "The flow type of NetworkSimplex must be signed");
653 654
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
654 655
        "The cost type of NetworkSimplex must be signed");
655 656

	
656 657
      // Reset data structures
657 658
      reset();
658 659
    }
659 660

	
660 661
    /// \name Parameters
661 662
    /// The parameters of the algorithm can be specified using these
662 663
    /// functions.
663 664

	
664 665
    /// @{
665 666

	
666 667
    /// \brief Set the lower bounds on the arcs.
667 668
    ///
668 669
    /// This function sets the lower bounds on the arcs.
669 670
    /// If it is not used before calling \ref run(), the lower bounds
670 671
    /// will be set to zero on all arcs.
671 672
    ///
672 673
    /// \param map An arc map storing the lower bounds.
673 674
    /// Its \c Value type must be convertible to the \c Value type
674 675
    /// of the algorithm.
675 676
    ///
676 677
    /// \return <tt>(*this)</tt>
677 678
    template <typename LowerMap>
678 679
    NetworkSimplex& lowerMap(const LowerMap& map) {
679 680
      _have_lower = true;
680 681
      for (ArcIt a(_graph); a != INVALID; ++a) {
681 682
        _lower[_arc_id[a]] = map[a];
682 683
      }
683 684
      return *this;
684 685
    }
685 686

	
686 687
    /// \brief Set the upper bounds (capacities) on the arcs.
687 688
    ///
688 689
    /// This function sets the upper bounds (capacities) on the arcs.
689 690
    /// If it is not used before calling \ref run(), the upper bounds
690 691
    /// will be set to \ref INF on all arcs (i.e. the flow value will be
691 692
    /// unbounded from above).
... ...
@@ -885,103 +886,103 @@
885 886
    /// \ref supplyType().
886 887
    ///
887 888
    /// It is useful for multiple \ref run() calls. Basically, all the given
888 889
    /// parameters are kept for the next \ref run() call, unless
889 890
    /// \ref resetParams() or \ref reset() is used.
890 891
    /// If the underlying digraph was also modified after the construction
891 892
    /// of the class or the last \ref reset() call, then the \ref reset()
892 893
    /// function must be used, otherwise \ref resetParams() is sufficient.
893 894
    ///
894 895
    /// See \ref resetParams() for examples.
895 896
    ///
896 897
    /// \return <tt>(*this)</tt>
897 898
    ///
898 899
    /// \see resetParams(), run()
899 900
    NetworkSimplex& reset() {
900 901
      // Resize vectors
901 902
      _node_num = countNodes(_graph);
902 903
      _arc_num = countArcs(_graph);
903 904
      int all_node_num = _node_num + 1;
904 905
      int max_arc_num = _arc_num + 2 * _node_num;
905 906

	
906 907
      _source.resize(max_arc_num);
907 908
      _target.resize(max_arc_num);
908 909

	
909 910
      _lower.resize(_arc_num);
910 911
      _upper.resize(_arc_num);
911 912
      _cap.resize(max_arc_num);
912 913
      _cost.resize(max_arc_num);
913 914
      _supply.resize(all_node_num);
914 915
      _flow.resize(max_arc_num);
915 916
      _pi.resize(all_node_num);
916 917

	
917 918
      _parent.resize(all_node_num);
918 919
      _pred.resize(all_node_num);
919 920
      _pred_dir.resize(all_node_num);
920 921
      _thread.resize(all_node_num);
921 922
      _rev_thread.resize(all_node_num);
922 923
      _succ_num.resize(all_node_num);
923 924
      _last_succ.resize(all_node_num);
924 925
      _state.resize(max_arc_num);
925 926

	
926 927
      // Copy the graph
927 928
      int i = 0;
928 929
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
929 930
        _node_id[n] = i;
930 931
      }
931 932
      if (_arc_mixing) {
932 933
        // Store the arcs in a mixed order
933
        int k = std::max(int(std::sqrt(double(_arc_num))), 10);
934
        const int skip = std::max(_arc_num / _node_num, 3);
934 935
        int i = 0, j = 0;
935 936
        for (ArcIt a(_graph); a != INVALID; ++a) {
936 937
          _arc_id[a] = i;
937 938
          _source[i] = _node_id[_graph.source(a)];
938 939
          _target[i] = _node_id[_graph.target(a)];
939
          if ((i += k) >= _arc_num) i = ++j;
940
          if ((i += skip) >= _arc_num) i = ++j;
940 941
        }
941 942
      } else {
942 943
        // Store the arcs in the original order
943 944
        int i = 0;
944 945
        for (ArcIt a(_graph); a != INVALID; ++a, ++i) {
945 946
          _arc_id[a] = i;
946 947
          _source[i] = _node_id[_graph.source(a)];
947 948
          _target[i] = _node_id[_graph.target(a)];
948 949
        }
949 950
      }
950 951

	
951 952
      // Reset parameters
952 953
      resetParams();
953 954
      return *this;
954 955
    }
955 956

	
956 957
    /// @}
957 958

	
958 959
    /// \name Query Functions
959 960
    /// The results of the algorithm can be obtained using these
960 961
    /// functions.\n
961 962
    /// The \ref run() function must be called before using them.
962 963

	
963 964
    /// @{
964 965

	
965 966
    /// \brief Return the total cost of the found flow.
966 967
    ///
967 968
    /// This function returns the total cost of the found flow.
968 969
    /// Its complexity is O(e).
969 970
    ///
970 971
    /// \note The return type of the function can be specified as a
971 972
    /// template parameter. For example,
972 973
    /// \code
973 974
    ///   ns.totalCost<double>();
974 975
    /// \endcode
975 976
    /// It is useful if the total cost cannot be stored in the \c Cost
976 977
    /// type of the algorithm, which is the default return type of the
977 978
    /// function.
978 979
    ///
979 980
    /// \pre \ref run() must be called before using this function.
980 981
    template <typename Number>
981 982
    Number totalCost() const {
982 983
      Number c = 0;
983 984
      for (ArcIt a(_graph); a != INVALID; ++a) {
984 985
        int i = _arc_id[a];
985 986
        c += Number(_flow[i]) * Number(_cost[i]);
986 987
      }
987 988
      return c;
0 comments (0 inline)