3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
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/graph_utils.h>
32 #include <lemon/math.h>
36 /// \addtogroup min_cost_flow
39 /// \brief Implementation of the primal network simplex algorithm
40 /// for finding a minimum cost flow.
42 /// \ref NetworkSimplex implements the primal network simplex algorithm
43 /// for finding a minimum cost flow.
45 /// \tparam Graph The directed graph type the algorithm runs on.
46 /// \tparam LowerMap The type of the lower bound map.
47 /// \tparam CapacityMap The type of the capacity (upper bound) map.
48 /// \tparam CostMap The type of the cost (length) map.
49 /// \tparam SupplyMap The type of the supply map.
52 /// - Edge capacities and costs should be \e non-negative \e integers.
53 /// - Supply values should be \e signed \e integers.
54 /// - The value types of the maps should be convertible to each other.
55 /// - \c CostMap::Value must be signed type.
57 /// \note \ref NetworkSimplex provides five different pivot rule
58 /// implementations that significantly affect the efficiency of the
60 /// By default "Block Search" pivot rule is used, which proved to be
61 /// by far the most efficient according to our benchmark tests.
62 /// However another pivot rule can be selected using \ref run()
63 /// function with the proper parameter.
65 /// \author Peter Kovacs
66 template < typename Graph,
67 typename LowerMap = typename Graph::template EdgeMap<int>,
68 typename CapacityMap = typename Graph::template EdgeMap<int>,
69 typename CostMap = typename Graph::template EdgeMap<int>,
70 typename SupplyMap = typename Graph::template NodeMap<int> >
73 GRAPH_TYPEDEFS(typename Graph);
75 typedef typename CapacityMap::Value Capacity;
76 typedef typename CostMap::Value Cost;
77 typedef typename SupplyMap::Value Supply;
79 typedef std::vector<Edge> EdgeVector;
80 typedef std::vector<Node> NodeVector;
81 typedef std::vector<int> IntVector;
82 typedef std::vector<bool> BoolVector;
83 typedef std::vector<Capacity> CapacityVector;
84 typedef std::vector<Cost> CostVector;
85 typedef std::vector<Supply> SupplyVector;
87 typedef typename Graph::template NodeMap<int> IntNodeMap;
91 /// The type of the flow map.
92 typedef typename Graph::template EdgeMap<Capacity> FlowMap;
93 /// The type of the potential map.
94 typedef typename Graph::template NodeMap<Cost> PotentialMap;
98 /// Enum type to select the pivot rule used by \ref run().
100 FIRST_ELIGIBLE_PIVOT,
103 CANDIDATE_LIST_PIVOT,
109 /// \brief Implementation of the "First Eligible" pivot rule for the
110 /// \ref NetworkSimplex "network simplex" algorithm.
112 /// This class implements the "First Eligible" pivot rule
113 /// for the \ref NetworkSimplex "network simplex" algorithm.
115 /// For more information see \ref NetworkSimplex::run().
116 class FirstEligiblePivotRule
120 // References to the NetworkSimplex class
121 const EdgeVector &_edge;
122 const IntVector &_source;
123 const IntVector &_target;
124 const CostVector &_cost;
125 const IntVector &_state;
126 const CostVector &_pi;
136 FirstEligiblePivotRule(NetworkSimplex &ns) :
137 _edge(ns._edge), _source(ns._source), _target(ns._target),
138 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
139 _in_edge(ns._in_edge), _edge_num(ns._edge_num), _next_edge(0)
142 /// Find next entering edge
143 bool findEnteringEdge() {
145 for (int e = _next_edge; e < _edge_num; ++e) {
146 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
153 for (int e = 0; e < _next_edge; ++e) {
154 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
164 }; //class FirstEligiblePivotRule
167 /// \brief Implementation of the "Best Eligible" pivot rule for the
168 /// \ref NetworkSimplex "network simplex" algorithm.
170 /// This class implements the "Best Eligible" pivot rule
171 /// for the \ref NetworkSimplex "network simplex" algorithm.
173 /// For more information see \ref NetworkSimplex::run().
174 class BestEligiblePivotRule
178 // References to the NetworkSimplex class
179 const EdgeVector &_edge;
180 const IntVector &_source;
181 const IntVector &_target;
182 const CostVector &_cost;
183 const IntVector &_state;
184 const CostVector &_pi;
191 BestEligiblePivotRule(NetworkSimplex &ns) :
192 _edge(ns._edge), _source(ns._source), _target(ns._target),
193 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
194 _in_edge(ns._in_edge), _edge_num(ns._edge_num)
197 /// Find next entering edge
198 bool findEnteringEdge() {
200 for (int e = 0; e < _edge_num; ++e) {
201 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
210 }; //class BestEligiblePivotRule
213 /// \brief Implementation of the "Block Search" pivot rule for the
214 /// \ref NetworkSimplex "network simplex" algorithm.
216 /// This class implements the "Block Search" pivot rule
217 /// for the \ref NetworkSimplex "network simplex" algorithm.
219 /// For more information see \ref NetworkSimplex::run().
220 class BlockSearchPivotRule
224 // References to the NetworkSimplex class
225 const EdgeVector &_edge;
226 const IntVector &_source;
227 const IntVector &_target;
228 const CostVector &_cost;
229 const IntVector &_state;
230 const CostVector &_pi;
241 BlockSearchPivotRule(NetworkSimplex &ns) :
242 _edge(ns._edge), _source(ns._source), _target(ns._target),
243 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
244 _in_edge(ns._in_edge), _edge_num(ns._edge_num + ns._node_num), _next_edge(0)
246 // The main parameters of the pivot rule
247 const double BLOCK_SIZE_FACTOR = 2.0;
248 const int MIN_BLOCK_SIZE = 10;
250 _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_edge_num)),
254 /// Find next entering edge
255 bool findEnteringEdge() {
257 int cnt = _block_size;
258 int e, min_edge = _next_edge;
259 for (e = _next_edge; e < _edge_num; ++e) {
260 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
270 if (min == 0 || cnt > 0) {
271 for (e = 0; e < _next_edge; ++e) {
272 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
283 if (min >= 0) return false;
289 }; //class BlockSearchPivotRule
292 /// \brief Implementation of the "Candidate List" pivot rule for the
293 /// \ref NetworkSimplex "network simplex" algorithm.
295 /// This class implements the "Candidate List" pivot rule
296 /// for the \ref NetworkSimplex "network simplex" algorithm.
298 /// For more information see \ref NetworkSimplex::run().
299 class CandidateListPivotRule
303 // References to the NetworkSimplex class
304 const EdgeVector &_edge;
305 const IntVector &_source;
306 const IntVector &_target;
307 const CostVector &_cost;
308 const IntVector &_state;
309 const CostVector &_pi;
314 IntVector _candidates;
315 int _list_length, _minor_limit;
316 int _curr_length, _minor_count;
322 CandidateListPivotRule(NetworkSimplex &ns) :
323 _edge(ns._edge), _source(ns._source), _target(ns._target),
324 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
325 _in_edge(ns._in_edge), _edge_num(ns._edge_num), _next_edge(0)
327 // The main parameters of the pivot rule
328 const double LIST_LENGTH_FACTOR = 1.0;
329 const int MIN_LIST_LENGTH = 10;
330 const double MINOR_LIMIT_FACTOR = 0.1;
331 const int MIN_MINOR_LIMIT = 3;
333 _list_length = std::max( int(LIST_LENGTH_FACTOR * sqrt(_edge_num)),
335 _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
337 _curr_length = _minor_count = 0;
338 _candidates.resize(_list_length);
341 /// Find next entering edge
342 bool findEnteringEdge() {
344 int e, min_edge = _next_edge;
345 if (_curr_length > 0 && _minor_count < _minor_limit) {
346 // Minor iteration: select the best eligible edge from the
347 // current candidate list
350 for (int i = 0; i < _curr_length; ++i) {
352 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
358 _candidates[i--] = _candidates[--_curr_length];
367 // Major iteration: build a new candidate list
370 for (e = _next_edge; e < _edge_num; ++e) {
371 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
373 _candidates[_curr_length++] = e;
378 if (_curr_length == _list_length) break;
381 if (_curr_length < _list_length) {
382 for (e = 0; e < _next_edge; ++e) {
383 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
385 _candidates[_curr_length++] = e;
390 if (_curr_length == _list_length) break;
394 if (_curr_length == 0) return false;
401 }; //class CandidateListPivotRule
404 /// \brief Implementation of the "Altering Candidate List" pivot rule
405 /// for the \ref NetworkSimplex "network simplex" algorithm.
407 /// This class implements the "Altering Candidate List" pivot rule
408 /// for the \ref NetworkSimplex "network simplex" algorithm.
410 /// For more information see \ref NetworkSimplex::run().
411 class AlteringListPivotRule
415 // References to the NetworkSimplex class
416 const EdgeVector &_edge;
417 const IntVector &_source;
418 const IntVector &_target;
419 const CostVector &_cost;
420 const IntVector &_state;
421 const CostVector &_pi;
425 int _block_size, _head_length, _curr_length;
427 IntVector _candidates;
428 CostVector _cand_cost;
430 // Functor class to compare edges during sort of the candidate list
434 const CostVector &_map;
436 SortFunc(const CostVector &map) : _map(map) {}
437 bool operator()(int left, int right) {
438 return _map[left] > _map[right];
447 AlteringListPivotRule(NetworkSimplex &ns) :
448 _edge(ns._edge), _source(ns._source), _target(ns._target),
449 _cost(ns._cost), _state(ns._state), _pi(ns._pi),
450 _in_edge(ns._in_edge), _edge_num(ns._edge_num),
451 _next_edge(0), _cand_cost(ns._edge_num),_sort_func(_cand_cost)
453 // The main parameters of the pivot rule
454 const double BLOCK_SIZE_FACTOR = 1.5;
455 const int MIN_BLOCK_SIZE = 10;
456 const double HEAD_LENGTH_FACTOR = 0.1;
457 const int MIN_HEAD_LENGTH = 3;
459 _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_edge_num)),
461 _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
463 _candidates.resize(_head_length + _block_size);
467 /// Find next entering edge
468 bool findEnteringEdge() {
469 // Check the current candidate list
471 for (int i = 0; i < _curr_length; ++i) {
473 _cand_cost[e] = _state[e] *
474 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
475 if (_cand_cost[e] >= 0) {
476 _candidates[i--] = _candidates[--_curr_length];
481 int cnt = _block_size;
483 int limit = _head_length;
485 for (int e = _next_edge; e < _edge_num; ++e) {
486 _cand_cost[e] = _state[e] *
487 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
488 if (_cand_cost[e] < 0) {
489 _candidates[_curr_length++] = e;
493 if (_curr_length > limit) break;
498 if (_curr_length <= limit) {
499 for (int e = 0; e < _next_edge; ++e) {
500 _cand_cost[e] = _state[e] *
501 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
502 if (_cand_cost[e] < 0) {
503 _candidates[_curr_length++] = e;
507 if (_curr_length > limit) break;
513 if (_curr_length == 0) return false;
514 _next_edge = last_edge + 1;
516 // Make heap of the candidate list (approximating a partial sort)
517 make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
520 // Pop the first element of the heap
521 _in_edge = _candidates[0];
522 pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
524 _curr_length = std::min(_head_length, _curr_length - 1);
528 }; //class AlteringListPivotRule
532 // State constants for edges
541 // The original graph
542 const Graph &_orig_graph;
543 // The original lower bound map
544 const LowerMap *_orig_lower;
545 // The original capacity map
546 const CapacityMap &_orig_cap;
547 // The original cost map
548 const CostMap &_orig_cost;
549 // The original supply map
550 const SupplyMap *_orig_supply;
551 // The source node (if no supply map was given)
553 // The target node (if no supply map was given)
555 // The flow value (if no supply map was given)
556 Capacity _orig_flow_value;
558 // The flow result map
559 FlowMap *_flow_result;
560 // The potential result map
561 PotentialMap *_potential_result;
562 // Indicate if the flow result map is local
564 // Indicate if the potential result map is local
565 bool _local_potential;
567 // The edge references
569 // The node references
573 // The source nodes of the edges
575 // The target nodess of the edges
578 // The (modified) capacity vector
582 // The (modified) supply vector
584 // The current flow vector
585 CapacityVector _flow;
586 // The current potential vector
589 // The number of nodes in the original graph
591 // The number of edges in the original graph
594 // The parent vector of the spanning tree structure
596 // The pred_edge vector of the spanning tree structure
598 // The thread vector of the spanning tree structure
601 IntVector _rev_thread;
603 IntVector _last_succ;
605 IntVector _dirty_revs;
607 // The forward vector of the spanning tree structure
614 // The entering edge of the current pivot iteration
617 // Temporary nodes used in the current pivot iteration
618 int join, u_in, v_in, u_out, v_out;
619 int right, first, second, last;
620 int stem, par_stem, new_stem;
622 // The maximum augment amount along the found cycle in the current
628 /// \brief General constructor (with lower bounds).
630 /// General constructor (with lower bounds).
632 /// \param graph The directed graph the algorithm runs on.
633 /// \param lower The lower bounds of the edges.
634 /// \param capacity The capacities (upper bounds) of the edges.
635 /// \param cost The cost (length) values of the edges.
636 /// \param supply The supply values of the nodes (signed).
637 NetworkSimplex( const Graph &graph,
638 const LowerMap &lower,
639 const CapacityMap &capacity,
641 const SupplyMap &supply ) :
642 _orig_graph(graph), _orig_lower(&lower), _orig_cap(capacity),
643 _orig_cost(cost), _orig_supply(&supply),
644 _flow_result(NULL), _potential_result(NULL),
645 _local_flow(false), _local_potential(false),
649 /// \brief General constructor (without lower bounds).
651 /// General constructor (without lower bounds).
653 /// \param graph The directed graph the algorithm runs on.
654 /// \param capacity The capacities (upper bounds) of the edges.
655 /// \param cost The cost (length) values of the edges.
656 /// \param supply The supply values of the nodes (signed).
657 NetworkSimplex( const Graph &graph,
658 const CapacityMap &capacity,
660 const SupplyMap &supply ) :
661 _orig_graph(graph), _orig_lower(NULL), _orig_cap(capacity),
662 _orig_cost(cost), _orig_supply(&supply),
663 _flow_result(NULL), _potential_result(NULL),
664 _local_flow(false), _local_potential(false),
668 /// \brief Simple constructor (with lower bounds).
670 /// Simple constructor (with lower bounds).
672 /// \param graph The directed graph the algorithm runs on.
673 /// \param lower The lower bounds of the edges.
674 /// \param capacity The capacities (upper bounds) of the edges.
675 /// \param cost The cost (length) values of the edges.
676 /// \param s The source node.
677 /// \param t The target node.
678 /// \param flow_value The required amount of flow from node \c s
679 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
680 NetworkSimplex( const Graph &graph,
681 const LowerMap &lower,
682 const CapacityMap &capacity,
685 Capacity flow_value ) :
686 _orig_graph(graph), _orig_lower(&lower), _orig_cap(capacity),
687 _orig_cost(cost), _orig_supply(NULL),
688 _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
689 _flow_result(NULL), _potential_result(NULL),
690 _local_flow(false), _local_potential(false),
694 /// \brief Simple constructor (without lower bounds).
696 /// Simple constructor (without lower bounds).
698 /// \param graph The directed graph the algorithm runs on.
699 /// \param capacity The capacities (upper bounds) of the edges.
700 /// \param cost The cost (length) values of the edges.
701 /// \param s The source node.
702 /// \param t The target node.
703 /// \param flow_value The required amount of flow from node \c s
704 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
705 NetworkSimplex( const Graph &graph,
706 const CapacityMap &capacity,
709 Capacity flow_value ) :
710 _orig_graph(graph), _orig_lower(NULL), _orig_cap(capacity),
711 _orig_cost(cost), _orig_supply(NULL),
712 _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
713 _flow_result(NULL), _potential_result(NULL),
714 _local_flow(false), _local_potential(false),
720 if (_local_flow) delete _flow_result;
721 if (_local_potential) delete _potential_result;
724 /// \brief Set the flow map.
726 /// Set the flow map.
728 /// \return \c (*this)
729 NetworkSimplex& flowMap(FlowMap &map) {
738 /// \brief Set the potential map.
740 /// Set the potential map.
742 /// \return \c (*this)
743 NetworkSimplex& potentialMap(PotentialMap &map) {
744 if (_local_potential) {
745 delete _potential_result;
746 _local_potential = false;
748 _potential_result = ↦
752 /// \name Execution control
756 /// \brief Runs the algorithm.
758 /// Runs the algorithm.
760 /// \param pivot_rule The pivot rule that is used during the
763 /// The available pivot rules:
765 /// - FIRST_ELIGIBLE_PIVOT The next eligible edge is selected in
766 /// a wraparound fashion in every iteration
767 /// (\ref FirstEligiblePivotRule).
769 /// - BEST_ELIGIBLE_PIVOT The best eligible edge is selected in
770 /// every iteration (\ref BestEligiblePivotRule).
772 /// - BLOCK_SEARCH_PIVOT A specified number of edges are examined in
773 /// every iteration in a wraparound fashion and the best eligible
774 /// edge is selected from this block (\ref BlockSearchPivotRule).
776 /// - CANDIDATE_LIST_PIVOT In a major iteration a candidate list is
777 /// built from eligible edges in a wraparound fashion and in the
778 /// following minor iterations the best eligible edge is selected
779 /// from this list (\ref CandidateListPivotRule).
781 /// - ALTERING_LIST_PIVOT It is a modified version of the
782 /// "Candidate List" pivot rule. It keeps only the several best
783 /// eligible edges from the former candidate list and extends this
784 /// list in every iteration (\ref AlteringListPivotRule).
786 /// According to our comprehensive benchmark tests the "Block Search"
787 /// pivot rule proved to be the fastest and the most robust on
788 /// various test inputs. Thus it is the default option.
790 /// \return \c true if a feasible flow can be found.
791 bool run(PivotRuleEnum pivot_rule = BLOCK_SEARCH_PIVOT) {
792 return init() && start(pivot_rule);
797 /// \name Query Functions
798 /// The results of the algorithm can be obtained using these
800 /// \ref lemon::NetworkSimplex::run() "run()" must be called before
805 /// \brief Return a const reference to the edge map storing the
808 /// Return a const reference to the edge map storing the found flow.
810 /// \pre \ref run() must be called before using this function.
811 const FlowMap& flowMap() const {
812 return *_flow_result;
815 /// \brief Return a const reference to the node map storing the
816 /// found potentials (the dual solution).
818 /// Return a const reference to the node map storing the found
819 /// potentials (the dual solution).
821 /// \pre \ref run() must be called before using this function.
822 const PotentialMap& potentialMap() const {
823 return *_potential_result;
826 /// \brief Return the flow on the given edge.
828 /// Return the flow on the given edge.
830 /// \pre \ref run() must be called before using this function.
831 Capacity flow(const typename Graph::Edge& edge) const {
832 return (*_flow_result)[edge];
835 /// \brief Return the potential of the given node.
837 /// Return the potential of the given node.
839 /// \pre \ref run() must be called before using this function.
840 Cost potential(const typename Graph::Node& node) const {
841 return (*_potential_result)[node];
844 /// \brief Return the total cost of the found flow.
846 /// Return the total cost of the found flow. The complexity of the
847 /// function is \f$ O(e) \f$.
849 /// \pre \ref run() must be called before using this function.
850 Cost totalCost() const {
852 for (EdgeIt e(_orig_graph); e != INVALID; ++e)
853 c += (*_flow_result)[e] * _orig_cost[e];
861 // Initialize internal data structures
863 // Initialize result maps
865 _flow_result = new FlowMap(_orig_graph);
868 if (!_potential_result) {
869 _potential_result = new PotentialMap(_orig_graph);
870 _local_potential = true;
873 // Initialize vectors
874 _node_num = countNodes(_orig_graph);
875 _edge_num = countEdges(_orig_graph);
876 int all_node_num = _node_num + 1;
877 int all_edge_num = _edge_num + _node_num;
879 _edge.resize(_edge_num);
880 _node.reserve(_node_num);
881 _source.resize(all_edge_num);
882 _target.resize(all_edge_num);
884 _cap.resize(all_edge_num);
885 _cost.resize(all_edge_num);
886 _supply.resize(all_node_num);
887 _flow.resize(all_edge_num, 0);
888 _pi.resize(all_node_num, 0);
890 _parent.resize(all_node_num);
891 _pred.resize(all_node_num);
892 _forward.resize(all_node_num);
893 _thread.resize(all_node_num);
894 _rev_thread.resize(all_node_num);
895 _succ_num.resize(all_node_num);
896 _last_succ.resize(all_node_num);
897 _state.resize(all_edge_num, STATE_LOWER);
899 // Initialize node related data
900 bool valid_supply = true;
904 for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
907 _supply[i] = (*_orig_supply)[n];
910 valid_supply = (sum == 0);
913 for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
918 _supply[_node_id[_orig_source]] = _orig_flow_value;
919 _supply[_node_id[_orig_target]] = -_orig_flow_value;
921 if (!valid_supply) return false;
923 // Set data for the artificial root node
928 _rev_thread[0] = _root;
929 _succ_num[_root] = all_node_num;
930 _last_succ[_root] = _root - 1;
934 // Store the edges in a mixed order
935 int k = std::max(int(sqrt(_edge_num)), 10);
937 for (EdgeIt e(_orig_graph); e != INVALID; ++e) {
939 if ((i += k) >= _edge_num) i = (i % k) + 1;
942 // Initialize edge maps
943 for (int i = 0; i != _edge_num; ++i) {
945 _source[i] = _node_id[_orig_graph.source(e)];
946 _target[i] = _node_id[_orig_graph.target(e)];
947 _cost[i] = _orig_cost[e];
948 _cap[i] = _orig_cap[e];
951 // Remove non-zero lower bounds
953 for (int i = 0; i != _edge_num; ++i) {
954 Capacity c = (*_orig_lower)[_edge[i]];
957 _supply[_source[i]] -= c;
958 _supply[_target[i]] += c;
963 // Add artificial edges and initialize the spanning tree data structure
964 Cost max_cost = std::numeric_limits<Cost>::max() / 4;
965 Capacity max_cap = std::numeric_limits<Capacity>::max();
966 for (int u = 0, e = _edge_num; u != _node_num; ++u, ++e) {
970 _rev_thread[u + 1] = u;
974 _state[e] = STATE_TREE;
975 if (_supply[u] >= 0) {
980 _flow[e] = _supply[u];
988 _flow[e] = -_supply[u];
996 // Find the join node
997 void findJoinNode() {
998 int u = _source[_in_edge];
999 int v = _target[_in_edge];
1001 if (_succ_num[u] < _succ_num[v]) {
1010 // Find the leaving edge of the cycle and returns true if the
1011 // leaving edge is not the same as the entering edge
1012 bool findLeavingEdge() {
1013 // Initialize first and second nodes according to the direction
1015 if (_state[_in_edge] == STATE_LOWER) {
1016 first = _source[_in_edge];
1017 second = _target[_in_edge];
1019 first = _target[_in_edge];
1020 second = _source[_in_edge];
1022 delta = _cap[_in_edge];
1027 // Search the cycle along the path form the first node to the root
1028 for (int u = first; u != join; u = _parent[u]) {
1030 d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
1037 // Search the cycle along the path form the second node to the root
1038 for (int u = second; u != join; u = _parent[u]) {
1040 d = _forward[u] ? _cap[e] - _flow[e] : _flow[e];
1058 // Change _flow and _state vectors
1059 void changeFlow(bool change) {
1060 // Augment along the cycle
1062 Capacity val = _state[_in_edge] * delta;
1063 _flow[_in_edge] += val;
1064 for (int u = _source[_in_edge]; u != join; u = _parent[u]) {
1065 _flow[_pred[u]] += _forward[u] ? -val : val;
1067 for (int u = _target[_in_edge]; u != join; u = _parent[u]) {
1068 _flow[_pred[u]] += _forward[u] ? val : -val;
1071 // Update the state of the entering and leaving edges
1073 _state[_in_edge] = STATE_TREE;
1074 _state[_pred[u_out]] =
1075 (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
1077 _state[_in_edge] = -_state[_in_edge];
1081 // Update the tree structure
1082 void updateTreeStructure() {
1084 int old_rev_thread = _rev_thread[u_out];
1085 int old_succ_num = _succ_num[u_out];
1086 int old_last_succ = _last_succ[u_out];
1087 v_out = _parent[u_out];
1089 u = _last_succ[u_in]; // the last successor of u_in
1090 right = _thread[u]; // the node after it
1092 // Handle the case when old_rev_thread equals to v_in
1093 // (it also means that join and v_out coincide)
1094 if (old_rev_thread == v_in) {
1095 last = _thread[_last_succ[u_out]];
1097 last = _thread[v_in];
1100 // Update _thread and _parent along the stem nodes (i.e. the nodes
1101 // between u_in and u_out, whose parent have to be changed)
1102 _thread[v_in] = stem = u_in;
1103 _dirty_revs.clear();
1104 _dirty_revs.push_back(v_in);
1106 while (stem != u_out) {
1107 // Insert the next stem node into the thread list
1108 new_stem = _parent[stem];
1109 _thread[u] = new_stem;
1110 _dirty_revs.push_back(u);
1112 // Remove the subtree of stem from the thread list
1113 w = _rev_thread[stem];
1115 _rev_thread[right] = w;
1117 // Change the parent node and shift stem nodes
1118 _parent[stem] = par_stem;
1122 // Update u and right nodes
1123 u = _last_succ[stem] == _last_succ[par_stem] ?
1124 _rev_thread[par_stem] : _last_succ[stem];
1127 _parent[u_out] = par_stem;
1128 _last_succ[u_out] = u;
1130 _rev_thread[last] = u;
1132 // Remove the subtree of u_out from the thread list except for
1133 // the case when old_rev_thread equals to v_in
1134 // (it also means that join and v_out coincide)
1135 if (old_rev_thread != v_in) {
1136 _thread[old_rev_thread] = right;
1137 _rev_thread[right] = old_rev_thread;
1140 // Update _rev_thread using the new _thread values
1141 for (int i = 0; i < int(_dirty_revs.size()); ++i) {
1143 _rev_thread[_thread[u]] = u;
1146 // Update _last_succ for the stem nodes from u_out to u_in
1147 for (u = u_out; u != u_in; u = _parent[u]) {
1148 _last_succ[_parent[u]] = _last_succ[u];
1151 // Set limits for updating _last_succ form v_in and v_out
1153 int up_limit_in = -1;
1154 int up_limit_out = -1;
1155 if (_last_succ[join] == v_in) {
1156 up_limit_out = join;
1161 // Update _last_succ from v_in towards the root
1162 for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
1164 _last_succ[u] = _last_succ[u_out];
1166 // Update _last_succ from v_out towards the root
1167 if (join != old_rev_thread && v_in != old_rev_thread) {
1168 for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1170 _last_succ[u] = old_rev_thread;
1173 for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1175 _last_succ[u] = _last_succ[u_out];
1179 // Update _pred and _forward for the stem nodes from u_out to u_in
1183 _pred[u] = _pred[w];
1184 _forward[u] = !_forward[w];
1187 _pred[u_in] = _in_edge;
1188 _forward[u_in] = (u_in == _source[_in_edge]);
1190 // Update _succ_num from v_in to join
1191 for (u = v_in; u != join; u = _parent[u]) {
1192 _succ_num[u] += old_succ_num;
1194 // Update _succ_num from v_out to join
1195 for (u = v_out; u != join; u = _parent[u]) {
1196 _succ_num[u] -= old_succ_num;
1198 // Update _succ_num for the stem nodes from u_out to u_in
1203 tmp = _succ_num[u] - _succ_num[w] + tmp;
1207 _succ_num[u_in] = old_succ_num;
1210 // Update potentials
1211 void updatePotential() {
1212 Cost sigma = _forward[u_in] ?
1213 _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1214 _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
1215 // Update in the lower subtree (which has been moved)
1216 int end = _thread[_last_succ[u_in]];
1217 for (int u = u_in; u != end; u = _thread[u]) {
1222 // Execute the algorithm
1223 bool start(PivotRuleEnum pivot_rule) {
1224 // Select the pivot rule implementation
1225 switch (pivot_rule) {
1226 case FIRST_ELIGIBLE_PIVOT:
1227 return start<FirstEligiblePivotRule>();
1228 case BEST_ELIGIBLE_PIVOT:
1229 return start<BestEligiblePivotRule>();
1230 case BLOCK_SEARCH_PIVOT:
1231 return start<BlockSearchPivotRule>();
1232 case CANDIDATE_LIST_PIVOT:
1233 return start<CandidateListPivotRule>();
1234 case ALTERING_LIST_PIVOT:
1235 return start<AlteringListPivotRule>();
1240 template<class PivotRuleImplementation>
1242 PivotRuleImplementation pivot(*this);
1244 // Execute the network simplex algorithm
1245 while (pivot.findEnteringEdge()) {
1247 bool change = findLeavingEdge();
1250 updateTreeStructure();
1255 // Check if the flow amount equals zero on all the artificial edges
1256 for (int e = _edge_num; e != _edge_num + _node_num; ++e) {
1257 if (_flow[e] > 0) return false;
1260 // Copy flow values to _flow_result
1262 for (int i = 0; i != _edge_num; ++i) {
1264 (*_flow_result)[e] = (*_orig_lower)[e] + _flow[i];
1267 for (int i = 0; i != _edge_num; ++i) {
1268 (*_flow_result)[_edge[i]] = _flow[i];
1271 // Copy potential values to _potential_result
1272 for (int i = 0; i != _node_num; ++i) {
1273 (*_potential_result)[_node[i]] = _pi[i];
1279 }; //class NetworkSimplex
1285 #endif //LEMON_NETWORK_SIMPLEX_H