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