lemon/min_cost_flow.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 1875 98698b69a902
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@906
    18
alpar@921
    19
#ifndef LEMON_MIN_COST_FLOW_H
alpar@921
    20
#define LEMON_MIN_COST_FLOW_H
alpar@899
    21
alpar@899
    22
///\ingroup flowalgs
alpar@899
    23
///\file
alpar@899
    24
///\brief An algorithm for finding a flow of value \c k (for small values of \c k) having minimal total cost 
alpar@899
    25
alpar@899
    26
alpar@921
    27
#include <lemon/dijkstra.h>
alpar@1401
    28
#include <lemon/graph_adaptor.h>
alpar@921
    29
#include <lemon/maps.h>
alpar@899
    30
#include <vector>
alpar@899
    31
alpar@921
    32
namespace lemon {
alpar@899
    33
alpar@899
    34
/// \addtogroup flowalgs
alpar@899
    35
/// @{
alpar@899
    36
alpar@899
    37
  ///\brief Implementation of an algorithm for finding a flow of value \c k 
alpar@899
    38
  ///(for small values of \c k) having minimal total cost between 2 nodes 
alpar@899
    39
  /// 
alpar@899
    40
  ///
jacint@1270
    41
  /// The class \ref lemon::MinCostFlow "MinCostFlow" implements an
jacint@1270
    42
  /// algorithm for finding a flow of value \c k having minimal total
athos@1527
    43
  /// cost from a given source node to a given target node in a
athos@1527
    44
  /// directed graph with a cost function on the edges. To
athos@1527
    45
  /// this end, the edge-capacities and edge-costs have to be
athos@1527
    46
  /// nonnegative.  The edge-capacities should be integers, but the
athos@1527
    47
  /// edge-costs can be integers, reals or of other comparable
athos@1527
    48
  /// numeric type.  This algorithm is intended to be used only for
athos@1527
    49
  /// small values of \c k, since it is only polynomial in k, not in
athos@1527
    50
  /// the length of k (which is log k): in order to find the minimum
athos@1527
    51
  /// cost flow of value \c k it finds the minimum cost flow of value
athos@1527
    52
  /// \c i for every \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
alpar@1401
    73
    typedef ResGraphAdaptor<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. 
athos@1527
   122
    \param _length The length (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
	
jacint@1270
   152
	//Augmenting on the shortest path
alpar@899
   153
	Node n=t;
alpar@899
   154
	ResGraphEdge e;
alpar@899
   155
	while (n!=s){
deba@1763
   156
	  e = dijkstra.predEdge(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
athos@1527
   208
    /// Total cost of the found flow.
alpar@899
   209
athos@1527
   210
    /// This function gives back the total cost 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 
jacint@1270
   229
    satisfy the complementary slackness conditions (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