diff -r 3f1c7a6c33cd -r c9218405595b lemon/network_simplex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/network_simplex.h Mon May 07 11:42:18 2007 +0000 @@ -0,0 +1,945 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2007 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_NETWORK_SIMPLEX_H +#define LEMON_NETWORK_SIMPLEX_H + +/// \ingroup min_cost_flow +/// +/// \file +/// \brief The network simplex algorithm for finding a minimum cost +/// flow. + +#include +#include +#include + +/// \brief The pivot rule used in the algorithm. +#define EDGE_BLOCK_PIVOT +//#define FIRST_ELIGIBLE_PIVOT +//#define BEST_ELIGIBLE_PIVOT +//#define CANDIDATE_LIST_PIVOT +//#define SORTED_LIST_PIVOT + +/// \brief State constant for edges at their lower bounds. +#define LOWER 1 +/// \brief State constant for edges in the spanning tree. +#define TREE 0 +/// \brief State constant for edges at their upper bounds. +#define UPPER -1 + +#ifdef EDGE_BLOCK_PIVOT + /// \brief Number of blocks for the "Edge Block" pivot rule. + #define BLOCK_NUM 100 + /// \brief Lower bound for the number of edges to use "Edge Block" + // pivot rule instead of "First Eligible" pivot rule. + #define MIN_BOUND 1000 +#endif + +#ifdef CANDIDATE_LIST_PIVOT + #include + /// \brief The maximum length of the edge list for the + /// "Candidate List" pivot rule. + #define LIST_LENGTH 100 + /// \brief The maximum number of minor iterations between two major + /// itarations. + #define MINOR_LIMIT 50 +#endif + +#ifdef SORTED_LIST_PIVOT + #include + #include + /// \brief The maximum length of the edge list for the + /// "Sorted List" pivot rule. + #define LIST_LENGTH 500 + #define LOWER_DIV 4 +#endif + +//#define _DEBUG_ITER_ + +namespace lemon { + + /// \addtogroup min_cost_flow + /// @{ + + /// \brief Implementation of the network simplex algorithm for + /// finding a minimum cost flow. + /// + /// \ref lemon::NetworkSimplex "NetworkSimplex" implements the + /// network simplex algorithm for finding a minimum cost flow. + /// + /// \param Graph The directed graph type the algorithm runs on. + /// \param LowerMap The type of the lower bound map. + /// \param CapacityMap The type of the capacity (upper bound) map. + /// \param CostMap The type of the cost (length) map. + /// \param SupplyMap The type of the supply map. + /// + /// \warning + /// - Edge capacities and costs should be nonnegative integers. + /// However \c CostMap::Value should be signed type. + /// - Supply values should be integers. + /// - \c LowerMap::Value must be convertible to + /// \c CapacityMap::Value and \c CapacityMap::Value must be + /// convertible to \c SupplyMap::Value. + /// + /// \author Peter Kovacs + +template < typename Graph, + typename LowerMap = typename Graph::template EdgeMap, + typename CapacityMap = LowerMap, + typename CostMap = typename Graph::template EdgeMap, + typename SupplyMap = typename Graph::template NodeMap + > + class NetworkSimplex + { + typedef typename LowerMap::Value Lower; + typedef typename CapacityMap::Value Capacity; + typedef typename CostMap::Value Cost; + typedef typename SupplyMap::Value Supply; + + typedef SmartGraph SGraph; + typedef typename SGraph::Node Node; + typedef typename SGraph::NodeIt NodeIt; + typedef typename SGraph::Edge Edge; + typedef typename SGraph::EdgeIt EdgeIt; + typedef typename SGraph::InEdgeIt InEdgeIt; + typedef typename SGraph::OutEdgeIt OutEdgeIt; + + typedef typename SGraph::template EdgeMap SLowerMap; + typedef typename SGraph::template EdgeMap SCapacityMap; + typedef typename SGraph::template EdgeMap SCostMap; + typedef typename SGraph::template NodeMap SSupplyMap; + typedef typename SGraph::template NodeMap SPotentialMap; + + typedef typename SGraph::template NodeMap IntNodeMap; + typedef typename SGraph::template NodeMap BoolNodeMap; + typedef typename SGraph::template NodeMap NodeNodeMap; + typedef typename SGraph::template NodeMap EdgeNodeMap; + typedef typename SGraph::template EdgeMap IntEdgeMap; + + typedef typename Graph::template NodeMap NodeRefMap; + typedef typename Graph::template EdgeMap EdgeRefMap; + + public: + + /// \brief The type of the flow map. + typedef typename Graph::template EdgeMap FlowMap; + /// \brief The type of the potential map. + typedef typename Graph::template NodeMap PotentialMap; + + protected: + + /// \brief Map adaptor class for handling reduced edge costs. + class ReducedCostMap : public MapBase + { + private: + + const SGraph &gr; + const SCostMap &cost_map; + const SPotentialMap &pot_map; + + public: + + typedef typename MapBase::Value Value; + typedef typename MapBase::Key Key; + + ReducedCostMap( const SGraph &_gr, + const SCostMap &_cm, + const SPotentialMap &_pm ) : + gr(_gr), cost_map(_cm), pot_map(_pm) {} + + Value operator[](const Key &e) const { + return cost_map[e] - pot_map[gr.source(e)] + pot_map[gr.target(e)]; + } + + }; //class ReducedCostMap + + protected: + + /// \brief The directed graph the algorithm runs on. + SGraph graph; + /// \brief The original graph. + const Graph &graph_ref; + /// \brief The original lower bound map. + const LowerMap *lower; + /// \brief The capacity map. + SCapacityMap capacity; + /// \brief The cost map. + SCostMap cost; + /// \brief The supply map. + SSupplyMap supply; + /// \brief The reduced cost map. + ReducedCostMap red_cost; + /// \brief The sum of supply values equals zero. + bool valid_supply; + + /// \brief The edge map of the current flow. + SCapacityMap flow; + /// \brief The edge map of the found flow on the original graph. + FlowMap flow_result; + /// \brief The potential node map. + SPotentialMap potential; + /// \brief The potential node map on the original graph. + PotentialMap potential_result; + + /// \brief Node reference for the original graph. + NodeRefMap node_ref; + /// \brief Edge reference for the original graph. + EdgeRefMap edge_ref; + + /// \brief The depth node map of the spanning tree structure. + IntNodeMap depth; + /// \brief The parent node map of the spanning tree structure. + NodeNodeMap parent; + /// \brief The pred_edge node map of the spanning tree structure. + EdgeNodeMap pred_edge; + /// \brief The thread node map of the spanning tree structure. + NodeNodeMap thread; + /// \brief The forward node map of the spanning tree structure. + BoolNodeMap forward; + /// \brief The state edge map. + IntEdgeMap state; + + +#ifdef EDGE_BLOCK_PIVOT + /// \brief The size of blocks for the "Edge Block" pivot rule. + int block_size; +#endif +#ifdef CANDIDATE_LIST_PIVOT + /// \brief The list of candidate edges for the "Candidate List" + /// pivot rule. + std::list candidates; + /// \brief The number of minor iterations. + int minor_count; +#endif +#ifdef SORTED_LIST_PIVOT + /// \brief The list of candidate edges for the "Sorted List" + /// pivot rule. + std::deque candidates; +#endif + + // Root node of the starting spanning tree. + Node root; + // The entering edge of the current pivot iteration. + Edge in_edge; + // Temporary nodes used in the current pivot iteration. + Node join, u_in, v_in, u_out, v_out; + Node right, first, second, last; + Node stem, par_stem, new_stem; + // The maximum augment amount along the cycle in the current pivot + // iteration. + Capacity delta; + + public : + + /// \brief General constructor of the class (with lower bounds). + /// + /// General constructor of the class (with lower bounds). + /// + /// \param _graph The directed graph the algorithm runs on. + /// \param _lower The lower bounds of the edges. + /// \param _capacity The capacities (upper bounds) of the edges. + /// \param _cost The cost (length) values of the edges. + /// \param _supply The supply values of the nodes (signed). + NetworkSimplex( const Graph &_graph, + const LowerMap &_lower, + const CapacityMap &_capacity, + const CostMap &_cost, + const SupplyMap &_supply ) : + graph_ref(_graph), lower(&_lower), capacity(graph), cost(graph), + supply(graph), flow(graph), flow_result(_graph), potential(graph), + potential_result(_graph), depth(graph), parent(graph), + pred_edge(graph), thread(graph), forward(graph), state(graph), + node_ref(graph_ref), edge_ref(graph_ref), + red_cost(graph, cost, potential) + { + // Checking the sum of supply values + Supply sum = 0; + for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) + sum += _supply[n]; + if (!(valid_supply = sum == 0)) return; + + // Copying graph_ref to graph + copyGraph(graph, graph_ref) + .edgeMap(cost, _cost) + .nodeRef(node_ref) + .edgeRef(edge_ref) + .run(); + + // Removing nonzero lower bounds + for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) { + capacity[edge_ref[e]] = _capacity[e] - _lower[e]; + } + for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) { + Supply s = _supply[n]; + for (typename Graph::InEdgeIt e(graph_ref, n); e != INVALID; ++e) + s += _lower[e]; + for (typename Graph::OutEdgeIt e(graph_ref, n); e != INVALID; ++e) + s -= _lower[e]; + supply[node_ref[n]] = s; + } + } + + /// \brief General constructor of the class (without lower bounds). + /// + /// General constructor of the class (without lower bounds). + /// + /// \param _graph The directed graph the algorithm runs on. + /// \param _capacity The capacities (upper bounds) of the edges. + /// \param _cost The cost (length) values of the edges. + /// \param _supply The supply values of the nodes (signed). + NetworkSimplex( const Graph &_graph, + const CapacityMap &_capacity, + const CostMap &_cost, + const SupplyMap &_supply ) : + graph_ref(_graph), lower(NULL), capacity(graph), cost(graph), + supply(graph), flow(graph), flow_result(_graph), potential(graph), + potential_result(_graph), depth(graph), parent(graph), + pred_edge(graph), thread(graph), forward(graph), state(graph), + node_ref(graph_ref), edge_ref(graph_ref), + red_cost(graph, cost, potential) + { + // Checking the sum of supply values + Supply sum = 0; + for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) + sum += _supply[n]; + if (!(valid_supply = sum == 0)) return; + + // Copying graph_ref to graph + copyGraph(graph, graph_ref) + .edgeMap(capacity, _capacity) + .edgeMap(cost, _cost) + .nodeMap(supply, _supply) + .nodeRef(node_ref) + .edgeRef(edge_ref) + .run(); + } + + /// \brief Simple constructor of the class (with lower bounds). + /// + /// Simple constructor of the class (with lower bounds). + /// + /// \param _graph The directed graph the algorithm runs on. + /// \param _lower The lower bounds of the edges. + /// \param _capacity The capacities (upper bounds) of the edges. + /// \param _cost The cost (length) values of the edges. + /// \param _s The source node. + /// \param _t The target node. + /// \param _flow_value The required amount of flow from node \c _s + /// to node \c _t (i.e. the supply of \c _s and the demand of + /// \c _t). + NetworkSimplex( const Graph &_graph, + const LowerMap &_lower, + const CapacityMap &_capacity, + const CostMap &_cost, + typename Graph::Node _s, + typename Graph::Node _t, + typename SupplyMap::Value _flow_value ) : + graph_ref(_graph), lower(&_lower), capacity(graph), cost(graph), + supply(graph), flow(graph), flow_result(_graph), potential(graph), + potential_result(_graph), depth(graph), parent(graph), + pred_edge(graph), thread(graph), forward(graph), state(graph), + node_ref(graph_ref), edge_ref(graph_ref), + red_cost(graph, cost, potential) + { + // Copying graph_ref to graph + copyGraph(graph, graph_ref) + .edgeMap(cost, _cost) + .nodeRef(node_ref) + .edgeRef(edge_ref) + .run(); + + // Removing nonzero lower bounds + for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) { + capacity[edge_ref[e]] = _capacity[e] - _lower[e]; + } + for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) { + Supply s = 0; + if (n == _s) s = _flow_value; + if (n == _t) s = -_flow_value; + for (typename Graph::InEdgeIt e(graph_ref, n); e != INVALID; ++e) + s += _lower[e]; + for (typename Graph::OutEdgeIt e(graph_ref, n); e != INVALID; ++e) + s -= _lower[e]; + supply[node_ref[n]] = s; + } + valid_supply = true; + } + + /// \brief Simple constructor of the class (without lower bounds). + /// + /// Simple constructor of the class (without lower bounds). + /// + /// \param _graph The directed graph the algorithm runs on. + /// \param _capacity The capacities (upper bounds) of the edges. + /// \param _cost The cost (length) values of the edges. + /// \param _s The source node. + /// \param _t The target node. + /// \param _flow_value The required amount of flow from node \c _s + /// to node \c _t (i.e. the supply of \c _s and the demand of + /// \c _t). + NetworkSimplex( const Graph &_graph, + const CapacityMap &_capacity, + const CostMap &_cost, + typename Graph::Node _s, + typename Graph::Node _t, + typename SupplyMap::Value _flow_value ) : + graph_ref(_graph), lower(NULL), capacity(graph), cost(graph), + supply(graph, 0), flow(graph), flow_result(_graph), potential(graph), + potential_result(_graph), depth(graph), parent(graph), + pred_edge(graph), thread(graph), forward(graph), state(graph), + node_ref(graph_ref), edge_ref(graph_ref), + red_cost(graph, cost, potential) + { + // Copying graph_ref to graph + copyGraph(graph, graph_ref) + .edgeMap(capacity, _capacity) + .edgeMap(cost, _cost) + .nodeRef(node_ref) + .edgeRef(edge_ref) + .run(); + supply[node_ref[_s]] = _flow_value; + supply[node_ref[_t]] = -_flow_value; + valid_supply = true; + } + + /// \brief Returns a const reference to the flow map. + /// + /// Returns a const reference to the flow map. + /// + /// \pre \ref run() must be called before using this function. + const FlowMap& flowMap() const { + return flow_result; + } + + /// \brief Returns a const reference to the potential map (the dual + /// solution). + /// + /// Returns a const reference to the potential map (the dual + /// solution). + /// + /// \pre \ref run() must be called before using this function. + const PotentialMap& potentialMap() const { + return potential_result; + } + + /// \brief Returns the total cost of the found flow. + /// + /// Returns the total cost of the found flow. The complexity of the + /// function is \f$ O(e) \f$. + /// + /// \pre \ref run() must be called before using this function. + Cost totalCost() const { + Cost c = 0; + for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) + c += flow_result[e] * cost[edge_ref[e]]; + return c; + } + + /// \brief Runs the algorithm. + /// + /// Runs the algorithm. + /// + /// \return \c true if a feasible flow can be found. + bool run() { + return init() && start(); + } + + protected: + + /// \brief Extends the underlaying graph and initializes all the + /// node and edge maps. + bool init() { + if (!valid_supply) return false; + + // Initializing state and flow maps + for (EdgeIt e(graph); e != INVALID; ++e) { + flow[e] = 0; + state[e] = LOWER; + } + + // Adding an artificial root node to the graph + root = graph.addNode(); + parent[root] = INVALID; + pred_edge[root] = INVALID; + depth[root] = supply[root] = potential[root] = 0; + + // Adding artificial edges to the graph and initializing the node + // maps of the spanning tree data structure + Supply sum = 0; + Node last = root; + Edge e; + Cost max_cost = std::numeric_limits::max() / 4; + for (NodeIt u(graph); u != INVALID; ++u) { + if (u == root) continue; + thread[last] = u; + last = u; + parent[u] = root; + depth[u] = 1; + sum += supply[u]; + if (supply[u] >= 0) { + e = graph.addEdge(u, root); + flow[e] = supply[u]; + forward[u] = true; + potential[u] = max_cost; + } else { + e = graph.addEdge(root, u); + flow[e] = -supply[u]; + forward[u] = false; + potential[u] = -max_cost; + } + cost[e] = max_cost; + capacity[e] = std::numeric_limits::max(); + state[e] = TREE; + pred_edge[u] = e; + } + thread[last] = root; + +#ifdef EDGE_BLOCK_PIVOT + // Initializing block_size for the edge block pivot rule + int edge_num = countEdges(graph); + block_size = edge_num > MIN_BOUND ? edge_num / BLOCK_NUM + 1 : 1; +#endif +#ifdef CANDIDATE_LIST_PIVOT + minor_count = 0; +#endif + + return sum == 0; + } + +#ifdef FIRST_ELIGIBLE_PIVOT + /// \brief Finds entering edge according to the "First Eligible" + /// pivot rule. + bool findEnteringEdge(EdgeIt &next_edge) { + for (EdgeIt e = next_edge; e != INVALID; ++e) { + if (state[e] * red_cost[e] < 0) { + in_edge = e; + next_edge = ++e; + return true; + } + } + for (EdgeIt e(graph); e != next_edge; ++e) { + if (state[e] * red_cost[e] < 0) { + in_edge = e; + next_edge = ++e; + return true; + } + } + return false; + } +#endif + +#ifdef BEST_ELIGIBLE_PIVOT + /// \brief Finds entering edge according to the "Best Eligible" + /// pivot rule. + bool findEnteringEdge() { + Cost min = 0; + for (EdgeIt e(graph); e != INVALID; ++e) { + if (state[e] * red_cost[e] < min) { + min = state[e] * red_cost[e]; + in_edge = e; + } + } + return min < 0; + } +#endif + +#ifdef EDGE_BLOCK_PIVOT + /// \brief Finds entering edge according to the "Edge Block" + /// pivot rule. + bool findEnteringEdge(EdgeIt &next_edge) { + if (block_size == 1) { + // Performing first eligible selection + for (EdgeIt e = next_edge; e != INVALID; ++e) { + if (state[e] * red_cost[e] < 0) { + in_edge = e; + next_edge = ++e; + return true; + } + } + for (EdgeIt e(graph); e != next_edge; ++e) { + if (state[e] * red_cost[e] < 0) { + in_edge = e; + next_edge = ++e; + return true; + } + } + return false; + } else { + // Performing edge block selection + Cost curr, min = 0; + EdgeIt min_edge(graph); + int cnt = 0; + for (EdgeIt e = next_edge; e != INVALID; ++e) { + if ((curr = state[e] * red_cost[e]) < min) { + min = curr; + min_edge = e; + } + if (++cnt == block_size) { + if (min < 0) break; + cnt = 0; + } + } + if (!(min < 0)) { + for (EdgeIt e(graph); e != next_edge; ++e) { + if ((curr = state[e] * red_cost[e]) < min) { + min = curr; + min_edge = e; + } + if (++cnt == block_size) { + if (min < 0) break; + cnt = 0; + } + } + } + in_edge = min_edge; + if ((next_edge = ++min_edge) == INVALID) + next_edge = EdgeIt(graph); + return min < 0; + } + } +#endif + +#ifdef CANDIDATE_LIST_PIVOT + /// \brief Functor class for removing non-eligible edges from the + /// candidate list. + class RemoveFunc + { + private: + const IntEdgeMap &st; + const ReducedCostMap &rc; + public: + RemoveFunc(const IntEdgeMap &_st, const ReducedCostMap &_rc) : + st(_st), rc(_rc) {} + bool operator()(const Edge &e) { + return st[e] * rc[e] >= 0; + } + }; + + /// \brief Finds entering edge according to the "Candidate List" + /// pivot rule. + bool findEnteringEdge() { + static RemoveFunc remove_func(state, red_cost); + typedef typename std::list::iterator ListIt; + + candidates.remove_if(remove_func); + if (minor_count >= MINOR_LIMIT || candidates.size() == 0) { + // Major iteration + for (EdgeIt e(graph); e != INVALID; ++e) { + if (state[e] * red_cost[e] < 0) { + candidates.push_back(e); + if (candidates.size() == LIST_LENGTH) break; + } + } + if (candidates.size() == 0) return false; + } + + // Minor iteration + ++minor_count; + Cost min = 0; + for (ListIt it = candidates.begin(); it != candidates.end(); ++it) { + if (state[*it] * red_cost[*it] < min) { + min = state[*it] * red_cost[*it]; + in_edge = *it; + } + } + return true; + } +#endif + +#ifdef SORTED_LIST_PIVOT + /// \brief Functor class to compare edges during sort of the + /// candidate list. + class SortFunc + { + private: + const IntEdgeMap &st; + const ReducedCostMap &rc; + public: + SortFunc(const IntEdgeMap &_st, const ReducedCostMap &_rc) : + st(_st), rc(_rc) {} + bool operator()(const Edge &e1, const Edge &e2) { + return st[e1] * rc[e1] < st[e2] * rc[e2]; + } + }; + + /// \brief Finds entering edge according to the "Sorted List" + /// pivot rule. + bool findEnteringEdge() { + static SortFunc sort_func(state, red_cost); + + // Minor iteration + while (candidates.size() > 0) { + in_edge = candidates.front(); + candidates.pop_front(); + if (state[in_edge] * red_cost[in_edge] < 0) return true; + } + + // Major iteration + Cost curr, min = 0; + for (EdgeIt e(graph); e != INVALID; ++e) { + if ((curr = state[e] * red_cost[e]) < min / LOWER_DIV) { + candidates.push_back(e); + if (curr < min) min = curr; + if (candidates.size() >= LIST_LENGTH) break; + } + } + if (candidates.size() == 0) return false; + sort(candidates.begin(), candidates.end(), sort_func); + return true; + } +#endif + + /// \brief Finds the join node. + Node findJoinNode() { + // Finding the join node + Node u = graph.source(in_edge); + Node v = graph.target(in_edge); + while (u != v) { + if (depth[u] == depth[v]) { + u = parent[u]; + v = parent[v]; + } + else if (depth[u] > depth[v]) u = parent[u]; + else v = parent[v]; + } + return u; + } + + /// \brief Finds the leaving edge of the cycle. Returns \c true if + /// the leaving edge is not the same as the entering edge. + bool findLeavingEdge() { + // Initializing first and second nodes according to the direction + // of the cycle + if (state[in_edge] == LOWER) { + first = graph.source(in_edge); + second = graph.target(in_edge); + } else { + first = graph.target(in_edge); + second = graph.source(in_edge); + } + delta = capacity[in_edge]; + bool result = false; + Capacity d; + Edge e; + + // Searching the cycle along the path form the first node to the + // root node + for (Node u = first; u != join; u = parent[u]) { + e = pred_edge[u]; + d = forward[u] ? flow[e] : capacity[e] - flow[e]; + if (d < delta) { + delta = d; + u_out = u; + u_in = first; + v_in = second; + result = true; + } + } + // Searching the cycle along the path form the second node to the + // root node + for (Node u = second; u != join; u = parent[u]) { + e = pred_edge[u]; + d = forward[u] ? capacity[e] - flow[e] : flow[e]; + if (d <= delta) { + delta = d; + u_out = u; + u_in = second; + v_in = first; + result = true; + } + } + return result; + } + + /// \brief Changes flow and state edge maps. + void changeFlows(bool change) { + // Augmenting along the cycle + if (delta > 0) { + Capacity val = state[in_edge] * delta; + flow[in_edge] += val; + for (Node u = graph.source(in_edge); u != join; u = parent[u]) { + flow[pred_edge[u]] += forward[u] ? -val : val; + } + for (Node u = graph.target(in_edge); u != join; u = parent[u]) { + flow[pred_edge[u]] += forward[u] ? val : -val; + } + } + // Updating the state of the entering and leaving edges + if (change) { + state[in_edge] = TREE; + state[pred_edge[u_out]] = + (flow[pred_edge[u_out]] == 0) ? LOWER : UPPER; + } else { + state[in_edge] = -state[in_edge]; + } + } + + /// \brief Updates thread and parent node maps. + void updateThreadParent() { + Node u; + v_out = parent[u_out]; + + // Handling the case when join and v_out coincide + bool par_first = false; + if (join == v_out) { + for (u = join; u != u_in && u != v_in; u = thread[u]) ; + if (u == v_in) { + par_first = true; + while (thread[u] != u_out) u = thread[u]; + first = u; + } + } + + // Finding the last successor of u_in (u) and the node after it + // (right) according to the thread index + for (u = u_in; depth[thread[u]] > depth[u_in]; u = thread[u]) ; + right = thread[u]; + if (thread[v_in] == u_out) { + for (last = u; depth[last] > depth[u_out]; last = thread[last]) ; + if (last == u_out) last = thread[last]; + } + else last = thread[v_in]; + + // Updating stem nodes + thread[v_in] = stem = u_in; + par_stem = v_in; + while (stem != u_out) { + thread[u] = new_stem = parent[stem]; + + // Finding the node just before the stem node (u) according to + // the original thread index + for (u = new_stem; thread[u] != stem; u = thread[u]) ; + thread[u] = right; + + // Changing the parent node of stem and shifting stem and + // par_stem nodes + parent[stem] = par_stem; + par_stem = stem; + stem = new_stem; + + // Finding the last successor of stem (u) and the node after it + // (right) according to the thread index + for (u = stem; depth[thread[u]] > depth[stem]; u = thread[u]) ; + right = thread[u]; + } + parent[u_out] = par_stem; + thread[u] = last; + + if (join == v_out && par_first) { + if (first != v_in) thread[first] = right; + } else { + for (u = v_out; thread[u] != u_out; u = thread[u]) ; + thread[u] = right; + } + } + + /// \brief Updates pred_edge and forward node maps. + void updatePredEdge() { + Node u = u_out, v; + while (u != u_in) { + v = parent[u]; + pred_edge[u] = pred_edge[v]; + forward[u] = !forward[v]; + u = v; + } + pred_edge[u_in] = in_edge; + forward[u_in] = (u_in == graph.source(in_edge)); + } + + /// \brief Updates depth and potential node maps. + void updateDepthPotential() { + depth[u_in] = depth[v_in] + 1; + potential[u_in] = forward[u_in] ? + potential[v_in] + cost[pred_edge[u_in]] : + potential[v_in] - cost[pred_edge[u_in]]; + + Node u = thread[u_in], v; + while (true) { + v = parent[u]; + if (v == INVALID) break; + depth[u] = depth[v] + 1; + potential[u] = forward[u] ? + potential[v] + cost[pred_edge[u]] : + potential[v] - cost[pred_edge[u]]; + if (depth[u] <= depth[v_in]) break; + u = thread[u]; + } + } + + /// \brief Executes the algorithm. + bool start() { + // Processing pivots +#ifdef _DEBUG_ITER_ + int iter_num = 0; +#endif +#if defined(FIRST_ELIGIBLE_PIVOT) || defined(EDGE_BLOCK_PIVOT) + EdgeIt next_edge(graph); + while (findEnteringEdge(next_edge)) +#else + while (findEnteringEdge()) +#endif + { + join = findJoinNode(); + bool change = findLeavingEdge(); + changeFlows(change); + if (change) { + updateThreadParent(); + updatePredEdge(); + updateDepthPotential(); + } +#ifdef _DEBUG_ITER_ + ++iter_num; +#endif + } + +#ifdef _DEBUG_ITER_ + t_iter.stop(); + std::cout << "Network Simplex algorithm finished. " << iter_num + << " pivot iterations performed."; +#endif + + // Checking if the flow amount equals zero on all the + // artificial edges + for (InEdgeIt e(graph, root); e != INVALID; ++e) + if (flow[e] > 0) return false; + for (OutEdgeIt e(graph, root); e != INVALID; ++e) + if (flow[e] > 0) return false; + + // Copying flow values to flow_result + if (lower) { + for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) + flow_result[e] = (*lower)[e] + flow[edge_ref[e]]; + } else { + for (typename Graph::EdgeIt e(graph_ref); e != INVALID; ++e) + flow_result[e] = flow[edge_ref[e]]; + } + // Copying potential values to potential_result + for (typename Graph::NodeIt n(graph_ref); n != INVALID; ++n) + potential_result[n] = potential[node_ref[n]]; + + return true; + } + + }; //class NetworkSimplex + + ///@} + +} //namespace lemon + +#endif //LEMON_NETWORK_SIMPLEX_H