# HG changeset patch
# User Peter Kovacs <kpeter@inf.elte.hu>
# Date 1327951305 -3600
# Node ID fcb6ad1e67d066f8960c43cf1c51bd763f46a306
# Parent 48e17328c1551cb8196973d6056a04e40e5d624a
Improve the Altering List pivot rule for NetworkSimplex (#435)
Much less candidate arcs are preserved from an iteration to the
next one and partial_sort() is used instead of heap operations.
diff --git a/lemon/network_simplex.h b/lemon/network_simplex.h
a
|
b
|
|
122 | 122 | /// Enum type containing constants for selecting the pivot rule for |
123 | 123 | /// the \ref run() function. |
124 | 124 | /// |
125 | | /// \ref NetworkSimplex provides five different pivot rule |
126 | | /// implementations that significantly affect the running time |
| 125 | /// \ref NetworkSimplex provides five different implementations for |
| 126 | /// the pivot strategy that significantly affects the running time |
127 | 127 | /// of the algorithm. |
128 | | /// By default, \ref BLOCK_SEARCH "Block Search" is used, which |
129 | | /// turend out to be the most efficient and the most robust on various |
130 | | /// test inputs. |
131 | | /// However, another pivot rule can be selected using the \ref run() |
132 | | /// function with the proper parameter. |
| 128 | /// According to experimental tests conducted on various problem |
| 129 | /// instances, \ref BLOCK_SEARCH "Block Search" and |
| 130 | /// \ref ALTERING_LIST "Altering Candidate List" rules turned out |
| 131 | /// to be the most efficient. |
| 132 | /// Since \ref BLOCK_SEARCH "Block Search" is a simpler strategy that |
| 133 | /// seemed to be slightly more robust, it is used by default. |
| 134 | /// However, another pivot rule can easily be selected using the |
| 135 | /// \ref run() function with the proper parameter. |
133 | 136 | enum PivotRule { |
134 | 137 | |
135 | 138 | /// The \e First \e Eligible pivot rule. |
… |
… |
|
155 | 158 | |
156 | 159 | /// The \e Altering \e Candidate \e List pivot rule. |
157 | 160 | /// It is a modified version of the Candidate List method. |
158 | | /// It keeps only the several best eligible arcs from the former |
| 161 | /// It keeps only a few of the best eligible arcs from the former |
159 | 162 | /// candidate list and extends this list in every iteration. |
160 | 163 | ALTERING_LIST |
161 | 164 | }; |
… |
… |
|
538 | 541 | public: |
539 | 542 | SortFunc(const CostVector &map) : _map(map) {} |
540 | 543 | bool operator()(int left, int right) { |
541 | | return _map[left] > _map[right]; |
| 544 | return _map[left] < _map[right]; |
542 | 545 | } |
543 | 546 | }; |
544 | 547 | |
… |
… |
|
556 | 559 | // The main parameters of the pivot rule |
557 | 560 | const double BLOCK_SIZE_FACTOR = 1.0; |
558 | 561 | const int MIN_BLOCK_SIZE = 10; |
559 | | const double HEAD_LENGTH_FACTOR = 0.1; |
| 562 | const double HEAD_LENGTH_FACTOR = 0.01; |
560 | 563 | const int MIN_HEAD_LENGTH = 3; |
561 | 564 | |
562 | 565 | _block_size = std::max( int(BLOCK_SIZE_FACTOR * |
… |
… |
|
600 | 603 | } |
601 | 604 | } |
602 | 605 | for (e = 0; e != _next_arc; ++e) { |
603 | | _cand_cost[e] = _state[e] * |
604 | | (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
605 | | if (_cand_cost[e] < 0) { |
| 606 | c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
| 607 | if (c < 0) { |
| 608 | _cand_cost[e] = c; |
606 | 609 | _candidates[_curr_length++] = e; |
607 | 610 | } |
608 | 611 | if (--cnt == 0) { |
… |
… |
|
615 | 618 | |
616 | 619 | search_end: |
617 | 620 | |
618 | | // Make heap of the candidate list (approximating a partial sort) |
619 | | make_heap( _candidates.begin(), _candidates.begin() + _curr_length, |
620 | | _sort_func ); |
| 621 | // Perform partial sort operation on the candidate list |
| 622 | int new_length = std::min(_head_length + 1, _curr_length); |
| 623 | std::partial_sort(_candidates.begin(), _candidates.begin() + new_length, |
| 624 | _candidates.begin() + _curr_length, _sort_func); |
621 | 625 | |
622 | | // Pop the first element of the heap |
| 626 | // Select the entering arc and remove it from the list |
623 | 627 | _in_arc = _candidates[0]; |
624 | 628 | _next_arc = e; |
625 | | pop_heap( _candidates.begin(), _candidates.begin() + _curr_length, |
626 | | _sort_func ); |
627 | | _curr_length = std::min(_head_length, _curr_length - 1); |
| 629 | _candidates[0] = _candidates[new_length - 1]; |
| 630 | _curr_length = new_length - 1; |
628 | 631 | return true; |
629 | 632 | } |
630 | 633 | |