Major improvements in NetworkSimplex.
Main changes:
- Use -potenital[] instead of potential[] to conform to the usual
terminology.
- Use function parameter instead of #define commands to select pivot rule.
- Use much faster implementation for the candidate list pivot rule.
It is about 5-20 times faster now.
- Add a new pivot rule called "Limited Search" that is a modified
version of "Block Search". It is about 25 percent faster on rather
sparse graphs.
- By default "Limited Search" is used for sparse graphs and
"Block Search" is used otherwise. This combined method is the most
efficient on every input class.
- Change the name of private members to start with "_".
- Change the name of function parameters not to start with "_".
- Remove unnecessary documentation for private members.
- Many doc improvements.
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 /// - \c LowerMap::Value must be convertible to \c CapacityMap::Value.
56 /// - \c CapacityMap::Value and \c SupplyMap::Value must be
57 /// convertible to each other.
58 /// - All value types must be convertible to \c CostMap::Value, which
59 /// must be signed type.
61 /// \note \ref NetworkSimplex provides six different pivot rule
62 /// implementations that significantly affect the efficiency of the
64 /// By default a combined pivot rule is used, which is the fastest
65 /// implementation according to our benchmark tests.
66 /// Another pivot rule can be selected using \ref run() function
67 /// with the proper parameter.
69 /// \author Peter Kovacs
71 template < typename Graph,
72 typename LowerMap = typename Graph::template EdgeMap<int>,
73 typename CapacityMap = typename Graph::template EdgeMap<int>,
74 typename CostMap = typename Graph::template EdgeMap<int>,
75 typename SupplyMap = typename Graph::template NodeMap<int> >
78 typedef typename CapacityMap::Value Capacity;
79 typedef typename CostMap::Value Cost;
80 typedef typename SupplyMap::Value Supply;
82 typedef SmartGraph SGraph;
83 GRAPH_TYPEDEFS(typename SGraph);
85 typedef typename SGraph::template EdgeMap<Capacity> SCapacityMap;
86 typedef typename SGraph::template EdgeMap<Cost> SCostMap;
87 typedef typename SGraph::template NodeMap<Supply> SSupplyMap;
88 typedef typename SGraph::template NodeMap<Cost> SPotentialMap;
90 typedef typename SGraph::template NodeMap<int> IntNodeMap;
91 typedef typename SGraph::template NodeMap<bool> BoolNodeMap;
92 typedef typename SGraph::template NodeMap<Node> NodeNodeMap;
93 typedef typename SGraph::template NodeMap<Edge> EdgeNodeMap;
94 typedef typename SGraph::template EdgeMap<int> IntEdgeMap;
96 typedef typename Graph::template NodeMap<Node> NodeRefMap;
97 typedef typename Graph::template EdgeMap<Edge> EdgeRefMap;
101 /// The type of the flow map.
102 typedef typename Graph::template EdgeMap<Capacity> FlowMap;
103 /// The type of the potential map.
104 typedef typename Graph::template NodeMap<Cost> PotentialMap;
108 /// Enum type to select the pivot rule used by \ref run().
110 FIRST_ELIGIBLE_PIVOT,
113 LIMITED_SEARCH_PIVOT,
114 CANDIDATE_LIST_PIVOT,
120 /// \brief Map adaptor class for handling reduced edge costs.
122 /// Map adaptor class for handling reduced edge costs.
123 class ReducedCostMap : public MapBase<Edge, Cost>
128 const SCostMap &_cost_map;
129 const SPotentialMap &_pot_map;
134 ReducedCostMap( const SGraph &gr,
135 const SCostMap &cost_map,
136 const SPotentialMap &pot_map ) :
137 _gr(gr), _cost_map(cost_map), _pot_map(pm) {}
140 Cost operator[](const Edge &e) const {
141 return _cost_map[e] + _pot_map[_gr.source(e)]
142 - _pot_map[_gr.target(e)];
145 }; //class ReducedCostMap
149 /// \brief Implementation of the "First Eligible" pivot rule for the
150 /// \ref NetworkSimplex "network simplex" algorithm.
152 /// This class implements the "First Eligible" pivot rule
153 /// for the \ref NetworkSimplex "network simplex" algorithm.
154 class FirstEligiblePivotRule
164 FirstEligiblePivotRule(NetworkSimplex &ns) :
165 _ns(ns), _next_edge(ns._graph) {}
167 /// Finds the next entering edge.
168 bool findEnteringEdge() {
169 for (EdgeIt e = _next_edge; e != INVALID; ++e) {
170 if (_ns._state[e] * _ns._red_cost[e] < 0) {
176 for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
177 if (_ns._state[e] * _ns._red_cost[e] < 0) {
185 }; //class FirstEligiblePivotRule
187 /// \brief Implementation of the "Best Eligible" pivot rule for the
188 /// \ref NetworkSimplex "network simplex" algorithm.
190 /// This class implements the "Best Eligible" pivot rule
191 /// for the \ref NetworkSimplex "network simplex" algorithm.
192 class BestEligiblePivotRule
201 BestEligiblePivotRule(NetworkSimplex &ns) : _ns(ns) {}
203 /// Finds the next entering edge.
204 bool findEnteringEdge() {
206 for (EdgeIt e(_ns._graph); e != INVALID; ++e) {
207 if (_ns._state[e] * _ns._red_cost[e] < min) {
208 min = _ns._state[e] * _ns._red_cost[e];
214 }; //class BestEligiblePivotRule
216 /// \brief Implementation of the "Block Search" pivot rule for the
217 /// \ref NetworkSimplex "network simplex" algorithm.
219 /// This class implements the "Block Search" pivot rule
220 /// for the \ref NetworkSimplex "network simplex" algorithm.
221 class BlockSearchPivotRule
226 EdgeIt _next_edge, _min_edge;
229 static const int MIN_BLOCK_SIZE = 10;
234 BlockSearchPivotRule(NetworkSimplex &ns) :
235 _ns(ns), _next_edge(ns._graph), _min_edge(ns._graph)
237 _block_size = 2 * int(sqrt(countEdges(_ns._graph)));
238 if (_block_size < MIN_BLOCK_SIZE) _block_size = MIN_BLOCK_SIZE;
241 /// Finds the next entering edge.
242 bool findEnteringEdge() {
245 for (EdgeIt e = _next_edge; e != INVALID; ++e) {
246 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
250 if (++cnt == _block_size) {
256 for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
257 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
261 if (++cnt == _block_size) {
267 _ns._in_edge = _min_edge;
268 _next_edge = ++_min_edge;
271 }; //class BlockSearchPivotRule
273 /// \brief Implementation of the "Limited Search" pivot rule for the
274 /// \ref NetworkSimplex "network simplex" algorithm.
276 /// This class implements the "Limited Search" pivot rule
277 /// for the \ref NetworkSimplex "network simplex" algorithm.
278 class LimitedSearchPivotRule
283 EdgeIt _next_edge, _min_edge;
286 static const int MIN_SAMPLE_SIZE = 10;
287 static const double SAMPLE_SIZE_FACTOR = 0.0015;
292 LimitedSearchPivotRule(NetworkSimplex &ns) :
293 _ns(ns), _next_edge(ns._graph), _min_edge(ns._graph)
295 _sample_size = int(SAMPLE_SIZE_FACTOR * countEdges(_ns._graph));
296 if (_sample_size < MIN_SAMPLE_SIZE)
297 _sample_size = MIN_SAMPLE_SIZE;
300 /// Finds the next entering edge.
301 bool findEnteringEdge() {
304 for (EdgeIt e = _next_edge; e != INVALID; ++e) {
305 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
309 if (curr < 0 && ++cnt == _sample_size) break;
312 for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
313 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
317 if (curr < 0 && ++cnt == _sample_size) break;
320 _ns._in_edge = _min_edge;
321 _next_edge = ++_min_edge;
324 }; //class LimitedSearchPivotRule
326 /// \brief Implementation of the "Candidate List" pivot rule for the
327 /// \ref NetworkSimplex "network simplex" algorithm.
329 /// This class implements the "Candidate List" pivot rule
330 /// for the \ref NetworkSimplex "network simplex" algorithm.
331 class CandidateListPivotRule
337 // The list of candidate edges.
338 std::vector<Edge> _candidates;
339 // The maximum length of the edge list.
341 // The maximum number of minor iterations between two major
348 static const double LIST_LENGTH_FACTOR = 0.002;
349 static const double MINOR_LIMIT_FACTOR = 0.1;
350 static const int MIN_LIST_LENGTH = 10;
351 static const int MIN_MINOR_LIMIT = 2;
356 CandidateListPivotRule(NetworkSimplex &ns) :
357 _ns(ns), _next_edge(ns._graph)
359 int edge_num = countEdges(_ns._graph);
361 _list_length = int(edge_num * LIST_LENGTH_FACTOR);
362 if (_list_length < MIN_LIST_LENGTH)
363 _list_length = MIN_LIST_LENGTH;
364 _minor_limit = int(_list_length * MINOR_LIMIT_FACTOR);
365 if (_minor_limit < MIN_MINOR_LIMIT)
366 _minor_limit = MIN_MINOR_LIMIT;
369 /// Finds the next entering edge.
370 bool findEnteringEdge() {
372 if (_minor_count < _minor_limit && _candidates.size() > 0) {
377 for (int i = 0; i < int(_candidates.size()); ++i) {
379 if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
384 if (min < 0) return true;
389 EdgeIt e = _next_edge;
391 for ( ; e != INVALID; ++e) {
392 if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
393 _candidates.push_back(e);
398 if (int(_candidates.size()) == _list_length) break;
401 if (int(_candidates.size()) < _list_length) {
402 for (e = EdgeIt(_ns._graph); e != _next_edge; ++e) {
403 if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
404 _candidates.push_back(e);
409 if (int(_candidates.size()) == _list_length) break;
413 if (_candidates.size() == 0) return false;
418 }; //class CandidateListPivotRule
422 // State constant for edges at their lower bounds.
423 static const int STATE_LOWER = 1;
424 // State constant for edges in the spanning tree.
425 static const int STATE_TREE = 0;
426 // State constant for edges at their upper bounds.
427 static const int STATE_UPPER = -1;
429 // Constant for the combined pivot rule.
430 static const int COMBINED_PIVOT_MAX_DEG = 5;
434 // The directed graph the algorithm runs on
436 // The original graph
437 const Graph &_graph_ref;
438 // The original lower bound map
439 const LowerMap *_lower;
441 SCapacityMap _capacity;
448 // Edge map of the current flow
450 // Node map of the current potentials
451 SPotentialMap _potential;
453 // The depth node map of the spanning tree structure
455 // The parent node map of the spanning tree structure
457 // The pred_edge node map of the spanning tree structure
458 EdgeNodeMap _pred_edge;
459 // The thread node map of the spanning tree structure
461 // The forward node map of the spanning tree structure
462 BoolNodeMap _forward;
463 // The state edge map
465 // The root node of the starting spanning tree
468 // The reduced cost map
469 ReducedCostMap _red_cost;
471 // Members for handling the original graph
472 FlowMap _flow_result;
473 PotentialMap _potential_result;
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 of the class (with lower bounds).
492 /// General constructor of the class (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(graph), _potential_result(graph),
510 _node_ref(graph), _edge_ref(graph)
512 // Checking the sum of supply values
514 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
516 if (!(_valid_supply = sum == 0)) return;
518 // Copying _graph_ref to _graph
519 _graph.reserveNode(countNodes(_graph_ref) + 1);
520 _graph.reserveEdge(countEdges(_graph_ref) + countNodes(_graph_ref));
521 copyGraph(_graph, _graph_ref)
522 .edgeMap(_cost, cost)
527 // Removing non-zero lower bounds
528 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
529 _capacity[_edge_ref[e]] = capacity[e] - lower[e];
531 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
532 Supply s = supply[n];
533 for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
535 for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
537 _supply[_node_ref[n]] = s;
541 /// \brief General constructor of the class (without lower bounds).
543 /// General constructor of the class (without lower bounds).
545 /// \param graph The directed graph the algorithm runs on.
546 /// \param capacity The capacities (upper bounds) of the edges.
547 /// \param cost The cost (length) values of the edges.
548 /// \param supply The supply values of the nodes (signed).
549 NetworkSimplex( const Graph &graph,
550 const CapacityMap &capacity,
552 const SupplyMap &supply ) :
553 _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
554 _cost(_graph), _supply(_graph), _flow(_graph),
555 _potential(_graph), _depth(_graph), _parent(_graph),
556 _pred_edge(_graph), _thread(_graph), _forward(_graph),
557 _state(_graph), _red_cost(_graph, _cost, _potential),
558 _flow_result(graph), _potential_result(graph),
559 _node_ref(graph), _edge_ref(graph)
561 // Checking the sum of supply values
563 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
565 if (!(_valid_supply = sum == 0)) return;
567 // Copying _graph_ref to graph
568 copyGraph(_graph, _graph_ref)
569 .edgeMap(_capacity, capacity)
570 .edgeMap(_cost, cost)
571 .nodeMap(_supply, supply)
577 /// \brief Simple constructor of the class (with lower bounds).
579 /// Simple constructor of the class (with lower bounds).
581 /// \param graph The directed graph the algorithm runs on.
582 /// \param lower The lower bounds of the edges.
583 /// \param capacity The capacities (upper bounds) of the edges.
584 /// \param cost The cost (length) values of the edges.
585 /// \param s The source node.
586 /// \param t The target node.
587 /// \param flow_value The required amount of flow from node \c s
588 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
589 NetworkSimplex( const Graph &graph,
590 const LowerMap &lower,
591 const CapacityMap &capacity,
593 typename Graph::Node s,
594 typename Graph::Node t,
595 typename SupplyMap::Value flow_value ) :
596 _graph(), _graph_ref(graph), _lower(&lower), _capacity(_graph),
597 _cost(_graph), _supply(_graph), _flow(_graph),
598 _potential(_graph), _depth(_graph), _parent(_graph),
599 _pred_edge(_graph), _thread(_graph), _forward(_graph),
600 _state(_graph), _red_cost(_graph, _cost, _potential),
601 _flow_result(graph), _potential_result(graph),
602 _node_ref(graph), _edge_ref(graph)
604 // Copying _graph_ref to graph
605 copyGraph(_graph, _graph_ref)
606 .edgeMap(_cost, cost)
611 // Removing non-zero lower bounds
612 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
613 _capacity[_edge_ref[e]] = capacity[e] - lower[e];
615 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
617 if (n == s) sum = flow_value;
618 if (n == t) sum = -flow_value;
619 for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
621 for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
623 _supply[_node_ref[n]] = sum;
625 _valid_supply = true;
628 /// \brief Simple constructor of the class (without lower bounds).
630 /// Simple constructor of the class (without lower bounds).
632 /// \param graph The directed graph the algorithm runs on.
633 /// \param capacity The capacities (upper bounds) of the edges.
634 /// \param cost The cost (length) values of the edges.
635 /// \param s The source node.
636 /// \param t The target node.
637 /// \param flow_value The required amount of flow from node \c s
638 /// to node \c t (i.e. the supply of \c s and the demand of \c t).
639 NetworkSimplex( const Graph &graph,
640 const CapacityMap &capacity,
642 typename Graph::Node s,
643 typename Graph::Node t,
644 typename SupplyMap::Value flow_value ) :
645 _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
646 _cost(_graph), _supply(_graph, 0), _flow(_graph),
647 _potential(_graph), _depth(_graph), _parent(_graph),
648 _pred_edge(_graph), _thread(_graph), _forward(_graph),
649 _state(_graph), _red_cost(_graph, _cost, _potential),
650 _flow_result(graph), _potential_result(graph),
651 _node_ref(graph), _edge_ref(graph)
653 // Copying _graph_ref to graph
654 copyGraph(_graph, _graph_ref)
655 .edgeMap(_capacity, capacity)
656 .edgeMap(_cost, cost)
660 _supply[_node_ref[s]] = flow_value;
661 _supply[_node_ref[t]] = -flow_value;
662 _valid_supply = true;
665 /// \brief Runs the algorithm.
667 /// Runs the algorithm.
669 /// \param pivot_rule The pivot rule that is used during the
672 /// The available pivot rules:
674 /// - FIRST_ELIGIBLE_PIVOT The next eligible edge is selected in
675 /// a wraparound fashion in every iteration
676 /// (\ref FirstEligiblePivotRule).
678 /// - BEST_ELIGIBLE_PIVOT The best eligible edge is selected in
679 /// every iteration (\ref BestEligiblePivotRule).
681 /// - BLOCK_SEARCH_PIVOT A specified number of edges are examined in
682 /// every iteration in a wraparound fashion and the best eligible
683 /// edge is selected from this block (\ref BlockSearchPivotRule).
685 /// - LIMITED_SEARCH_PIVOT A specified number of eligible edges are
686 /// examined in every iteration in a wraparound fashion and the best
687 /// one is selected from them (\ref LimitedSearchPivotRule).
689 /// - CANDIDATE_LIST_PIVOT In major iterations a candidate list is
690 /// built from eligible edges and it is used for edge selection in
691 /// the following minor iterations (\ref CandidateListPivotRule).
693 /// - COMBINED_PIVOT This is a combined version of the two fastest
695 /// For rather sparse graphs \ref LimitedSearchPivotRule
696 /// "Limited Search" implementation is used, otherwise
697 /// \ref BlockSearchPivotRule "Block Search" pivot rule is used.
698 /// According to our benchmark tests this combined method is the
701 /// \return \c true if a feasible flow can be found.
702 bool run(PivotRuleEnum pivot_rule = COMBINED_PIVOT) {
703 return init() && start(pivot_rule);
706 /// \brief Returns a const reference to the edge map storing the
709 /// Returns a const reference to the edge map storing the found flow.
711 /// \pre \ref run() must be called before using this function.
712 const FlowMap& flowMap() const {
716 /// \brief Returns a const reference to the node map storing the
717 /// found potentials (the dual solution).
719 /// Returns a const reference to the node map storing the found
720 /// potentials (the dual solution).
722 /// \pre \ref run() must be called before using this function.
723 const PotentialMap& potentialMap() const {
724 return _potential_result;
727 /// \brief Returns the total cost of the found flow.
729 /// Returns the total cost of the found flow. The complexity of the
730 /// function is \f$ O(e) \f$.
732 /// \pre \ref run() must be called before using this function.
733 Cost totalCost() const {
735 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
736 c += _flow_result[e] * _cost[_edge_ref[e]];
742 /// \brief Extends the underlaying graph and initializes all the
743 /// node and edge maps.
745 if (!_valid_supply) return false;
747 // Initializing state and flow maps
748 for (EdgeIt e(_graph); e != INVALID; ++e) {
750 _state[e] = STATE_LOWER;
753 // Adding an artificial root node to the graph
754 _root = _graph.addNode();
755 _parent[_root] = INVALID;
756 _pred_edge[_root] = INVALID;
759 _potential[_root] = 0;
761 // Adding artificial edges to the graph and initializing the node
762 // maps of the spanning tree data structure
765 Cost max_cost = std::numeric_limits<Cost>::max() / 4;
766 for (NodeIt u(_graph); u != INVALID; ++u) {
767 if (u == _root) continue;
772 if (_supply[u] >= 0) {
773 e = _graph.addEdge(u, _root);
774 _flow[e] = _supply[u];
776 _potential[u] = -max_cost;
778 e = _graph.addEdge(_root, u);
779 _flow[e] = -_supply[u];
781 _potential[u] = max_cost;
784 _capacity[e] = std::numeric_limits<Capacity>::max();
785 _state[e] = STATE_TREE;
788 _thread[last] = _root;
793 /// Finds the join node.
794 Node findJoinNode() {
795 Node u = _graph.source(_in_edge);
796 Node v = _graph.target(_in_edge);
798 if (_depth[u] == _depth[v]) {
802 else if (_depth[u] > _depth[v]) u = _parent[u];
808 /// \brief Finds the leaving edge of the cycle. Returns \c true if
809 /// the leaving edge is not the same as the entering edge.
810 bool findLeavingEdge() {
811 // Initializing first and second nodes according to the direction
813 if (_state[_in_edge] == STATE_LOWER) {
814 first = _graph.source(_in_edge);
815 second = _graph.target(_in_edge);
817 first = _graph.target(_in_edge);
818 second = _graph.source(_in_edge);
820 delta = _capacity[_in_edge];
825 // Searching the cycle along the path form the first node to the
827 for (Node u = first; u != join; u = _parent[u]) {
829 d = _forward[u] ? _flow[e] : _capacity[e] - _flow[e];
838 // Searching the cycle along the path form the second node to the
840 for (Node u = second; u != join; u = _parent[u]) {
842 d = _forward[u] ? _capacity[e] - _flow[e] : _flow[e];
854 /// Changes \c flow and \c state edge maps.
855 void changeFlows(bool change) {
856 // Augmenting along the cycle
858 Capacity val = _state[_in_edge] * delta;
859 _flow[_in_edge] += val;
860 for (Node u = _graph.source(_in_edge); u != join; u = _parent[u]) {
861 _flow[_pred_edge[u]] += _forward[u] ? -val : val;
863 for (Node u = _graph.target(_in_edge); u != join; u = _parent[u]) {
864 _flow[_pred_edge[u]] += _forward[u] ? val : -val;
867 // Updating the state of the entering and leaving edges
869 _state[_in_edge] = STATE_TREE;
870 _state[_pred_edge[u_out]] =
871 (_flow[_pred_edge[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
873 _state[_in_edge] = -_state[_in_edge];
877 /// Updates \c thread and \c parent node maps.
878 void updateThreadParent() {
880 v_out = _parent[u_out];
882 // Handling the case when join and v_out coincide
883 bool par_first = false;
885 for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
888 while (_thread[u] != u_out) u = _thread[u];
893 // Finding the last successor of u_in (u) and the node after it
894 // (right) according to the thread index
895 for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
897 if (_thread[v_in] == u_out) {
898 for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
899 if (last == u_out) last = _thread[last];
901 else last = _thread[v_in];
903 // Updating stem nodes
904 _thread[v_in] = stem = u_in;
906 while (stem != u_out) {
907 _thread[u] = new_stem = _parent[stem];
909 // Finding the node just before the stem node (u) according to
910 // the original thread index
911 for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
914 // Changing the parent node of stem and shifting stem and
916 _parent[stem] = par_stem;
920 // Finding the last successor of stem (u) and the node after it
921 // (right) according to the thread index
922 for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
925 _parent[u_out] = par_stem;
928 if (join == v_out && par_first) {
929 if (first != v_in) _thread[first] = right;
931 for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
936 /// Updates \c pred_edge and \c forward node maps.
937 void updatePredEdge() {
941 _pred_edge[u] = _pred_edge[v];
942 _forward[u] = !_forward[v];
945 _pred_edge[u_in] = _in_edge;
946 _forward[u_in] = (u_in == _graph.source(_in_edge));
949 /// Updates \c depth and \c potential node maps.
950 void updateDepthPotential() {
951 _depth[u_in] = _depth[v_in] + 1;
952 _potential[u_in] = _forward[u_in] ?
953 _potential[v_in] - _cost[_pred_edge[u_in]] :
954 _potential[v_in] + _cost[_pred_edge[u_in]];
956 Node u = _thread[u_in], v;
959 if (v == INVALID) break;
960 _depth[u] = _depth[v] + 1;
961 _potential[u] = _forward[u] ?
962 _potential[v] - _cost[_pred_edge[u]] :
963 _potential[v] + _cost[_pred_edge[u]];
964 if (_depth[u] <= _depth[v_in]) break;
969 /// Executes the algorithm.
970 bool start(PivotRuleEnum pivot_rule) {
971 switch (pivot_rule) {
972 case FIRST_ELIGIBLE_PIVOT:
973 return start<FirstEligiblePivotRule>();
974 case BEST_ELIGIBLE_PIVOT:
975 return start<BestEligiblePivotRule>();
976 case BLOCK_SEARCH_PIVOT:
977 return start<BlockSearchPivotRule>();
978 case LIMITED_SEARCH_PIVOT:
979 return start<LimitedSearchPivotRule>();
980 case CANDIDATE_LIST_PIVOT:
981 return start<CandidateListPivotRule>();
983 if ( countEdges(_graph) / countNodes(_graph) <=
984 COMBINED_PIVOT_MAX_DEG )
985 return start<LimitedSearchPivotRule>();
987 return start<BlockSearchPivotRule>();
992 template<class PivotRuleImplementation>
994 PivotRuleImplementation pivot(*this);
996 // Executing the network simplex algorithm
997 while (pivot.findEnteringEdge()) {
998 join = findJoinNode();
999 bool change = findLeavingEdge();
1000 changeFlows(change);
1002 updateThreadParent();
1004 updateDepthPotential();
1008 // Checking if the flow amount equals zero on all the artificial
1010 for (InEdgeIt e(_graph, _root); e != INVALID; ++e)
1011 if (_flow[e] > 0) return false;
1012 for (OutEdgeIt e(_graph, _root); e != INVALID; ++e)
1013 if (_flow[e] > 0) return false;
1015 // Copying flow values to _flow_result
1017 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
1018 _flow_result[e] = (*_lower)[e] + _flow[_edge_ref[e]];
1020 for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
1021 _flow_result[e] = _flow[_edge_ref[e]];
1023 // Copying potential values to _potential_result
1024 for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
1025 _potential_result[n] = _potential[_node_ref[n]];
1030 }; //class NetworkSimplex
1036 #endif //LEMON_NETWORK_SIMPLEX_H