Consider the CPXMIP_OPTIMAL_TOL status as OPTIMAL too.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
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 The network simplex algorithm for finding a minimum cost
29 #include <lemon/smart_graph.h>
30 #include <lemon/graph_utils.h>
32 /// \brief The pivot rule used in the algorithm.
33 //#define FIRST_ELIGIBLE_PIVOT
34 //#define BEST_ELIGIBLE_PIVOT
35 #define EDGE_BLOCK_PIVOT
36 //#define CANDIDATE_LIST_PIVOT
37 //#define SORTED_LIST_PIVOT
39 //#define _DEBUG_ITER_
42 /// \brief State constant for edges at their lower bounds.
44 /// \brief State constant for edges in the spanning tree.
46 /// \brief State constant for edges at their upper bounds.
49 #ifdef EDGE_BLOCK_PIVOT
50 /// \brief Number of blocks for the "Edge Block" pivot rule.
52 /// \brief Lower bound for the size of blocks.
53 #define MIN_BLOCK_SIZE 10
56 #ifdef CANDIDATE_LIST_PIVOT
58 /// \brief The maximum length of the edge list for the
59 /// "Candidate List" pivot rule.
60 #define LIST_LENGTH 100
61 /// \brief The maximum number of minor iterations between two major
63 #define MINOR_LIMIT 10
66 #ifdef SORTED_LIST_PIVOT
69 /// \brief The maximum length of the edge list for the
70 /// "Sorted List" pivot rule.
71 #define LIST_LENGTH 500
77 /// \addtogroup min_cost_flow
80 /// \brief Implementation of the network simplex algorithm for
81 /// finding a minimum cost flow.
83 /// \ref lemon::NetworkSimplex "NetworkSimplex" implements the
84 /// network simplex algorithm for finding a minimum cost flow.
86 /// \param Graph The directed graph type the algorithm runs on.
87 /// \param LowerMap The type of the lower bound map.
88 /// \param CapacityMap The type of the capacity (upper bound) map.
89 /// \param CostMap The type of the cost (length) map.
90 /// \param SupplyMap The type of the supply map.
93 /// - Edge capacities and costs should be nonnegative integers.
94 /// However \c CostMap::Value should be signed type.
95 /// - Supply values should be integers.
96 /// - \c LowerMap::Value must be convertible to
97 /// \c CapacityMap::Value and \c CapacityMap::Value must be
98 /// convertible to \c SupplyMap::Value.
100 /// \author Peter Kovacs
102 template < typename Graph,
103 typename LowerMap = typename Graph::template EdgeMap<int>,
104 typename CapacityMap = LowerMap,
105 typename CostMap = typename Graph::template EdgeMap<int>,
106 typename SupplyMap = typename Graph::template NodeMap
107 <typename CapacityMap::Value> >
110 typedef typename LowerMap::Value Lower;
111 typedef typename CapacityMap::Value Capacity;
112 typedef typename CostMap::Value Cost;
113 typedef typename SupplyMap::Value Supply;
115 typedef SmartGraph SGraph;
116 typedef typename SGraph::Node Node;
117 typedef typename SGraph::NodeIt NodeIt;
118 typedef typename SGraph::Edge Edge;
119 typedef typename SGraph::EdgeIt EdgeIt;
120 typedef typename SGraph::InEdgeIt InEdgeIt;
121 typedef typename SGraph::OutEdgeIt OutEdgeIt;
123 typedef typename SGraph::template EdgeMap<Lower> SLowerMap;
124 typedef typename SGraph::template EdgeMap<Capacity> SCapacityMap;
125 typedef typename SGraph::template EdgeMap<Cost> SCostMap;
126 typedef typename SGraph::template NodeMap<Supply> SSupplyMap;
127 typedef typename SGraph::template NodeMap<Cost> SPotentialMap;
129 typedef typename SGraph::template NodeMap<int> IntNodeMap;
130 typedef typename SGraph::template NodeMap<bool> BoolNodeMap;
131 typedef typename SGraph::template NodeMap<Node> NodeNodeMap;
132 typedef typename SGraph::template NodeMap<Edge> EdgeNodeMap;
133 typedef typename SGraph::template EdgeMap<int> IntEdgeMap;
135 typedef typename Graph::template NodeMap<Node> NodeRefMap;
136 typedef typename Graph::template EdgeMap<Edge> EdgeRefMap;
140 /// \brief The type of the flow map.
141 typedef typename Graph::template EdgeMap<Capacity> FlowMap;
142 /// \brief The type of the potential map.
143 typedef typename Graph::template NodeMap<Cost> PotentialMap;
147 /// \brief Map adaptor class for handling reduced edge costs.
148 class ReducedCostMap : public MapBase<Edge, Cost>
153 const SCostMap &cost_map;
154 const SPotentialMap &pot_map;
158 typedef typename MapBase<Edge, Cost>::Value Value;
159 typedef typename MapBase<Edge, Cost>::Key Key;
161 ReducedCostMap( const SGraph &_gr,
163 const SPotentialMap &_pm ) :
164 gr(_gr), cost_map(_cm), pot_map(_pm) {}
166 Value operator[](const Key &e) const {
167 return cost_map[e] - pot_map[gr.source(e)] + pot_map[gr.target(e)];
170 }; //class ReducedCostMap
174 /// \brief The directed graph the algorithm runs on.
176 /// \brief The original graph.
177 const Graph &graph_ref;
178 /// \brief The original lower bound map.
179 const LowerMap *lower;
180 /// \brief The capacity map.
181 SCapacityMap capacity;
182 /// \brief The cost map.
184 /// \brief The supply map.
186 /// \brief The reduced cost map.
187 ReducedCostMap red_cost;
188 /// \brief The sum of supply values equals zero.
191 /// \brief The edge map of the current flow.
193 /// \brief The edge map of the found flow on the original graph.
195 /// \brief The potential node map.
196 SPotentialMap potential;
197 /// \brief The potential node map on the original graph.
198 PotentialMap potential_result;
200 /// \brief Node reference for the original graph.
202 /// \brief Edge reference for the original graph.
205 /// \brief The depth node map of the spanning tree structure.
207 /// \brief The parent node map of the spanning tree structure.
209 /// \brief The pred_edge node map of the spanning tree structure.
210 EdgeNodeMap pred_edge;
211 /// \brief The thread node map of the spanning tree structure.
213 /// \brief The forward node map of the spanning tree structure.
215 /// \brief The state edge map.
219 #ifdef EDGE_BLOCK_PIVOT
220 /// \brief The size of blocks for the "Edge Block" pivot rule.
223 #ifdef CANDIDATE_LIST_PIVOT
224 /// \brief The list of candidate edges for the "Candidate List"
226 std::list<Edge> candidates;
227 /// \brief The number of minor iterations.
230 #ifdef SORTED_LIST_PIVOT
231 /// \brief The list of candidate edges for the "Sorted List"
233 std::deque<Edge> candidates;
236 // Root node of the starting spanning tree.
238 // The entering edge of the current pivot iteration.
240 // Temporary nodes used in the current pivot iteration.
241 Node join, u_in, v_in, u_out, v_out;
242 Node right, first, second, last;
243 Node stem, par_stem, new_stem;
244 // The maximum augment amount along the cycle in the current pivot
250 /// \brief General constructor of the class (with lower bounds).
252 /// General constructor of the class (with lower bounds).
254 /// \param _graph The directed graph the algorithm runs on.
255 /// \param _lower The lower bounds of the edges.
256 /// \param _capacity The capacities (upper bounds) of the edges.
257 /// \param _cost The cost (length) values of the edges.
258 /// \param _supply The supply values of the nodes (signed).
259 NetworkSimplex( const Graph &_graph,
260 const LowerMap &_lower,
261 const CapacityMap &_capacity,
262 const CostMap &_cost,
263 const SupplyMap &_supply ) :
264 graph_ref(_graph), lower(&_lower), capacity(graph), cost(graph),
265 supply(graph), flow(graph), flow_result(_graph), potential(graph),
266 potential_result(_graph), depth(graph), parent(graph),
267 pred_edge(graph), thread(graph), forward(graph), state(graph),
268 node_ref(graph_ref), edge_ref(graph_ref),
269 red_cost(graph, cost, potential)
271 // Checking the sum of supply values
273 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n)
275 if (!(valid_supply = sum == 0)) return;
277 // Copying graph_ref to graph
278 graph.reserveNode(countNodes(graph_ref) + 1);
279 graph.reserveEdge(countEdges(graph_ref) + countNodes(graph_ref));
280 copyGraph(graph, graph_ref)
281 .edgeMap(cost, _cost)
286 // Removing nonzero lower bounds
287 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) {
288 capacity[edge_ref[e]] = _capacity[e] - _lower[e];
290 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) {
291 Supply s = _supply[n];
292 for (typename Graph::InEdgeIt e(graph_ref, n); e != INVALID; ++e)
294 for (typename Graph::OutEdgeIt e(graph_ref, n); e != INVALID; ++e)
296 supply[node_ref[n]] = s;
300 /// \brief General constructor of the class (without lower bounds).
302 /// General constructor of the class (without lower bounds).
304 /// \param _graph The directed graph the algorithm runs on.
305 /// \param _capacity The capacities (upper bounds) of the edges.
306 /// \param _cost The cost (length) values of the edges.
307 /// \param _supply The supply values of the nodes (signed).
308 NetworkSimplex( const Graph &_graph,
309 const CapacityMap &_capacity,
310 const CostMap &_cost,
311 const SupplyMap &_supply ) :
312 graph_ref(_graph), lower(NULL), capacity(graph), cost(graph),
313 supply(graph), flow(graph), flow_result(_graph), potential(graph),
314 potential_result(_graph), depth(graph), parent(graph),
315 pred_edge(graph), thread(graph), forward(graph), state(graph),
316 node_ref(graph_ref), edge_ref(graph_ref),
317 red_cost(graph, cost, potential)
319 // Checking the sum of supply values
321 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n)
323 if (!(valid_supply = sum == 0)) return;
325 // Copying graph_ref to graph
326 copyGraph(graph, graph_ref)
327 .edgeMap(capacity, _capacity)
328 .edgeMap(cost, _cost)
329 .nodeMap(supply, _supply)
335 /// \brief Simple constructor of the class (with lower bounds).
337 /// Simple constructor of the class (with lower bounds).
339 /// \param _graph The directed graph the algorithm runs on.
340 /// \param _lower The lower bounds of the edges.
341 /// \param _capacity The capacities (upper bounds) of the edges.
342 /// \param _cost The cost (length) values of the edges.
343 /// \param _s The source node.
344 /// \param _t The target node.
345 /// \param _flow_value The required amount of flow from node \c _s
346 /// to node \c _t (i.e. the supply of \c _s and the demand of
348 NetworkSimplex( const Graph &_graph,
349 const LowerMap &_lower,
350 const CapacityMap &_capacity,
351 const CostMap &_cost,
352 typename Graph::Node _s,
353 typename Graph::Node _t,
354 typename SupplyMap::Value _flow_value ) :
355 graph_ref(_graph), lower(&_lower), capacity(graph), cost(graph),
356 supply(graph), flow(graph), flow_result(_graph), potential(graph),
357 potential_result(_graph), depth(graph), parent(graph),
358 pred_edge(graph), thread(graph), forward(graph), state(graph),
359 node_ref(graph_ref), edge_ref(graph_ref),
360 red_cost(graph, cost, potential)
362 // Copying graph_ref to graph
363 copyGraph(graph, graph_ref)
364 .edgeMap(cost, _cost)
369 // Removing nonzero lower bounds
370 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) {
371 capacity[edge_ref[e]] = _capacity[e] - _lower[e];
373 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) {
375 if (n == _s) s = _flow_value;
376 if (n == _t) s = -_flow_value;
377 for (typename Graph::InEdgeIt e(graph_ref, n); e != INVALID; ++e)
379 for (typename Graph::OutEdgeIt e(graph_ref, n); e != INVALID; ++e)
381 supply[node_ref[n]] = s;
386 /// \brief Simple constructor of the class (without lower bounds).
388 /// Simple constructor of the class (without lower bounds).
390 /// \param _graph The directed graph the algorithm runs on.
391 /// \param _capacity The capacities (upper bounds) of the edges.
392 /// \param _cost The cost (length) values of the edges.
393 /// \param _s The source node.
394 /// \param _t The target node.
395 /// \param _flow_value The required amount of flow from node \c _s
396 /// to node \c _t (i.e. the supply of \c _s and the demand of
398 NetworkSimplex( const Graph &_graph,
399 const CapacityMap &_capacity,
400 const CostMap &_cost,
401 typename Graph::Node _s,
402 typename Graph::Node _t,
403 typename SupplyMap::Value _flow_value ) :
404 graph_ref(_graph), lower(NULL), capacity(graph), cost(graph),
405 supply(graph, 0), flow(graph), flow_result(_graph), potential(graph),
406 potential_result(_graph), depth(graph), parent(graph),
407 pred_edge(graph), thread(graph), forward(graph), state(graph),
408 node_ref(graph_ref), edge_ref(graph_ref),
409 red_cost(graph, cost, potential)
411 // Copying graph_ref to graph
412 copyGraph(graph, graph_ref)
413 .edgeMap(capacity, _capacity)
414 .edgeMap(cost, _cost)
418 supply[node_ref[_s]] = _flow_value;
419 supply[node_ref[_t]] = -_flow_value;
423 /// \brief Returns a const reference to the flow map.
425 /// Returns a const reference to the flow map.
427 /// \pre \ref run() must be called before using this function.
428 const FlowMap& flowMap() const {
432 /// \brief Returns a const reference to the potential map (the dual
435 /// Returns a const reference to the potential map (the dual
438 /// \pre \ref run() must be called before using this function.
439 const PotentialMap& potentialMap() const {
440 return potential_result;
443 /// \brief Returns the total cost of the found flow.
445 /// Returns the total cost of the found flow. The complexity of the
446 /// function is \f$ O(e) \f$.
448 /// \pre \ref run() must be called before using this function.
449 Cost totalCost() const {
451 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e)
452 c += flow_result[e] * cost[edge_ref[e]];
456 /// \brief Runs the algorithm.
458 /// Runs the algorithm.
460 /// \return \c true if a feasible flow can be found.
462 return init() && start();
467 /// \brief Extends the underlaying graph and initializes all the
468 /// node and edge maps.
470 if (!valid_supply) return false;
472 // Initializing state and flow maps
473 for (EdgeIt e(graph); e != INVALID; ++e) {
478 // Adding an artificial root node to the graph
479 root = graph.addNode();
480 parent[root] = INVALID;
481 pred_edge[root] = INVALID;
486 // Adding artificial edges to the graph and initializing the node
487 // maps of the spanning tree data structure
491 Cost max_cost = std::numeric_limits<Cost>::max() / 4;
492 for (NodeIt u(graph); u != INVALID; ++u) {
493 if (u == root) continue;
499 if (supply[u] >= 0) {
500 e = graph.addEdge(u, root);
503 potential[u] = max_cost;
505 e = graph.addEdge(root, u);
506 flow[e] = -supply[u];
508 potential[u] = -max_cost;
511 capacity[e] = std::numeric_limits<Capacity>::max();
517 #ifdef EDGE_BLOCK_PIVOT
518 // Initializing block_size for the edge block pivot rule
519 int edge_num = countEdges(graph);
520 block_size = edge_num >= BLOCK_NUM * MIN_BLOCK_SIZE ?
521 edge_num / BLOCK_NUM : MIN_BLOCK_SIZE;
523 #ifdef CANDIDATE_LIST_PIVOT
530 #ifdef FIRST_ELIGIBLE_PIVOT
531 /// \brief Finds entering edge according to the "First Eligible"
533 bool findEnteringEdge(EdgeIt &next_edge) {
534 for (EdgeIt e = next_edge; e != INVALID; ++e) {
535 if (state[e] * red_cost[e] < 0) {
541 for (EdgeIt e(graph); e != next_edge; ++e) {
542 if (state[e] * red_cost[e] < 0) {
552 #ifdef BEST_ELIGIBLE_PIVOT
553 /// \brief Finds entering edge according to the "Best Eligible"
555 bool findEnteringEdge() {
557 for (EdgeIt e(graph); e != INVALID; ++e) {
558 if (state[e] * red_cost[e] < min) {
559 min = state[e] * red_cost[e];
567 #ifdef EDGE_BLOCK_PIVOT
568 /// \brief Finds entering edge according to the "Edge Block"
570 bool findEnteringEdge(EdgeIt &next_edge) {
571 // Performing edge block selection
573 EdgeIt min_edge(graph);
575 for (EdgeIt e = next_edge; e != INVALID; ++e) {
576 if ((curr = state[e] * red_cost[e]) < min) {
580 if (++cnt == block_size) {
586 for (EdgeIt e(graph); e != next_edge; ++e) {
587 if ((curr = state[e] * red_cost[e]) < min) {
591 if (++cnt == block_size) {
598 if ((next_edge = ++min_edge) == INVALID)
599 next_edge = EdgeIt(graph);
604 #ifdef CANDIDATE_LIST_PIVOT
605 /// \brief Functor class for removing non-eligible edges from the
610 const IntEdgeMap &st;
611 const ReducedCostMap &rc;
613 RemoveFunc(const IntEdgeMap &_st, const ReducedCostMap &_rc) :
615 bool operator()(const Edge &e) {
616 return st[e] * rc[e] >= 0;
620 /// \brief Finds entering edge according to the "Candidate List"
622 bool findEnteringEdge() {
623 static RemoveFunc remove_func(state, red_cost);
624 typedef typename std::list<Edge>::iterator ListIt;
626 candidates.remove_if(remove_func);
627 if (minor_count >= MINOR_LIMIT || candidates.size() == 0) {
629 for (EdgeIt e(graph); e != INVALID; ++e) {
630 if (state[e] * red_cost[e] < 0) {
631 candidates.push_back(e);
632 if (candidates.size() == LIST_LENGTH) break;
635 if (candidates.size() == 0) return false;
641 for (ListIt it = candidates.begin(); it != candidates.end(); ++it) {
642 if (state[*it] * red_cost[*it] < min) {
643 min = state[*it] * red_cost[*it];
651 #ifdef SORTED_LIST_PIVOT
652 /// \brief Functor class to compare edges during sort of the
657 const IntEdgeMap &st;
658 const ReducedCostMap &rc;
660 SortFunc(const IntEdgeMap &_st, const ReducedCostMap &_rc) :
662 bool operator()(const Edge &e1, const Edge &e2) {
663 return st[e1] * rc[e1] < st[e2] * rc[e2];
667 /// \brief Finds entering edge according to the "Sorted List"
669 bool findEnteringEdge() {
670 static SortFunc sort_func(state, red_cost);
673 while (candidates.size() > 0) {
674 in_edge = candidates.front();
675 candidates.pop_front();
676 if (state[in_edge] * red_cost[in_edge] < 0) return true;
681 for (EdgeIt e(graph); e != INVALID; ++e) {
682 if ((curr = state[e] * red_cost[e]) < min / LOWER_DIV) {
683 candidates.push_back(e);
684 if (curr < min) min = curr;
685 if (candidates.size() == LIST_LENGTH) break;
688 if (candidates.size() == 0) return false;
689 sort(candidates.begin(), candidates.end(), sort_func);
690 in_edge = candidates.front();
691 candidates.pop_front();
696 /// \brief Finds the join node.
697 Node findJoinNode() {
698 // Finding the join node
699 Node u = graph.source(in_edge);
700 Node v = graph.target(in_edge);
702 if (depth[u] == depth[v]) {
706 else if (depth[u] > depth[v]) u = parent[u];
712 /// \brief Finds the leaving edge of the cycle. Returns \c true if
713 /// the leaving edge is not the same as the entering edge.
714 bool findLeavingEdge() {
715 // Initializing first and second nodes according to the direction
717 if (state[in_edge] == LOWER) {
718 first = graph.source(in_edge);
719 second = graph.target(in_edge);
721 first = graph.target(in_edge);
722 second = graph.source(in_edge);
724 delta = capacity[in_edge];
729 // Searching the cycle along the path form the first node to the
731 for (Node u = first; u != join; u = parent[u]) {
733 d = forward[u] ? flow[e] : capacity[e] - flow[e];
742 // Searching the cycle along the path form the second node to the
744 for (Node u = second; u != join; u = parent[u]) {
746 d = forward[u] ? capacity[e] - flow[e] : flow[e];
758 /// \brief Changes flow and state edge maps.
759 void changeFlows(bool change) {
760 // Augmenting along the cycle
762 Capacity val = state[in_edge] * delta;
763 flow[in_edge] += val;
764 for (Node u = graph.source(in_edge); u != join; u = parent[u]) {
765 flow[pred_edge[u]] += forward[u] ? -val : val;
767 for (Node u = graph.target(in_edge); u != join; u = parent[u]) {
768 flow[pred_edge[u]] += forward[u] ? val : -val;
771 // Updating the state of the entering and leaving edges
773 state[in_edge] = TREE;
774 state[pred_edge[u_out]] =
775 (flow[pred_edge[u_out]] == 0) ? LOWER : UPPER;
777 state[in_edge] = -state[in_edge];
781 /// \brief Updates thread and parent node maps.
782 void updateThreadParent() {
784 v_out = parent[u_out];
786 // Handling the case when join and v_out coincide
787 bool par_first = false;
789 for (u = join; u != u_in && u != v_in; u = thread[u]) ;
792 while (thread[u] != u_out) u = thread[u];
797 // Finding the last successor of u_in (u) and the node after it
798 // (right) according to the thread index
799 for (u = u_in; depth[thread[u]] > depth[u_in]; u = thread[u]) ;
801 if (thread[v_in] == u_out) {
802 for (last = u; depth[last] > depth[u_out]; last = thread[last]) ;
803 if (last == u_out) last = thread[last];
805 else last = thread[v_in];
807 // Updating stem nodes
808 thread[v_in] = stem = u_in;
810 while (stem != u_out) {
811 thread[u] = new_stem = parent[stem];
813 // Finding the node just before the stem node (u) according to
814 // the original thread index
815 for (u = new_stem; thread[u] != stem; u = thread[u]) ;
818 // Changing the parent node of stem and shifting stem and
820 parent[stem] = par_stem;
824 // Finding the last successor of stem (u) and the node after it
825 // (right) according to the thread index
826 for (u = stem; depth[thread[u]] > depth[stem]; u = thread[u]) ;
829 parent[u_out] = par_stem;
832 if (join == v_out && par_first) {
833 if (first != v_in) thread[first] = right;
835 for (u = v_out; thread[u] != u_out; u = thread[u]) ;
840 /// \brief Updates pred_edge and forward node maps.
841 void updatePredEdge() {
845 pred_edge[u] = pred_edge[v];
846 forward[u] = !forward[v];
849 pred_edge[u_in] = in_edge;
850 forward[u_in] = (u_in == graph.source(in_edge));
853 /// \brief Updates depth and potential node maps.
854 void updateDepthPotential() {
855 depth[u_in] = depth[v_in] + 1;
856 potential[u_in] = forward[u_in] ?
857 potential[v_in] + cost[pred_edge[u_in]] :
858 potential[v_in] - cost[pred_edge[u_in]];
860 Node u = thread[u_in], v;
863 if (v == INVALID) break;
864 depth[u] = depth[v] + 1;
865 potential[u] = forward[u] ?
866 potential[v] + cost[pred_edge[u]] :
867 potential[v] - cost[pred_edge[u]];
868 if (depth[u] <= depth[v_in]) break;
873 /// \brief Executes the algorithm.
879 #if defined(FIRST_ELIGIBLE_PIVOT) || defined(EDGE_BLOCK_PIVOT)
880 EdgeIt next_edge(graph);
881 while (findEnteringEdge(next_edge))
883 while (findEnteringEdge())
886 join = findJoinNode();
887 bool change = findLeavingEdge();
890 updateThreadParent();
892 updateDepthPotential();
900 std::cout << "Network Simplex algorithm finished. " << iter_num
901 << " pivot iterations performed." << std::endl;
904 // Checking if the flow amount equals zero on all the
906 for (InEdgeIt e(graph, root); e != INVALID; ++e)
907 if (flow[e] > 0) return false;
908 for (OutEdgeIt e(graph, root); e != INVALID; ++e)
909 if (flow[e] > 0) return false;
911 // Copying flow values to flow_result
913 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e)
914 flow_result[e] = (*lower)[e] + flow[edge_ref[e]];
916 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e)
917 flow_result[e] = flow[edge_ref[e]];
919 // Copying potential values to potential_result
920 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n)
921 potential_result[n] = potential[node_ref[n]];
926 }; //class NetworkSimplex
932 #endif //LEMON_NETWORK_SIMPLEX_H