kpeter@805: /* -*- C++ -*- kpeter@805: * kpeter@805: * This file is a part of LEMON, a generic C++ optimization library kpeter@805: * kpeter@805: * Copyright (C) 2003-2008 kpeter@805: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@805: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@805: * kpeter@805: * Permission to use, modify and distribute this software is granted kpeter@805: * provided that this copyright notice appears in all copies. For kpeter@805: * precise terms see the accompanying LICENSE file. kpeter@805: * kpeter@805: * This software is provided "AS IS" with no warranty of any kind, kpeter@805: * express or implied, and with no claim as to its suitability for any kpeter@805: * purpose. kpeter@805: * kpeter@805: */ kpeter@805: kpeter@805: #ifndef LEMON_CAPACITY_SCALING_H kpeter@805: #define LEMON_CAPACITY_SCALING_H kpeter@805: kpeter@806: /// \ingroup min_cost_flow_algs kpeter@805: /// kpeter@805: /// \file kpeter@806: /// \brief Capacity Scaling algorithm for finding a minimum cost flow. kpeter@805: kpeter@805: #include kpeter@806: #include kpeter@806: #include kpeter@805: #include kpeter@805: kpeter@805: namespace lemon { kpeter@805: kpeter@807: /// \brief Default traits class of CapacityScaling algorithm. kpeter@807: /// kpeter@807: /// Default traits class of CapacityScaling algorithm. kpeter@807: /// \tparam GR Digraph type. kpeter@812: /// \tparam V The number type used for flow amounts, capacity bounds kpeter@807: /// and supply values. By default it is \c int. kpeter@812: /// \tparam C The number type used for costs and potentials. kpeter@807: /// By default it is the same as \c V. kpeter@807: template kpeter@807: struct CapacityScalingDefaultTraits kpeter@807: { kpeter@807: /// The type of the digraph kpeter@807: typedef GR Digraph; kpeter@807: /// The type of the flow amounts, capacity bounds and supply values kpeter@807: typedef V Value; kpeter@807: /// The type of the arc costs kpeter@807: typedef C Cost; kpeter@807: kpeter@807: /// \brief The type of the heap used for internal Dijkstra computations. kpeter@807: /// kpeter@807: /// The type of the heap used for internal Dijkstra computations. kpeter@807: /// It must conform to the \ref lemon::concepts::Heap "Heap" concept, kpeter@807: /// its priority type must be \c Cost and its cross reference type kpeter@807: /// must be \ref RangeMap "RangeMap". kpeter@807: typedef BinHeap > Heap; kpeter@807: }; kpeter@807: kpeter@806: /// \addtogroup min_cost_flow_algs kpeter@805: /// @{ kpeter@805: kpeter@806: /// \brief Implementation of the Capacity Scaling algorithm for kpeter@806: /// finding a \ref min_cost_flow "minimum cost flow". kpeter@805: /// kpeter@805: /// \ref CapacityScaling implements the capacity scaling version kpeter@806: /// of the successive shortest path algorithm for finding a kpeter@813: /// \ref min_cost_flow "minimum cost flow" \ref amo93networkflows, kpeter@813: /// \ref edmondskarp72theoretical. It is an efficient dual kpeter@806: /// solution method. kpeter@805: /// kpeter@806: /// Most of the parameters of the problem (except for the digraph) kpeter@806: /// can be given using separate functions, and the algorithm can be kpeter@806: /// executed using the \ref run() function. If some parameters are not kpeter@806: /// specified, then default values will be used. kpeter@805: /// kpeter@806: /// \tparam GR The digraph type the algorithm runs on. kpeter@812: /// \tparam V The number type used for flow amounts, capacity bounds kpeter@825: /// and supply values in the algorithm. By default, it is \c int. kpeter@812: /// \tparam C The number type used for costs and potentials in the kpeter@825: /// algorithm. By default, it is the same as \c V. kpeter@825: /// \tparam TR The traits class that defines various types used by the kpeter@825: /// algorithm. By default, it is \ref CapacityScalingDefaultTraits kpeter@825: /// "CapacityScalingDefaultTraits". kpeter@825: /// In most cases, this parameter should not be set directly, kpeter@825: /// consider to use the named template parameters instead. kpeter@805: /// kpeter@812: /// \warning Both number types must be signed and all input data must kpeter@806: /// be integer. kpeter@806: /// \warning This algorithm does not support negative costs for such kpeter@806: /// arcs that have infinite upper bound. kpeter@807: #ifdef DOXYGEN kpeter@807: template kpeter@807: #else kpeter@807: template < typename GR, typename V = int, typename C = V, kpeter@807: typename TR = CapacityScalingDefaultTraits > kpeter@807: #endif kpeter@805: class CapacityScaling kpeter@805: { kpeter@806: public: kpeter@805: kpeter@807: /// The type of the digraph kpeter@807: typedef typename TR::Digraph Digraph; kpeter@806: /// The type of the flow amounts, capacity bounds and supply values kpeter@807: typedef typename TR::Value Value; kpeter@806: /// The type of the arc costs kpeter@807: typedef typename TR::Cost Cost; kpeter@807: kpeter@807: /// The type of the heap used for internal Dijkstra computations kpeter@807: typedef typename TR::Heap Heap; kpeter@807: kpeter@807: /// The \ref CapacityScalingDefaultTraits "traits class" of the algorithm kpeter@807: typedef TR Traits; kpeter@805: kpeter@805: public: kpeter@805: kpeter@806: /// \brief Problem type constants for the \c run() function. kpeter@806: /// kpeter@806: /// Enum type containing the problem type constants that can be kpeter@806: /// returned by the \ref run() function of the algorithm. kpeter@806: enum ProblemType { kpeter@806: /// The problem has no feasible solution (flow). kpeter@806: INFEASIBLE, kpeter@806: /// The problem has optimal solution (i.e. it is feasible and kpeter@806: /// bounded), and the algorithm has found optimal flow and node kpeter@806: /// potentials (primal and dual solutions). kpeter@806: OPTIMAL, kpeter@806: /// The digraph contains an arc of negative cost and infinite kpeter@806: /// upper bound. It means that the objective function is unbounded kpeter@812: /// on that arc, however, note that it could actually be bounded kpeter@806: /// over the feasible flows, but this algroithm cannot handle kpeter@806: /// these cases. kpeter@806: UNBOUNDED kpeter@806: }; kpeter@806: kpeter@806: private: kpeter@806: kpeter@806: TEMPLATE_DIGRAPH_TYPEDEFS(GR); kpeter@806: kpeter@806: typedef std::vector IntVector; kpeter@811: typedef std::vector BoolVector; kpeter@806: typedef std::vector ValueVector; kpeter@806: typedef std::vector CostVector; kpeter@805: kpeter@805: private: kpeter@805: kpeter@806: // Data related to the underlying digraph kpeter@806: const GR &_graph; kpeter@806: int _node_num; kpeter@806: int _arc_num; kpeter@806: int _res_arc_num; kpeter@806: int _root; kpeter@806: kpeter@806: // Parameters of the problem kpeter@806: bool _have_lower; kpeter@806: Value _sum_supply; kpeter@806: kpeter@806: // Data structures for storing the digraph kpeter@806: IntNodeMap _node_id; kpeter@806: IntArcMap _arc_idf; kpeter@806: IntArcMap _arc_idb; kpeter@806: IntVector _first_out; kpeter@806: BoolVector _forward; kpeter@806: IntVector _source; kpeter@806: IntVector _target; kpeter@806: IntVector _reverse; kpeter@806: kpeter@806: // Node and arc data kpeter@806: ValueVector _lower; kpeter@806: ValueVector _upper; kpeter@806: CostVector _cost; kpeter@806: ValueVector _supply; kpeter@806: kpeter@806: ValueVector _res_cap; kpeter@806: CostVector _pi; kpeter@806: ValueVector _excess; kpeter@806: IntVector _excess_nodes; kpeter@806: IntVector _deficit_nodes; kpeter@806: kpeter@806: Value _delta; kpeter@810: int _factor; kpeter@806: IntVector _pred; kpeter@806: kpeter@806: public: kpeter@806: kpeter@806: /// \brief Constant for infinite upper bounds (capacities). kpeter@805: /// kpeter@806: /// Constant for infinite upper bounds (capacities). kpeter@806: /// It is \c std::numeric_limits::infinity() if available, kpeter@806: /// \c std::numeric_limits::max() otherwise. kpeter@806: const Value INF; kpeter@806: kpeter@806: private: kpeter@806: kpeter@806: // Special implementation of the Dijkstra algorithm for finding kpeter@806: // shortest paths in the residual network of the digraph with kpeter@806: // respect to the reduced arc costs and modifying the node kpeter@806: // potentials according to the found distance labels. kpeter@805: class ResidualDijkstra kpeter@805: { kpeter@805: private: kpeter@805: kpeter@806: int _node_num; kpeter@811: bool _geq; kpeter@806: const IntVector &_first_out; kpeter@806: const IntVector &_target; kpeter@806: const CostVector &_cost; kpeter@806: const ValueVector &_res_cap; kpeter@806: const ValueVector &_excess; kpeter@806: CostVector &_pi; kpeter@806: IntVector &_pred; kpeter@806: kpeter@806: IntVector _proc_nodes; kpeter@806: CostVector _dist; kpeter@806: kpeter@805: public: kpeter@805: kpeter@806: ResidualDijkstra(CapacityScaling& cs) : kpeter@811: _node_num(cs._node_num), _geq(cs._sum_supply < 0), kpeter@811: _first_out(cs._first_out), _target(cs._target), _cost(cs._cost), kpeter@811: _res_cap(cs._res_cap), _excess(cs._excess), _pi(cs._pi), kpeter@811: _pred(cs._pred), _dist(cs._node_num) kpeter@805: {} kpeter@805: kpeter@806: int run(int s, Value delta = 1) { kpeter@807: RangeMap heap_cross_ref(_node_num, Heap::PRE_HEAP); kpeter@805: Heap heap(heap_cross_ref); kpeter@805: heap.push(s, 0); kpeter@806: _pred[s] = -1; kpeter@805: _proc_nodes.clear(); kpeter@805: kpeter@806: // Process nodes kpeter@805: while (!heap.empty() && _excess[heap.top()] > -delta) { kpeter@806: int u = heap.top(), v; kpeter@806: Cost d = heap.prio() + _pi[u], dn; kpeter@805: _dist[u] = heap.prio(); kpeter@806: _proc_nodes.push_back(u); kpeter@805: heap.pop(); kpeter@805: kpeter@806: // Traverse outgoing residual arcs kpeter@811: int last_out = _geq ? _first_out[u+1] : _first_out[u+1] - 1; kpeter@811: for (int a = _first_out[u]; a != last_out; ++a) { kpeter@806: if (_res_cap[a] < delta) continue; kpeter@806: v = _target[a]; kpeter@806: switch (heap.state(v)) { kpeter@805: case Heap::PRE_HEAP: kpeter@806: heap.push(v, d + _cost[a] - _pi[v]); kpeter@806: _pred[v] = a; kpeter@805: break; kpeter@805: case Heap::IN_HEAP: kpeter@806: dn = d + _cost[a] - _pi[v]; kpeter@806: if (dn < heap[v]) { kpeter@806: heap.decrease(v, dn); kpeter@806: _pred[v] = a; kpeter@805: } kpeter@805: break; kpeter@805: case Heap::POST_HEAP: kpeter@805: break; kpeter@805: } kpeter@805: } kpeter@805: } kpeter@806: if (heap.empty()) return -1; kpeter@805: kpeter@806: // Update potentials of processed nodes kpeter@806: int t = heap.top(); kpeter@806: Cost dt = heap.prio(); kpeter@806: for (int i = 0; i < int(_proc_nodes.size()); ++i) { kpeter@806: _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - dt; kpeter@806: } kpeter@805: kpeter@805: return t; kpeter@805: } kpeter@805: kpeter@805: }; //class ResidualDijkstra kpeter@805: kpeter@805: public: kpeter@805: kpeter@807: /// \name Named Template Parameters kpeter@807: /// @{ kpeter@807: kpeter@807: template kpeter@807: struct SetHeapTraits : public Traits { kpeter@807: typedef T Heap; kpeter@807: }; kpeter@807: kpeter@807: /// \brief \ref named-templ-param "Named parameter" for setting kpeter@807: /// \c Heap type. kpeter@807: /// kpeter@807: /// \ref named-templ-param "Named parameter" for setting \c Heap kpeter@807: /// type, which is used for internal Dijkstra computations. kpeter@807: /// It must conform to the \ref lemon::concepts::Heap "Heap" concept, kpeter@807: /// its priority type must be \c Cost and its cross reference type kpeter@807: /// must be \ref RangeMap "RangeMap". kpeter@807: template kpeter@807: struct SetHeap kpeter@807: : public CapacityScaling > { kpeter@807: typedef CapacityScaling > Create; kpeter@807: }; kpeter@807: kpeter@807: /// @} kpeter@807: kpeter@807: public: kpeter@807: kpeter@806: /// \brief Constructor. kpeter@805: /// kpeter@806: /// The constructor of the class. kpeter@805: /// kpeter@806: /// \param graph The digraph the algorithm runs on. kpeter@806: CapacityScaling(const GR& graph) : kpeter@806: _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph), kpeter@806: INF(std::numeric_limits::has_infinity ? kpeter@806: std::numeric_limits::infinity() : kpeter@806: std::numeric_limits::max()) kpeter@805: { kpeter@812: // Check the number types kpeter@806: LEMON_ASSERT(std::numeric_limits::is_signed, kpeter@806: "The flow type of CapacityScaling must be signed"); kpeter@806: LEMON_ASSERT(std::numeric_limits::is_signed, kpeter@806: "The cost type of CapacityScaling must be signed"); kpeter@806: kpeter@806: // Resize vectors kpeter@806: _node_num = countNodes(_graph); kpeter@806: _arc_num = countArcs(_graph); kpeter@806: _res_arc_num = 2 * (_arc_num + _node_num); kpeter@806: _root = _node_num; kpeter@806: ++_node_num; kpeter@806: kpeter@806: _first_out.resize(_node_num + 1); kpeter@806: _forward.resize(_res_arc_num); kpeter@806: _source.resize(_res_arc_num); kpeter@806: _target.resize(_res_arc_num); kpeter@806: _reverse.resize(_res_arc_num); kpeter@806: kpeter@806: _lower.resize(_res_arc_num); kpeter@806: _upper.resize(_res_arc_num); kpeter@806: _cost.resize(_res_arc_num); kpeter@806: _supply.resize(_node_num); kpeter@806: kpeter@806: _res_cap.resize(_res_arc_num); kpeter@806: _pi.resize(_node_num); kpeter@806: _excess.resize(_node_num); kpeter@806: _pred.resize(_node_num); kpeter@806: kpeter@806: // Copy the graph kpeter@806: int i = 0, j = 0, k = 2 * _arc_num + _node_num - 1; kpeter@806: for (NodeIt n(_graph); n != INVALID; ++n, ++i) { kpeter@806: _node_id[n] = i; kpeter@805: } kpeter@806: i = 0; kpeter@806: for (NodeIt n(_graph); n != INVALID; ++n, ++i) { kpeter@806: _first_out[i] = j; kpeter@806: for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) { kpeter@806: _arc_idf[a] = j; kpeter@806: _forward[j] = true; kpeter@806: _source[j] = i; kpeter@806: _target[j] = _node_id[_graph.runningNode(a)]; kpeter@806: } kpeter@806: for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) { kpeter@806: _arc_idb[a] = j; kpeter@806: _forward[j] = false; kpeter@806: _source[j] = i; kpeter@806: _target[j] = _node_id[_graph.runningNode(a)]; kpeter@806: } kpeter@806: _forward[j] = false; kpeter@806: _source[j] = i; kpeter@806: _target[j] = _root; kpeter@806: _reverse[j] = k; kpeter@806: _forward[k] = true; kpeter@806: _source[k] = _root; kpeter@806: _target[k] = i; kpeter@806: _reverse[k] = j; kpeter@806: ++j; ++k; kpeter@806: } kpeter@806: _first_out[i] = j; kpeter@806: _first_out[_node_num] = k; kpeter@805: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@806: int fi = _arc_idf[a]; kpeter@806: int bi = _arc_idb[a]; kpeter@806: _reverse[fi] = bi; kpeter@806: _reverse[bi] = fi; kpeter@805: } kpeter@806: kpeter@806: // Reset parameters kpeter@806: reset(); kpeter@805: } kpeter@805: kpeter@806: /// \name Parameters kpeter@806: /// The parameters of the algorithm can be specified using these kpeter@806: /// functions. kpeter@806: kpeter@806: /// @{ kpeter@806: kpeter@806: /// \brief Set the lower bounds on the arcs. kpeter@805: /// kpeter@806: /// This function sets the lower bounds on the arcs. kpeter@806: /// If it is not used before calling \ref run(), the lower bounds kpeter@806: /// will be set to zero on all arcs. kpeter@805: /// kpeter@806: /// \param map An arc map storing the lower bounds. kpeter@806: /// Its \c Value type must be convertible to the \c Value type kpeter@806: /// of the algorithm. kpeter@806: /// kpeter@806: /// \return (*this) kpeter@806: template kpeter@806: CapacityScaling& lowerMap(const LowerMap& map) { kpeter@806: _have_lower = true; kpeter@806: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@806: _lower[_arc_idf[a]] = map[a]; kpeter@806: _lower[_arc_idb[a]] = map[a]; kpeter@805: } kpeter@805: return *this; kpeter@805: } kpeter@805: kpeter@806: /// \brief Set the upper bounds (capacities) on the arcs. kpeter@805: /// kpeter@806: /// This function sets the upper bounds (capacities) on the arcs. kpeter@806: /// If it is not used before calling \ref run(), the upper bounds kpeter@806: /// will be set to \ref INF on all arcs (i.e. the flow value will be kpeter@812: /// unbounded from above). kpeter@805: /// kpeter@806: /// \param map An arc map storing the upper bounds. kpeter@806: /// Its \c Value type must be convertible to the \c Value type kpeter@806: /// of the algorithm. kpeter@806: /// kpeter@806: /// \return (*this) kpeter@806: template kpeter@806: CapacityScaling& upperMap(const UpperMap& map) { kpeter@806: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@806: _upper[_arc_idf[a]] = map[a]; kpeter@805: } kpeter@805: return *this; kpeter@805: } kpeter@805: kpeter@806: /// \brief Set the costs of the arcs. kpeter@806: /// kpeter@806: /// This function sets the costs of the arcs. kpeter@806: /// If it is not used before calling \ref run(), the costs kpeter@806: /// will be set to \c 1 on all arcs. kpeter@806: /// kpeter@806: /// \param map An arc map storing the costs. kpeter@806: /// Its \c Value type must be convertible to the \c Cost type kpeter@806: /// of the algorithm. kpeter@806: /// kpeter@806: /// \return (*this) kpeter@806: template kpeter@806: CapacityScaling& costMap(const CostMap& map) { kpeter@806: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@806: _cost[_arc_idf[a]] = map[a]; kpeter@806: _cost[_arc_idb[a]] = -map[a]; kpeter@806: } kpeter@806: return *this; kpeter@806: } kpeter@806: kpeter@806: /// \brief Set the supply values of the nodes. kpeter@806: /// kpeter@806: /// This function sets the supply values of the nodes. kpeter@806: /// If neither this function nor \ref stSupply() is used before kpeter@806: /// calling \ref run(), the supply of each node will be set to zero. kpeter@806: /// kpeter@806: /// \param map A node map storing the supply values. kpeter@806: /// Its \c Value type must be convertible to the \c Value type kpeter@806: /// of the algorithm. kpeter@806: /// kpeter@806: /// \return (*this) kpeter@806: template kpeter@806: CapacityScaling& supplyMap(const SupplyMap& map) { kpeter@806: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@806: _supply[_node_id[n]] = map[n]; kpeter@806: } kpeter@806: return *this; kpeter@806: } kpeter@806: kpeter@806: /// \brief Set single source and target nodes and a supply value. kpeter@806: /// kpeter@806: /// This function sets a single source node and a single target node kpeter@806: /// and the required flow value. kpeter@806: /// If neither this function nor \ref supplyMap() is used before kpeter@806: /// calling \ref run(), the supply of each node will be set to zero. kpeter@806: /// kpeter@806: /// Using this function has the same effect as using \ref supplyMap() kpeter@806: /// with such a map in which \c k is assigned to \c s, \c -k is kpeter@806: /// assigned to \c t and all other nodes have zero supply value. kpeter@806: /// kpeter@806: /// \param s The source node. kpeter@806: /// \param t The target node. kpeter@806: /// \param k The required amount of flow from node \c s to node \c t kpeter@806: /// (i.e. the supply of \c s and the demand of \c t). kpeter@806: /// kpeter@806: /// \return (*this) kpeter@806: CapacityScaling& stSupply(const Node& s, const Node& t, Value k) { kpeter@806: for (int i = 0; i != _node_num; ++i) { kpeter@806: _supply[i] = 0; kpeter@806: } kpeter@806: _supply[_node_id[s]] = k; kpeter@806: _supply[_node_id[t]] = -k; kpeter@806: return *this; kpeter@806: } kpeter@806: kpeter@806: /// @} kpeter@806: kpeter@805: /// \name Execution control kpeter@807: /// The algorithm can be executed using \ref run(). kpeter@805: kpeter@805: /// @{ kpeter@805: kpeter@805: /// \brief Run the algorithm. kpeter@805: /// kpeter@805: /// This function runs the algorithm. kpeter@806: /// The paramters can be specified using functions \ref lowerMap(), kpeter@806: /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(). kpeter@806: /// For example, kpeter@806: /// \code kpeter@806: /// CapacityScaling cs(graph); kpeter@806: /// cs.lowerMap(lower).upperMap(upper).costMap(cost) kpeter@806: /// .supplyMap(sup).run(); kpeter@806: /// \endcode kpeter@806: /// kpeter@806: /// This function can be called more than once. All the parameters kpeter@806: /// that have been given are kept for the next call, unless kpeter@806: /// \ref reset() is called, thus only the modified parameters kpeter@806: /// have to be set again. See \ref reset() for examples. kpeter@812: /// However, the underlying digraph must not be modified after this kpeter@810: /// class have been constructed, since it copies and extends the graph. kpeter@805: /// kpeter@810: /// \param factor The capacity scaling factor. It must be larger than kpeter@810: /// one to use scaling. If it is less or equal to one, then scaling kpeter@810: /// will be disabled. kpeter@805: /// kpeter@806: /// \return \c INFEASIBLE if no feasible flow exists, kpeter@806: /// \n \c OPTIMAL if the problem has optimal solution kpeter@806: /// (i.e. it is feasible and bounded), and the algorithm has found kpeter@806: /// optimal flow and node potentials (primal and dual solutions), kpeter@806: /// \n \c UNBOUNDED if the digraph contains an arc of negative cost kpeter@806: /// and infinite upper bound. It means that the objective function kpeter@812: /// is unbounded on that arc, however, note that it could actually be kpeter@806: /// bounded over the feasible flows, but this algroithm cannot handle kpeter@806: /// these cases. kpeter@806: /// kpeter@806: /// \see ProblemType kpeter@810: ProblemType run(int factor = 4) { kpeter@810: _factor = factor; kpeter@810: ProblemType pt = init(); kpeter@806: if (pt != OPTIMAL) return pt; kpeter@806: return start(); kpeter@806: } kpeter@806: kpeter@806: /// \brief Reset all the parameters that have been given before. kpeter@806: /// kpeter@806: /// This function resets all the paramaters that have been given kpeter@806: /// before using functions \ref lowerMap(), \ref upperMap(), kpeter@806: /// \ref costMap(), \ref supplyMap(), \ref stSupply(). kpeter@806: /// kpeter@806: /// It is useful for multiple run() calls. If this function is not kpeter@806: /// used, all the parameters given before are kept for the next kpeter@806: /// \ref run() call. kpeter@810: /// However, the underlying digraph must not be modified after this kpeter@806: /// class have been constructed, since it copies and extends the graph. kpeter@806: /// kpeter@806: /// For example, kpeter@806: /// \code kpeter@806: /// CapacityScaling cs(graph); kpeter@806: /// kpeter@806: /// // First run kpeter@806: /// cs.lowerMap(lower).upperMap(upper).costMap(cost) kpeter@806: /// .supplyMap(sup).run(); kpeter@806: /// kpeter@806: /// // Run again with modified cost map (reset() is not called, kpeter@806: /// // so only the cost map have to be set again) kpeter@806: /// cost[e] += 100; kpeter@806: /// cs.costMap(cost).run(); kpeter@806: /// kpeter@806: /// // Run again from scratch using reset() kpeter@806: /// // (the lower bounds will be set to zero on all arcs) kpeter@806: /// cs.reset(); kpeter@806: /// cs.upperMap(capacity).costMap(cost) kpeter@806: /// .supplyMap(sup).run(); kpeter@806: /// \endcode kpeter@806: /// kpeter@806: /// \return (*this) kpeter@806: CapacityScaling& reset() { kpeter@806: for (int i = 0; i != _node_num; ++i) { kpeter@806: _supply[i] = 0; kpeter@806: } kpeter@806: for (int j = 0; j != _res_arc_num; ++j) { kpeter@806: _lower[j] = 0; kpeter@806: _upper[j] = INF; kpeter@806: _cost[j] = _forward[j] ? 1 : -1; kpeter@806: } kpeter@806: _have_lower = false; kpeter@806: return *this; kpeter@805: } kpeter@805: kpeter@805: /// @} kpeter@805: kpeter@805: /// \name Query Functions kpeter@805: /// The results of the algorithm can be obtained using these kpeter@805: /// functions.\n kpeter@806: /// The \ref run() function must be called before using them. kpeter@805: kpeter@805: /// @{ kpeter@805: kpeter@806: /// \brief Return the total cost of the found flow. kpeter@805: /// kpeter@806: /// This function returns the total cost of the found flow. kpeter@806: /// Its complexity is O(e). kpeter@806: /// kpeter@806: /// \note The return type of the function can be specified as a kpeter@806: /// template parameter. For example, kpeter@806: /// \code kpeter@806: /// cs.totalCost(); kpeter@806: /// \endcode kpeter@806: /// It is useful if the total cost cannot be stored in the \c Cost kpeter@806: /// type of the algorithm, which is the default return type of the kpeter@806: /// function. kpeter@805: /// kpeter@805: /// \pre \ref run() must be called before using this function. kpeter@806: template kpeter@806: Number totalCost() const { kpeter@806: Number c = 0; kpeter@806: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@806: int i = _arc_idb[a]; kpeter@806: c += static_cast(_res_cap[i]) * kpeter@806: (-static_cast(_cost[i])); kpeter@806: } kpeter@806: return c; kpeter@805: } kpeter@805: kpeter@806: #ifndef DOXYGEN kpeter@806: Cost totalCost() const { kpeter@806: return totalCost(); kpeter@805: } kpeter@806: #endif kpeter@805: kpeter@805: /// \brief Return the flow on the given arc. kpeter@805: /// kpeter@806: /// This function returns the flow on the given arc. kpeter@805: /// kpeter@805: /// \pre \ref run() must be called before using this function. kpeter@806: Value flow(const Arc& a) const { kpeter@806: return _res_cap[_arc_idb[a]]; kpeter@805: } kpeter@805: kpeter@806: /// \brief Return the flow map (the primal solution). kpeter@805: /// kpeter@806: /// This function copies the flow value on each arc into the given kpeter@806: /// map. The \c Value type of the algorithm must be convertible to kpeter@806: /// the \c Value type of the map. kpeter@805: /// kpeter@805: /// \pre \ref run() must be called before using this function. kpeter@806: template kpeter@806: void flowMap(FlowMap &map) const { kpeter@806: for (ArcIt a(_graph); a != INVALID; ++a) { kpeter@806: map.set(a, _res_cap[_arc_idb[a]]); kpeter@806: } kpeter@805: } kpeter@805: kpeter@806: /// \brief Return the potential (dual value) of the given node. kpeter@805: /// kpeter@806: /// This function returns the potential (dual value) of the kpeter@806: /// given node. kpeter@805: /// kpeter@805: /// \pre \ref run() must be called before using this function. kpeter@806: Cost potential(const Node& n) const { kpeter@806: return _pi[_node_id[n]]; kpeter@806: } kpeter@806: kpeter@806: /// \brief Return the potential map (the dual solution). kpeter@806: /// kpeter@806: /// This function copies the potential (dual value) of each node kpeter@806: /// into the given map. kpeter@806: /// The \c Cost type of the algorithm must be convertible to the kpeter@806: /// \c Value type of the map. kpeter@806: /// kpeter@806: /// \pre \ref run() must be called before using this function. kpeter@806: template kpeter@806: void potentialMap(PotentialMap &map) const { kpeter@806: for (NodeIt n(_graph); n != INVALID; ++n) { kpeter@806: map.set(n, _pi[_node_id[n]]); kpeter@806: } kpeter@805: } kpeter@805: kpeter@805: /// @} kpeter@805: kpeter@805: private: kpeter@805: kpeter@806: // Initialize the algorithm kpeter@810: ProblemType init() { kpeter@821: if (_node_num <= 1) return INFEASIBLE; kpeter@805: kpeter@806: // Check the sum of supply values kpeter@806: _sum_supply = 0; kpeter@806: for (int i = 0; i != _root; ++i) { kpeter@806: _sum_supply += _supply[i]; kpeter@805: } kpeter@806: if (_sum_supply > 0) return INFEASIBLE; kpeter@806: kpeter@811: // Initialize vectors kpeter@806: for (int i = 0; i != _root; ++i) { kpeter@806: _pi[i] = 0; kpeter@806: _excess[i] = _supply[i]; kpeter@805: } kpeter@805: kpeter@806: // Remove non-zero lower bounds kpeter@811: const Value MAX = std::numeric_limits::max(); kpeter@811: int last_out; kpeter@806: if (_have_lower) { kpeter@806: for (int i = 0; i != _root; ++i) { kpeter@811: last_out = _first_out[i+1]; kpeter@811: for (int j = _first_out[i]; j != last_out; ++j) { kpeter@806: if (_forward[j]) { kpeter@806: Value c = _lower[j]; kpeter@806: if (c >= 0) { kpeter@811: _res_cap[j] = _upper[j] < MAX ? _upper[j] - c : INF; kpeter@806: } else { kpeter@811: _res_cap[j] = _upper[j] < MAX + c ? _upper[j] - c : INF; kpeter@806: } kpeter@806: _excess[i] -= c; kpeter@806: _excess[_target[j]] += c; kpeter@806: } else { kpeter@806: _res_cap[j] = 0; kpeter@806: } kpeter@806: } kpeter@806: } kpeter@806: } else { kpeter@806: for (int j = 0; j != _res_arc_num; ++j) { kpeter@806: _res_cap[j] = _forward[j] ? _upper[j] : 0; kpeter@806: } kpeter@806: } kpeter@805: kpeter@806: // Handle negative costs kpeter@811: for (int i = 0; i != _root; ++i) { kpeter@811: last_out = _first_out[i+1] - 1; kpeter@811: for (int j = _first_out[i]; j != last_out; ++j) { kpeter@811: Value rc = _res_cap[j]; kpeter@811: if (_cost[j] < 0 && rc > 0) { kpeter@811: if (rc >= MAX) return UNBOUNDED; kpeter@811: _excess[i] -= rc; kpeter@811: _excess[_target[j]] += rc; kpeter@811: _res_cap[j] = 0; kpeter@811: _res_cap[_reverse[j]] += rc; kpeter@806: } kpeter@806: } kpeter@806: } kpeter@806: kpeter@806: // Handle GEQ supply type kpeter@806: if (_sum_supply < 0) { kpeter@806: _pi[_root] = 0; kpeter@806: _excess[_root] = -_sum_supply; kpeter@806: for (int a = _first_out[_root]; a != _res_arc_num; ++a) { kpeter@811: int ra = _reverse[a]; kpeter@811: _res_cap[a] = -_sum_supply + 1; kpeter@811: _res_cap[ra] = 0; kpeter@806: _cost[a] = 0; kpeter@811: _cost[ra] = 0; kpeter@806: } kpeter@806: } else { kpeter@806: _pi[_root] = 0; kpeter@806: _excess[_root] = 0; kpeter@806: for (int a = _first_out[_root]; a != _res_arc_num; ++a) { kpeter@811: int ra = _reverse[a]; kpeter@806: _res_cap[a] = 1; kpeter@811: _res_cap[ra] = 0; kpeter@806: _cost[a] = 0; kpeter@811: _cost[ra] = 0; kpeter@806: } kpeter@806: } kpeter@806: kpeter@806: // Initialize delta value kpeter@810: if (_factor > 1) { kpeter@805: // With scaling kpeter@806: Value max_sup = 0, max_dem = 0; kpeter@806: for (int i = 0; i != _node_num; ++i) { kpeter@811: Value ex = _excess[i]; kpeter@811: if ( ex > max_sup) max_sup = ex; kpeter@811: if (-ex > max_dem) max_dem = -ex; kpeter@805: } kpeter@806: Value max_cap = 0; kpeter@806: for (int j = 0; j != _res_arc_num; ++j) { kpeter@806: if (_res_cap[j] > max_cap) max_cap = _res_cap[j]; kpeter@805: } kpeter@805: max_sup = std::min(std::min(max_sup, max_dem), max_cap); kpeter@810: for (_delta = 1; 2 * _delta <= max_sup; _delta *= 2) ; kpeter@805: } else { kpeter@805: // Without scaling kpeter@805: _delta = 1; kpeter@805: } kpeter@805: kpeter@806: return OPTIMAL; kpeter@805: } kpeter@805: kpeter@806: ProblemType start() { kpeter@806: // Execute the algorithm kpeter@806: ProblemType pt; kpeter@805: if (_delta > 1) kpeter@806: pt = startWithScaling(); kpeter@805: else kpeter@806: pt = startWithoutScaling(); kpeter@806: kpeter@806: // Handle non-zero lower bounds kpeter@806: if (_have_lower) { kpeter@811: int limit = _first_out[_root]; kpeter@811: for (int j = 0; j != limit; ++j) { kpeter@806: if (!_forward[j]) _res_cap[j] += _lower[j]; kpeter@806: } kpeter@806: } kpeter@806: kpeter@806: // Shift potentials if necessary kpeter@806: Cost pr = _pi[_root]; kpeter@806: if (_sum_supply < 0 || pr > 0) { kpeter@806: for (int i = 0; i != _node_num; ++i) { kpeter@806: _pi[i] -= pr; kpeter@806: } kpeter@806: } kpeter@806: kpeter@806: return pt; kpeter@805: } kpeter@805: kpeter@806: // Execute the capacity scaling algorithm kpeter@806: ProblemType startWithScaling() { kpeter@807: // Perform capacity scaling phases kpeter@806: int s, t; kpeter@806: ResidualDijkstra _dijkstra(*this); kpeter@805: while (true) { kpeter@806: // Saturate all arcs not satisfying the optimality condition kpeter@811: int last_out; kpeter@806: for (int u = 0; u != _node_num; ++u) { kpeter@811: last_out = _sum_supply < 0 ? kpeter@811: _first_out[u+1] : _first_out[u+1] - 1; kpeter@811: for (int a = _first_out[u]; a != last_out; ++a) { kpeter@806: int v = _target[a]; kpeter@806: Cost c = _cost[a] + _pi[u] - _pi[v]; kpeter@806: Value rc = _res_cap[a]; kpeter@806: if (c < 0 && rc >= _delta) { kpeter@806: _excess[u] -= rc; kpeter@806: _excess[v] += rc; kpeter@806: _res_cap[a] = 0; kpeter@806: _res_cap[_reverse[a]] += rc; kpeter@806: } kpeter@805: } kpeter@805: } kpeter@805: kpeter@806: // Find excess nodes and deficit nodes kpeter@805: _excess_nodes.clear(); kpeter@805: _deficit_nodes.clear(); kpeter@806: for (int u = 0; u != _node_num; ++u) { kpeter@811: Value ex = _excess[u]; kpeter@811: if (ex >= _delta) _excess_nodes.push_back(u); kpeter@811: if (ex <= -_delta) _deficit_nodes.push_back(u); kpeter@805: } kpeter@805: int next_node = 0, next_def_node = 0; kpeter@805: kpeter@806: // Find augmenting shortest paths kpeter@805: while (next_node < int(_excess_nodes.size())) { kpeter@806: // Check deficit nodes kpeter@805: if (_delta > 1) { kpeter@805: bool delta_deficit = false; kpeter@805: for ( ; next_def_node < int(_deficit_nodes.size()); kpeter@805: ++next_def_node ) { kpeter@805: if (_excess[_deficit_nodes[next_def_node]] <= -_delta) { kpeter@805: delta_deficit = true; kpeter@805: break; kpeter@805: } kpeter@805: } kpeter@805: if (!delta_deficit) break; kpeter@805: } kpeter@805: kpeter@806: // Run Dijkstra in the residual network kpeter@805: s = _excess_nodes[next_node]; kpeter@806: if ((t = _dijkstra.run(s, _delta)) == -1) { kpeter@805: if (_delta > 1) { kpeter@805: ++next_node; kpeter@805: continue; kpeter@805: } kpeter@806: return INFEASIBLE; kpeter@805: } kpeter@805: kpeter@806: // Augment along a shortest path from s to t kpeter@806: Value d = std::min(_excess[s], -_excess[t]); kpeter@806: int u = t; kpeter@806: int a; kpeter@805: if (d > _delta) { kpeter@806: while ((a = _pred[u]) != -1) { kpeter@806: if (_res_cap[a] < d) d = _res_cap[a]; kpeter@806: u = _source[a]; kpeter@805: } kpeter@805: } kpeter@805: u = t; kpeter@806: while ((a = _pred[u]) != -1) { kpeter@806: _res_cap[a] -= d; kpeter@806: _res_cap[_reverse[a]] += d; kpeter@806: u = _source[a]; kpeter@805: } kpeter@805: _excess[s] -= d; kpeter@805: _excess[t] += d; kpeter@805: kpeter@805: if (_excess[s] < _delta) ++next_node; kpeter@805: } kpeter@805: kpeter@805: if (_delta == 1) break; kpeter@810: _delta = _delta <= _factor ? 1 : _delta / _factor; kpeter@805: } kpeter@805: kpeter@806: return OPTIMAL; kpeter@805: } kpeter@805: kpeter@806: // Execute the successive shortest path algorithm kpeter@806: ProblemType startWithoutScaling() { kpeter@806: // Find excess nodes kpeter@806: _excess_nodes.clear(); kpeter@806: for (int i = 0; i != _node_num; ++i) { kpeter@806: if (_excess[i] > 0) _excess_nodes.push_back(i); kpeter@806: } kpeter@806: if (_excess_nodes.size() == 0) return OPTIMAL; kpeter@805: int next_node = 0; kpeter@805: kpeter@806: // Find shortest paths kpeter@806: int s, t; kpeter@806: ResidualDijkstra _dijkstra(*this); kpeter@805: while ( _excess[_excess_nodes[next_node]] > 0 || kpeter@805: ++next_node < int(_excess_nodes.size()) ) kpeter@805: { kpeter@806: // Run Dijkstra in the residual network kpeter@805: s = _excess_nodes[next_node]; kpeter@806: if ((t = _dijkstra.run(s)) == -1) return INFEASIBLE; kpeter@805: kpeter@806: // Augment along a shortest path from s to t kpeter@806: Value d = std::min(_excess[s], -_excess[t]); kpeter@806: int u = t; kpeter@806: int a; kpeter@805: if (d > 1) { kpeter@806: while ((a = _pred[u]) != -1) { kpeter@806: if (_res_cap[a] < d) d = _res_cap[a]; kpeter@806: u = _source[a]; kpeter@805: } kpeter@805: } kpeter@805: u = t; kpeter@806: while ((a = _pred[u]) != -1) { kpeter@806: _res_cap[a] -= d; kpeter@806: _res_cap[_reverse[a]] += d; kpeter@806: u = _source[a]; kpeter@805: } kpeter@805: _excess[s] -= d; kpeter@805: _excess[t] += d; kpeter@805: } kpeter@805: kpeter@806: return OPTIMAL; kpeter@805: } kpeter@805: kpeter@805: }; //class CapacityScaling kpeter@805: kpeter@805: ///@} kpeter@805: kpeter@805: } //namespace lemon kpeter@805: kpeter@805: #endif //LEMON_CAPACITY_SCALING_H