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