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