lemon/ssp_min_cost_flow.h
author kpeter
Tue, 05 Feb 2008 11:03:55 +0000
changeset 2560 635e7985be46
parent 2418 89cbf0a2ed57
permissions -rw-r--r--
Fix the rename script.
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2008
     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_SSP_MIN_COST_FLOW_H
    20 #define LEMON_SSP_MIN_COST_FLOW_H
    21 
    22 ///\ingroup min_cost_flow 
    23 ///
    24 ///\file
    25 ///\brief An algorithm for finding a flow of value \c k (for
    26 ///small values of \c k) having minimal total cost
    27 
    28 
    29 #include <lemon/dijkstra.h>
    30 #include <lemon/graph_adaptor.h>
    31 #include <lemon/maps.h>
    32 #include <vector>
    33 
    34 namespace lemon {
    35 
    36   /// \addtogroup min_cost_flow
    37   /// @{
    38 
    39   /// \brief Implementation of an algorithm for finding a flow of
    40   /// value \c k (for small values of \c k) having minimal total cost
    41   /// between two nodes
    42   /// 
    43   ///
    44   /// The \ref lemon::SspMinCostFlow "Successive Shortest Path Minimum
    45   /// Cost Flow" implements an algorithm for finding a flow of value
    46   /// \c k having minimal total cost from a given source node to a
    47   /// given target node in a directed graph with a cost function on
    48   /// the edges. To this end, the edge-capacities and edge-costs have
    49   /// to be nonnegative.  The edge-capacities should be integers, but
    50   /// the edge-costs can be integers, reals or of other comparable
    51   /// numeric type.  This algorithm is intended to be used only for
    52   /// small values of \c k, since it is only polynomial in k, not in
    53   /// the length of k (which is log k): in order to find the minimum
    54   /// cost flow of value \c k it finds the minimum cost flow of value
    55   /// \c i for every \c i between 0 and \c k.
    56   ///
    57   ///\param Graph The directed graph type the algorithm runs on.
    58   ///\param LengthMap The type of the length map.
    59   ///\param CapacityMap The capacity map type.
    60   ///
    61   ///\author Attila Bernath
    62   template <typename Graph, typename LengthMap, typename CapacityMap>
    63   class SspMinCostFlow {
    64 
    65     typedef typename LengthMap::Value Length;
    66 
    67     //Warning: this should be integer type
    68     typedef typename CapacityMap::Value Capacity;
    69     
    70     typedef typename Graph::Node Node;
    71     typedef typename Graph::NodeIt NodeIt;
    72     typedef typename Graph::Edge Edge;
    73     typedef typename Graph::OutEdgeIt OutEdgeIt;
    74     typedef typename Graph::template EdgeMap<int> EdgeIntMap;
    75 
    76     typedef ResGraphAdaptor<const Graph,int,CapacityMap,EdgeIntMap> ResGW;
    77     typedef typename ResGW::Edge ResGraphEdge;
    78 
    79   protected:
    80 
    81     const Graph& g;
    82     const LengthMap& length;
    83     const CapacityMap& capacity;
    84 
    85     EdgeIntMap flow; 
    86     typedef typename Graph::template NodeMap<Length> PotentialMap;
    87     PotentialMap potential;
    88 
    89     Node s;
    90     Node t;
    91     
    92     Length total_length;
    93 
    94     class ModLengthMap {   
    95       typedef typename Graph::template NodeMap<Length> NodeMap;
    96       const ResGW& g;
    97       const LengthMap &length;
    98       const NodeMap &pot;
    99     public :
   100       typedef typename LengthMap::Key Key;
   101       typedef typename LengthMap::Value Value;
   102 
   103       ModLengthMap(const ResGW& _g, 
   104 		   const LengthMap &_length, const NodeMap &_pot) : 
   105 	g(_g), /*rev(_rev),*/ length(_length), pot(_pot) { }
   106 	
   107       Value operator[](typename ResGW::Edge e) const {     
   108 	if (g.forward(e))
   109 	  return  length[e]-(pot[g.target(e)]-pot[g.source(e)]);   
   110 	else
   111 	  return -length[e]-(pot[g.target(e)]-pot[g.source(e)]);   
   112       }     
   113 	
   114     }; //ModLengthMap
   115 
   116     ResGW res_graph;
   117     ModLengthMap mod_length;
   118     Dijkstra<ResGW, ModLengthMap> dijkstra;
   119 
   120   public :
   121 
   122     /// \brief The constructor of the class.
   123     ///
   124     /// \param _g The directed graph the algorithm runs on. 
   125     /// \param _length The length (cost) of the edges. 
   126     /// \param _cap The capacity of the edges. 
   127     /// \param _s Source node.
   128     /// \param _t Target node.
   129     SspMinCostFlow(Graph& _g, LengthMap& _length, CapacityMap& _cap, 
   130                    Node _s, Node _t) : 
   131       g(_g), length(_length), capacity(_cap), flow(_g), potential(_g), 
   132       s(_s), t(_t), 
   133       res_graph(g, capacity, flow), 
   134       mod_length(res_graph, length, potential),
   135       dijkstra(res_graph, mod_length) { 
   136       reset();
   137     }
   138     
   139     /// \brief Tries to augment the flow between s and t by 1. The
   140     /// return value shows if the augmentation is successful.
   141     bool augment() {
   142       dijkstra.run(s);
   143       if (!dijkstra.reached(t)) {
   144 
   145 	//Unsuccessful augmentation.
   146 	return false;
   147       } else {
   148 
   149 	//We have to change the potential
   150 	for(typename ResGW::NodeIt n(res_graph); n!=INVALID; ++n)
   151 	  potential.set(n, potential[n]+dijkstra.distMap()[n]);
   152 	
   153 	//Augmenting on the shortest path
   154 	Node n=t;
   155 	ResGraphEdge e;
   156 	while (n!=s){
   157 	  e = dijkstra.predEdge(n);
   158 	  n = dijkstra.predNode(n);
   159 	  res_graph.augment(e,1);
   160 	  //Let's update the total length
   161 	  if (res_graph.forward(e))
   162 	    total_length += length[e];
   163 	  else 
   164 	    total_length -= length[e];	    
   165 	}
   166 
   167 	return true;
   168       }
   169     }
   170     
   171     /// \brief Runs the algorithm.
   172     ///
   173     /// Runs the algorithm.
   174     /// Returns k if there is a flow of value at least k from s to t.
   175     /// Otherwise it returns the maximum value of a flow from s to t.
   176     ///
   177     /// \param k The value of the flow we are looking for.
   178     ///
   179     /// \todo May be it does make sense to be able to start with a
   180     /// nonzero feasible primal-dual solution pair as well.
   181     ///
   182     /// \todo If the current flow value is bigger than k, then
   183     /// everything is cleared and the algorithm starts from zero
   184     /// flow. Is it a good approach?
   185     int run(int k) {
   186       if (flowValue()>k) reset();
   187       while (flowValue()<k && augment()) { }
   188       return flowValue();
   189     }
   190 
   191     /// \brief The 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 current 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_SSP_MIN_COST_FLOW_H