diff -r cd72eae05bdf -r 3c00344f49c9 lemon/capacity_scaling.h --- a/lemon/capacity_scaling.h Mon Jul 16 16:21:40 2018 +0200 +++ b/lemon/capacity_scaling.h Wed Oct 17 19:14:07 2018 +0200 @@ -2,7 +2,7 @@ * * This file is a part of LEMON, a generic C++ optimization library. * - * Copyright (C) 2003-2010 + * Copyright (C) 2003-2013 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace lemon { @@ -66,9 +67,16 @@ /// /// \ref CapacityScaling implements the capacity scaling version /// of the successive shortest path algorithm for finding a - /// \ref min_cost_flow "minimum cost flow" \ref amo93networkflows, - /// \ref edmondskarp72theoretical. It is an efficient dual - /// solution method. + /// \ref min_cost_flow "minimum cost flow" \cite amo93networkflows, + /// \cite edmondskarp72theoretical. It is an efficient dual + /// solution method, which runs in polynomial time + /// \f$O(m\log U (n+m)\log n)\f$, where U denotes the maximum + /// of node supply and arc capacity values. + /// + /// This algorithm is typically slower than \ref CostScaling and + /// \ref NetworkSimplex, but in special cases, it can be more + /// efficient than them. + /// (For more information, see \ref min_cost_flow_algs "the module page".) /// /// Most of the parameters of the problem (except for the digraph) /// can be given using separate functions, and the algorithm can be @@ -86,10 +94,11 @@ /// In most cases, this parameter should not be set directly, /// consider to use the named template parameters instead. /// - /// \warning Both number types must be signed and all input data must - /// be integer. - /// \warning This algorithm does not support negative costs for such - /// arcs that have infinite upper bound. + /// \warning Both \c V and \c C must be signed number types. + /// \warning Capacity bounds and supply values must be integer, but + /// arc costs can be arbitrary real numbers. + /// \warning This algorithm does not support negative costs for + /// arcs having infinite upper bound. #ifdef DOXYGEN template #else @@ -110,7 +119,8 @@ /// The type of the heap used for internal Dijkstra computations typedef typename TR::Heap Heap; - /// The \ref CapacityScalingDefaultTraits "traits class" of the algorithm + /// \brief The \ref lemon::CapacityScalingDefaultTraits "traits class" + /// of the algorithm typedef TR Traits; public: @@ -154,7 +164,7 @@ int _root; // Parameters of the problem - bool _have_lower; + bool _has_lower; Value _sum_supply; // Data structures for storing the digraph @@ -347,10 +357,9 @@ /// \return (*this) template CapacityScaling& lowerMap(const LowerMap& map) { - _have_lower = true; + _has_lower = true; for (ArcIt a(_graph); a != INVALID; ++a) { _lower[_arc_idf[a]] = map[a]; - _lower[_arc_idb[a]] = map[a]; } return *this; } @@ -422,7 +431,7 @@ /// calling \ref run(), the supply of each node will be set to zero. /// /// Using this function has the same effect as using \ref supplyMap() - /// with such a map in which \c k is assigned to \c s, \c -k is + /// with a map in which \c k is assigned to \c s, \c -k is /// assigned to \c t and all other nodes have zero supply value. /// /// \param s The source node. @@ -534,7 +543,7 @@ _upper[j] = INF; _cost[j] = _forward[j] ? 1 : -1; } - _have_lower = false; + _has_lower = false; return *this; } @@ -637,7 +646,7 @@ /// \brief Return the total cost of the found flow. /// /// This function returns the total cost of the found flow. - /// Its complexity is O(e). + /// Its complexity is O(m). /// /// \note The return type of the function can be specified as a /// template parameter. For example, @@ -675,7 +684,8 @@ return _res_cap[_arc_idb[a]]; } - /// \brief Return the flow map (the primal solution). + /// \brief Copy the flow values (the primal solution) into the + /// given map. /// /// This function copies the flow value on each arc into the given /// map. The \c Value type of the algorithm must be convertible to @@ -699,7 +709,8 @@ return _pi[_node_id[n]]; } - /// \brief Return the potential map (the dual solution). + /// \brief Copy the potential values (the dual solution) into the + /// given map. /// /// This function copies the potential (dual value) of each node /// into the given map. @@ -729,6 +740,11 @@ } if (_sum_supply > 0) return INFEASIBLE; + // Check lower and upper bounds + LEMON_DEBUG(checkBoundMaps(), + "Upper bounds must be greater or equal to the lower bounds"); + + // Initialize vectors for (int i = 0; i != _root; ++i) { _pi[i] = 0; @@ -738,7 +754,7 @@ // Remove non-zero lower bounds const Value MAX = std::numeric_limits::max(); int last_out; - if (_have_lower) { + if (_has_lower) { for (int i = 0; i != _root; ++i) { last_out = _first_out[i+1]; for (int j = _first_out[i]; j != last_out; ++j) { @@ -823,6 +839,15 @@ return OPTIMAL; } + // Check if the upper bound is greater than or equal to the lower bound + // on each forward arc. + bool checkBoundMaps() { + for (int j = 0; j != _res_arc_num; ++j) { + if (_forward[j] && _upper[j] < _lower[j]) return false; + } + return true; + } + ProblemType start() { // Execute the algorithm ProblemType pt; @@ -832,10 +857,10 @@ pt = startWithoutScaling(); // Handle non-zero lower bounds - if (_have_lower) { + if (_has_lower) { int limit = _first_out[_root]; for (int j = 0; j != limit; ++j) { - if (!_forward[j]) _res_cap[j] += _lower[j]; + if (_forward[j]) _res_cap[_reverse[j]] += _lower[j]; } }