kpeter@2636: /* -*- C++ -*- kpeter@2636: * kpeter@2636: * This file is a part of LEMON, a generic C++ optimization library kpeter@2636: * kpeter@2636: * Copyright (C) 2003-2008 kpeter@2636: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@2636: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@2636: * kpeter@2636: * Permission to use, modify and distribute this software is granted kpeter@2636: * provided that this copyright notice appears in all copies. For kpeter@2636: * precise terms see the accompanying LICENSE file. kpeter@2636: * kpeter@2636: * This software is provided "AS IS" with no warranty of any kind, kpeter@2636: * express or implied, and with no claim as to its suitability for any kpeter@2636: * purpose. kpeter@2636: * kpeter@2636: */ kpeter@2636: kpeter@2636: #ifndef LEMON_CANCEL_AND_TIGHTEN_H kpeter@2636: #define LEMON_CANCEL_AND_TIGHTEN_H kpeter@2636: kpeter@2636: /// \ingroup min_cost_flow kpeter@2636: /// kpeter@2636: /// \file kpeter@2636: /// \brief Cancel and Tighten algorithm for finding a minimum cost flow. kpeter@2636: kpeter@2636: #include kpeter@2636: kpeter@2636: #include kpeter@2636: #include kpeter@2636: #include kpeter@2636: #include kpeter@2636: #include kpeter@2636: #include kpeter@2636: kpeter@2636: #include kpeter@2636: kpeter@2636: namespace lemon { kpeter@2636: kpeter@2636: /// \addtogroup min_cost_flow kpeter@2636: /// @{ kpeter@2636: kpeter@2636: /// \brief Implementation of the Cancel and Tighten algorithm for kpeter@2636: /// finding a minimum cost flow. kpeter@2636: /// kpeter@2636: /// \ref CancelAndTighten implements the Cancel and Tighten algorithm for kpeter@2636: /// finding a minimum cost flow. kpeter@2636: /// kpeter@2636: /// \tparam Graph The directed graph type the algorithm runs on. kpeter@2636: /// \tparam LowerMap The type of the lower bound map. kpeter@2636: /// \tparam CapacityMap The type of the capacity (upper bound) map. kpeter@2636: /// \tparam CostMap The type of the cost (length) map. kpeter@2636: /// \tparam SupplyMap The type of the supply map. kpeter@2636: /// kpeter@2636: /// \warning kpeter@2636: /// - Edge capacities and costs should be \e non-negative \e integers. kpeter@2636: /// - Supply values should be \e signed \e integers. kpeter@2636: /// - The value types of the maps should be convertible to each other. kpeter@2636: /// - \c CostMap::Value must be signed type. kpeter@2636: /// kpeter@2636: /// \author Peter Kovacs kpeter@2636: template < typename Graph, kpeter@2636: typename LowerMap = typename Graph::template EdgeMap, kpeter@2636: typename CapacityMap = typename Graph::template EdgeMap, kpeter@2636: typename CostMap = typename Graph::template EdgeMap, kpeter@2636: typename SupplyMap = typename Graph::template NodeMap > kpeter@2636: class CancelAndTighten kpeter@2636: { kpeter@2636: GRAPH_TYPEDEFS(typename Graph); kpeter@2636: kpeter@2636: typedef typename CapacityMap::Value Capacity; kpeter@2636: typedef typename CostMap::Value Cost; kpeter@2636: typedef typename SupplyMap::Value Supply; kpeter@2636: typedef typename Graph::template EdgeMap CapacityEdgeMap; kpeter@2636: typedef typename Graph::template NodeMap SupplyNodeMap; kpeter@2636: kpeter@2636: typedef ResGraphAdaptor< const Graph, Capacity, kpeter@2636: CapacityEdgeMap, CapacityEdgeMap > ResGraph; kpeter@2636: kpeter@2636: public: kpeter@2636: kpeter@2636: /// The type of the flow map. kpeter@2636: typedef typename Graph::template EdgeMap FlowMap; kpeter@2636: /// The type of the potential map. kpeter@2636: typedef typename Graph::template NodeMap PotentialMap; kpeter@2636: kpeter@2636: private: kpeter@2636: kpeter@2636: /// \brief Map adaptor class for handling residual edge costs. kpeter@2636: /// kpeter@2636: /// Map adaptor class for handling residual edge costs. kpeter@2636: class ResidualCostMap : public MapBase kpeter@2636: { kpeter@2636: typedef typename ResGraph::Edge Edge; kpeter@2636: kpeter@2636: private: kpeter@2636: kpeter@2636: const CostMap &_cost_map; kpeter@2636: kpeter@2636: public: kpeter@2636: kpeter@2636: ///\e kpeter@2636: ResidualCostMap(const CostMap &cost_map) : _cost_map(cost_map) {} kpeter@2636: kpeter@2636: ///\e kpeter@2636: Cost operator[](const Edge &e) const { kpeter@2636: return ResGraph::forward(e) ? _cost_map[e] : -_cost_map[e]; kpeter@2636: } kpeter@2636: kpeter@2636: }; //class ResidualCostMap kpeter@2636: kpeter@2636: /// \brief Map adaptor class for handling reduced edge costs. kpeter@2636: /// kpeter@2636: /// Map adaptor class for handling reduced edge costs. kpeter@2636: class ReducedCostMap : public MapBase kpeter@2636: { kpeter@2636: private: kpeter@2636: kpeter@2636: const Graph &_gr; kpeter@2636: const CostMap &_cost_map; kpeter@2636: const PotentialMap &_pot_map; kpeter@2636: kpeter@2636: public: kpeter@2636: kpeter@2636: ///\e kpeter@2636: ReducedCostMap( const Graph &gr, kpeter@2636: const CostMap &cost_map, kpeter@2636: const PotentialMap &pot_map ) : kpeter@2636: _gr(gr), _cost_map(cost_map), _pot_map(pot_map) {} kpeter@2636: kpeter@2636: ///\e kpeter@2636: inline Cost operator[](const Edge &e) const { kpeter@2636: return _cost_map[e] + _pot_map[_gr.source(e)] kpeter@2636: - _pot_map[_gr.target(e)]; kpeter@2636: } kpeter@2636: kpeter@2636: }; //class ReducedCostMap kpeter@2636: kpeter@2636: struct BFOperationTraits { kpeter@2636: static double zero() { return 0; } kpeter@2636: kpeter@2636: static double infinity() { kpeter@2636: return std::numeric_limits::infinity(); kpeter@2636: } kpeter@2636: kpeter@2636: static double plus(const double& left, const double& right) { kpeter@2636: return left + right; kpeter@2636: } kpeter@2636: kpeter@2636: static bool less(const double& left, const double& right) { kpeter@2636: return left + 1e-6 < right; kpeter@2636: } kpeter@2636: }; // class BFOperationTraits kpeter@2636: kpeter@2636: private: kpeter@2636: kpeter@2636: // The directed graph the algorithm runs on kpeter@2636: const Graph &_graph; kpeter@2636: // The original lower bound map kpeter@2636: const LowerMap *_lower; kpeter@2636: // The modified capacity map kpeter@2636: CapacityEdgeMap _capacity; kpeter@2636: // The original cost map kpeter@2636: const CostMap &_cost; kpeter@2636: // The modified supply map kpeter@2636: SupplyNodeMap _supply; kpeter@2636: bool _valid_supply; kpeter@2636: kpeter@2636: // Edge map of the current flow kpeter@2636: FlowMap *_flow; kpeter@2636: bool _local_flow; kpeter@2636: // Node map of the current potentials kpeter@2636: PotentialMap *_potential; kpeter@2636: bool _local_potential; kpeter@2636: kpeter@2636: // The residual graph kpeter@2636: ResGraph *_res_graph; kpeter@2636: // The residual cost map kpeter@2636: ResidualCostMap _res_cost; kpeter@2636: kpeter@2636: public: kpeter@2636: kpeter@2636: /// \brief General constructor (with lower bounds). kpeter@2636: /// kpeter@2636: /// General constructor (with lower bounds). kpeter@2636: /// kpeter@2636: /// \param graph The directed graph the algorithm runs on. kpeter@2636: /// \param lower The lower bounds of the edges. kpeter@2636: /// \param capacity The capacities (upper bounds) of the edges. kpeter@2636: /// \param cost The cost (length) values of the edges. kpeter@2636: /// \param supply The supply values of the nodes (signed). kpeter@2636: CancelAndTighten( const Graph &graph, kpeter@2636: const LowerMap &lower, kpeter@2636: const CapacityMap &capacity, kpeter@2636: const CostMap &cost, kpeter@2636: const SupplyMap &supply ) : kpeter@2636: _graph(graph), _lower(&lower), _capacity(capacity), _cost(cost), kpeter@2636: _supply(supply), _flow(NULL), _local_flow(false), kpeter@2636: _potential(NULL), _local_potential(false), kpeter@2636: _res_graph(NULL), _res_cost(_cost) kpeter@2636: { kpeter@2636: // Check the sum of supply values kpeter@2636: Supply sum = 0; kpeter@2636: for (NodeIt n(_graph); n != INVALID; ++n) sum += _supply[n]; kpeter@2636: _valid_supply = sum == 0; kpeter@2636: kpeter@2636: // Remove non-zero lower bounds kpeter@2636: for (EdgeIt e(_graph); e != INVALID; ++e) { kpeter@2636: if (lower[e] != 0) { kpeter@2636: _capacity[e] -= lower[e]; kpeter@2636: _supply[_graph.source(e)] -= lower[e]; kpeter@2636: _supply[_graph.target(e)] += lower[e]; kpeter@2636: } kpeter@2636: } kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief General constructor (without lower bounds). kpeter@2636: /// kpeter@2636: /// General constructor (without lower bounds). kpeter@2636: /// kpeter@2636: /// \param graph The directed graph the algorithm runs on. kpeter@2636: /// \param capacity The capacities (upper bounds) of the edges. kpeter@2636: /// \param cost The cost (length) values of the edges. kpeter@2636: /// \param supply The supply values of the nodes (signed). kpeter@2636: CancelAndTighten( const Graph &graph, kpeter@2636: const CapacityMap &capacity, kpeter@2636: const CostMap &cost, kpeter@2636: const SupplyMap &supply ) : kpeter@2636: _graph(graph), _lower(NULL), _capacity(capacity), _cost(cost), kpeter@2636: _supply(supply), _flow(NULL), _local_flow(false), kpeter@2636: _potential(NULL), _local_potential(false), kpeter@2636: _res_graph(NULL), _res_cost(_cost) kpeter@2636: { kpeter@2636: // Check the sum of supply values kpeter@2636: Supply sum = 0; kpeter@2636: for (NodeIt n(_graph); n != INVALID; ++n) sum += _supply[n]; kpeter@2636: _valid_supply = sum == 0; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Simple constructor (with lower bounds). kpeter@2636: /// kpeter@2636: /// Simple constructor (with lower bounds). kpeter@2636: /// kpeter@2636: /// \param graph The directed graph the algorithm runs on. kpeter@2636: /// \param lower The lower bounds of the edges. kpeter@2636: /// \param capacity The capacities (upper bounds) of the edges. kpeter@2636: /// \param cost The cost (length) values of the edges. kpeter@2636: /// \param s The source node. kpeter@2636: /// \param t The target node. kpeter@2636: /// \param flow_value The required amount of flow from node \c s kpeter@2636: /// to node \c t (i.e. the supply of \c s and the demand of \c t). kpeter@2636: CancelAndTighten( const Graph &graph, kpeter@2636: const LowerMap &lower, kpeter@2636: const CapacityMap &capacity, kpeter@2636: const CostMap &cost, kpeter@2636: Node s, Node t, kpeter@2636: Supply flow_value ) : kpeter@2636: _graph(graph), _lower(&lower), _capacity(capacity), _cost(cost), kpeter@2636: _supply(graph, 0), _flow(NULL), _local_flow(false), kpeter@2636: _potential(NULL), _local_potential(false), kpeter@2636: _res_graph(NULL), _res_cost(_cost) kpeter@2636: { kpeter@2636: // Remove non-zero lower bounds kpeter@2636: _supply[s] = flow_value; kpeter@2636: _supply[t] = -flow_value; kpeter@2636: for (EdgeIt e(_graph); e != INVALID; ++e) { kpeter@2636: if (lower[e] != 0) { kpeter@2636: _capacity[e] -= lower[e]; kpeter@2636: _supply[_graph.source(e)] -= lower[e]; kpeter@2636: _supply[_graph.target(e)] += lower[e]; kpeter@2636: } kpeter@2636: } kpeter@2636: _valid_supply = true; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Simple constructor (without lower bounds). kpeter@2636: /// kpeter@2636: /// Simple constructor (without lower bounds). kpeter@2636: /// kpeter@2636: /// \param graph The directed graph the algorithm runs on. kpeter@2636: /// \param capacity The capacities (upper bounds) of the edges. kpeter@2636: /// \param cost The cost (length) values of the edges. kpeter@2636: /// \param s The source node. kpeter@2636: /// \param t The target node. kpeter@2636: /// \param flow_value The required amount of flow from node \c s kpeter@2636: /// to node \c t (i.e. the supply of \c s and the demand of \c t). kpeter@2636: CancelAndTighten( const Graph &graph, kpeter@2636: const CapacityMap &capacity, kpeter@2636: const CostMap &cost, kpeter@2636: Node s, Node t, kpeter@2636: Supply flow_value ) : kpeter@2636: _graph(graph), _lower(NULL), _capacity(capacity), _cost(cost), kpeter@2636: _supply(graph, 0), _flow(NULL), _local_flow(false), kpeter@2636: _potential(NULL), _local_potential(false), kpeter@2636: _res_graph(NULL), _res_cost(_cost) kpeter@2636: { kpeter@2636: _supply[s] = flow_value; kpeter@2636: _supply[t] = -flow_value; kpeter@2636: _valid_supply = true; kpeter@2636: } kpeter@2636: kpeter@2636: /// Destructor. kpeter@2636: ~CancelAndTighten() { kpeter@2636: if (_local_flow) delete _flow; kpeter@2636: if (_local_potential) delete _potential; kpeter@2636: delete _res_graph; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Set the flow map. kpeter@2636: /// kpeter@2636: /// Set the flow map. kpeter@2636: /// kpeter@2636: /// \return \c (*this) kpeter@2636: CancelAndTighten& flowMap(FlowMap &map) { kpeter@2636: if (_local_flow) { kpeter@2636: delete _flow; kpeter@2636: _local_flow = false; kpeter@2636: } kpeter@2636: _flow = ↦ kpeter@2636: return *this; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Set the potential map. kpeter@2636: /// kpeter@2636: /// Set the potential map. kpeter@2636: /// kpeter@2636: /// \return \c (*this) kpeter@2636: CancelAndTighten& potentialMap(PotentialMap &map) { kpeter@2636: if (_local_potential) { kpeter@2636: delete _potential; kpeter@2636: _local_potential = false; kpeter@2636: } kpeter@2636: _potential = ↦ kpeter@2636: return *this; kpeter@2636: } kpeter@2636: kpeter@2636: /// \name Execution control kpeter@2636: kpeter@2636: /// @{ kpeter@2636: kpeter@2636: /// \brief Run the algorithm. kpeter@2636: /// kpeter@2636: /// Run the algorithm. kpeter@2636: /// kpeter@2636: /// \return \c true if a feasible flow can be found. kpeter@2636: bool run() { kpeter@2636: return init() && start(); kpeter@2636: } kpeter@2636: kpeter@2636: /// @} kpeter@2636: kpeter@2636: /// \name Query Functions kpeter@2636: /// The result of the algorithm can be obtained using these kpeter@2636: /// functions.\n kpeter@2636: /// \ref lemon::CancelAndTighten::run() "run()" must be called before kpeter@2636: /// using them. kpeter@2636: kpeter@2636: /// @{ kpeter@2636: kpeter@2636: /// \brief Return a const reference to the edge map storing the kpeter@2636: /// found flow. kpeter@2636: /// kpeter@2636: /// Return a const reference to the edge map storing the found flow. kpeter@2636: /// kpeter@2636: /// \pre \ref run() must be called before using this function. kpeter@2636: const FlowMap& flowMap() const { kpeter@2636: return *_flow; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Return a const reference to the node map storing the kpeter@2636: /// found potentials (the dual solution). kpeter@2636: /// kpeter@2636: /// Return a const reference to the node map storing the found kpeter@2636: /// potentials (the dual solution). kpeter@2636: /// kpeter@2636: /// \pre \ref run() must be called before using this function. kpeter@2636: const PotentialMap& potentialMap() const { kpeter@2636: return *_potential; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Return the flow on the given edge. kpeter@2636: /// kpeter@2636: /// Return the flow on the given edge. kpeter@2636: /// kpeter@2636: /// \pre \ref run() must be called before using this function. kpeter@2636: Capacity flow(const Edge& edge) const { kpeter@2636: return (*_flow)[edge]; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Return the potential of the given node. kpeter@2636: /// kpeter@2636: /// Return the potential of the given node. kpeter@2636: /// kpeter@2636: /// \pre \ref run() must be called before using this function. kpeter@2636: Cost potential(const Node& node) const { kpeter@2636: return (*_potential)[node]; kpeter@2636: } kpeter@2636: kpeter@2636: /// \brief Return the total cost of the found flow. kpeter@2636: /// kpeter@2636: /// Return the total cost of the found flow. The complexity of the kpeter@2636: /// function is \f$ O(e) \f$. kpeter@2636: /// kpeter@2636: /// \pre \ref run() must be called before using this function. kpeter@2636: Cost totalCost() const { kpeter@2636: Cost c = 0; kpeter@2636: for (EdgeIt e(_graph); e != INVALID; ++e) kpeter@2636: c += (*_flow)[e] * _cost[e]; kpeter@2636: return c; kpeter@2636: } kpeter@2636: kpeter@2636: /// @} kpeter@2636: kpeter@2636: private: kpeter@2636: kpeter@2636: /// Initialize the algorithm. kpeter@2636: bool init() { kpeter@2636: if (!_valid_supply) return false; kpeter@2636: kpeter@2636: // Initialize flow and potential maps kpeter@2636: if (!_flow) { kpeter@2636: _flow = new FlowMap(_graph); kpeter@2636: _local_flow = true; kpeter@2636: } kpeter@2636: if (!_potential) { kpeter@2636: _potential = new PotentialMap(_graph); kpeter@2636: _local_potential = true; kpeter@2636: } kpeter@2636: kpeter@2636: _res_graph = new ResGraph(_graph, _capacity, *_flow); kpeter@2636: kpeter@2636: // Find a feasible flow using Circulation kpeter@2636: Circulation< Graph, ConstMap, kpeter@2636: CapacityEdgeMap, SupplyMap > kpeter@2636: circulation( _graph, constMap(Capacity(0)), kpeter@2636: _capacity, _supply ); kpeter@2636: return circulation.flowMap(*_flow).run(); kpeter@2636: } kpeter@2636: kpeter@2636: bool start() { kpeter@2636: const double LIMIT_FACTOR = 0.01; kpeter@2636: const int MIN_LIMIT = 3; kpeter@2636: kpeter@2636: typedef typename Graph::template NodeMap FloatPotentialMap; kpeter@2636: typedef typename Graph::template NodeMap LevelMap; kpeter@2636: typedef typename Graph::template NodeMap BoolNodeMap; kpeter@2636: typedef typename Graph::template NodeMap PredNodeMap; kpeter@2636: typedef typename Graph::template NodeMap PredEdgeMap; kpeter@2636: typedef typename ResGraph::template EdgeMap ResShiftCostMap; kpeter@2636: FloatPotentialMap pi(_graph); kpeter@2636: LevelMap level(_graph); kpeter@2636: BoolNodeMap reached(_graph); kpeter@2636: BoolNodeMap processed(_graph); kpeter@2636: PredNodeMap pred_node(_graph); kpeter@2636: PredEdgeMap pred_edge(_graph); kpeter@2636: int node_num = countNodes(_graph); kpeter@2636: typedef std::pair pair; kpeter@2636: std::vector stack(node_num); kpeter@2636: std::vector proc_vector(node_num); kpeter@2636: ResShiftCostMap shift_cost(*_res_graph); kpeter@2636: kpeter@2636: Tolerance tol; kpeter@2636: tol.epsilon(1e-6); kpeter@2636: kpeter@2636: Timer t1, t2, t3; kpeter@2636: t1.reset(); kpeter@2636: t2.reset(); kpeter@2636: t3.reset(); kpeter@2636: kpeter@2636: // Initialize epsilon and the node potentials kpeter@2636: double epsilon = 0; kpeter@2636: for (EdgeIt e(_graph); e != INVALID; ++e) { kpeter@2636: if (_capacity[e] - (*_flow)[e] > 0 && _cost[e] < -epsilon) kpeter@2636: epsilon = -_cost[e]; kpeter@2636: else if ((*_flow)[e] > 0 && _cost[e] > epsilon) kpeter@2636: epsilon = _cost[e]; kpeter@2636: } kpeter@2636: for (NodeIt v(_graph); v != INVALID; ++v) { kpeter@2636: pi[v] = 0; kpeter@2636: } kpeter@2636: kpeter@2636: // Start phases kpeter@2636: int limit = int(LIMIT_FACTOR * node_num); kpeter@2636: if (limit < MIN_LIMIT) limit = MIN_LIMIT; kpeter@2636: int iter = limit; kpeter@2636: while (epsilon * node_num >= 1) { kpeter@2636: t1.start(); kpeter@2636: // Find and cancel cycles in the admissible graph using DFS kpeter@2636: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@2636: reached[n] = false; kpeter@2636: processed[n] = false; kpeter@2636: } kpeter@2636: int stack_head = -1; kpeter@2636: int proc_head = -1; kpeter@2636: kpeter@2636: for (NodeIt start(_graph); start != INVALID; ++start) { kpeter@2636: if (reached[start]) continue; kpeter@2636: kpeter@2636: // New start node kpeter@2636: reached[start] = true; kpeter@2636: pred_edge[start] = INVALID; kpeter@2636: pred_node[start] = INVALID; kpeter@2636: kpeter@2636: // Find the first admissible residual outgoing edge kpeter@2636: double p = pi[start]; kpeter@2636: Edge e; kpeter@2636: _graph.firstOut(e, start); kpeter@2636: while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 || kpeter@2636: !tol.negative(_cost[e] + p - pi[_graph.target(e)])) ) kpeter@2636: _graph.nextOut(e); kpeter@2636: if (e != INVALID) { kpeter@2636: stack[++stack_head] = pair(e, true); kpeter@2636: goto next_step_1; kpeter@2636: } kpeter@2636: _graph.firstIn(e, start); kpeter@2636: while ( e != INVALID && ((*_flow)[e] == 0 || kpeter@2636: !tol.negative(-_cost[e] + p - pi[_graph.source(e)])) ) kpeter@2636: _graph.nextIn(e); kpeter@2636: if (e != INVALID) { kpeter@2636: stack[++stack_head] = pair(e, false); kpeter@2636: goto next_step_1; kpeter@2636: } kpeter@2636: processed[start] = true; kpeter@2636: proc_vector[++proc_head] = start; kpeter@2636: continue; kpeter@2636: next_step_1: kpeter@2636: kpeter@2636: while (stack_head >= 0) { kpeter@2636: Edge se = stack[stack_head].first; kpeter@2636: bool sf = stack[stack_head].second; kpeter@2636: Node u, v; kpeter@2636: if (sf) { kpeter@2636: u = _graph.source(se); kpeter@2636: v = _graph.target(se); kpeter@2636: } else { kpeter@2636: u = _graph.target(se); kpeter@2636: v = _graph.source(se); kpeter@2636: } kpeter@2636: kpeter@2636: if (!reached[v]) { kpeter@2636: // A new node is reached kpeter@2636: reached[v] = true; kpeter@2636: pred_node[v] = u; kpeter@2636: pred_edge[v] = se; kpeter@2636: // Find the first admissible residual outgoing edge kpeter@2636: double p = pi[v]; kpeter@2636: Edge e; kpeter@2636: _graph.firstOut(e, v); kpeter@2636: while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 || kpeter@2636: !tol.negative(_cost[e] + p - pi[_graph.target(e)])) ) kpeter@2636: _graph.nextOut(e); kpeter@2636: if (e != INVALID) { kpeter@2636: stack[++stack_head] = pair(e, true); kpeter@2636: goto next_step_2; kpeter@2636: } kpeter@2636: _graph.firstIn(e, v); kpeter@2636: while ( e != INVALID && ((*_flow)[e] == 0 || kpeter@2636: !tol.negative(-_cost[e] + p - pi[_graph.source(e)])) ) kpeter@2636: _graph.nextIn(e); kpeter@2636: stack[++stack_head] = pair(e, false); kpeter@2636: next_step_2: ; kpeter@2636: } else { kpeter@2636: if (!processed[v]) { kpeter@2636: // A cycle is found kpeter@2636: Node n, w = u; kpeter@2636: Capacity d, delta = sf ? _capacity[se] - (*_flow)[se] : kpeter@2636: (*_flow)[se]; kpeter@2636: for (n = u; n != v; n = pred_node[n]) { kpeter@2636: d = _graph.target(pred_edge[n]) == n ? kpeter@2636: _capacity[pred_edge[n]] - (*_flow)[pred_edge[n]] : kpeter@2636: (*_flow)[pred_edge[n]]; kpeter@2636: if (d <= delta) { kpeter@2636: delta = d; kpeter@2636: w = pred_node[n]; kpeter@2636: } kpeter@2636: } kpeter@2636: kpeter@2636: /* kpeter@2636: std::cout << "CYCLE FOUND: "; kpeter@2636: if (sf) kpeter@2636: std::cout << _cost[se] + pi[_graph.source(se)] - pi[_graph.target(se)]; kpeter@2636: else kpeter@2636: std::cout << _graph.id(se) << ":" << -(_cost[se] + pi[_graph.source(se)] - pi[_graph.target(se)]); kpeter@2636: for (n = u; n != v; n = pred_node[n]) { kpeter@2636: if (_graph.target(pred_edge[n]) == n) kpeter@2636: std::cout << " " << _cost[pred_edge[n]] + pi[_graph.source(pred_edge[n])] - pi[_graph.target(pred_edge[n])]; kpeter@2636: else kpeter@2636: std::cout << " " << -(_cost[pred_edge[n]] + pi[_graph.source(pred_edge[n])] - pi[_graph.target(pred_edge[n])]); kpeter@2636: } kpeter@2636: std::cout << "\n"; kpeter@2636: */ kpeter@2636: // Augment along the cycle kpeter@2636: (*_flow)[se] = sf ? (*_flow)[se] + delta : kpeter@2636: (*_flow)[se] - delta; kpeter@2636: for (n = u; n != v; n = pred_node[n]) { kpeter@2636: if (_graph.target(pred_edge[n]) == n) kpeter@2636: (*_flow)[pred_edge[n]] += delta; kpeter@2636: else kpeter@2636: (*_flow)[pred_edge[n]] -= delta; kpeter@2636: } kpeter@2636: for (n = u; stack_head > 0 && n != w; n = pred_node[n]) { kpeter@2636: --stack_head; kpeter@2636: reached[n] = false; kpeter@2636: } kpeter@2636: u = w; kpeter@2636: } kpeter@2636: v = u; kpeter@2636: kpeter@2636: // Find the next admissible residual outgoing edge kpeter@2636: double p = pi[v]; kpeter@2636: Edge e = stack[stack_head].first; kpeter@2636: if (!stack[stack_head].second) { kpeter@2636: _graph.nextIn(e); kpeter@2636: goto in_edge_3; kpeter@2636: } kpeter@2636: _graph.nextOut(e); kpeter@2636: while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 || kpeter@2636: !tol.negative(_cost[e] + p - pi[_graph.target(e)])) ) kpeter@2636: _graph.nextOut(e); kpeter@2636: if (e != INVALID) { kpeter@2636: stack[stack_head] = pair(e, true); kpeter@2636: goto next_step_3; kpeter@2636: } kpeter@2636: _graph.firstIn(e, v); kpeter@2636: in_edge_3: kpeter@2636: while ( e != INVALID && ((*_flow)[e] == 0 || kpeter@2636: !tol.negative(-_cost[e] + p - pi[_graph.source(e)])) ) kpeter@2636: _graph.nextIn(e); kpeter@2636: stack[stack_head] = pair(e, false); kpeter@2636: next_step_3: ; kpeter@2636: } kpeter@2636: kpeter@2636: while (stack_head >= 0 && stack[stack_head].first == INVALID) { kpeter@2636: processed[v] = true; kpeter@2636: proc_vector[++proc_head] = v; kpeter@2636: if (--stack_head >= 0) { kpeter@2636: v = stack[stack_head].second ? kpeter@2636: _graph.source(stack[stack_head].first) : kpeter@2636: _graph.target(stack[stack_head].first); kpeter@2636: // Find the next admissible residual outgoing edge kpeter@2636: double p = pi[v]; kpeter@2636: Edge e = stack[stack_head].first; kpeter@2636: if (!stack[stack_head].second) { kpeter@2636: _graph.nextIn(e); kpeter@2636: goto in_edge_4; kpeter@2636: } kpeter@2636: _graph.nextOut(e); kpeter@2636: while ( e != INVALID && (_capacity[e] - (*_flow)[e] == 0 || kpeter@2636: !tol.negative(_cost[e] + p - pi[_graph.target(e)])) ) kpeter@2636: _graph.nextOut(e); kpeter@2636: if (e != INVALID) { kpeter@2636: stack[stack_head] = pair(e, true); kpeter@2636: goto next_step_4; kpeter@2636: } kpeter@2636: _graph.firstIn(e, v); kpeter@2636: in_edge_4: kpeter@2636: while ( e != INVALID && ((*_flow)[e] == 0 || kpeter@2636: !tol.negative(-_cost[e] + p - pi[_graph.source(e)])) ) kpeter@2636: _graph.nextIn(e); kpeter@2636: stack[stack_head] = pair(e, false); kpeter@2636: next_step_4: ; kpeter@2636: } kpeter@2636: } kpeter@2636: } kpeter@2636: } kpeter@2636: t1.stop(); kpeter@2636: kpeter@2636: // Tighten potentials and epsilon kpeter@2636: if (--iter > 0) { kpeter@2636: // Compute levels kpeter@2636: t2.start(); kpeter@2636: for (int i = proc_head; i >= 0; --i) { kpeter@2636: Node v = proc_vector[i]; kpeter@2636: double p = pi[v]; kpeter@2636: int l = 0; kpeter@2636: for (InEdgeIt e(_graph, v); e != INVALID; ++e) { kpeter@2636: Node u = _graph.source(e); kpeter@2636: if ( _capacity[e] - (*_flow)[e] > 0 && kpeter@2636: tol.negative(_cost[e] + pi[u] - p) && kpeter@2636: level[u] + 1 > l ) l = level[u] + 1; kpeter@2636: } kpeter@2636: for (OutEdgeIt e(_graph, v); e != INVALID; ++e) { kpeter@2636: Node u = _graph.target(e); kpeter@2636: if ( (*_flow)[e] > 0 && kpeter@2636: tol.negative(-_cost[e] + pi[u] - p) && kpeter@2636: level[u] + 1 > l ) l = level[u] + 1; kpeter@2636: } kpeter@2636: level[v] = l; kpeter@2636: } kpeter@2636: kpeter@2636: // Modify potentials kpeter@2636: double p, q = -1; kpeter@2636: for (EdgeIt e(_graph); e != INVALID; ++e) { kpeter@2636: Node u = _graph.source(e); kpeter@2636: Node v = _graph.target(e); kpeter@2636: if (_capacity[e] - (*_flow)[e] > 0 && level[u] - level[v] > 0) { kpeter@2636: p = (_cost[e] + pi[u] - pi[v] + epsilon) / kpeter@2636: (level[u] - level[v] + 1); kpeter@2636: if (q < 0 || p < q) q = p; kpeter@2636: } kpeter@2636: else if ((*_flow)[e] > 0 && level[v] - level[u] > 0) { kpeter@2636: p = (-_cost[e] - pi[u] + pi[v] + epsilon) / kpeter@2636: (level[v] - level[u] + 1); kpeter@2636: if (q < 0 || p < q) q = p; kpeter@2636: } kpeter@2636: } kpeter@2636: for (NodeIt v(_graph); v != INVALID; ++v) { kpeter@2636: pi[v] -= q * level[v]; kpeter@2636: } kpeter@2636: kpeter@2636: // Modify epsilon kpeter@2636: epsilon = 0; kpeter@2636: for (EdgeIt e(_graph); e != INVALID; ++e) { kpeter@2636: double curr = _cost[e] + pi[_graph.source(e)] kpeter@2636: - pi[_graph.target(e)]; kpeter@2636: if (_capacity[e] - (*_flow)[e] > 0 && curr < -epsilon) kpeter@2636: epsilon = -curr; kpeter@2636: else if ((*_flow)[e] > 0 && curr > epsilon) kpeter@2636: epsilon = curr; kpeter@2636: } kpeter@2636: t2.stop(); kpeter@2636: } else { kpeter@2636: // Set epsilon to the minimum cycle mean kpeter@2636: t3.start(); kpeter@2636: kpeter@2636: /**/ kpeter@2636: StaticGraph static_graph; kpeter@2636: typename ResGraph::template NodeMap node_ref(*_res_graph); kpeter@2636: typename ResGraph::template EdgeMap edge_ref(*_res_graph); kpeter@2636: static_graph.build(*_res_graph, node_ref, edge_ref); kpeter@2636: typename StaticGraph::template NodeMap static_pi(static_graph); kpeter@2636: typename StaticGraph::template EdgeMap static_cost(static_graph); kpeter@2636: kpeter@2636: for (typename ResGraph::EdgeIt e(*_res_graph); e != INVALID; ++e) kpeter@2636: static_cost[edge_ref[e]] = _res_cost[e]; kpeter@2636: kpeter@2636: MinMeanCycle > kpeter@2636: mmc(static_graph, static_cost); kpeter@2636: mmc.init(); kpeter@2636: mmc.findMinMean(); kpeter@2636: epsilon = -mmc.cycleMean(); kpeter@2636: /**/ kpeter@2636: kpeter@2636: /* kpeter@2636: MinMeanCycle mmc(*_res_graph, _res_cost); kpeter@2636: mmc.init(); kpeter@2636: mmc.findMinMean(); kpeter@2636: epsilon = -mmc.cycleMean(); kpeter@2636: */ kpeter@2636: kpeter@2636: // Compute feasible potentials for the current epsilon kpeter@2636: for (typename StaticGraph::EdgeIt e(static_graph); e != INVALID; ++e) kpeter@2636: static_cost[e] += epsilon; kpeter@2636: typename BellmanFord >:: kpeter@2636: template DefDistMap >:: kpeter@2636: template DefOperationTraits::Create kpeter@2636: bf(static_graph, static_cost); kpeter@2636: bf.distMap(static_pi).init(0); kpeter@2636: bf.start(); kpeter@2636: for (NodeIt n(_graph); n != INVALID; ++n) kpeter@2636: pi[n] = static_pi[node_ref[n]]; kpeter@2636: kpeter@2636: /* kpeter@2636: for (typename ResGraph::EdgeIt e(*_res_graph); e != INVALID; ++e) kpeter@2636: shift_cost[e] = _res_cost[e] + epsilon; kpeter@2636: typename BellmanFord:: kpeter@2636: template DefDistMap:: kpeter@2636: template DefOperationTraits::Create kpeter@2636: bf(*_res_graph, shift_cost); kpeter@2636: bf.distMap(pi).init(0); kpeter@2636: bf.start(); kpeter@2636: */ kpeter@2636: kpeter@2636: iter = limit; kpeter@2636: t3.stop(); kpeter@2636: } kpeter@2636: } kpeter@2636: kpeter@2636: // std::cout << t1.realTime() << " " << t2.realTime() << " " << t3.realTime() << "\n"; kpeter@2636: kpeter@2636: // Handle non-zero lower bounds kpeter@2636: if (_lower) { kpeter@2636: for (EdgeIt e(_graph); e != INVALID; ++e) kpeter@2636: (*_flow)[e] += (*_lower)[e]; kpeter@2636: } kpeter@2636: return true; kpeter@2636: } kpeter@2636: kpeter@2636: }; //class CancelAndTighten kpeter@2636: kpeter@2636: ///@} kpeter@2636: kpeter@2636: } //namespace lemon kpeter@2636: kpeter@2636: #endif //LEMON_CANCEL_AND_TIGHTEN_H