Rel.07 NEWS - 3. round
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.
30 #include <lemon/graph_adaptor.h>
31 #include <lemon/graph_utils.h>
32 #include <lemon/smart_graph.h>
33 #include <lemon/math.h>
37 /// \addtogroup min_cost_flow
40 /// \brief Implementation of the network simplex algorithm for
41 /// finding a minimum cost flow.
43 /// \ref NetworkSimplex implements the network simplex algorithm for
44 /// finding a minimum cost flow.
46 /// \tparam Graph The directed graph type the algorithm runs on.
47 /// \tparam LowerMap The type of the lower bound map.
48 /// \tparam CapacityMap The type of the capacity (upper bound) map.
49 /// \tparam CostMap The type of the cost (length) map.
50 /// \tparam SupplyMap The type of the supply map.
53 /// - Edge capacities and costs should be \e non-negative \e integers.
54 /// - Supply values should be \e signed \e integers.
55 /// - The value types of the maps should be convertible to each other.
56 /// - \c CostMap::Value must be signed type.
58 /// \note \ref NetworkSimplex provides six different pivot rule
59 /// implementations that significantly affect the efficiency of the
61 /// By default a combined pivot rule is used, which is the fastest
62 /// implementation according to our benchmark tests.
63 /// Another pivot rule can be selected using \ref run() function
64 /// with the proper parameter.
66 /// \author Peter Kovacs
68 template < typename Graph,
69 typename LowerMap = typename Graph::template EdgeMap<int>,
70 typename CapacityMap = typename Graph::template EdgeMap<int>,
71 typename CostMap = typename Graph::template EdgeMap<int>,
72 typename SupplyMap = typename Graph::template NodeMap<int> >
75 typedef typename CapacityMap::Value Capacity;
76 typedef typename CostMap::Value Cost;
77 typedef typename SupplyMap::Value Supply;
79 typedef SmartGraph SGraph;
80 GRAPH_TYPEDEFS(typename SGraph);
82 typedef typename SGraph::template EdgeMap<Capacity> SCapacityMap;
83 typedef typename SGraph::template EdgeMap<Cost> SCostMap;
84 typedef typename SGraph::template NodeMap<Supply> SSupplyMap;
85 typedef typename SGraph::template NodeMap<Cost> SPotentialMap;
87 typedef typename SGraph::template NodeMap<int> IntNodeMap;
88 typedef typename SGraph::template NodeMap<bool> BoolNodeMap;
89 typedef typename SGraph::template NodeMap<Node> NodeNodeMap;
90 typedef typename SGraph::template NodeMap<Edge> EdgeNodeMap;
91 typedef typename SGraph::template EdgeMap<int> IntEdgeMap;
93 typedef typename Graph::template NodeMap<Node> NodeRefMap;
94 typedef typename Graph::template EdgeMap<Edge> EdgeRefMap;
98 /// The type of the flow map.
99 typedef typename Graph::template EdgeMap<Capacity> FlowMap;
100 /// The type of the potential map.
101 typedef typename Graph::template NodeMap<Cost> PotentialMap;
105 /// Enum type to select the pivot rule used by \ref run().
107 FIRST_ELIGIBLE_PIVOT,
110 LIMITED_SEARCH_PIVOT,
111 CANDIDATE_LIST_PIVOT,
117 /// \brief Map adaptor class for handling reduced edge costs.
119 /// Map adaptor class for handling reduced edge costs.
120 class ReducedCostMap : public MapBase<Edge, Cost>
125 const SCostMap &_cost_map;
126 const SPotentialMap &_pot_map;
131 ReducedCostMap( const SGraph &gr,
132 const SCostMap &cost_map,
133 const SPotentialMap &pot_map ) :
134 _gr(gr), _cost_map(cost_map), _pot_map(pot_map) {}
137 Cost operator[](const Edge &e) const {
138 return _cost_map[e] + _pot_map[_gr.source(e)]
139 - _pot_map[_gr.target(e)];
142 }; //class ReducedCostMap
146 /// \brief Implementation of the "First Eligible" pivot rule for the
147 /// \ref NetworkSimplex "network simplex" algorithm.
149 /// This class implements the "First Eligible" pivot rule
150 /// for the \ref NetworkSimplex "network simplex" algorithm.
151 class FirstEligiblePivotRule
161 FirstEligiblePivotRule(NetworkSimplex &ns) :
162 _ns(ns), _next_edge(ns._graph) {}
164 /// Finds the next entering edge.
165 bool findEnteringEdge() {
166 for (EdgeIt e = _next_edge; e != INVALID; ++e) {
167 if (_ns._state[e] * _ns._red_cost[e] < 0) {
173 for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
174 if (_ns._state[e] * _ns._red_cost[e] < 0) {
182 }; //class FirstEligiblePivotRule
184 /// \brief Implementation of the "Best Eligible" pivot rule for the
185 /// \ref NetworkSimplex "network simplex" algorithm.
187 /// This class implements the "Best Eligible" pivot rule
188 /// for the \ref NetworkSimplex "network simplex" algorithm.
189 class BestEligiblePivotRule
198 BestEligiblePivotRule(NetworkSimplex &ns) : _ns(ns) {}
200 /// Finds the next entering edge.
201 bool findEnteringEdge() {
203 for (EdgeIt e(_ns._graph); e != INVALID; ++e) {
204 if (_ns._state[e] * _ns._red_cost[e] < min) {
205 min = _ns._state[e] * _ns._red_cost[e];
211 }; //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.
218 class BlockSearchPivotRule
223 EdgeIt _next_edge, _min_edge;
226 static const int MIN_BLOCK_SIZE = 10;
231 BlockSearchPivotRule(NetworkSimplex &ns) :
232 _ns(ns), _next_edge(ns._graph), _min_edge(ns._graph)
234 _block_size = 2 * int(sqrt(countEdges(_ns._graph)));
235 if (_block_size < MIN_BLOCK_SIZE) _block_size = MIN_BLOCK_SIZE;
238 /// Finds the next entering edge.
239 bool findEnteringEdge() {
242 for (EdgeIt e = _next_edge; e != INVALID; ++e) {
243 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
247 if (++cnt == _block_size) {
253 for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
254 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
258 if (++cnt == _block_size) {
264 _ns._in_edge = _min_edge;
265 _next_edge = ++_min_edge;
268 }; //class BlockSearchPivotRule
270 /// \brief Implementation of the "Limited Search" pivot rule for the
271 /// \ref NetworkSimplex "network simplex" algorithm.
273 /// This class implements the "Limited Search" pivot rule
274 /// for the \ref NetworkSimplex "network simplex" algorithm.
275 class LimitedSearchPivotRule
280 EdgeIt _next_edge, _min_edge;
283 static const int SAMPLE_SIZE_FACTOR = 15;
284 static const int MIN_SAMPLE_SIZE = 10;
289 LimitedSearchPivotRule(NetworkSimplex &ns) :
290 _ns(ns), _next_edge(ns._graph), _min_edge(ns._graph)
292 _sample_size = countEdges(_ns._graph) *
293 SAMPLE_SIZE_FACTOR / 10000;
294 if (_sample_size < MIN_SAMPLE_SIZE)
295 _sample_size = MIN_SAMPLE_SIZE;
298 /// Finds the next entering edge.
299 bool findEnteringEdge() {
302 for (EdgeIt e = _next_edge; e != INVALID; ++e) {
303 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
307 if (curr < 0 && ++cnt == _sample_size) break;
310 for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
311 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
315 if (curr < 0 && ++cnt == _sample_size) break;
318 _ns._in_edge = _min_edge;
319 _next_edge = ++_min_edge;
322 }; //class LimitedSearchPivotRule
324 /// \brief Implementation of the "Candidate List" pivot rule for the
325 /// \ref NetworkSimplex "network simplex" algorithm.
327 /// This class implements the "Candidate List" pivot rule
328 /// for the \ref NetworkSimplex "network simplex" algorithm.
329 class CandidateListPivotRule
335 // The list of candidate edges.
336 std::vector<Edge> _candidates;
337 // The maximum length of the edge list.
339 // The maximum number of minor iterations between two major
346 static const int LIST_LENGTH_FACTOR = 20;
347 static const int MINOR_LIMIT_FACTOR = 10;
348 static const int MIN_LIST_LENGTH = 10;
349 static const int MIN_MINOR_LIMIT = 2;
354 CandidateListPivotRule(NetworkSimplex &ns) :
355 _ns(ns), _next_edge(ns._graph)
357 int edge_num = countEdges(_ns._graph);
359 _list_length = edge_num * LIST_LENGTH_FACTOR / 10000;
360 if (_list_length < MIN_LIST_LENGTH)
361 _list_length = MIN_LIST_LENGTH;
362 _minor_limit = _list_length * MINOR_LIMIT_FACTOR / 100;
363 if (_minor_limit < MIN_MINOR_LIMIT)
364 _minor_limit = MIN_MINOR_LIMIT;
367 /// Finds the next entering edge.
368 bool findEnteringEdge() {
370 if (_minor_count < _minor_limit && _candidates.size() > 0) {
375 for (int i = 0; i < int(_candidates.size()); ++i) {
377 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
382 if (min < 0) return true;
387 EdgeIt e = _next_edge;
389 for ( ; e != INVALID; ++e) {
390 if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
391 _candidates.push_back(e);
396 if (int(_candidates.size()) == _list_length) break;
399 if (int(_candidates.size()) < _list_length) {
400 for (e = EdgeIt(_ns._graph); e != _next_edge; ++e) {
401 if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
402 _candidates.push_back(e);
407 if (int(_candidates.size()) == _list_length) break;
411 if (_candidates.size() == 0) return false;
416 }; //class CandidateListPivotRule
420 // State constants for edges
427 // Constant for the combined pivot rule.
428 static const int COMBINED_PIVOT_MAX_DEG = 5;
432 // The directed graph the algorithm runs on
434 // The original graph
435 const Graph &_graph_ref;
436 // The original lower bound map
437 const LowerMap *_lower;
439 SCapacityMap _capacity;
446 // Edge map of the current flow
448 // Node map of the current potentials
449 SPotentialMap _potential;
451 // The depth node map of the spanning tree structure
453 // The parent node map of the spanning tree structure
455 // The pred_edge node map of the spanning tree structure
456 EdgeNodeMap _pred_edge;
457 // The thread node map of the spanning tree structure
459 // The forward node map of the spanning tree structure
460 BoolNodeMap _forward;
461 // The state edge map
463 // The root node of the starting spanning tree
466 // The reduced cost map
467 ReducedCostMap _red_cost;
469 // Members for handling the original graph
470 FlowMap *_flow_result;
471 PotentialMap *_potential_result;
473 bool _local_potential;
474 NodeRefMap _node_ref;
475 EdgeRefMap _edge_ref;
477 // The entering edge of the current pivot iteration.
480 // Temporary nodes used in the current pivot iteration.
481 Node join, u_in, v_in, u_out, v_out;
482 Node right, first, second, last;
483 Node stem, par_stem, new_stem;
484 // The maximum augment amount along the found cycle in the current
490 /// \brief General constructor (with lower bounds).
492 /// General constructor (with lower bounds).
494 /// \param graph The directed graph the algorithm runs on.
495 /// \param lower The lower bounds of the edges.
496 /// \param capacity The capacities (upper bounds) of the edges.
497 /// \param cost The cost (length) values of the edges.
498 /// \param supply The supply values of the nodes (signed).
499 NetworkSimplex( const Graph &graph,
500 const LowerMap &lower,
501 const CapacityMap &capacity,
503 const SupplyMap &supply ) :
504 _graph(), _graph_ref(graph), _lower(&lower), _capacity(_graph),
505 _cost(_graph), _supply(_graph), _flow(_graph),
506 _potential(_graph), _depth(_graph), _parent(_graph),
507 _pred_edge(_graph), _thread(_graph), _forward(_graph),
508 _state(_graph), _red_cost(_graph, _cost, _potential),
509 _flow_result(0), _potential_result(0),
510 _local_flow(false), _local_potential(false),
511 _node_ref(graph), _edge_ref(graph)
513 // Checking the sum of supply values
515 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
517 if (!(_valid_supply = sum == 0)) return;
519 // Copying _graph_ref to _graph
520 _graph.reserveNode(countNodes(_graph_ref) + 1);
521 _graph.reserveEdge(countEdges(_graph_ref) + countNodes(_graph_ref));
522 copyGraph(_graph, _graph_ref)
523 .edgeMap(_cost, cost)
528 // Removing non-zero lower bounds
529 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
530 _capacity[_edge_ref[e]] = capacity[e] - lower[e];
532 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
533 Supply s = supply[n];
534 for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
536 for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
538 _supply[_node_ref[n]] = s;
542 /// \brief General constructor (without lower bounds).
544 /// General constructor (without lower bounds).
546 /// \param graph The directed graph the algorithm runs on.
547 /// \param capacity The capacities (upper bounds) of the edges.
548 /// \param cost The cost (length) values of the edges.
549 /// \param supply The supply values of the nodes (signed).
550 NetworkSimplex( const Graph &graph,
551 const CapacityMap &capacity,
553 const SupplyMap &supply ) :
554 _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
555 _cost(_graph), _supply(_graph), _flow(_graph),
556 _potential(_graph), _depth(_graph), _parent(_graph),
557 _pred_edge(_graph), _thread(_graph), _forward(_graph),
558 _state(_graph), _red_cost(_graph, _cost, _potential),
559 _flow_result(0), _potential_result(0),
560 _local_flow(false), _local_potential(false),
561 _node_ref(graph), _edge_ref(graph)
563 // Checking the sum of supply values
565 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
567 if (!(_valid_supply = sum == 0)) return;
569 // Copying _graph_ref to graph
570 copyGraph(_graph, _graph_ref)
571 .edgeMap(_capacity, capacity)
572 .edgeMap(_cost, cost)
573 .nodeMap(_supply, supply)
579 /// \brief Simple constructor (with lower bounds).
581 /// Simple constructor (with lower bounds).
583 /// \param graph The directed graph the algorithm runs on.
584 /// \param lower The lower bounds of the edges.
585 /// \param capacity The capacities (upper bounds) of the edges.
586 /// \param cost The cost (length) values of the edges.
587 /// \param s The source node.
588 /// \param t The target node.
589 /// \param flow_value The required amount of flow from node \c s
590 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
591 NetworkSimplex( const Graph &graph,
592 const LowerMap &lower,
593 const CapacityMap &capacity,
595 typename Graph::Node s,
596 typename Graph::Node t,
597 typename SupplyMap::Value flow_value ) :
598 _graph(), _graph_ref(graph), _lower(&lower), _capacity(_graph),
599 _cost(_graph), _supply(_graph), _flow(_graph),
600 _potential(_graph), _depth(_graph), _parent(_graph),
601 _pred_edge(_graph), _thread(_graph), _forward(_graph),
602 _state(_graph), _red_cost(_graph, _cost, _potential),
603 _flow_result(0), _potential_result(0),
604 _local_flow(false), _local_potential(false),
605 _node_ref(graph), _edge_ref(graph)
607 // Copying _graph_ref to graph
608 copyGraph(_graph, _graph_ref)
609 .edgeMap(_cost, cost)
614 // Removing non-zero lower bounds
615 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
616 _capacity[_edge_ref[e]] = capacity[e] - lower[e];
618 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
620 if (n == s) sum = flow_value;
621 if (n == t) sum = -flow_value;
622 for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
624 for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
626 _supply[_node_ref[n]] = sum;
628 _valid_supply = true;
631 /// \brief Simple constructor (without lower bounds).
633 /// Simple constructor (without lower bounds).
635 /// \param graph The directed graph the algorithm runs on.
636 /// \param capacity The capacities (upper bounds) of the edges.
637 /// \param cost The cost (length) values of the edges.
638 /// \param s The source node.
639 /// \param t The target node.
640 /// \param flow_value The required amount of flow from node \c s
641 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
642 NetworkSimplex( const Graph &graph,
643 const CapacityMap &capacity,
645 typename Graph::Node s,
646 typename Graph::Node t,
647 typename SupplyMap::Value flow_value ) :
648 _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
649 _cost(_graph), _supply(_graph, 0), _flow(_graph),
650 _potential(_graph), _depth(_graph), _parent(_graph),
651 _pred_edge(_graph), _thread(_graph), _forward(_graph),
652 _state(_graph), _red_cost(_graph, _cost, _potential),
653 _flow_result(0), _potential_result(0),
654 _local_flow(false), _local_potential(false),
655 _node_ref(graph), _edge_ref(graph)
657 // Copying _graph_ref to graph
658 copyGraph(_graph, _graph_ref)
659 .edgeMap(_capacity, capacity)
660 .edgeMap(_cost, cost)
664 _supply[_node_ref[s]] = flow_value;
665 _supply[_node_ref[t]] = -flow_value;
666 _valid_supply = true;
671 if (_local_flow) delete _flow_result;
672 if (_local_potential) delete _potential_result;
675 /// \brief Sets the flow map.
677 /// Sets the flow map.
679 /// \return \c (*this)
680 NetworkSimplex& flowMap(FlowMap &map) {
689 /// \brief Sets the potential map.
691 /// Sets the potential map.
693 /// \return \c (*this)
694 NetworkSimplex& potentialMap(PotentialMap &map) {
695 if (_local_potential) {
696 delete _potential_result;
697 _local_potential = false;
699 _potential_result = ↦
703 /// \name Execution control
704 /// The only way to execute the algorithm is to call the run()
709 /// \brief Runs the algorithm.
711 /// Runs the algorithm.
713 /// \param pivot_rule The pivot rule that is used during the
716 /// The available pivot rules:
718 /// - FIRST_ELIGIBLE_PIVOT The next eligible edge is selected in
719 /// a wraparound fashion in every iteration
720 /// (\ref FirstEligiblePivotRule).
722 /// - BEST_ELIGIBLE_PIVOT The best eligible edge is selected in
723 /// every iteration (\ref BestEligiblePivotRule).
725 /// - BLOCK_SEARCH_PIVOT A specified number of edges are examined in
726 /// every iteration in a wraparound fashion and the best eligible
727 /// edge is selected from this block (\ref BlockSearchPivotRule).
729 /// - LIMITED_SEARCH_PIVOT A specified number of eligible edges are
730 /// examined in every iteration in a wraparound fashion and the best
731 /// one is selected from them (\ref LimitedSearchPivotRule).
733 /// - CANDIDATE_LIST_PIVOT In major iterations a candidate list is
734 /// built from eligible edges and it is used for edge selection in
735 /// the following minor iterations (\ref CandidateListPivotRule).
737 /// - COMBINED_PIVOT This is a combined version of the two fastest
739 /// For rather sparse graphs \ref LimitedSearchPivotRule
740 /// "Limited Search" implementation is used, otherwise
741 /// \ref BlockSearchPivotRule "Block Search" pivot rule is used.
742 /// According to our benchmark tests this combined method is the
745 /// \return \c true if a feasible flow can be found.
746 bool run(PivotRuleEnum pivot_rule = COMBINED_PIVOT) {
747 return init() && start(pivot_rule);
752 /// \name Query Functions
753 /// The result of the algorithm can be obtained using these
755 /// \n run() must be called before using them.
759 /// \brief Returns a const reference to the edge map storing the
762 /// Returns a const reference to the edge map storing the found flow.
764 /// \pre \ref run() must be called before using this function.
765 const FlowMap& flowMap() const {
766 return *_flow_result;
769 /// \brief Returns a const reference to the node map storing the
770 /// found potentials (the dual solution).
772 /// Returns a const reference to the node map storing the found
773 /// potentials (the dual solution).
775 /// \pre \ref run() must be called before using this function.
776 const PotentialMap& potentialMap() const {
777 return *_potential_result;
780 /// \brief Returns the flow on the given edge.
782 /// Returns the flow on the given edge.
784 /// \pre \ref run() must be called before using this function.
785 Capacity flow(const typename Graph::Edge& edge) const {
786 return (*_flow_result)[edge];
789 /// \brief Returns the potential of the given node.
791 /// Returns the potential of the given node.
793 /// \pre \ref run() must be called before using this function.
794 Cost potential(const typename Graph::Node& node) const {
795 return (*_potential_result)[node];
798 /// \brief Returns the total cost of the found flow.
800 /// Returns the total cost of the found flow. The complexity of the
801 /// function is \f$ O(e) \f$.
803 /// \pre \ref run() must be called before using this function.
804 Cost totalCost() const {
806 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
807 c += (*_flow_result)[e] * _cost[_edge_ref[e]];
815 /// \brief Extends the underlaying graph and initializes all the
816 /// node and edge maps.
818 if (!_valid_supply) return false;
820 // Initializing result maps
822 _flow_result = new FlowMap(_graph_ref);
825 if (!_potential_result) {
826 _potential_result = new PotentialMap(_graph_ref);
827 _local_potential = true;
830 // Initializing state and flow maps
831 for (EdgeIt e(_graph); e != INVALID; ++e) {
833 _state[e] = STATE_LOWER;
836 // Adding an artificial root node to the graph
837 _root = _graph.addNode();
838 _parent[_root] = INVALID;
839 _pred_edge[_root] = INVALID;
842 _potential[_root] = 0;
844 // Adding artificial edges to the graph and initializing the node
845 // maps of the spanning tree data structure
848 Cost max_cost = std::numeric_limits<Cost>::max() / 4;
849 for (NodeIt u(_graph); u != INVALID; ++u) {
850 if (u == _root) continue;
855 if (_supply[u] >= 0) {
856 e = _graph.addEdge(u, _root);
857 _flow[e] = _supply[u];
859 _potential[u] = -max_cost;
861 e = _graph.addEdge(_root, u);
862 _flow[e] = -_supply[u];
864 _potential[u] = max_cost;
867 _capacity[e] = std::numeric_limits<Capacity>::max();
868 _state[e] = STATE_TREE;
871 _thread[last] = _root;
876 /// Finds the join node.
877 Node findJoinNode() {
878 Node u = _graph.source(_in_edge);
879 Node v = _graph.target(_in_edge);
881 if (_depth[u] == _depth[v]) {
885 else if (_depth[u] > _depth[v]) u = _parent[u];
891 /// \brief Finds the leaving edge of the cycle. Returns \c true if
892 /// the leaving edge is not the same as the entering edge.
893 bool findLeavingEdge() {
894 // Initializing first and second nodes according to the direction
896 if (_state[_in_edge] == STATE_LOWER) {
897 first = _graph.source(_in_edge);
898 second = _graph.target(_in_edge);
900 first = _graph.target(_in_edge);
901 second = _graph.source(_in_edge);
903 delta = _capacity[_in_edge];
908 // Searching the cycle along the path form the first node to the
910 for (Node u = first; u != join; u = _parent[u]) {
912 d = _forward[u] ? _flow[e] : _capacity[e] - _flow[e];
921 // Searching the cycle along the path form the second node to the
923 for (Node u = second; u != join; u = _parent[u]) {
925 d = _forward[u] ? _capacity[e] - _flow[e] : _flow[e];
937 /// Changes \c flow and \c state edge maps.
938 void changeFlows(bool change) {
939 // Augmenting along the cycle
941 Capacity val = _state[_in_edge] * delta;
942 _flow[_in_edge] += val;
943 for (Node u = _graph.source(_in_edge); u != join; u = _parent[u]) {
944 _flow[_pred_edge[u]] += _forward[u] ? -val : val;
946 for (Node u = _graph.target(_in_edge); u != join; u = _parent[u]) {
947 _flow[_pred_edge[u]] += _forward[u] ? val : -val;
950 // Updating the state of the entering and leaving edges
952 _state[_in_edge] = STATE_TREE;
953 _state[_pred_edge[u_out]] =
954 (_flow[_pred_edge[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
956 _state[_in_edge] = -_state[_in_edge];
960 /// Updates \c thread and \c parent node maps.
961 void updateThreadParent() {
963 v_out = _parent[u_out];
965 // Handling the case when join and v_out coincide
966 bool par_first = false;
968 for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
971 while (_thread[u] != u_out) u = _thread[u];
976 // Finding the last successor of u_in (u) and the node after it
977 // (right) according to the thread index
978 for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
980 if (_thread[v_in] == u_out) {
981 for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
982 if (last == u_out) last = _thread[last];
984 else last = _thread[v_in];
986 // Updating stem nodes
987 _thread[v_in] = stem = u_in;
989 while (stem != u_out) {
990 _thread[u] = new_stem = _parent[stem];
992 // Finding the node just before the stem node (u) according to
993 // the original thread index
994 for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
997 // Changing the parent node of stem and shifting stem and
999 _parent[stem] = par_stem;
1003 // Finding the last successor of stem (u) and the node after it
1004 // (right) according to the thread index
1005 for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
1008 _parent[u_out] = par_stem;
1011 if (join == v_out && par_first) {
1012 if (first != v_in) _thread[first] = right;
1014 for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
1019 /// Updates \c pred_edge and \c forward node maps.
1020 void updatePredEdge() {
1024 _pred_edge[u] = _pred_edge[v];
1025 _forward[u] = !_forward[v];
1028 _pred_edge[u_in] = _in_edge;
1029 _forward[u_in] = (u_in == _graph.source(_in_edge));
1032 /// Updates \c depth and \c potential node maps.
1033 void updateDepthPotential() {
1034 _depth[u_in] = _depth[v_in] + 1;
1035 _potential[u_in] = _forward[u_in] ?
1036 _potential[v_in] - _cost[_pred_edge[u_in]] :
1037 _potential[v_in] + _cost[_pred_edge[u_in]];
1039 Node u = _thread[u_in], v;
1042 if (v == INVALID) break;
1043 _depth[u] = _depth[v] + 1;
1044 _potential[u] = _forward[u] ?
1045 _potential[v] - _cost[_pred_edge[u]] :
1046 _potential[v] + _cost[_pred_edge[u]];
1047 if (_depth[u] <= _depth[v_in]) break;
1052 /// Executes the algorithm.
1053 bool start(PivotRuleEnum pivot_rule) {
1054 switch (pivot_rule) {
1055 case FIRST_ELIGIBLE_PIVOT:
1056 return start<FirstEligiblePivotRule>();
1057 case BEST_ELIGIBLE_PIVOT:
1058 return start<BestEligiblePivotRule>();
1059 case BLOCK_SEARCH_PIVOT:
1060 return start<BlockSearchPivotRule>();
1061 case LIMITED_SEARCH_PIVOT:
1062 return start<LimitedSearchPivotRule>();
1063 case CANDIDATE_LIST_PIVOT:
1064 return start<CandidateListPivotRule>();
1065 case COMBINED_PIVOT:
1066 if ( countEdges(_graph) / countNodes(_graph) <=
1067 COMBINED_PIVOT_MAX_DEG )
1068 return start<LimitedSearchPivotRule>();
1070 return start<BlockSearchPivotRule>();
1075 template<class PivotRuleImplementation>
1077 PivotRuleImplementation pivot(*this);
1079 // Executing the network simplex algorithm
1080 while (pivot.findEnteringEdge()) {
1081 join = findJoinNode();
1082 bool change = findLeavingEdge();
1083 changeFlows(change);
1085 updateThreadParent();
1087 updateDepthPotential();
1091 // Checking if the flow amount equals zero on all the artificial
1093 for (InEdgeIt e(_graph, _root); e != INVALID; ++e)
1094 if (_flow[e] > 0) return false;
1095 for (OutEdgeIt e(_graph, _root); e != INVALID; ++e)
1096 if (_flow[e] > 0) return false;
1098 // Copying flow values to _flow_result
1100 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
1101 (*_flow_result)[e] = (*_lower)[e] + _flow[_edge_ref[e]];
1103 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
1104 (*_flow_result)[e] = _flow[_edge_ref[e]];
1106 // Copying potential values to _potential_result
1107 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
1108 (*_potential_result)[n] = _potential[_node_ref[n]];
1113 }; //class NetworkSimplex
1119 #endif //LEMON_NETWORK_SIMPLEX_H