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 copyGraph(graph, graph_ref)
279 .edgeMap(cost, _cost)
284 // Removing nonzero lower bounds
285 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) {
286 capacity[edge_ref[e]] = _capacity[e] - _lower[e];
288 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) {
289 Supply s = _supply[n];
290 for (typename Graph::InEdgeIt e(graph_ref, n); e != INVALID; ++e)
292 for (typename Graph::OutEdgeIt e(graph_ref, n); e != INVALID; ++e)
294 supply[node_ref[n]] = s;
298 /// \brief General constructor of the class (without lower bounds).
300 /// General constructor of the class (without lower bounds).
302 /// \param _graph The directed graph the algorithm runs on.
303 /// \param _capacity The capacities (upper bounds) of the edges.
304 /// \param _cost The cost (length) values of the edges.
305 /// \param _supply The supply values of the nodes (signed).
306 NetworkSimplex( const Graph &_graph,
307 const CapacityMap &_capacity,
308 const CostMap &_cost,
309 const SupplyMap &_supply ) :
310 graph_ref(_graph), lower(NULL), capacity(graph), cost(graph),
311 supply(graph), flow(graph), flow_result(_graph), potential(graph),
312 potential_result(_graph), depth(graph), parent(graph),
313 pred_edge(graph), thread(graph), forward(graph), state(graph),
314 node_ref(graph_ref), edge_ref(graph_ref),
315 red_cost(graph, cost, potential)
317 // Checking the sum of supply values
319 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n)
321 if (!(valid_supply = sum == 0)) return;
323 // Copying graph_ref to graph
324 copyGraph(graph, graph_ref)
325 .edgeMap(capacity, _capacity)
326 .edgeMap(cost, _cost)
327 .nodeMap(supply, _supply)
333 /// \brief Simple constructor of the class (with lower bounds).
335 /// Simple constructor of the class (with lower bounds).
337 /// \param _graph The directed graph the algorithm runs on.
338 /// \param _lower The lower bounds of the edges.
339 /// \param _capacity The capacities (upper bounds) of the edges.
340 /// \param _cost The cost (length) values of the edges.
341 /// \param _s The source node.
342 /// \param _t The target node.
343 /// \param _flow_value The required amount of flow from node \c _s
344 /// to node \c _t (i.e. the supply of \c _s and the demand of
346 NetworkSimplex( const Graph &_graph,
347 const LowerMap &_lower,
348 const CapacityMap &_capacity,
349 const CostMap &_cost,
350 typename Graph::Node _s,
351 typename Graph::Node _t,
352 typename SupplyMap::Value _flow_value ) :
353 graph_ref(_graph), lower(&_lower), capacity(graph), cost(graph),
354 supply(graph), flow(graph), flow_result(_graph), potential(graph),
355 potential_result(_graph), depth(graph), parent(graph),
356 pred_edge(graph), thread(graph), forward(graph), state(graph),
357 node_ref(graph_ref), edge_ref(graph_ref),
358 red_cost(graph, cost, potential)
360 // Copying graph_ref to graph
361 copyGraph(graph, graph_ref)
362 .edgeMap(cost, _cost)
367 // Removing nonzero lower bounds
368 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) {
369 capacity[edge_ref[e]] = _capacity[e] - _lower[e];
371 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) {
373 if (n == _s) s = _flow_value;
374 if (n == _t) s = -_flow_value;
375 for (typename Graph::InEdgeIt e(graph_ref, n); e != INVALID; ++e)
377 for (typename Graph::OutEdgeIt e(graph_ref, n); e != INVALID; ++e)
379 supply[node_ref[n]] = s;
384 /// \brief Simple constructor of the class (without lower bounds).
386 /// Simple constructor of the class (without lower bounds).
388 /// \param _graph The directed graph the algorithm runs on.
389 /// \param _capacity The capacities (upper bounds) of the edges.
390 /// \param _cost The cost (length) values of the edges.
391 /// \param _s The source node.
392 /// \param _t The target node.
393 /// \param _flow_value The required amount of flow from node \c _s
394 /// to node \c _t (i.e. the supply of \c _s and the demand of
396 NetworkSimplex( const Graph &_graph,
397 const CapacityMap &_capacity,
398 const CostMap &_cost,
399 typename Graph::Node _s,
400 typename Graph::Node _t,
401 typename SupplyMap::Value _flow_value ) :
402 graph_ref(_graph), lower(NULL), capacity(graph), cost(graph),
403 supply(graph, 0), flow(graph), flow_result(_graph), potential(graph),
404 potential_result(_graph), depth(graph), parent(graph),
405 pred_edge(graph), thread(graph), forward(graph), state(graph),
406 node_ref(graph_ref), edge_ref(graph_ref),
407 red_cost(graph, cost, potential)
409 // Copying graph_ref to graph
410 copyGraph(graph, graph_ref)
411 .edgeMap(capacity, _capacity)
412 .edgeMap(cost, _cost)
416 supply[node_ref[_s]] = _flow_value;
417 supply[node_ref[_t]] = -_flow_value;
421 /// \brief Returns a const reference to the flow map.
423 /// Returns a const reference to the flow map.
425 /// \pre \ref run() must be called before using this function.
426 const FlowMap& flowMap() const {
430 /// \brief Returns a const reference to the potential map (the dual
433 /// Returns a const reference to the potential map (the dual
436 /// \pre \ref run() must be called before using this function.
437 const PotentialMap& potentialMap() const {
438 return potential_result;
441 /// \brief Returns the total cost of the found flow.
443 /// Returns the total cost of the found flow. The complexity of the
444 /// function is \f$ O(e) \f$.
446 /// \pre \ref run() must be called before using this function.
447 Cost totalCost() const {
449 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e)
450 c += flow_result[e] * cost[edge_ref[e]];
454 /// \brief Runs the algorithm.
456 /// Runs the algorithm.
458 /// \return \c true if a feasible flow can be found.
460 return init() && start();
465 /// \brief Extends the underlaying graph and initializes all the
466 /// node and edge maps.
468 if (!valid_supply) return false;
470 // Initializing state and flow maps
471 for (EdgeIt e(graph); e != INVALID; ++e) {
476 // Adding an artificial root node to the graph
477 root = graph.addNode();
478 parent[root] = INVALID;
479 pred_edge[root] = INVALID;
480 depth[root] = supply[root] = potential[root] = 0;
482 // Adding artificial edges to the graph and initializing the node
483 // maps of the spanning tree data structure
487 Cost max_cost = std::numeric_limits<Cost>::max() / 4;
488 for (NodeIt u(graph); u != INVALID; ++u) {
489 if (u == root) continue;
495 if (supply[u] >= 0) {
496 e = graph.addEdge(u, root);
499 potential[u] = max_cost;
501 e = graph.addEdge(root, u);
502 flow[e] = -supply[u];
504 potential[u] = -max_cost;
507 capacity[e] = std::numeric_limits<Capacity>::max();
513 #ifdef EDGE_BLOCK_PIVOT
514 // Initializing block_size for the edge block pivot rule
515 int edge_num = countEdges(graph);
516 block_size = edge_num >= BLOCK_NUM * MIN_BLOCK_SIZE ?
517 edge_num / BLOCK_NUM : MIN_BLOCK_SIZE;
519 #ifdef CANDIDATE_LIST_PIVOT
526 #ifdef FIRST_ELIGIBLE_PIVOT
527 /// \brief Finds entering edge according to the "First Eligible"
529 bool findEnteringEdge(EdgeIt &next_edge) {
530 for (EdgeIt e = next_edge; e != INVALID; ++e) {
531 if (state[e] * red_cost[e] < 0) {
537 for (EdgeIt e(graph); e != next_edge; ++e) {
538 if (state[e] * red_cost[e] < 0) {
548 #ifdef BEST_ELIGIBLE_PIVOT
549 /// \brief Finds entering edge according to the "Best Eligible"
551 bool findEnteringEdge() {
553 for (EdgeIt e(graph); e != INVALID; ++e) {
554 if (state[e] * red_cost[e] < min) {
555 min = state[e] * red_cost[e];
563 #ifdef EDGE_BLOCK_PIVOT
564 /// \brief Finds entering edge according to the "Edge Block"
566 bool findEnteringEdge(EdgeIt &next_edge) {
567 // Performing edge block selection
569 EdgeIt min_edge(graph);
571 for (EdgeIt e = next_edge; e != INVALID; ++e) {
572 if ((curr = state[e] * red_cost[e]) < min) {
576 if (++cnt == block_size) {
582 for (EdgeIt e(graph); e != next_edge; ++e) {
583 if ((curr = state[e] * red_cost[e]) < min) {
587 if (++cnt == block_size) {
594 if ((next_edge = ++min_edge) == INVALID)
595 next_edge = EdgeIt(graph);
600 #ifdef CANDIDATE_LIST_PIVOT
601 /// \brief Functor class for removing non-eligible edges from the
606 const IntEdgeMap &st;
607 const ReducedCostMap &rc;
609 RemoveFunc(const IntEdgeMap &_st, const ReducedCostMap &_rc) :
611 bool operator()(const Edge &e) {
612 return st[e] * rc[e] >= 0;
616 /// \brief Finds entering edge according to the "Candidate List"
618 bool findEnteringEdge() {
619 static RemoveFunc remove_func(state, red_cost);
620 typedef typename std::list<Edge>::iterator ListIt;
622 candidates.remove_if(remove_func);
623 if (minor_count >= MINOR_LIMIT || candidates.size() == 0) {
625 for (EdgeIt e(graph); e != INVALID; ++e) {
626 if (state[e] * red_cost[e] < 0) {
627 candidates.push_back(e);
628 if (candidates.size() == LIST_LENGTH) break;
631 if (candidates.size() == 0) return false;
637 for (ListIt it = candidates.begin(); it != candidates.end(); ++it) {
638 if (state[*it] * red_cost[*it] < min) {
639 min = state[*it] * red_cost[*it];
647 #ifdef SORTED_LIST_PIVOT
648 /// \brief Functor class to compare edges during sort of the
653 const IntEdgeMap &st;
654 const ReducedCostMap &rc;
656 SortFunc(const IntEdgeMap &_st, const ReducedCostMap &_rc) :
658 bool operator()(const Edge &e1, const Edge &e2) {
659 return st[e1] * rc[e1] < st[e2] * rc[e2];
663 /// \brief Finds entering edge according to the "Sorted List"
665 bool findEnteringEdge() {
666 static SortFunc sort_func(state, red_cost);
669 while (candidates.size() > 0) {
670 in_edge = candidates.front();
671 candidates.pop_front();
672 if (state[in_edge] * red_cost[in_edge] < 0) return true;
677 for (EdgeIt e(graph); e != INVALID; ++e) {
678 if ((curr = state[e] * red_cost[e]) < min / LOWER_DIV) {
679 candidates.push_back(e);
680 if (curr < min) min = curr;
681 if (candidates.size() == LIST_LENGTH) break;
684 if (candidates.size() == 0) return false;
685 sort(candidates.begin(), candidates.end(), sort_func);
686 in_edge = candidates.front();
687 candidates.pop_front();
692 /// \brief Finds the join node.
693 Node findJoinNode() {
694 // Finding the join node
695 Node u = graph.source(in_edge);
696 Node v = graph.target(in_edge);
698 if (depth[u] == depth[v]) {
702 else if (depth[u] > depth[v]) u = parent[u];
708 /// \brief Finds the leaving edge of the cycle. Returns \c true if
709 /// the leaving edge is not the same as the entering edge.
710 bool findLeavingEdge() {
711 // Initializing first and second nodes according to the direction
713 if (state[in_edge] == LOWER) {
714 first = graph.source(in_edge);
715 second = graph.target(in_edge);
717 first = graph.target(in_edge);
718 second = graph.source(in_edge);
720 delta = capacity[in_edge];
725 // Searching the cycle along the path form the first node to the
727 for (Node u = first; u != join; u = parent[u]) {
729 d = forward[u] ? flow[e] : capacity[e] - flow[e];
738 // Searching the cycle along the path form the second node to the
740 for (Node u = second; u != join; u = parent[u]) {
742 d = forward[u] ? capacity[e] - flow[e] : flow[e];
754 /// \brief Changes flow and state edge maps.
755 void changeFlows(bool change) {
756 // Augmenting along the cycle
758 Capacity val = state[in_edge] * delta;
759 flow[in_edge] += val;
760 for (Node u = graph.source(in_edge); u != join; u = parent[u]) {
761 flow[pred_edge[u]] += forward[u] ? -val : val;
763 for (Node u = graph.target(in_edge); u != join; u = parent[u]) {
764 flow[pred_edge[u]] += forward[u] ? val : -val;
767 // Updating the state of the entering and leaving edges
769 state[in_edge] = TREE;
770 state[pred_edge[u_out]] =
771 (flow[pred_edge[u_out]] == 0) ? LOWER : UPPER;
773 state[in_edge] = -state[in_edge];
777 /// \brief Updates thread and parent node maps.
778 void updateThreadParent() {
780 v_out = parent[u_out];
782 // Handling the case when join and v_out coincide
783 bool par_first = false;
785 for (u = join; u != u_in && u != v_in; u = thread[u]) ;
788 while (thread[u] != u_out) u = thread[u];
793 // Finding the last successor of u_in (u) and the node after it
794 // (right) according to the thread index
795 for (u = u_in; depth[thread[u]] > depth[u_in]; u = thread[u]) ;
797 if (thread[v_in] == u_out) {
798 for (last = u; depth[last] > depth[u_out]; last = thread[last]) ;
799 if (last == u_out) last = thread[last];
801 else last = thread[v_in];
803 // Updating stem nodes
804 thread[v_in] = stem = u_in;
806 while (stem != u_out) {
807 thread[u] = new_stem = parent[stem];
809 // Finding the node just before the stem node (u) according to
810 // the original thread index
811 for (u = new_stem; thread[u] != stem; u = thread[u]) ;
814 // Changing the parent node of stem and shifting stem and
816 parent[stem] = par_stem;
820 // Finding the last successor of stem (u) and the node after it
821 // (right) according to the thread index
822 for (u = stem; depth[thread[u]] > depth[stem]; u = thread[u]) ;
825 parent[u_out] = par_stem;
828 if (join == v_out && par_first) {
829 if (first != v_in) thread[first] = right;
831 for (u = v_out; thread[u] != u_out; u = thread[u]) ;
836 /// \brief Updates pred_edge and forward node maps.
837 void updatePredEdge() {
841 pred_edge[u] = pred_edge[v];
842 forward[u] = !forward[v];
845 pred_edge[u_in] = in_edge;
846 forward[u_in] = (u_in == graph.source(in_edge));
849 /// \brief Updates depth and potential node maps.
850 void updateDepthPotential() {
851 depth[u_in] = depth[v_in] + 1;
852 potential[u_in] = forward[u_in] ?
853 potential[v_in] + cost[pred_edge[u_in]] :
854 potential[v_in] - cost[pred_edge[u_in]];
856 Node u = thread[u_in], v;
859 if (v == INVALID) break;
860 depth[u] = depth[v] + 1;
861 potential[u] = forward[u] ?
862 potential[v] + cost[pred_edge[u]] :
863 potential[v] - cost[pred_edge[u]];
864 if (depth[u] <= depth[v_in]) break;
869 /// \brief Executes the algorithm.
875 #if defined(FIRST_ELIGIBLE_PIVOT) || defined(EDGE_BLOCK_PIVOT)
876 EdgeIt next_edge(graph);
877 while (findEnteringEdge(next_edge))
879 while (findEnteringEdge())
882 join = findJoinNode();
883 bool change = findLeavingEdge();
886 updateThreadParent();
888 updateDepthPotential();
896 std::cout << "Network Simplex algorithm finished. " << iter_num
897 << " pivot iterations performed." << std::endl;
900 // Checking if the flow amount equals zero on all the
902 for (InEdgeIt e(graph, root); e != INVALID; ++e)
903 if (flow[e] > 0) return false;
904 for (OutEdgeIt e(graph, root); e != INVALID; ++e)
905 if (flow[e] > 0) return false;
907 // Copying flow values to flow_result
909 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e)
910 flow_result[e] = (*lower)[e] + flow[edge_ref[e]];
912 for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e)
913 flow_result[e] = flow[edge_ref[e]];
915 // Copying potential values to potential_result
916 for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n)
917 potential_result[n] = potential[node_ref[n]];
922 }; //class NetworkSimplex
928 #endif //LEMON_NETWORK_SIMPLEX_H