lemon/ssp_min_cost_flow.h
author deba
Thu, 11 Jan 2007 22:08:18 +0000
changeset 2344 48ecc4feb42b
child 2350 eb371753e814
permissions -rw-r--r--
Bug fix
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_MIN_COST_FLOW_H
    20 #define LEMON_MIN_COST_FLOW_H
    21 
    22 ///\ingroup flowalgs 
    23 ///
    24 ///\file \brief An algorithm for finding a flow of value \c k (for
    25 ///small values of \c k) having minimal total cost
    26 
    27 
    28 #include <lemon/dijkstra.h>
    29 #include <lemon/graph_adaptor.h>
    30 #include <lemon/maps.h>
    31 #include <vector>
    32 
    33 namespace lemon {
    34 
    35   /// \addtogroup flowalgs
    36   /// @{
    37 
    38   /// \brief Implementation of an algorithm for finding a flow of
    39   /// value \c k (for small values of \c k) having minimal total cost
    40   /// between two nodes
    41   /// 
    42   ///
    43   /// The \ref lemon::SspMinCostFlow "Successive Shortest Path Minimum
    44   /// Cost Flow" implements an algorithm for finding a flow of value
    45   /// \c k having minimal total cost from a given source node to a
    46   /// given target node in a directed graph with a cost function on
    47   /// the edges. To this end, the edge-capacities and edge-costs have
    48   /// to be nonnegative.  The edge-capacities should be integers, but
    49   /// the edge-costs can be integers, reals or of other comparable
    50   /// numeric type.  This algorithm is intended to be used only for
    51   /// small values of \c k, since it is only polynomial in k, not in
    52   /// the length of k (which is log k): in order to find the minimum
    53   /// cost flow of value \c k it finds the minimum cost flow of value
    54   /// \c i for every \c i between 0 and \c k.
    55   ///
    56   ///\param Graph The directed graph type the algorithm runs on.
    57   ///\param LengthMap The type of the length map.
    58   ///\param CapacityMap The capacity map type.
    59   ///
    60   ///\author Attila Bernath
    61   template <typename Graph, typename LengthMap, typename CapacityMap>
    62   class SspMinCostFlow {
    63 
    64     typedef typename LengthMap::Value Length;
    65 
    66     //Warning: this should be integer type
    67     typedef typename CapacityMap::Value Capacity;
    68     
    69     typedef typename Graph::Node Node;
    70     typedef typename Graph::NodeIt NodeIt;
    71     typedef typename Graph::Edge Edge;
    72     typedef typename Graph::OutEdgeIt OutEdgeIt;
    73     typedef typename Graph::template EdgeMap<int> EdgeIntMap;
    74 
    75     typedef ResGraphAdaptor<const Graph,int,CapacityMap,EdgeIntMap> ResGW;
    76     typedef typename ResGW::Edge ResGraphEdge;
    77 
    78   protected:
    79 
    80     const Graph& g;
    81     const LengthMap& length;
    82     const CapacityMap& capacity;
    83 
    84     EdgeIntMap flow; 
    85     typedef typename Graph::template NodeMap<Length> PotentialMap;
    86     PotentialMap potential;
    87 
    88     Node s;
    89     Node t;
    90     
    91     Length total_length;
    92 
    93     class ModLengthMap {   
    94       typedef typename Graph::template NodeMap<Length> NodeMap;
    95       const ResGW& g;
    96       const LengthMap &length;
    97       const NodeMap &pot;
    98     public :
    99       typedef typename LengthMap::Key Key;
   100       typedef typename LengthMap::Value Value;
   101 
   102       ModLengthMap(const ResGW& _g, 
   103 		   const LengthMap &_length, const NodeMap &_pot) : 
   104 	g(_g), /*rev(_rev),*/ length(_length), pot(_pot) { }
   105 	
   106       Value operator[](typename ResGW::Edge e) const {     
   107 	if (g.forward(e))
   108 	  return  length[e]-(pot[g.target(e)]-pot[g.source(e)]);   
   109 	else
   110 	  return -length[e]-(pot[g.target(e)]-pot[g.source(e)]);   
   111       }     
   112 	
   113     }; //ModLengthMap
   114 
   115     ResGW res_graph;
   116     ModLengthMap mod_length;
   117     Dijkstra<ResGW, ModLengthMap> dijkstra;
   118 
   119   public :
   120 
   121     /// \brief The constructor of the class.
   122     ///
   123     /// \param _g The directed graph the algorithm runs on. 
   124     /// \param _length The length (cost) of the edges. 
   125     /// \param _cap The capacity of the edges. 
   126     /// \param _s Source node.
   127     /// \param _t Target node.
   128     SspMinCostFlow(Graph& _g, LengthMap& _length, CapacityMap& _cap, 
   129                    Node _s, Node _t) : 
   130       g(_g), length(_length), capacity(_cap), flow(_g), potential(_g), 
   131       s(_s), t(_t), 
   132       res_graph(g, capacity, flow), 
   133       mod_length(res_graph, length, potential),
   134       dijkstra(res_graph, mod_length) { 
   135       reset();
   136     }
   137     
   138     /// \brief Tries to augment the flow between s and t by 1. The
   139     /// return value shows if the augmentation is successful.
   140     bool augment() {
   141       dijkstra.run(s);
   142       if (!dijkstra.reached(t)) {
   143 
   144 	//Unsuccessful augmentation.
   145 	return false;
   146       } else {
   147 
   148 	//We have to change the potential
   149 	for(typename ResGW::NodeIt n(res_graph); n!=INVALID; ++n)
   150 	  potential.set(n, potential[n]+dijkstra.distMap()[n]);
   151 	
   152 	//Augmenting on the shortest path
   153 	Node n=t;
   154 	ResGraphEdge e;
   155 	while (n!=s){
   156 	  e = dijkstra.predEdge(n);
   157 	  n = dijkstra.predNode(n);
   158 	  res_graph.augment(e,1);
   159 	  //Let's update the total length
   160 	  if (res_graph.forward(e))
   161 	    total_length += length[e];
   162 	  else 
   163 	    total_length -= length[e];	    
   164 	}
   165 
   166 	return true;
   167       }
   168     }
   169     
   170     /// \brief Runs the algorithm.
   171     ///
   172     /// Runs the algorithm.
   173     /// Returns k if there is a flow of value at least k from s to t.
   174     /// Otherwise it returns the maximum value of a flow from s to t.
   175     ///
   176     /// \param k The value of the flow we are looking for.
   177     ///
   178     /// \todo May be it does make sense to be able to start with a
   179     /// nonzero feasible primal-dual solution pair as well.
   180     ///
   181     /// \todo If the actual flow value is bigger than k, then
   182     /// everything is cleared and the algorithm starts from zero
   183     /// flow. Is it a good approach?
   184     int run(int k) {
   185       if (flowValue()>k) reset();
   186       while (flowValue()<k && augment()) { }
   187       return flowValue();
   188     }
   189 
   190     /// \brief The class is reset to zero flow and potential. The
   191     /// class is reset to zero flow and potential.
   192     void reset() {
   193       total_length=0;
   194       for (typename Graph::EdgeIt e(g); e!=INVALID; ++e) flow.set(e, 0);
   195       for (typename Graph::NodeIt n(g); n!=INVALID; ++n) potential.set(n, 0);  
   196     }
   197 
   198     /// \brief Returns the value of the actual flow. 
   199     int flowValue() const {
   200       int i=0;
   201       for (typename Graph::OutEdgeIt e(g, s); e!=INVALID; ++e) i+=flow[e];
   202       for (typename Graph::InEdgeIt e(g, s); e!=INVALID; ++e) i-=flow[e];
   203       return i;
   204     }
   205 
   206     /// \brief Total cost of the found flow.
   207     ///
   208     /// This function gives back the total cost of the found flow.
   209     Length totalLength(){
   210       return total_length;
   211     }
   212 
   213     /// \brief Returns a const reference to the EdgeMap \c flow. 
   214     ///
   215     /// Returns a const reference to the EdgeMap \c flow. 
   216     const EdgeIntMap &getFlow() const { return flow;}
   217 
   218     /// \brief Returns a const reference to the NodeMap \c potential
   219     /// (the dual solution).
   220     ///
   221     /// Returns a const reference to the NodeMap \c potential (the
   222     /// dual solution).
   223     const PotentialMap &getPotential() const { return potential;}
   224 
   225     /// \brief Checking the complementary slackness optimality criteria.
   226     ///
   227     /// This function checks, whether the given flow and potential 
   228     /// satisfy the complementary slackness conditions (i.e. these are optimal).
   229     /// This function only checks optimality, doesn't bother with feasibility.
   230     /// For testing purpose.
   231     bool checkComplementarySlackness(){
   232       Length mod_pot;
   233       Length fl_e;
   234         for(typename Graph::EdgeIt e(g); e!=INVALID; ++e) {
   235 	//C^{\Pi}_{i,j}
   236 	mod_pot = length[e]-potential[g.target(e)]+potential[g.source(e)];
   237 	fl_e = flow[e];
   238 	if (0<fl_e && fl_e<capacity[e]) {
   239 	  /// \todo better comparison is needed for real types, moreover, 
   240 	  /// this comparison here is superfluous.
   241 	  if (mod_pot != 0)
   242 	    return false;
   243 	} 
   244 	else {
   245 	  if (mod_pot > 0 && fl_e != 0)
   246 	    return false;
   247 	  if (mod_pot < 0 && fl_e != capacity[e])
   248 	    return false;
   249 	}
   250       }
   251       return true;
   252     }
   253     
   254   }; //class SspMinCostFlow
   255 
   256   ///@}
   257 
   258 } //namespace lemon
   259 
   260 #endif //LEMON_MIN_COST_FLOW_H