1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_NETWORK_SIMPLEX_H
20 #define LEMON_NETWORK_SIMPLEX_H
22 /// \ingroup min_cost_flow
25 /// \brief Network simplex algorithm for finding a minimum cost flow.
31 #include <lemon/math.h>
35 /// \addtogroup min_cost_flow
38 /// \brief Implementation of the primal network simplex algorithm
39 /// for finding a \ref min_cost_flow "minimum cost flow".
41 /// \ref NetworkSimplex implements the primal network simplex algorithm
42 /// for finding a \ref min_cost_flow "minimum cost flow".
44 /// \tparam Digraph The digraph type the algorithm runs on.
45 /// \tparam LowerMap The type of the lower bound map.
46 /// \tparam CapacityMap The type of the capacity (upper bound) map.
47 /// \tparam CostMap The type of the cost (length) map.
48 /// \tparam SupplyMap The type of the supply map.
51 /// - Arc capacities and costs should be \e non-negative \e integers.
52 /// - Supply values should be \e signed \e integers.
53 /// - The value types of the maps should be convertible to each other.
54 /// - \c CostMap::Value must be signed type.
56 /// \note \ref NetworkSimplex provides five different pivot rule
57 /// implementations that significantly affect the efficiency of the
59 /// By default "Block Search" pivot rule is used, which proved to be
60 /// by far the most efficient according to our benchmark tests.
61 /// However another pivot rule can be selected using \ref run()
62 /// function with the proper parameter.
64 template < typename Digraph,
71 template < typename Digraph,
72 typename LowerMap = typename Digraph::template ArcMap<int>,
73 typename CapacityMap = typename Digraph::template ArcMap<int>,
74 typename CostMap = typename Digraph::template ArcMap<int>,
75 typename SupplyMap = typename Digraph::template NodeMap<int> >
79 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
81 typedef typename CapacityMap::Value Capacity;
82 typedef typename CostMap::Value Cost;
83 typedef typename SupplyMap::Value Supply;
85 typedef std::vector<Arc> ArcVector;
86 typedef std::vector<Node> NodeVector;
87 typedef std::vector<int> IntVector;
88 typedef std::vector<bool> BoolVector;
89 typedef std::vector<Capacity> CapacityVector;
90 typedef std::vector<Cost> CostVector;
91 typedef std::vector<Supply> SupplyVector;
95 /// The type of the flow map
96 typedef typename Digraph::template ArcMap<Capacity> FlowMap;
97 /// The type of the potential map
98 typedef typename Digraph::template NodeMap<Cost> PotentialMap;
102 /// Enum type for selecting the pivot rule used by \ref run()
104 FIRST_ELIGIBLE_PIVOT,
107 CANDIDATE_LIST_PIVOT,
113 // State constants for arcs
122 // References for the original data
123 const Digraph &_orig_graph;
124 const LowerMap *_orig_lower;
125 const CapacityMap &_orig_cap;
126 const CostMap &_orig_cost;
127 const SupplyMap *_orig_supply;
130 Capacity _orig_flow_value;
133 FlowMap *_flow_result;
134 PotentialMap *_potential_result;
136 bool _local_potential;
138 // Data structures for storing the graph
145 // The number of nodes and arcs in the original graph
153 CapacityVector _flow;
156 // Node and arc maps for the spanning tree structure
167 // The entering arc in the current pivot iteration
170 // Temporary data used in the current pivot iteration
171 int join, u_in, v_in, u_out, v_out;
172 int right, first, second, last;
173 int stem, par_stem, new_stem;
178 /// \brief Implementation of the "First Eligible" pivot rule for the
179 /// \ref NetworkSimplex "network simplex" algorithm.
181 /// This class implements the "First Eligible" pivot rule
182 /// for the \ref NetworkSimplex "network simplex" algorithm.
184 /// For more information see \ref NetworkSimplex::run().
185 class FirstEligiblePivotRule
189 // References to the NetworkSimplex class
190 const ArcVector &_arc;
191 const IntVector &_source;
192 const IntVector &_target;
193 const CostVector &_cost;
194 const IntVector &_state;
195 const CostVector &_pi;
205 FirstEligiblePivotRule(NetworkSimplex &ns) :
206 _arc(ns._arc), _source(ns._source), _target(ns._target),
207 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
208 _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
211 /// Find next entering arc
212 bool findEnteringArc() {
214 for (int e = _next_arc; e < _arc_num; ++e) {
215 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
222 for (int e = 0; e < _next_arc; ++e) {
223 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
233 }; //class FirstEligiblePivotRule
236 /// \brief Implementation of the "Best Eligible" pivot rule for the
237 /// \ref NetworkSimplex "network simplex" algorithm.
239 /// This class implements the "Best Eligible" pivot rule
240 /// for the \ref NetworkSimplex "network simplex" algorithm.
242 /// For more information see \ref NetworkSimplex::run().
243 class BestEligiblePivotRule
247 // References to the NetworkSimplex class
248 const ArcVector &_arc;
249 const IntVector &_source;
250 const IntVector &_target;
251 const CostVector &_cost;
252 const IntVector &_state;
253 const CostVector &_pi;
260 BestEligiblePivotRule(NetworkSimplex &ns) :
261 _arc(ns._arc), _source(ns._source), _target(ns._target),
262 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
263 _in_arc(ns._in_arc), _arc_num(ns._arc_num)
266 /// Find next entering arc
267 bool findEnteringArc() {
269 for (int e = 0; e < _arc_num; ++e) {
270 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
279 }; //class BestEligiblePivotRule
282 /// \brief Implementation of the "Block Search" pivot rule for the
283 /// \ref NetworkSimplex "network simplex" algorithm.
285 /// This class implements the "Block Search" pivot rule
286 /// for the \ref NetworkSimplex "network simplex" algorithm.
288 /// For more information see \ref NetworkSimplex::run().
289 class BlockSearchPivotRule
293 // References to the NetworkSimplex class
294 const ArcVector &_arc;
295 const IntVector &_source;
296 const IntVector &_target;
297 const CostVector &_cost;
298 const IntVector &_state;
299 const CostVector &_pi;
310 BlockSearchPivotRule(NetworkSimplex &ns) :
311 _arc(ns._arc), _source(ns._source), _target(ns._target),
312 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
313 _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
315 // The main parameters of the pivot rule
316 const double BLOCK_SIZE_FACTOR = 2.0;
317 const int MIN_BLOCK_SIZE = 10;
319 _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
323 /// Find next entering arc
324 bool findEnteringArc() {
326 int cnt = _block_size;
327 int e, min_arc = _next_arc;
328 for (e = _next_arc; e < _arc_num; ++e) {
329 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
339 if (min == 0 || cnt > 0) {
340 for (e = 0; e < _next_arc; ++e) {
341 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
352 if (min >= 0) return false;
358 }; //class BlockSearchPivotRule
361 /// \brief Implementation of the "Candidate List" pivot rule for the
362 /// \ref NetworkSimplex "network simplex" algorithm.
364 /// This class implements the "Candidate List" pivot rule
365 /// for the \ref NetworkSimplex "network simplex" algorithm.
367 /// For more information see \ref NetworkSimplex::run().
368 class CandidateListPivotRule
372 // References to the NetworkSimplex class
373 const ArcVector &_arc;
374 const IntVector &_source;
375 const IntVector &_target;
376 const CostVector &_cost;
377 const IntVector &_state;
378 const CostVector &_pi;
383 IntVector _candidates;
384 int _list_length, _minor_limit;
385 int _curr_length, _minor_count;
391 CandidateListPivotRule(NetworkSimplex &ns) :
392 _arc(ns._arc), _source(ns._source), _target(ns._target),
393 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
394 _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
396 // The main parameters of the pivot rule
397 const double LIST_LENGTH_FACTOR = 1.0;
398 const int MIN_LIST_LENGTH = 10;
399 const double MINOR_LIMIT_FACTOR = 0.1;
400 const int MIN_MINOR_LIMIT = 3;
402 _list_length = std::max( int(LIST_LENGTH_FACTOR * sqrt(_arc_num)),
404 _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
406 _curr_length = _minor_count = 0;
407 _candidates.resize(_list_length);
410 /// Find next entering arc
411 bool findEnteringArc() {
413 int e, min_arc = _next_arc;
414 if (_curr_length > 0 && _minor_count < _minor_limit) {
415 // Minor iteration: select the best eligible arc from the
416 // current candidate list
419 for (int i = 0; i < _curr_length; ++i) {
421 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
427 _candidates[i--] = _candidates[--_curr_length];
436 // Major iteration: build a new candidate list
439 for (e = _next_arc; e < _arc_num; ++e) {
440 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
442 _candidates[_curr_length++] = e;
447 if (_curr_length == _list_length) break;
450 if (_curr_length < _list_length) {
451 for (e = 0; e < _next_arc; ++e) {
452 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
454 _candidates[_curr_length++] = e;
459 if (_curr_length == _list_length) break;
463 if (_curr_length == 0) return false;
470 }; //class CandidateListPivotRule
473 /// \brief Implementation of the "Altering Candidate List" pivot rule
474 /// for the \ref NetworkSimplex "network simplex" algorithm.
476 /// This class implements the "Altering Candidate List" pivot rule
477 /// for the \ref NetworkSimplex "network simplex" algorithm.
479 /// For more information see \ref NetworkSimplex::run().
480 class AlteringListPivotRule
484 // References to the NetworkSimplex class
485 const ArcVector &_arc;
486 const IntVector &_source;
487 const IntVector &_target;
488 const CostVector &_cost;
489 const IntVector &_state;
490 const CostVector &_pi;
495 int _block_size, _head_length, _curr_length;
497 IntVector _candidates;
498 CostVector _cand_cost;
500 // Functor class to compare arcs during sort of the candidate list
504 const CostVector &_map;
506 SortFunc(const CostVector &map) : _map(map) {}
507 bool operator()(int left, int right) {
508 return _map[left] > _map[right];
517 AlteringListPivotRule(NetworkSimplex &ns) :
518 _arc(ns._arc), _source(ns._source), _target(ns._target),
519 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
520 _in_arc(ns._in_arc), _arc_num(ns._arc_num),
521 _next_arc(0), _cand_cost(ns._arc_num), _sort_func(_cand_cost)
523 // The main parameters of the pivot rule
524 const double BLOCK_SIZE_FACTOR = 1.5;
525 const int MIN_BLOCK_SIZE = 10;
526 const double HEAD_LENGTH_FACTOR = 0.1;
527 const int MIN_HEAD_LENGTH = 3;
529 _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
531 _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
533 _candidates.resize(_head_length + _block_size);
537 /// Find next entering arc
538 bool findEnteringArc() {
539 // Check the current candidate list
541 for (int i = 0; i < _curr_length; ++i) {
543 _cand_cost[e] = _state[e] *
544 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
545 if (_cand_cost[e] >= 0) {
546 _candidates[i--] = _candidates[--_curr_length];
551 int cnt = _block_size;
553 int limit = _head_length;
555 for (int e = _next_arc; e < _arc_num; ++e) {
556 _cand_cost[e] = _state[e] *
557 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
558 if (_cand_cost[e] < 0) {
559 _candidates[_curr_length++] = e;
563 if (_curr_length > limit) break;
568 if (_curr_length <= limit) {
569 for (int e = 0; e < _next_arc; ++e) {
570 _cand_cost[e] = _state[e] *
571 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
572 if (_cand_cost[e] < 0) {
573 _candidates[_curr_length++] = e;
577 if (_curr_length > limit) break;
583 if (_curr_length == 0) return false;
584 _next_arc = last_edge + 1;
586 // Make heap of the candidate list (approximating a partial sort)
587 make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
590 // Pop the first element of the heap
591 _in_arc = _candidates[0];
592 pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
594 _curr_length = std::min(_head_length, _curr_length - 1);
598 }; //class AlteringListPivotRule
602 /// \brief General constructor (with lower bounds).
604 /// General constructor (with lower bounds).
606 /// \param digraph The digraph the algorithm runs on.
607 /// \param lower The lower bounds of the arcs.
608 /// \param capacity The capacities (upper bounds) of the arcs.
609 /// \param cost The cost (length) values of the arcs.
610 /// \param supply The supply values of the nodes (signed).
611 NetworkSimplex( const Digraph &digraph,
612 const LowerMap &lower,
613 const CapacityMap &capacity,
615 const SupplyMap &supply ) :
616 _orig_graph(digraph), _orig_lower(&lower), _orig_cap(capacity),
617 _orig_cost(cost), _orig_supply(&supply),
618 _flow_result(NULL), _potential_result(NULL),
619 _local_flow(false), _local_potential(false),
623 /// \brief General constructor (without lower bounds).
625 /// General constructor (without lower bounds).
627 /// \param digraph The digraph the algorithm runs on.
628 /// \param capacity The capacities (upper bounds) of the arcs.
629 /// \param cost The cost (length) values of the arcs.
630 /// \param supply The supply values of the nodes (signed).
631 NetworkSimplex( const Digraph &digraph,
632 const CapacityMap &capacity,
634 const SupplyMap &supply ) :
635 _orig_graph(digraph), _orig_lower(NULL), _orig_cap(capacity),
636 _orig_cost(cost), _orig_supply(&supply),
637 _flow_result(NULL), _potential_result(NULL),
638 _local_flow(false), _local_potential(false),
642 /// \brief Simple constructor (with lower bounds).
644 /// Simple constructor (with lower bounds).
646 /// \param digraph The digraph the algorithm runs on.
647 /// \param lower The lower bounds of the arcs.
648 /// \param capacity The capacities (upper bounds) of the arcs.
649 /// \param cost The cost (length) values of the arcs.
650 /// \param s The source node.
651 /// \param t The target node.
652 /// \param flow_value The required amount of flow from node \c s
653 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
654 NetworkSimplex( const Digraph &digraph,
655 const LowerMap &lower,
656 const CapacityMap &capacity,
659 Capacity flow_value ) :
660 _orig_graph(digraph), _orig_lower(&lower), _orig_cap(capacity),
661 _orig_cost(cost), _orig_supply(NULL),
662 _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
663 _flow_result(NULL), _potential_result(NULL),
664 _local_flow(false), _local_potential(false),
668 /// \brief Simple constructor (without lower bounds).
670 /// Simple constructor (without lower bounds).
672 /// \param digraph The digraph the algorithm runs on.
673 /// \param capacity The capacities (upper bounds) of the arcs.
674 /// \param cost The cost (length) values of the arcs.
675 /// \param s The source node.
676 /// \param t The target node.
677 /// \param flow_value The required amount of flow from node \c s
678 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
679 NetworkSimplex( const Digraph &digraph,
680 const CapacityMap &capacity,
683 Capacity flow_value ) :
684 _orig_graph(digraph), _orig_lower(NULL), _orig_cap(capacity),
685 _orig_cost(cost), _orig_supply(NULL),
686 _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
687 _flow_result(NULL), _potential_result(NULL),
688 _local_flow(false), _local_potential(false),
694 if (_local_flow) delete _flow_result;
695 if (_local_potential) delete _potential_result;
698 /// \brief Set the flow map.
700 /// This function sets the flow map.
702 /// \return <tt>(*this)</tt>
703 NetworkSimplex& flowMap(FlowMap &map) {
712 /// \brief Set the potential map.
714 /// This function sets the potential map.
716 /// \return <tt>(*this)</tt>
717 NetworkSimplex& potentialMap(PotentialMap &map) {
718 if (_local_potential) {
719 delete _potential_result;
720 _local_potential = false;
722 _potential_result = ↦
726 /// \name Execution control
727 /// The algorithm can be executed using the
728 /// \ref lemon::NetworkSimplex::run() "run()" function.
731 /// \brief Run the algorithm.
733 /// This function runs the algorithm.
735 /// \param pivot_rule The pivot rule that is used during the
738 /// The available pivot rules:
740 /// - FIRST_ELIGIBLE_PIVOT The next eligible arc is selected in
741 /// a wraparound fashion in every iteration
742 /// (\ref FirstEligiblePivotRule).
744 /// - BEST_ELIGIBLE_PIVOT The best eligible arc is selected in
745 /// every iteration (\ref BestEligiblePivotRule).
747 /// - BLOCK_SEARCH_PIVOT A specified number of arcs are examined in
748 /// every iteration in a wraparound fashion and the best eligible
749 /// arc is selected from this block (\ref BlockSearchPivotRule).
751 /// - CANDIDATE_LIST_PIVOT In a major iteration a candidate list is
752 /// built from eligible arcs in a wraparound fashion and in the
753 /// following minor iterations the best eligible arc is selected
754 /// from this list (\ref CandidateListPivotRule).
756 /// - ALTERING_LIST_PIVOT It is a modified version of the
757 /// "Candidate List" pivot rule. It keeps only the several best
758 /// eligible arcs from the former candidate list and extends this
759 /// list in every iteration (\ref AlteringListPivotRule).
761 /// According to our comprehensive benchmark tests the "Block Search"
762 /// pivot rule proved to be the fastest and the most robust on
763 /// various test inputs. Thus it is the default option.
765 /// \return \c true if a feasible flow can be found.
766 bool run(PivotRuleEnum pivot_rule = BLOCK_SEARCH_PIVOT) {
767 return init() && start(pivot_rule);
772 /// \name Query Functions
773 /// The results of the algorithm can be obtained using these
775 /// \ref lemon::NetworkSimplex::run() "run()" must be called before
779 /// \brief Return a const reference to the flow map.
781 /// This function returns a const reference to an arc map storing
784 /// \pre \ref run() must be called before using this function.
785 const FlowMap& flowMap() const {
786 return *_flow_result;
789 /// \brief Return a const reference to the potential map
790 /// (the dual solution).
792 /// This function returns a const reference to a node map storing
793 /// the found potentials (the dual solution).
795 /// \pre \ref run() must be called before using this function.
796 const PotentialMap& potentialMap() const {
797 return *_potential_result;
800 /// \brief Return the flow on the given arc.
802 /// This function returns the flow on the given arc.
804 /// \pre \ref run() must be called before using this function.
805 Capacity flow(const Arc& arc) const {
806 return (*_flow_result)[arc];
809 /// \brief Return the potential of the given node.
811 /// This function returns the potential of the given node.
813 /// \pre \ref run() must be called before using this function.
814 Cost potential(const Node& node) const {
815 return (*_potential_result)[node];
818 /// \brief Return the total cost of the found flow.
820 /// This function returns the total cost of the found flow.
821 /// The complexity of the function is \f$ O(e) \f$.
823 /// \pre \ref run() must be called before using this function.
824 Cost totalCost() const {
826 for (ArcIt e(_orig_graph); e != INVALID; ++e)
827 c += (*_flow_result)[e] * _orig_cost[e];
835 // Initialize internal data structures
837 // Initialize result maps
839 _flow_result = new FlowMap(_orig_graph);
842 if (!_potential_result) {
843 _potential_result = new PotentialMap(_orig_graph);
844 _local_potential = true;
847 // Initialize vectors
848 _node_num = countNodes(_orig_graph);
849 _arc_num = countArcs(_orig_graph);
850 int all_node_num = _node_num + 1;
851 int all_edge_num = _arc_num + _node_num;
853 _arc.resize(_arc_num);
854 _node.reserve(_node_num);
855 _source.resize(all_edge_num);
856 _target.resize(all_edge_num);
858 _cap.resize(all_edge_num);
859 _cost.resize(all_edge_num);
860 _supply.resize(all_node_num);
861 _flow.resize(all_edge_num, 0);
862 _pi.resize(all_node_num, 0);
864 _depth.resize(all_node_num);
865 _parent.resize(all_node_num);
866 _pred.resize(all_node_num);
867 _thread.resize(all_node_num);
868 _forward.resize(all_node_num);
869 _state.resize(all_edge_num, STATE_LOWER);
871 // Initialize node related data
872 bool valid_supply = true;
876 for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
879 _supply[i] = (*_orig_supply)[n];
882 valid_supply = (sum == 0);
885 for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
890 _supply[_node_id[_orig_source]] = _orig_flow_value;
891 _supply[_node_id[_orig_target]] = -_orig_flow_value;
893 if (!valid_supply) return false;
895 // Set data for the artificial root node
904 // Store the arcs in a mixed order
905 int k = std::max(int(sqrt(_arc_num)), 10);
907 for (ArcIt e(_orig_graph); e != INVALID; ++e) {
909 if ((i += k) >= _arc_num) i = (i % k) + 1;
912 // Initialize arc maps
913 for (int i = 0; i != _arc_num; ++i) {
915 _source[i] = _node_id[_orig_graph.source(e)];
916 _target[i] = _node_id[_orig_graph.target(e)];
917 _cost[i] = _orig_cost[e];
918 _cap[i] = _orig_cap[e];
921 // Remove non-zero lower bounds
923 for (int i = 0; i != _arc_num; ++i) {
924 Capacity c = (*_orig_lower)[_arc[i]];
927 _supply[_source[i]] -= c;
928 _supply[_target[i]] += c;
933 // Add artificial arcs and initialize the spanning tree data structure
934 Cost max_cost = std::numeric_limits<Cost>::max() / 4;
935 Capacity max_cap = std::numeric_limits<Capacity>::max();
936 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
941 if (_supply[u] >= 0) {
942 _flow[e] = _supply[u];
946 _flow[e] = -_supply[u];
952 _state[e] = STATE_TREE;
958 // Find the join node
959 void findJoinNode() {
960 int u = _source[_in_arc];
961 int v = _target[_in_arc];
962 while (_depth[u] > _depth[v]) u = _parent[u];
963 while (_depth[v] > _depth[u]) v = _parent[v];
971 // Find the leaving arc of the cycle and returns true if the
972 // leaving arc is not the same as the entering arc
973 bool findLeavingArc() {
974 // Initialize first and second nodes according to the direction
976 if (_state[_in_arc] == STATE_LOWER) {
977 first = _source[_in_arc];
978 second = _target[_in_arc];
980 first = _target[_in_arc];
981 second = _source[_in_arc];
983 delta = _cap[_in_arc];
988 // Search the cycle along the path form the first node to the root
989 for (int u = first; u != join; u = _parent[u]) {
991 d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
998 // Search the cycle along the path form the second node to the root
999 for (int u = second; u != join; u = _parent[u]) {
1001 d = _forward[u] ? _cap[e] - _flow[e] : _flow[e];
1019 // Change _flow and _state vectors
1020 void changeFlow(bool change) {
1021 // Augment along the cycle
1023 Capacity val = _state[_in_arc] * delta;
1024 _flow[_in_arc] += val;
1025 for (int u = _source[_in_arc]; u != join; u = _parent[u]) {
1026 _flow[_pred[u]] += _forward[u] ? -val : val;
1028 for (int u = _target[_in_arc]; u != join; u = _parent[u]) {
1029 _flow[_pred[u]] += _forward[u] ? val : -val;
1032 // Update the state of the entering and leaving arcs
1034 _state[_in_arc] = STATE_TREE;
1035 _state[_pred[u_out]] =
1036 (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
1038 _state[_in_arc] = -_state[_in_arc];
1042 // Update _thread and _parent vectors
1043 void updateThreadParent() {
1045 v_out = _parent[u_out];
1047 // Handle the case when join and v_out coincide
1048 bool par_first = false;
1049 if (join == v_out) {
1050 for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
1053 while (_thread[u] != u_out) u = _thread[u];
1058 // Find the last successor of u_in (u) and the node after it (right)
1059 // according to the thread index
1060 for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
1062 if (_thread[v_in] == u_out) {
1063 for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
1064 if (last == u_out) last = _thread[last];
1066 else last = _thread[v_in];
1068 // Update stem nodes
1069 _thread[v_in] = stem = u_in;
1071 while (stem != u_out) {
1072 _thread[u] = new_stem = _parent[stem];
1074 // Find the node just before the stem node (u) according to
1075 // the original thread index
1076 for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
1079 // Change the parent node of stem and shift stem and par_stem nodes
1080 _parent[stem] = par_stem;
1084 // Find the last successor of stem (u) and the node after it (right)
1085 // according to the thread index
1086 for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
1089 _parent[u_out] = par_stem;
1092 if (join == v_out && par_first) {
1093 if (first != v_in) _thread[first] = right;
1095 for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
1100 // Update _pred and _forward vectors
1101 void updatePredArc() {
1105 _pred[u] = _pred[v];
1106 _forward[u] = !_forward[v];
1109 _pred[u_in] = _in_arc;
1110 _forward[u_in] = (u_in == _source[_in_arc]);
1113 // Update _depth and _potential vectors
1114 void updateDepthPotential() {
1115 _depth[u_in] = _depth[v_in] + 1;
1116 Cost sigma = _forward[u_in] ?
1117 _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1118 _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
1120 for(int u = _thread[u_in]; _parent[u] != -1; u = _thread[u]) {
1121 _depth[u] = _depth[_parent[u]] + 1;
1122 if (_depth[u] <= _depth[u_in]) break;
1127 // Execute the algorithm
1128 bool start(PivotRuleEnum pivot_rule) {
1129 // Select the pivot rule implementation
1130 switch (pivot_rule) {
1131 case FIRST_ELIGIBLE_PIVOT:
1132 return start<FirstEligiblePivotRule>();
1133 case BEST_ELIGIBLE_PIVOT:
1134 return start<BestEligiblePivotRule>();
1135 case BLOCK_SEARCH_PIVOT:
1136 return start<BlockSearchPivotRule>();
1137 case CANDIDATE_LIST_PIVOT:
1138 return start<CandidateListPivotRule>();
1139 case ALTERING_LIST_PIVOT:
1140 return start<AlteringListPivotRule>();
1145 template<class PivotRuleImplementation>
1147 PivotRuleImplementation pivot(*this);
1149 // Execute the network simplex algorithm
1150 while (pivot.findEnteringArc()) {
1152 bool change = findLeavingArc();
1155 updateThreadParent();
1157 updateDepthPotential();
1161 // Check if the flow amount equals zero on all the artificial arcs
1162 for (int e = _arc_num; e != _arc_num + _node_num; ++e) {
1163 if (_flow[e] > 0) return false;
1166 // Copy flow values to _flow_result
1168 for (int i = 0; i != _arc_num; ++i) {
1170 (*_flow_result)[e] = (*_orig_lower)[e] + _flow[i];
1173 for (int i = 0; i != _arc_num; ++i) {
1174 (*_flow_result)[_arc[i]] = _flow[i];
1177 // Copy potential values to _potential_result
1178 for (int i = 0; i != _node_num; ++i) {
1179 (*_potential_result)[_node[i]] = _pi[i];
1185 }; //class NetworkSimplex
1191 #endif //LEMON_NETWORK_SIMPLEX_H