lemon/min_cost_flow.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1527 7ceab500e1f6
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
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){
deba@1763
   154
	  e = dijkstra.predEdge(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