kpeter@814: /* -*- C++ -*- kpeter@814: * kpeter@814: * This file is a part of LEMON, a generic C++ optimization library kpeter@814: * kpeter@814: * Copyright (C) 2003-2008 kpeter@814: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@814: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@814: * kpeter@814: * Permission to use, modify and distribute this software is granted kpeter@814: * provided that this copyright notice appears in all copies. For kpeter@814: * precise terms see the accompanying LICENSE file. kpeter@814: * kpeter@814: * This software is provided "AS IS" with no warranty of any kind, kpeter@814: * express or implied, and with no claim as to its suitability for any kpeter@814: * purpose. kpeter@814: * kpeter@814: */ kpeter@814: kpeter@814: #ifndef LEMON_CYCLE_CANCELING_H kpeter@814: #define LEMON_CYCLE_CANCELING_H kpeter@814: kpeter@814: /// \ingroup min_cost_flow kpeter@814: /// kpeter@814: /// \file kpeter@814: /// \brief Cycle-canceling algorithm for finding a minimum cost flow. kpeter@814: kpeter@814: #include kpeter@814: #include kpeter@814: #include kpeter@814: kpeter@814: #include kpeter@814: #include kpeter@814: #include kpeter@814: kpeter@814: namespace lemon { kpeter@814: kpeter@814: /// \addtogroup min_cost_flow kpeter@814: /// @{ kpeter@814: kpeter@814: /// \brief Implementation of a cycle-canceling algorithm for kpeter@814: /// finding a minimum cost flow. kpeter@814: /// kpeter@814: /// \ref CycleCanceling implements a cycle-canceling algorithm for kpeter@814: /// finding a minimum cost flow. kpeter@814: /// kpeter@814: /// \tparam Digraph The digraph type the algorithm runs on. kpeter@814: /// \tparam LowerMap The type of the lower bound map. kpeter@814: /// \tparam CapacityMap The type of the capacity (upper bound) map. kpeter@814: /// \tparam CostMap The type of the cost (length) map. kpeter@814: /// \tparam SupplyMap The type of the supply map. kpeter@814: /// kpeter@814: /// \warning kpeter@814: /// - Arc capacities and costs should be \e non-negative \e integers. kpeter@814: /// - Supply values should be \e signed \e integers. kpeter@814: /// - The value types of the maps should be convertible to each other. kpeter@814: /// - \c CostMap::Value must be signed type. kpeter@814: /// kpeter@814: /// \note By default the \ref BellmanFord "Bellman-Ford" algorithm is kpeter@814: /// used for negative cycle detection with limited iteration number. kpeter@814: /// However \ref CycleCanceling also provides the "Minimum Mean kpeter@814: /// Cycle-Canceling" algorithm, which is \e strongly \e polynomial, kpeter@814: /// but rather slower in practice. kpeter@814: /// To use this version of the algorithm, call \ref run() with \c true kpeter@814: /// parameter. kpeter@814: /// kpeter@814: /// \author Peter Kovacs kpeter@814: template < typename Digraph, kpeter@814: typename LowerMap = typename Digraph::template ArcMap, kpeter@814: typename CapacityMap = typename Digraph::template ArcMap, kpeter@814: typename CostMap = typename Digraph::template ArcMap, kpeter@814: typename SupplyMap = typename Digraph::template NodeMap > kpeter@814: class CycleCanceling kpeter@814: { kpeter@814: TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); kpeter@814: kpeter@814: typedef typename CapacityMap::Value Capacity; kpeter@814: typedef typename CostMap::Value Cost; kpeter@814: typedef typename SupplyMap::Value Supply; kpeter@814: typedef typename Digraph::template ArcMap CapacityArcMap; kpeter@814: typedef typename Digraph::template NodeMap SupplyNodeMap; kpeter@814: kpeter@814: typedef ResidualDigraph< const Digraph, kpeter@814: CapacityArcMap, CapacityArcMap > ResDigraph; kpeter@814: typedef typename ResDigraph::Node ResNode; kpeter@814: typedef typename ResDigraph::NodeIt ResNodeIt; kpeter@814: typedef typename ResDigraph::Arc ResArc; kpeter@814: typedef typename ResDigraph::ArcIt ResArcIt; kpeter@814: kpeter@814: public: kpeter@814: kpeter@814: /// The type of the flow map. kpeter@814: typedef typename Digraph::template ArcMap FlowMap; kpeter@814: /// The type of the potential map. kpeter@814: typedef typename Digraph::template NodeMap PotentialMap; kpeter@814: kpeter@814: private: kpeter@814: kpeter@814: /// \brief Map adaptor class for handling residual arc costs. kpeter@814: /// kpeter@814: /// Map adaptor class for handling residual arc costs. kpeter@814: class ResidualCostMap : public MapBase kpeter@814: { kpeter@814: private: kpeter@814: kpeter@814: const CostMap &_cost_map; kpeter@814: kpeter@814: public: kpeter@814: kpeter@814: ///\e kpeter@814: ResidualCostMap(const CostMap &cost_map) : _cost_map(cost_map) {} kpeter@814: kpeter@814: ///\e kpeter@814: Cost operator[](const ResArc &e) const { kpeter@814: return ResDigraph::forward(e) ? _cost_map[e] : -_cost_map[e]; kpeter@814: } kpeter@814: kpeter@814: }; //class ResidualCostMap kpeter@814: kpeter@814: private: kpeter@814: kpeter@814: // The maximum number of iterations for the first execution of the kpeter@814: // Bellman-Ford algorithm. It should be at least 2. kpeter@814: static const int BF_FIRST_LIMIT = 2; kpeter@814: // The iteration limit for the Bellman-Ford algorithm is multiplied kpeter@814: // by BF_LIMIT_FACTOR/100 in every round. kpeter@814: static const int BF_LIMIT_FACTOR = 150; kpeter@814: kpeter@814: private: kpeter@814: kpeter@814: // The digraph the algorithm runs on kpeter@814: const Digraph &_graph; kpeter@814: // The original lower bound map kpeter@814: const LowerMap *_lower; kpeter@814: // The modified capacity map kpeter@814: CapacityArcMap _capacity; kpeter@814: // The original cost map kpeter@814: const CostMap &_cost; kpeter@814: // The modified supply map kpeter@814: SupplyNodeMap _supply; kpeter@814: bool _valid_supply; kpeter@814: kpeter@814: // Arc map of the current flow kpeter@814: FlowMap *_flow; kpeter@814: bool _local_flow; kpeter@814: // Node map of the current potentials kpeter@814: PotentialMap *_potential; kpeter@814: bool _local_potential; kpeter@814: kpeter@814: // The residual digraph kpeter@814: ResDigraph *_res_graph; kpeter@814: // The residual cost map kpeter@814: ResidualCostMap _res_cost; kpeter@814: kpeter@814: public: kpeter@814: kpeter@814: /// \brief General constructor (with lower bounds). kpeter@814: /// kpeter@814: /// General constructor (with lower bounds). kpeter@814: /// kpeter@814: /// \param digraph The digraph the algorithm runs on. kpeter@814: /// \param lower The lower bounds of the arcs. kpeter@814: /// \param capacity The capacities (upper bounds) of the arcs. kpeter@814: /// \param cost The cost (length) values of the arcs. kpeter@814: /// \param supply The supply values of the nodes (signed). kpeter@814: CycleCanceling( const Digraph &digraph, kpeter@814: const LowerMap &lower, kpeter@814: const CapacityMap &capacity, kpeter@814: const CostMap &cost, kpeter@814: const SupplyMap &supply ) : kpeter@814: _graph(digraph), _lower(&lower), _capacity(digraph), _cost(cost), kpeter@814: _supply(digraph), _flow(NULL), _local_flow(false), kpeter@814: _potential(NULL), _local_potential(false), kpeter@814: _res_graph(NULL), _res_cost(_cost) kpeter@814: { kpeter@814: // Check the sum of supply values kpeter@814: Supply sum = 0; kpeter@814: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@814: _supply[n] = supply[n]; kpeter@814: sum += _supply[n]; kpeter@814: } kpeter@814: _valid_supply = sum == 0; kpeter@814: kpeter@814: // Remove non-zero lower bounds kpeter@814: for (ArcIt e(_graph); e != INVALID; ++e) { kpeter@814: _capacity[e] = capacity[e]; kpeter@814: if (lower[e] != 0) { kpeter@814: _capacity[e] -= lower[e]; kpeter@814: _supply[_graph.source(e)] -= lower[e]; kpeter@814: _supply[_graph.target(e)] += lower[e]; kpeter@814: } kpeter@814: } kpeter@814: } kpeter@814: /* kpeter@814: /// \brief General constructor (without lower bounds). kpeter@814: /// kpeter@814: /// General constructor (without lower bounds). kpeter@814: /// kpeter@814: /// \param digraph The digraph the algorithm runs on. kpeter@814: /// \param capacity The capacities (upper bounds) of the arcs. kpeter@814: /// \param cost The cost (length) values of the arcs. kpeter@814: /// \param supply The supply values of the nodes (signed). kpeter@814: CycleCanceling( const Digraph &digraph, kpeter@814: const CapacityMap &capacity, kpeter@814: const CostMap &cost, kpeter@814: const SupplyMap &supply ) : kpeter@814: _graph(digraph), _lower(NULL), _capacity(capacity), _cost(cost), kpeter@814: _supply(supply), _flow(NULL), _local_flow(false), kpeter@814: _potential(NULL), _local_potential(false), _res_graph(NULL), kpeter@814: _res_cost(_cost) kpeter@814: { kpeter@814: // Check the sum of supply values kpeter@814: Supply sum = 0; kpeter@814: for (NodeIt n(_graph); n != INVALID; ++n) sum += _supply[n]; kpeter@814: _valid_supply = sum == 0; kpeter@814: } kpeter@814: kpeter@814: /// \brief Simple constructor (with lower bounds). kpeter@814: /// kpeter@814: /// Simple constructor (with lower bounds). kpeter@814: /// kpeter@814: /// \param digraph The digraph the algorithm runs on. kpeter@814: /// \param lower The lower bounds of the arcs. kpeter@814: /// \param capacity The capacities (upper bounds) of the arcs. kpeter@814: /// \param cost The cost (length) values of the arcs. kpeter@814: /// \param s The source node. kpeter@814: /// \param t The target node. kpeter@814: /// \param flow_value The required amount of flow from node \c s kpeter@814: /// to node \c t (i.e. the supply of \c s and the demand of \c t). kpeter@814: CycleCanceling( const Digraph &digraph, kpeter@814: const LowerMap &lower, kpeter@814: const CapacityMap &capacity, kpeter@814: const CostMap &cost, kpeter@814: Node s, Node t, kpeter@814: Supply flow_value ) : kpeter@814: _graph(digraph), _lower(&lower), _capacity(capacity), _cost(cost), kpeter@814: _supply(digraph, 0), _flow(NULL), _local_flow(false), kpeter@814: _potential(NULL), _local_potential(false), _res_graph(NULL), kpeter@814: _res_cost(_cost) kpeter@814: { kpeter@814: // Remove non-zero lower bounds kpeter@814: _supply[s] = flow_value; kpeter@814: _supply[t] = -flow_value; kpeter@814: for (ArcIt e(_graph); e != INVALID; ++e) { kpeter@814: if (lower[e] != 0) { kpeter@814: _capacity[e] -= lower[e]; kpeter@814: _supply[_graph.source(e)] -= lower[e]; kpeter@814: _supply[_graph.target(e)] += lower[e]; kpeter@814: } kpeter@814: } kpeter@814: _valid_supply = true; kpeter@814: } kpeter@814: kpeter@814: /// \brief Simple constructor (without lower bounds). kpeter@814: /// kpeter@814: /// Simple constructor (without lower bounds). kpeter@814: /// kpeter@814: /// \param digraph The digraph the algorithm runs on. kpeter@814: /// \param capacity The capacities (upper bounds) of the arcs. kpeter@814: /// \param cost The cost (length) values of the arcs. kpeter@814: /// \param s The source node. kpeter@814: /// \param t The target node. kpeter@814: /// \param flow_value The required amount of flow from node \c s kpeter@814: /// to node \c t (i.e. the supply of \c s and the demand of \c t). kpeter@814: CycleCanceling( const Digraph &digraph, kpeter@814: const CapacityMap &capacity, kpeter@814: const CostMap &cost, kpeter@814: Node s, Node t, kpeter@814: Supply flow_value ) : kpeter@814: _graph(digraph), _lower(NULL), _capacity(capacity), _cost(cost), kpeter@814: _supply(digraph, 0), _flow(NULL), _local_flow(false), kpeter@814: _potential(NULL), _local_potential(false), _res_graph(NULL), kpeter@814: _res_cost(_cost) kpeter@814: { kpeter@814: _supply[s] = flow_value; kpeter@814: _supply[t] = -flow_value; kpeter@814: _valid_supply = true; kpeter@814: } kpeter@814: */ kpeter@814: /// Destructor. kpeter@814: ~CycleCanceling() { kpeter@814: if (_local_flow) delete _flow; kpeter@814: if (_local_potential) delete _potential; kpeter@814: delete _res_graph; kpeter@814: } kpeter@814: kpeter@814: /// \brief Set the flow map. kpeter@814: /// kpeter@814: /// Set the flow map. kpeter@814: /// kpeter@814: /// \return \c (*this) kpeter@814: CycleCanceling& flowMap(FlowMap &map) { kpeter@814: if (_local_flow) { kpeter@814: delete _flow; kpeter@814: _local_flow = false; kpeter@814: } kpeter@814: _flow = ↦ kpeter@814: return *this; kpeter@814: } kpeter@814: kpeter@814: /// \brief Set the potential map. kpeter@814: /// kpeter@814: /// Set the potential map. kpeter@814: /// kpeter@814: /// \return \c (*this) kpeter@814: CycleCanceling& potentialMap(PotentialMap &map) { kpeter@814: if (_local_potential) { kpeter@814: delete _potential; kpeter@814: _local_potential = false; kpeter@814: } kpeter@814: _potential = ↦ kpeter@814: return *this; kpeter@814: } kpeter@814: kpeter@814: /// \name Execution control kpeter@814: kpeter@814: /// @{ kpeter@814: kpeter@814: /// \brief Run the algorithm. kpeter@814: /// kpeter@814: /// Run the algorithm. kpeter@814: /// kpeter@814: /// \param min_mean_cc Set this parameter to \c true to run the kpeter@814: /// "Minimum Mean Cycle-Canceling" algorithm, which is strongly kpeter@814: /// polynomial, but rather slower in practice. kpeter@814: /// kpeter@814: /// \return \c true if a feasible flow can be found. kpeter@814: bool run(bool min_mean_cc = false) { kpeter@814: return init() && start(min_mean_cc); kpeter@814: } kpeter@814: kpeter@814: /// @} kpeter@814: kpeter@814: /// \name Query Functions kpeter@814: /// The result of the algorithm can be obtained using these kpeter@814: /// functions.\n kpeter@814: /// \ref lemon::CycleCanceling::run() "run()" must be called before kpeter@814: /// using them. kpeter@814: kpeter@814: /// @{ kpeter@814: kpeter@814: /// \brief Return a const reference to the arc map storing the kpeter@814: /// found flow. kpeter@814: /// kpeter@814: /// Return a const reference to the arc map storing the found flow. kpeter@814: /// kpeter@814: /// \pre \ref run() must be called before using this function. kpeter@814: const FlowMap& flowMap() const { kpeter@814: return *_flow; kpeter@814: } kpeter@814: kpeter@814: /// \brief Return a const reference to the node map storing the kpeter@814: /// found potentials (the dual solution). kpeter@814: /// kpeter@814: /// Return a const reference to the node map storing the found kpeter@814: /// potentials (the dual solution). kpeter@814: /// kpeter@814: /// \pre \ref run() must be called before using this function. kpeter@814: const PotentialMap& potentialMap() const { kpeter@814: return *_potential; kpeter@814: } kpeter@814: kpeter@814: /// \brief Return the flow on the given arc. kpeter@814: /// kpeter@814: /// Return the flow on the given arc. kpeter@814: /// kpeter@814: /// \pre \ref run() must be called before using this function. kpeter@814: Capacity flow(const Arc& arc) const { kpeter@814: return (*_flow)[arc]; kpeter@814: } kpeter@814: kpeter@814: /// \brief Return the potential of the given node. kpeter@814: /// kpeter@814: /// Return the potential of the given node. kpeter@814: /// kpeter@814: /// \pre \ref run() must be called before using this function. kpeter@814: Cost potential(const Node& node) const { kpeter@814: return (*_potential)[node]; kpeter@814: } kpeter@814: kpeter@814: /// \brief Return the total cost of the found flow. kpeter@814: /// kpeter@814: /// Return the total cost of the found flow. The complexity of the kpeter@814: /// function is \f$ O(e) \f$. kpeter@814: /// kpeter@814: /// \pre \ref run() must be called before using this function. kpeter@814: Cost totalCost() const { kpeter@814: Cost c = 0; kpeter@814: for (ArcIt e(_graph); e != INVALID; ++e) kpeter@814: c += (*_flow)[e] * _cost[e]; kpeter@814: return c; kpeter@814: } kpeter@814: kpeter@814: /// @} kpeter@814: kpeter@814: private: kpeter@814: kpeter@814: /// Initialize the algorithm. kpeter@814: bool init() { kpeter@814: if (!_valid_supply) return false; kpeter@814: kpeter@814: // Initializing flow and potential maps kpeter@814: if (!_flow) { kpeter@814: _flow = new FlowMap(_graph); kpeter@814: _local_flow = true; kpeter@814: } kpeter@814: if (!_potential) { kpeter@814: _potential = new PotentialMap(_graph); kpeter@814: _local_potential = true; kpeter@814: } kpeter@814: kpeter@814: _res_graph = new ResDigraph(_graph, _capacity, *_flow); kpeter@814: kpeter@814: // Finding a feasible flow using Circulation kpeter@814: Circulation< Digraph, ConstMap, CapacityArcMap, kpeter@814: SupplyMap > kpeter@814: circulation( _graph, constMap(Capacity(0)), _capacity, kpeter@814: _supply ); kpeter@814: return circulation.flowMap(*_flow).run(); kpeter@814: } kpeter@814: kpeter@814: bool start(bool min_mean_cc) { kpeter@814: if (min_mean_cc) kpeter@814: startMinMean(); kpeter@814: else kpeter@814: start(); kpeter@814: kpeter@814: // Handling non-zero lower bounds kpeter@814: if (_lower) { kpeter@814: for (ArcIt e(_graph); e != INVALID; ++e) kpeter@814: (*_flow)[e] += (*_lower)[e]; kpeter@814: } kpeter@814: return true; kpeter@814: } kpeter@814: kpeter@814: /// \brief Execute the algorithm using \ref BellmanFord. kpeter@814: /// kpeter@814: /// Execute the algorithm using the \ref BellmanFord kpeter@814: /// "Bellman-Ford" algorithm for negative cycle detection with kpeter@814: /// successively larger limit for the number of iterations. kpeter@814: void start() { kpeter@814: typename BellmanFord::PredMap pred(*_res_graph); kpeter@814: typename ResDigraph::template NodeMap visited(*_res_graph); kpeter@814: std::vector cycle; kpeter@814: int node_num = countNodes(_graph); kpeter@814: kpeter@814: int length_bound = BF_FIRST_LIMIT; kpeter@814: bool optimal = false; kpeter@814: while (!optimal) { kpeter@814: BellmanFord bf(*_res_graph, _res_cost); kpeter@814: bf.predMap(pred); kpeter@814: bf.init(0); kpeter@814: int iter_num = 0; kpeter@814: bool cycle_found = false; kpeter@814: while (!cycle_found) { kpeter@814: int curr_iter_num = iter_num + length_bound <= node_num ? kpeter@814: length_bound : node_num - iter_num; kpeter@814: iter_num += curr_iter_num; kpeter@814: int real_iter_num = curr_iter_num; kpeter@814: for (int i = 0; i < curr_iter_num; ++i) { kpeter@814: if (bf.processNextWeakRound()) { kpeter@814: real_iter_num = i; kpeter@814: break; kpeter@814: } kpeter@814: } kpeter@814: if (real_iter_num < curr_iter_num) { kpeter@814: // Optimal flow is found kpeter@814: optimal = true; kpeter@814: // Setting node potentials kpeter@814: for (NodeIt n(_graph); n != INVALID; ++n) kpeter@814: (*_potential)[n] = bf.dist(n); kpeter@814: break; kpeter@814: } else { kpeter@814: // Searching for node disjoint negative cycles kpeter@814: for (ResNodeIt n(*_res_graph); n != INVALID; ++n) kpeter@814: visited[n] = 0; kpeter@814: int id = 0; kpeter@814: for (ResNodeIt n(*_res_graph); n != INVALID; ++n) { kpeter@814: if (visited[n] > 0) continue; kpeter@814: visited[n] = ++id; kpeter@814: ResNode u = pred[n] == INVALID ? kpeter@814: INVALID : _res_graph->source(pred[n]); kpeter@814: while (u != INVALID && visited[u] == 0) { kpeter@814: visited[u] = id; kpeter@814: u = pred[u] == INVALID ? kpeter@814: INVALID : _res_graph->source(pred[u]); kpeter@814: } kpeter@814: if (u != INVALID && visited[u] == id) { kpeter@814: // Finding the negative cycle kpeter@814: cycle_found = true; kpeter@814: cycle.clear(); kpeter@814: ResArc e = pred[u]; kpeter@814: cycle.push_back(e); kpeter@814: Capacity d = _res_graph->residualCapacity(e); kpeter@814: while (_res_graph->source(e) != u) { kpeter@814: cycle.push_back(e = pred[_res_graph->source(e)]); kpeter@814: if (_res_graph->residualCapacity(e) < d) kpeter@814: d = _res_graph->residualCapacity(e); kpeter@814: } kpeter@814: kpeter@814: // Augmenting along the cycle kpeter@814: for (int i = 0; i < int(cycle.size()); ++i) kpeter@814: _res_graph->augment(cycle[i], d); kpeter@814: } kpeter@814: } kpeter@814: } kpeter@814: kpeter@814: if (!cycle_found) kpeter@814: length_bound = length_bound * BF_LIMIT_FACTOR / 100; kpeter@814: } kpeter@814: } kpeter@814: } kpeter@814: kpeter@814: /// \brief Execute the algorithm using \ref Howard. kpeter@814: /// kpeter@814: /// Execute the algorithm using \ref Howard for negative kpeter@814: /// cycle detection. kpeter@814: void startMinMean() { kpeter@814: typedef Path ResPath; kpeter@814: Howard mmc(*_res_graph, _res_cost); kpeter@814: ResPath cycle; kpeter@814: kpeter@814: mmc.cycle(cycle); kpeter@814: if (mmc.findMinMean()) { kpeter@814: while (mmc.cycleLength() < 0) { kpeter@814: // Finding the cycle kpeter@814: mmc.findCycle(); kpeter@814: kpeter@814: // Finding the largest flow amount that can be augmented kpeter@814: // along the cycle kpeter@814: Capacity delta = 0; kpeter@814: for (typename ResPath::ArcIt e(cycle); e != INVALID; ++e) { kpeter@814: if (delta == 0 || _res_graph->residualCapacity(e) < delta) kpeter@814: delta = _res_graph->residualCapacity(e); kpeter@814: } kpeter@814: kpeter@814: // Augmenting along the cycle kpeter@814: for (typename ResPath::ArcIt e(cycle); e != INVALID; ++e) kpeter@814: _res_graph->augment(e, delta); kpeter@814: kpeter@814: // Finding the minimum cycle mean for the modified residual kpeter@814: // digraph kpeter@814: if (!mmc.findMinMean()) break; kpeter@814: } kpeter@814: } kpeter@814: kpeter@814: // Computing node potentials kpeter@814: BellmanFord bf(*_res_graph, _res_cost); kpeter@814: bf.init(0); bf.start(); kpeter@814: for (NodeIt n(_graph); n != INVALID; ++n) kpeter@814: (*_potential)[n] = bf.dist(n); kpeter@814: } kpeter@814: kpeter@814: }; //class CycleCanceling kpeter@814: kpeter@814: ///@} kpeter@814: kpeter@814: } //namespace lemon kpeter@814: kpeter@814: #endif //LEMON_CYCLE_CANCELING_H